refactor(dashboard): compose the page from a tile registry

The dashboard page held every tile and chart card in one 2,100-line
function: a 1,279-line inline block pushed 24 cards behind 36 show flags.
The cards now live in components/dashboard/tiles/, each with its layout
widget, its own visibility rule (data floor, module, resolved layout) and
its render; the layout toggle and order are applied once by the registry.

- use-dashboard-data: the snapshot or legacy reads, the layout, mood,
  thresholds, the batched chart series and the loading gate
- tile-context: summaries, display units, comparison deltas, freshness,
  directions and target bands, derived once per render
- strip-tiles / chart-tiles: the two registries and their builders
- dashboard-tiles: the strip, the chart row, their skeletons and the
  empty state

The page is a composer of about 170 lines. Rendering is unchanged. The
guards that read page-client.tsx read the whole registry through one
helper; the weight-direction, HRV freshness, BP-in-target comparison and
chart-reveal checks now build the real tiles instead of matching text.
This commit is contained in:
Marc-André Bombeck committed 2026-10-23 11:06:32 +02:00
1 parent 9de64cae3e
commit e25b6365fd
27 files changed
+2179 -2425

No files matched your search

@@ -1,3 +1,4 @@
import { dashboardSource } from "@/__tests__/helpers/dashboard-source";
import { describe, it, expect, vi } from "vitest";
import { readFileSync } from "node:fs";
import { join } from "node:path";
@@ -151,10 +152,7 @@ describe("dashboard layout save — every layout source is covered (source pins)
});
it("the dashboard reads layout from the snapshot (or the dashboardWidgets cell) only", () => {
const pageSrc = readFileSync(
join(process.cwd(), "src/app/page-client.tsx"),
"utf8",
);
const pageSrc = dashboardSource();
// Snapshot path: layout comes off the snapshot payload…
expect(pageSrc).toContain("snapshotQuery.data?.layout");
// …legacy path: the dashboardWidgets factory key (no bare literal).