From 34fbfe1c67ff32a10edcd738a064bd543e963f85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 18 Jun 2026 21:24:02 +0200 Subject: [PATCH] feat(insights): link the overview Trends cards to their detail pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The overview charted each trend but never offered a way into the metric's detail page — the steps page in particular exists and is used, yet Insights never linked to it. Give every Trends-row chart a routed detail target and a discreet "view details" link below the caption, so a metric the row surfaces (steps included, when the briefing flags it) drills into /insights/. --- messages/de.json | 3 ++- messages/en.json | 3 ++- messages/es.json | 3 ++- messages/fr.json | 3 ++- messages/it.json | 3 ++- messages/pl.json | 3 ++- .../insights/__tests__/trends-row.test.tsx | 18 +++++++++++++++ src/components/insights/trends-row.tsx | 19 +++++++++++++++- .../__tests__/trend-chart-select.test.ts | 13 +++++++++++ src/lib/insights/trend-chart-select.ts | 22 +++++++++++++++++++ 10 files changed, 83 insertions(+), 7 deletions(-) diff --git a/messages/de.json b/messages/de.json index 6e9a48271..db398f369 100644 --- a/messages/de.json +++ b/messages/de.json @@ -2029,7 +2029,8 @@ "distance": "Geh- und Laufstrecke der letzten 30 Tage.", "vo2_max": "VO₂max der letzten 30 Tage.", "body_temp": "Körpertemperatur der letzten 30 Tage." - } + }, + "viewDetail": "{metric} im Detail" }, "vo2Max": { "statLatest": "Aktuell", diff --git a/messages/en.json b/messages/en.json index c33810296..d8373bc5f 100644 --- a/messages/en.json +++ b/messages/en.json @@ -2029,7 +2029,8 @@ "distance": "Walking and running distance over the last 30 days.", "vo2_max": "VO₂ max over the last 30 days.", "body_temp": "Body temperature over the last 30 days." - } + }, + "viewDetail": "View {metric} details" }, "vo2Max": { "statLatest": "Latest", diff --git a/messages/es.json b/messages/es.json index 0a1b03839..4c76e91d2 100644 --- a/messages/es.json +++ b/messages/es.json @@ -2029,7 +2029,8 @@ "distance": "Distancia caminando y corriendo de los últimos 30 días.", "vo2_max": "VO₂ máx de los últimos 30 días.", "body_temp": "Temperatura corporal de los últimos 30 días." - } + }, + "viewDetail": "Ver detalles de {metric}" }, "vo2Max": { "statLatest": "Actual", diff --git a/messages/fr.json b/messages/fr.json index 38a840ea8..52691bd65 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -2029,7 +2029,8 @@ "distance": "Distance de marche et de course des 30 derniers jours.", "vo2_max": "VO₂ max des 30 derniers jours.", "body_temp": "Température corporelle des 30 derniers jours." - } + }, + "viewDetail": "Voir le détail de {metric}" }, "vo2Max": { "statLatest": "Actuel", diff --git a/messages/it.json b/messages/it.json index 489c26670..d53d58a54 100644 --- a/messages/it.json +++ b/messages/it.json @@ -2029,7 +2029,8 @@ "distance": "Distanza a piedi e di corsa degli ultimi 30 giorni.", "vo2_max": "VO₂ max degli ultimi 30 giorni.", "body_temp": "Temperatura corporea degli ultimi 30 giorni." - } + }, + "viewDetail": "Vedi i dettagli di {metric}" }, "vo2Max": { "statLatest": "Attuale", diff --git a/messages/pl.json b/messages/pl.json index 9b66dda9e..a6e7821c5 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -2029,7 +2029,8 @@ "distance": "Dystans marszu i biegu z ostatnich 30 dni.", "vo2_max": "VO₂ max z ostatnich 30 dni.", "body_temp": "Temperatura ciała z ostatnich 30 dni." - } + }, + "viewDetail": "Zobacz szczegóły: {metric}" }, "vo2Max": { "statLatest": "Aktualne", diff --git a/src/components/insights/__tests__/trends-row.test.tsx b/src/components/insights/__tests__/trends-row.test.tsx index 05f33aaa0..34e1fe848 100644 --- a/src/components/insights/__tests__/trends-row.test.tsx +++ b/src/components/insights/__tests__/trends-row.test.tsx @@ -284,4 +284,22 @@ describe("", () => { expect(html).toContain("Moderate confidence"); expect(html).toContain("Low confidence"); }); + + // ── v1.18.6 — detail-page cross-links (the Insights→steps gap) ────── + it("links each metric card to its detail page", () => { + const html = render(); + // The default BP / weight / mood triple each link to their sub-page. + expect(html).toContain('data-slot="trends-row-detail-link"'); + expect(html).toContain('href="/insights/blood-pressure"'); + expect(html).toContain('href="/insights/weight"'); + expect(html).toContain('href="/insights/mood"'); + }); + + it("offers the steps detail link when the briefing flags steps", () => { + // Steps has a routed sub-page but the overview never linked to it; a + // briefing finding on steps now charts it AND drills into /insights/steps. + const html = render(); + expect(html).toMatch(/data-metric="steps"/); + expect(html).toContain('href="/insights/steps"'); + }); }); diff --git a/src/components/insights/trends-row.tsx b/src/components/insights/trends-row.tsx index 5b9bcac4b..5bc1c51b3 100644 --- a/src/components/insights/trends-row.tsx +++ b/src/components/insights/trends-row.tsx @@ -1,7 +1,8 @@ "use client"; import dynamic from "next/dynamic"; -import { TrendingUp } from "lucide-react"; +import Link from "next/link"; +import { ArrowRight, TrendingUp } from "lucide-react"; import { useTranslations } from "@/lib/i18n/context"; import { useAuth } from "@/hooks/use-auth"; import { ChartSkeleton } from "@/components/charts/chart-skeleton"; @@ -301,6 +302,22 @@ export function TrendsRow({ text={t(config.captionKey)} /> )} + {/* v1.18.6 — drill-in link to the metric's detail page. The + overview charted these metrics but never offered a way INTO + their detail pages — notably the steps page, which exists and + is used but was unreachable from Insights. The link sits below + the caption so the chart keeps its own interactions. */} + {config.detailHref ? ( + + {t("insights.trendsRow.viewDetail", { metric: title })} +