Stu Mason
Stu Mason

Activity

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) — renders UPDATED 12:34 UTC · NEXT IN 18M under each report title. Recomputes every minute. Tooltip = full ISO.
  • <EmptyState> (new) — contextual messages where panels used to show No data. Defaults to ⏱ clock glyph since every Phase 3 case is "data not yet arrived".
  • <StatGrid> — em-dash + text-faint for 0 / 0% / null / empty values; optional awaitingReason sub-label in text-warning-fg per stat.
  • <DataTable> — accepts optional emptyMessage prop, threads through to <EmptyState>.
  • reports/show.tsx<TimestampLine> under title. reports/index.tsx — cards show REFRESHED Xm AGO from computedAt, falls back to publishedAt when cache cold.
  • PHP panelsLeaderboard and StatGrid accept new optional fields; Predictions wires 4 contextual messages + 1 awaitingReason. 5 new Pest cases.

Judgement calls flagged by the agent

  • Report::summary() now does a Cache::get() peek so the index page can show computedAt without materializing (no DB hit on cold start; gracefully falls back to publishedAt).
  • Report::materialize() rewritten to not spread summary() (would have recursed into the cache lookup).

Test plan

  • npm run build clean
  • vendor/bin/pint --dirty --format agent clean
  • 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