feat(charts): put the drawn data points under the chart as a table

A chart shows the shape and hides the numbers. An appointment needs the
numbers, and so does anyone moving readings into a spreadsheet.

The table reads the same expression the chart hands Recharts, after the range
slice, the week/month bucketing and the display scale, and it formats through
the chart's own value and date formatters. Nothing is re-derived, so a cell and
the tooltip cannot print two numbers for one point.

Collapsed by default, with the point count in the trigger so the size reads
while it is closed; the region scrolls in its own box rather than growing the
page, and the table primitive already scrolls a wide row set sideways. The
caption names the grain, because a weekly mean labelled as a daily reading
would be a lie, and the grain now has one source shared with the bucketing.
Derived overlays get no column: a moving average is drawn from the points, not
measured. An empty window renders no table at all, since the chart's own empty
state already says there is nothing there.

Opt-in per mount. The metric sub-pages take it; the dashboard tiles do not,
because a table under every tile buries the dashboard it summarises.

Refs #636
This commit is contained in:
Marc-André Bombeck committed 2026-07-26 19:23:52 +02:00
1 parent 8dc5c230da
commit 3f355fbde4
15 files changed
+1037 -453

No files matched your search

+1
View File
@@ -173,6 +173,7 @@ export default function InsightsBlutdruckPage() {
compareBaseline={compareBaseline}
userTimezone={user?.timezone}
onVisibleStats={onVisibleStats}
showDataTable
/>
{/* v1.12.4 — target card sits between the chart and the assessment on
+1
View File
@@ -123,6 +123,7 @@ export default function InsightsBmiPage() {
valueBands={BMI_BANDS}
compareBaseline={compareBaseline}
userTimezone={user?.timezone}
showDataTable
/>
<MetricTargetSummary slug="bmi" />
+1
View File
@@ -158,6 +158,7 @@ export default function InsightsPulsPage() {
compareBaseline={compareBaseline}
userTimezone={user?.timezone}
onVisibleStats={onVisibleStats}
showDataTable
/>
{/* S11 — the intraday "shape of the day" layer: 10-minute mean heart
+1
View File
@@ -162,6 +162,7 @@ export default function InsightsGewichtPage() {
userTimezone={user?.timezone}
valueScale={weightScale}
onVisibleStats={onVisibleStats}
showDataTable
/>
<MetricTargetSummary slug="weight" />