mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 21:32:18 +00:00
refactor(insights): point the pulse page to the cardio-fitness surface for VO2 max
VO2 max had two divergent surfaces — the dedicated /insights/cardio-fitness page (full chart + plain-language assessment) and a legacy compact chart-row on the pulse page. Replace the pulse-page row with a clear cross-link to the dedicated page so there is one VO2 max surface, and remove the now-unused chart-row component + its test. New cardioLink copy added across all six locales. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
4847d2fc40
commit
d2edaeb8d1
9 files changed
+64
-381
No files matched your search
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { Heart } from "lucide-react";
|
||||
import { ArrowRight, Gauge, Heart } from "lucide-react";
|
||||
|
||||
import { useAuth } from "@/hooks/use-auth";
|
||||
import { useInsightsAnalytics } from "@/hooks/use-insights-analytics";
|
||||
@@ -17,7 +17,6 @@ import { MetricCorrelationCard } from "@/components/insights/metric-correlation-
|
||||
import { MeasurementDiversityNudge } from "@/components/insights/measurement-diversity-nudge";
|
||||
import { MetricTargetSummary } from "@/components/insights/metric-target-summary";
|
||||
import { SubPageShell } from "@/components/insights/sub-page-shell";
|
||||
import { Vo2MaxChartRow } from "@/components/insights/vo2-max-chart-row";
|
||||
import {
|
||||
getAgeFromDateOfBirth,
|
||||
getPersonalizedPulseTarget,
|
||||
@@ -33,22 +32,21 @@ import {
|
||||
* MeasurementType filter is `PULSE` (the same field used elsewhere
|
||||
* in the codebase).
|
||||
*
|
||||
* v1.4.28 R3d (BK-F-H1 + BK-F-M1) — analytics fetch + empty-state
|
||||
* branch consume `useInsightsAnalytics()` + `<MetricEmptyState>`. The
|
||||
* VO2 max chart-row still reads `data.summaries.VO2_MAX` directly so
|
||||
* the hook exposes the unwrapped payload alongside `isEmpty`.
|
||||
* Analytics fetch + empty-state branch consume `useInsightsAnalytics()`
|
||||
* + `<MetricEmptyState>`. VO₂ max is a cardio-fitness metric, so the page
|
||||
* links across to the dedicated `/insights/cardio-fitness` surface (which
|
||||
* owns the full chart + assessment) rather than rendering a second view.
|
||||
*/
|
||||
export default function InsightsPulsPage() {
|
||||
const { isAuthenticated, user } = useAuth();
|
||||
const { t } = useTranslations();
|
||||
const { compareBaseline } = useInsightsLayoutPrefs(isAuthenticated);
|
||||
|
||||
// v1.4.25 W16a — VO2 max chart-row consumes the same `/api/analytics`
|
||||
// bundle the mother page reads. Sharing the cache key keeps the
|
||||
// payload single-fetch on tab navigation (React-Query unwraps from
|
||||
// the same key).
|
||||
const { data: analytics, isEmpty } = useInsightsAnalytics("PULSE");
|
||||
const vo2Summary = analytics?.summaries?.VO2_MAX ?? null;
|
||||
// VO₂ max rides on the same `/api/analytics` bundle; we only need the
|
||||
// sample count to decide whether to surface the cross-link to the
|
||||
// dedicated cardio-fitness page.
|
||||
const hasVo2 = (analytics?.summaries?.VO2_MAX?.count ?? 0) > 0;
|
||||
const pulseSummary = analytics?.summaries?.PULSE ?? null;
|
||||
|
||||
// v1.12.7 — brushed-window stats shared between the pulse chart and the
|
||||
@@ -152,17 +150,37 @@ export default function InsightsPulsPage() {
|
||||
|
||||
<MetricTargetSummary slug="pulse" />
|
||||
|
||||
{/* v1.4.25 W16a — VO2 max sits on the cardio sub-page because it
|
||||
is a cardio-fitness metric (Apple's Health app surfaces it
|
||||
under "Heart"). The chart-row stays mounted even at zero
|
||||
samples so a brand-new account sees the "no data yet" hint
|
||||
rather than a missing surface — same pattern the dashboard
|
||||
tile uses (opt-in via Settings → Dashboard). */}
|
||||
<Vo2MaxChartRow
|
||||
summary={vo2Summary}
|
||||
compareBaseline={compareBaseline}
|
||||
userTimezone={user?.timezone}
|
||||
/>
|
||||
{/* VO₂ max is a cardio-fitness metric (Apple's Health app surfaces it
|
||||
under "Heart"), so the pulse page links across to its dedicated
|
||||
`/insights/cardio-fitness` page — the single surface that carries
|
||||
the full chart plus the plain-language assessment — rather than
|
||||
duplicating a second, divergent VO₂ max view here. */}
|
||||
{hasVo2 ? (
|
||||
<Link
|
||||
href="/insights/cardio-fitness"
|
||||
data-slot="vo2-cardio-link"
|
||||
className="bg-card hover:bg-accent/40 focus-visible:ring-ring/50 flex items-center justify-between gap-3 rounded-xl border p-4 transition-colors focus-visible:ring-2 focus-visible:outline-none"
|
||||
>
|
||||
<span className="flex items-start gap-3">
|
||||
<Gauge
|
||||
className="text-muted-foreground mt-0.5 h-5 w-5 shrink-0"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span className="space-y-1">
|
||||
<span className="block text-sm font-semibold">
|
||||
{t("insights.vo2Max.cardioLinkTitle")}
|
||||
</span>
|
||||
<span className="text-muted-foreground block text-xs leading-snug">
|
||||
{t("insights.vo2Max.cardioLinkBody")}
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<span className="text-primary inline-flex shrink-0 items-center gap-1 text-xs font-medium">
|
||||
{t("insights.vo2Max.cardioLinkCta")}
|
||||
<ArrowRight className="h-4 w-4" aria-hidden="true" />
|
||||
</span>
|
||||
</Link>
|
||||
) : null}
|
||||
|
||||
{/* v1.12.0 — Pulse owns the mood × pulse correlation (relocated off
|
||||
the overview onto its metric page). */}
|
||||
|
||||
Reference in new issue
Block a user