trends.stumason.dev
TypeScript
Pull Request Merged
PR #114 merged: feat(ux): phase 3 — data freshness labelling
Scope
Phase 3 of the UX overhaul (plan / audit / tokens / brief).
Replaces stale publishedAt labels with live computedAt, adds contextual empty states, and fixes the "0%" awaiting-state false signal on StatGrids.
What's in
<TimestampLine>(new) — rendersUPDATED 12:34 UTC · NEXT IN 18Munder each report title. Recomputes every minute. Tooltip = full ISO.<EmptyState>(new) — contextual messages where panels used to showNo data. Defaults to ⏱ clock glyph since every Phase 3 case is "data not yet arrived".<StatGrid>— em-dash +text-faintfor0/0%/null/ empty values; optionalawaitingReasonsub-label intext-warning-fgper stat.<DataTable>— accepts optionalemptyMessageprop, threads through to<EmptyState>.reports/show.tsx—<TimestampLine>under title.reports/index.tsx— cards showREFRESHED Xm AGOfromcomputedAt, falls back topublishedAtwhen cache cold.- PHP panels —
LeaderboardandStatGridaccept new optional fields;Predictionswires 4 contextual messages + 1 awaitingReason. 5 new Pest cases.
Judgement calls flagged by the agent
Report::summary()now does aCache::get()peek so the index page can showcomputedAtwithout materializing (no DB hit on cold start; gracefully falls back topublishedAt).Report::materialize()rewritten to not spreadsummary()(would have recursed into the cache lookup).
Test plan
-
npm run buildclean -
vendor/bin/pint --dirty --format agentclean -
php artisan test --compact— 182 pass, 26 skipped, 2 pre-existing LinkedIn failures (unrelated) - Post-deploy Playwright on
/reports,/reports/predictions
+456
additions
-49
deletions
15
files changed