diff options
| author | Tyler Hoang <tyler@tylerhoang.xyz> | 2026-05-15 01:50:15 -0700 |
|---|---|---|
| committer | Tyler Hoang <tyler@tylerhoang.xyz> | 2026-05-15 01:50:15 -0700 |
| commit | 20c1d02b40bcb9abb5882d0503e596c82e9819bb (patch) | |
| tree | a2e8918b7f742b23a580daff7f844c576f31c33d /routers | |
| parent | 19f2fc05387ed0d7ad5f5fcb2fa92573ece1eae0 (diff) | |
Refine Lumi stats and detail UX
Diffstat (limited to 'routers')
| -rw-r--r-- | routers/films.py | 31 | ||||
| -rw-r--r-- | routers/stats.py | 20 |
2 files changed, 51 insertions, 0 deletions
diff --git a/routers/films.py b/routers/films.py index 56f50c5..21feab8 100644 --- a/routers/films.py +++ b/routers/films.py @@ -220,6 +220,34 @@ def _group_films_by_month(films: list[Film]) -> list[dict]: return grouped +def _shelf_snapshot(films: list[Film], shelf: str) -> list[dict[str, str | int]]: + if shelf == "diary": + rated = sum(1 for film in films if film.stars) + latest_watch = next((film.date_watched for film in films if film.date_watched), None) + return [ + {"label": "Entries", "value": len(films)}, + {"label": "Rated", "value": rated}, + {"label": "Latest", "value": latest_watch.isoformat() if latest_watch else "Not set"}, + ] + + if shelf == "queue": + with_posters = sum(1 for film in films if film.poster_url) + with_notes = sum(1 for film in films if film.notes) + return [ + {"label": "Queued", "value": len(films)}, + {"label": "With posters", "value": with_posters}, + {"label": "With notes", "value": with_notes}, + ] + + rated = sum(1 for film in films if film.stars) + with_notes = sum(1 for film in films if film.notes) + return [ + {"label": "Entries", "value": len(films)}, + {"label": "Rated", "value": rated}, + {"label": "With notes", "value": with_notes}, + ] + + def _render_shelf( shelf: str, request: Request, @@ -228,6 +256,7 @@ def _render_shelf( ): query = _get_shelf_query(db, shelf) total_films = query.count() + shelf_snapshot = _shelf_snapshot(query.all(), shelf) films = query.limit(20).all() has_more = total_films > 20 @@ -245,6 +274,7 @@ def _render_shelf( "grouped_films": grouped_films, "active_shelf": shelf, "shelf_meta": SHELF_META[shelf], + "shelf_snapshot": shelf_snapshot, "total_films": total_films, "has_more": has_more, **notices, @@ -483,6 +513,7 @@ async def film_detail(film_id: int, request: Request, db: Session = Depends(get_ "request": request, "film": film, "active_shelf": film.shelf, + "shelf_meta": SHELF_META.get(film.shelf, SHELF_META["diary"]), "tmdb_context": tmdb_context, "rewatch_history": rewatch_history, "ratings": ratings, diff --git a/routers/stats.py b/routers/stats.py index d600e5a..ad07e0c 100644 --- a/routers/stats.py +++ b/routers/stats.py @@ -65,7 +65,9 @@ def _build_stats_payload(films: list[Film]) -> dict: watched_with["solo"] += 1 total_watched = len(films) + rewatches = sum(1 for film in films if film.rewatch or film.rewatch_count > 0) total_runtime_minutes = sum(film.runtime for film in films if film.runtime) + average_stars = round(sum(film.stars for film in films) / total_watched, 1) if total_watched else 0 title_groups = defaultdict(list) for film in films: @@ -90,6 +92,16 @@ def _build_stats_payload(films: list[Film]) -> dict: rewatch_details.sort(key=lambda x: (-x["watches"], x["title"])) + top_director = None + if directors: + top_director_name, top_director_count = sorted(directors.items(), key=lambda item: (-item[1], item[0]))[0] + top_director = {"director": top_director_name, "count": top_director_count} + + top_month = None + if months: + top_month_key, top_month_count = sorted(months.items(), key=lambda item: (-item[1], item[0]))[0] + top_month = {"month": top_month_key, "count": top_month_count} + today = date.today() start_day = today - timedelta(days=364) trailing_days = [] @@ -105,6 +117,7 @@ def _build_stats_payload(films: list[Film]) -> dict: }, "total_watched": total_watched, "total_runtime_minutes": total_runtime_minutes, + "average_stars": average_stars, "films_per_country": [ {"country": country, "count": count} for country, count in sorted(countries.items(), key=lambda item: (-item[1], item[0])) @@ -143,6 +156,13 @@ def _build_stats_payload(films: list[Film]) -> dict: {"watched_with": watched_with_value, "count": count} for watched_with_value, count in sorted(watched_with.items(), key=lambda item: (-item[1], item[0])) ], + "rewatch_rate": { + "rewatched": rewatches, + "total_watched": total_watched, + "rate": round(rewatches / total_watched, 4) if total_watched else 0, + }, + "top_director": top_director, + "top_month": top_month, } |
