From e55058a1cee7cd6ef2b229583ef9417e763afdad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sun, 28 Jun 2026 15:41:53 +0200 Subject: [PATCH] fix(insights): stop the period review card leaking methodology and raw enums MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The weekly/monthly review card rendered an internal methodology line plus the raw MeasurementType tokens it drew on ('Based on: WEIGHT, BLOOD_PRESSURE_SYS…'), which read as broken and added no value. Drop the provenance caption entirely so no enum token is ever user-facing, and hide the card whenever there is no real generated narrative (no 'preparing' husk), consistent with the hide-when-empty pattern. The query keeps polling in the background, so the card appears the moment a narrative lands. --- .../insights/period-narrative-card.tsx | 106 ++++++------------ 1 file changed, 32 insertions(+), 74 deletions(-) diff --git a/src/components/insights/period-narrative-card.tsx b/src/components/insights/period-narrative-card.tsx index 1a787c131..47ffa3cde 100644 --- a/src/components/insights/period-narrative-card.tsx +++ b/src/components/insights/period-narrative-card.tsx @@ -62,33 +62,6 @@ async function fetchNarrative( return apiGet(`/api/insights/narrative?period=${period}`); } -/** - * v1.22 — the round ⓘ provenance glyph that hid the "how this was computed" - * read behind a popover is removed; the maintainer wants the trailing info - * affordance gone across the insights surface. The method line — and, when - * present, the metrics it drew on — now reads inline as a muted caption at the - * foot of the card, always visible rather than disclosure-only. - */ -function ProvenanceDisclosure({ - provenance, -}: { - provenance: NarrativeProvenance; -}) { - const { t } = useTranslations(); - const metrics = provenance.metrics.slice(0, 8).join(", "); - return ( -

- {t("insights.narrativeProvenanceMethod")} - {metrics - ? ` ${t("insights.narrativeProvenanceMetrics", { metrics })}` - : ""} -

- ); -} - const SHELL = "bg-card border-border flex w-full min-w-0 flex-col gap-3 rounded-xl border p-4 md:p-6"; // The in-flight skeleton keeps a `min-h` floor so the initial paint reserves the @@ -143,17 +116,16 @@ export function PeriodNarrativeCard({ ); } - // The route never errors the page; on a fetch error or a genuinely empty - // account (no narrative ever produced) the card un-mounts itself rather than - // showing an error or an empty husk on the overview. - if (query.isError || (!query.data?.narrative && !query.data?.revalidating)) { + // The route never errors the page; on a fetch error or whenever there is no + // real generated narrative yet (empty account, or a first warm still in + // flight) the card un-mounts itself rather than showing an error, a + // "preparing" husk, or the methodology framing. The query stays mounted and + // polls in the background, so the card appears the moment a narrative lands. + const narrative = query.data?.narrative ?? null; + if (query.isError || !narrative) { return null; } - const data = query.data; - const narrative = data?.narrative ?? null; - const preparing = !narrative && data?.revalidating === true; - return (
- {preparing ? ( -

- {t("insights.narrativePreparing")} -

- ) : ( - // v1.22 (W6) — real paragraphs via the shared ProseBlocks helper - // (still plain text children — NO markdown renderer, XSS posture). -
- -
- )} + {/* v1.22 (W6) — real paragraphs via the shared ProseBlocks helper + (still plain text children — NO markdown renderer, XSS posture). */} +
+ +
- {narrative?.provenance ? ( - - ) : null} - - {narrative ? ( -

- {data?.revalidating - ? t("insights.narrativeUpdating") - : formatUpdatedLabel( - narrative.updatedAt, - t, - fmt.dateShort, - fmt.time, - user?.timezone, - )} -

- ) : null} +

+ {query.data?.revalidating + ? t("insights.narrativeUpdating") + : formatUpdatedLabel( + narrative.updatedAt, + t, + fmt.dateShort, + fmt.time, + user?.timezone, + )} +

{/* v1.21.0 (C4 H2) — hand the period summary to the Coach. It spans the whole picture for the window, so no scope: the default snapshot reads best. */} - {narrative ? ( -
- -
- ) : null} +
+ +
);