feat(stats): link stats rows and counts to filtered lists (#65)

Wire the stats page to filter_url()/stats_links:
- Per-row session links on game superlatives, games-by-playtime, platform
  and month rows (game rows keep their detail GameLink, add a session icon).
- Count links: sessions, games, total/refunded/dropped/unfinished/backlog
  purchases.
- Cap preview lists to 5 with a 'View all (N)' link passing ?sort= for order
  parity; remove the redundant 'All Purchases' list.
- stats_data: carry platform_id for platform links; drop the all-time
  games-by-playtime [:10] slice so the view-all count is honest (rendering
  caps the preview).

Also make the filter bar's _extract_labeled tolerate bare choice/multi values
so a programmatically-built filter URL renders instead of crashing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RF5L4HtbcykTfY9YUYGds3
This commit is contained in:
2026-06-21 15:26:33 +02:00
parent 57980c407f
commit 90c6113772
5 changed files with 323 additions and 34 deletions
+9 -4
View File
@@ -247,7 +247,7 @@ def compute_stats(year: int | None = None) -> StatsData:
.annotate(total_playtime=Sum("sessions__duration_total"))
.filter(total_playtime__gt=timedelta(0))
)
top_games = games_with_playtime.order_by("-total_playtime")[:10]
top_games = games_with_playtime.order_by("-total_playtime")
else:
games_with_playtime = (
Game.objects.filter(sessions__timestamp_start__year=year)
@@ -256,11 +256,16 @@ def compute_stats(year: int | None = None) -> StatsData:
)
top_games = games_with_playtime.order_by("-total_playtime")
# platform_id is carried alongside the name so the stats row can link to a
# platform-scoped session list (#65).
total_playtime_per_platform = (
sessions.values("game__platform__name")
sessions.values("game__platform__name", "game__platform__id")
.annotate(playtime=Sum(F("duration_total")))
.annotate(platform_name=F("game__platform__name"))
.values("platform_name", "playtime")
.annotate(
platform_name=F("game__platform__name"),
platform_id=F("game__platform__id"),
)
.values("platform_name", "platform_id", "playtime")
.order_by("-playtime")
)