codeburn/app/renderer/sections
Resham Joshi dbd93fee51
app,dash: render pre-history days as no data, not a currency zero (#765)
* fix(app,dash): render pre-history days as no data, not a currency zero

Days before the first recorded day in history.daily were painted as a real
0.00/0 calls in the daily activity heatmap and the daily spend charts. That
zero is unknown, not measured, so those cells and bars now read "No data
recorded" instead of a currency zero. Genuinely idle days within recorded
history stay as real zeros.

- app: heatmap cells, the daily spend bars, and the daily-by-model columns
  get a distinct no-data style plus a "No data recorded" hover for days before
  the first recorded day.
- dash: the granular line chart drops buckets before the first recorded day so
  no flat zero line is drawn before any history exists.
- data-start is derived in the UI layer from history.daily; payload shape is
  unchanged.

Verified: app vitest 418 pass (7 new for the no-data behavior); app, dash, and
root typecheck clean; dash and app renderer vite builds succeed.

* no-data: cap guard, timezone-free dash trim, StackedBars aria

Three hardening fixes from adversarial review of the no-data rendering:

dataStartKey returns null at the payload's 365-entry history cap, where
the oldest retained entry is no longer the true data start; classifying
past it would label real aged-out history as no data on long custom
ranges. Documented that the install-to-first-use gap reading as no data
is literally accurate: nothing was recorded then either.

The dash granular chart now trims leading zero-only buckets by value
instead of comparing bucket timestamps against date keys, so producer
and viewer timezone skew can never drop a real first-day bucket, and an
all-zero series lands in the established empty state.

StackedBars no-data columns expose their state via aria-label, not only
a title on a non-focusable div.
2026-07-20 08:03:24 -07:00
..
Compare.test.tsx fix(app): accuracy batch A — provider scoping, honest chart axes, range threading, stale-error banner 2026-07-16 01:14:41 -07:00
Compare.tsx feat(app): refresh cadence, instant switching, cache coherence, telemetry v1 2026-07-16 11:47:05 -07:00
Models.test.tsx fix(app): models rows name their provider; picker shows all detected 2026-07-16 09:27:46 -07:00
Models.tsx feat(app): refresh cadence, instant switching, cache coherence, telemetry v1 2026-07-16 11:47:05 -07:00
Optimize.test.tsx feat(app): refresh cadence, instant switching, cache coherence, telemetry v1 2026-07-16 11:47:05 -07:00
Optimize.tsx feat(app): refresh cadence, instant switching, cache coherence, telemetry v1 2026-07-16 11:47:05 -07:00
Overview.test.tsx app,dash: render pre-history days as no data, not a currency zero (#765) 2026-07-20 08:03:24 -07:00
Overview.tsx app,dash: render pre-history days as no data, not a currency zero (#765) 2026-07-20 08:03:24 -07:00
Plans.test.tsx fix: audit batch — prefetch one-shot, turn-anchored day bucketing, warm-path collapse 2026-07-16 15:37:03 -07:00
Plans.tsx feat(app): refresh cadence, instant switching, cache coherence, telemetry v1 2026-07-16 11:47:05 -07:00
Sessions.test.tsx fix: hydration completeness markers, cold-only splash, honest switching, prefetch 2026-07-16 14:05:11 -07:00
Sessions.tsx fix: hydration completeness markers, cold-only splash, honest switching, prefetch 2026-07-16 14:05:11 -07:00
Settings.test.tsx fix(app): provider logos key on internal ids + monogram fallback 2026-07-16 09:27:46 -07:00
Settings.tsx feat(app): update-available notifications 2026-07-17 04:58:13 -07:00
Spend.test.tsx feat(app): Sessions provider quick-filter + Spend project inline expand 2026-07-16 02:49:17 -07:00
Spend.tsx app,dash: render pre-history days as no data, not a currency zero (#765) 2026-07-20 08:03:24 -07:00