Skip to content

feat: catalog cards show your library status, plus the grid, tab and footer key layout pass - #41

Merged
kris1027 merged 25 commits into
mainfrom
feat/catalog-card-status
Oct 11, 2026
Merged

kris1027 merged 25 commits into
mainfrom
feat/catalog-card-status

Conversation

@kris1027

Copy link
Copy Markdown
Owner

What

Two changes in one PR:

  1. Layout pass (prompts/grid-tabs-footer-legend.md): poster grids have at most four columns and are centred, the selected navbar tab is lit in the personal score cyan, the badge legend is now a footer icon key on every route (with Mark watched paired with Watched), and every skeleton matches the footprint of what replaces it.
  2. Catalog cards show your real status (prompts/catalog-card-status.md): a poster card on /movies, /shows and /search now shows a title the way its library page (Watchlist, Upcoming or Watched) does.

Why

Until now, a movie you had watched and scored showed on /movies with the TMDB rating and an empty Plan bookmark, while /watched showed your score. Catalog cards only knew whether a movie was planned or a show was tracked.

Changes (catalog cards)

Movies

  • Watched: your cyan score replaces the TMDB rating (the TMDB rating stays when unscored), plus the filled watched mark. Tapping it unmarks the movie and shows the movie page's score-removed toast with Undo.
  • Planned, unreleased or undated: the release date pill or Date TBA, no rating, and the Planned bookmark, the same as on Upcoming.
  • Planned and released, or untouched: unchanged.

Tracked shows (the Stop tracking bookmark stays on every one)

  • Upcoming: the next episode's date pill (for example "S2E1 · Oct 20") or Date TBA, and no rating.
  • Watched: the calculated show rating (the TMDB rating stays when unrated), with Finished or Caught up under the name. On /search it reads "2019 · Finished".
  • Watchlist: unchanged.

How it works

  • Placement uses the library pages' own classifiers (classifyMovie, classifyShow) with the same requestTodayUtc(), so a card can never disagree with its library page.
  • Movies: getMovieGridStates reads the state of every movie on a grid in one query.
  • Shows: getShowGridStatus reads the tracked set, then, for tracked shows only, the watched regular episodes, the cached TMDB details and the ratings of shows on Watched.
  • Each slot (badge, meta line, controls) streams in its own Suspense boundary, and the badge falls back to the TMDB rating. The grids keep their prerendered shells, and only your own titles swap.
  • A visitor, or anyone whose status read fails, gets the plain catalog card. A tracked show whose details or rating fail to load stays a plain tracked card, never a wrong label.
  • SearchResult now carries the movie releaseDate. ReleasePill and UpcomingShowPill are shared between the library pages and the catalog cards.
  • classifyMovie now takes a watched boolean instead of a timestamp.
  • card-bookmark.tsx and show-card-bookmark.tsx are replaced by movie-card-slots.tsx and show-card-slots.tsx.

Security

Every new read uses the session user, filters on user_id explicitly as well as through RLS, and never runs inside use cache. The unmark goes through the existing setMovieWatched Server Action. There is no schema change.

Test

  • pnpm typecheck, pnpm lint:ci (no errors, 3 old informational notes) and pnpm test (2163 tests in 129 files) all pass.
  • pnpm build succeeds, and /movies, /shows and /search are still partly prerendered.
  • Checked in the running app against the local stack:
    1. The Matrix (watched, scored 9) on /search shows the score and the watched mark. Unmarking switches it to TMDB 8.3 and the Plan bookmark, and Undo restores both.
    2. Planning Avengers: Doomsday shows the "Dec 16" pill, no rating and a filled Planned bookmark.
    3. Chernobyl, fully watched and rated, shows "Your show rating 9.0", "2019 · Finished" and Stop tracking, matching /watched?type=tv. Checked at 375px too.
  • Not checked in the browser: a tracked show on Upcoming. The unit tests cover it.

🤖 Generated with Claude Code

kris1027 and others added 14 commits October 11, 2026 10:03
…and skeletons

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A page holds 20 titles, which fills every row at two and four columns, so
the grid steps from 2 to 4 at md and never goes wider. It is capped at
1200px and centred; POSTER_SIZES and the eager poster counts follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The selected SHOWS | MOVIES tab and Library link use a new
glass-selected-personal utility: the glass-selected stack tinted from
--color-score-personal, with dark text-on-personal at 6.3:1 or better.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The per tab BadgeLegend under the library grids is gone. IconKey, a static
Server Component, is the footer's first row everywhere, centred under a
hairline, and always lists every card mark in a fixed order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Library pages draw one row instead of 20 cards, so a short list no longer
collapses on load. Catalog and search skeletons reserve the pagination row
and size captions with h-[1lh]; the detail and season skeletons mirror
their real layouts line for line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The key lists each two state mark as action then done, so the filled
watched check joins its outline the way Planned joins Plan.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move ReleasePill and releaseDateFor into dated-pill.tsx and export
UpcomingShowPill, so the catalog cards can reuse the Upcoming copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
classifyMovie only ever asked whether watched_at was set. Taking a
boolean lets the catalog grid read, which carries no timestamp, place a
movie through the same function as the library pages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A client button that unmarks a watched movie from a grid card, with the
movie page's score-removed toast and Undo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Movie cards on /movies and /search read every grid movie's state in one
query and show it as the library page does: the personal score and the
watched mark on a watched movie, the release pill on a planned unreleased
one, and the plan bookmark otherwise. The badge falls back to the TMDB
rating while the state streams in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
getShowGridStatus classifies the tracked shows of one catalog grid with
the library pages' own reads and classifier, adding the calculated show
rating for shows on Watched. A failed read leaves the card plain rather
than wrong.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Show cards on /shows and /search keep the Stop tracking bookmark and add
what the show's library page shows: the next episode date on Upcoming,
and the show rating with Finished or Caught up on Watched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
bestats Ready Ready Preview Oct 11, 2026 8:45am UTC

@kris1027 kris1027 added docs Documentation additions and updates feature New user-facing functionality test Automated tests and test infrastructure ui Layouts, styling, and shared interface components labels Oct 11, 2026
@kris1027 kris1027 self-assigned this Oct 11, 2026
kris1027 and others added 4 commits October 11, 2026 10:39
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…and shows

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kris1027 and others added 7 commits October 11, 2026 10:41
…ing per slot

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rom the plans

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kris1027
kris1027 merged commit 107e3ee into main Oct 11, 2026
4 checks passed
@kris1027
kris1027 deleted the feat/catalog-card-status branch October 11, 2026 08:47
@github-project-automation github-project-automation Bot moved this from In review to Done in BeStats Oct 11, 2026

This branch was successfully deployed

1 active deployment
Preview — 315ffedc Deployed Oct 11, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation additions and updates feature New user-facing functionality test Automated tests and test infrastructure ui Layouts, styling, and shared interface components

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant