* perf(web): render stats page shell immediately with per-panel skeletons
The stats route previously blocked the full SSR response on the workspace
stats query, leaving the user staring at a blank loading screen for the
entire round-trip. Drop the server-side stats fetch (server still resolves
the workspace id, which is cheap) and move the stats request to the client.
The header, range toggle, and every panel render their shell on mount, with
each panel showing its own skeleton until data arrives. Range changes also
re-show the skeletons during the refetch instead of staling the previous
data.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(web): address PR review feedback on stats page lazy-loading
- Drop unused `loading` flag from stats reducer (Claude)
- Show "Failed to load stats" subtitle on fetch error instead of stale
"Loading stats…" text (Claude, cubic)
- Read live `range` from useSearchParams() and validate against the
RangeKey union so skeletons reset immediately on toggle and invalid
?range values fall back to "month" (Claude, CodeRabbit)
- Render an error panel per section instead of perpetual skeletons when
the stats fetch fails (Greptile)
- Use router.replace with scroll:false on range toggle to avoid
re-running the server component for a URL-only change
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* test(web): extract stats pure helpers into stats-utils + unit tests
- Move statsReducer, isRangeKey, getRangeLabel, formatDuration,
getSubtitle, toPanelState, and buildStatsSummary into
apps/web/app/stats/stats-utils.ts so the testable units are reachable
outside the client component
- Add apps/web/app/stats/stats-utils.test.ts covering reducer
transitions, range-key validation, subtitle branching, panel-state
derivation, and the summary builder
- Switch useStatsData from a cancellation flag to AbortController so
fast range toggles actually abort the in-flight fetchStats request
instead of letting stale requests run to completion
Addresses Claude review blocker + suggestion on PR #1022.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* refactor(web): tighten stats lazy-loading per Claude suggestions
- loading.tsx now includes TopRepositoriesSkeleton, RepoLeadersSkeleton,
and WorkloadSkeleton so a cold navigation to /stats shows the full
page layout, not a layout that ends at Repository Activity
- Reuse the existing StatsRange union for RangeKey in stats-utils.ts
(one type alias, no risk of drift)
- Drop the unreachable default arm in getRangeLabel so a future
RangeKey addition triggers a TypeScript exhaustiveness error
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>