The frontend production build (tsc -b) was failing, which blocked deployment:
- api/jellyseerr.ts exported `JellyseerrStatsResponse` (double-r) while every
import used `JellyseerStatsResponse` (single-r) — a mismatch TS reported as
"no exported member" (with a misleading identical-name suggestion). The
sibling types (JellyseerStat, JellyseerRecentRequest) are single-r, so
align the export to single-r. (tsc --noEmit missed it because the root
tsconfig is solution-style; tsc -b builds the app project and catches it.)
- RequestsTab.test.tsx's useJellyseerrStats mock returned a partial object
that didn't satisfy UseQueryResult's full shape; cast via a typed helper.
`npm run build` (tsc -b && vite build) now succeeds; 184/184 tests + ESLint clean.
Frontend for Jellyseerr request stats, reusing the generic stat abstraction.
- api/jellyseerr.ts + hooks/useJellyseer.ts: fetchJellyseerrStats +
useJellyseerrStats (polls /api/jellyseerr/stats, no-retry; shares the backend
cache with the widgets).
- Two reusable widgets backed by the stat/stats_overview kinds:
- RequestStatWidget: a single selected stat (big value + label).
- RequestsOverviewWidget: a MetricCard grid of all stats + a recent-requests
list with status/media-status badges.
- registry.ts: Jellyfin gains `stat` (a dropdown over
total/pending/approved/declined/processing/available — the "extract one stat
into a widget" affordance, rendered as a Select via the existing enum UI) and
`stats_overview` widget kinds, wired to the new components.
- RequestsTab rewritten: live stats grid (6 counts) + recent-requests list +
a hint to pin individual stats via the Request stat widget. Reads
jellyseerr_url from config and the now-secret jellyseerr_api_key from
secrets_set.
Tests: RequestStatWidget + RequestsOverviewWidget rendering/error; RequestsTab
not-configured CTA, configured stats grid, and error states. 184/184 frontend
tests pass; tsc + ESLint clean.