refactor(insights): drop duplicate metric tile strip

The /insights page used to lead with a 5-column grid of TrendCards
(weight, BP-sys, BP-dia, pulse, plus body-fat and mood when
present) — exact duplicates of the dashboard tile-strip. Marc said
the tiles "duplizieren Dashboard, nehmen nur Platz weg" and asked
for them gone.

Drop the strip, the helper functions that supported only it
(`getRangeColorClass`, `getRangeHint`, `RangeDisplayConfig`), and
the bookkeeping locals (`bf`, `showBodyFatCard`, `moodSummary`,
`showMoodCard`, `fmt`). Remaining mood references on the page read
`data?.moodSummary` inline; every other helper was used only by the
removed strip.

Net: -157 lines, no behaviour change anywhere except the missing
duplicate strip. Recommendations grid + per-section status / chart
cards below stay intact — those are the actual value of /insights.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.7 committed 2026-05-10 13:14:05 +02:00
1 parent 98a3d10705
commit 335f288d69
1 file changed
+20 -157
+20 -157
View File
@@ -3,7 +3,7 @@
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { useAuth } from "@/hooks/use-auth"; import { useAuth } from "@/hooks/use-auth";
import { useTranslations, useFormatters } from "@/lib/i18n/context"; import { useTranslations } from "@/lib/i18n/context";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
@@ -27,14 +27,12 @@ const MoodChart = dynamic(
})), })),
{ ssr: false }, { ssr: false },
); );
import { TrendCard } from "@/components/charts/trend-card";
import { ComplianceHeatmap } from "@/components/charts/compliance-heatmap"; import { ComplianceHeatmap } from "@/components/charts/compliance-heatmap";
import { import {
Activity, Activity,
Heart, Heart,
HeartPulse, HeartPulse,
Loader2, Loader2,
Percent,
Pill, Pill,
Ruler, Ruler,
Scale, Scale,
@@ -79,7 +77,7 @@ import {
getAgeFromDateOfBirth, getAgeFromDateOfBirth,
getPersonalizedPulseTarget, getPersonalizedPulseTarget,
} from "@/lib/analytics/pulse-targets"; } from "@/lib/analytics/pulse-targets";
import type { DataSummary, TrendSlope } from "@/lib/analytics/trends"; import type { DataSummary } from "@/lib/analytics/trends";
import { import {
resolveDashboardLayout, resolveDashboardLayout,
type DashboardLayout, type DashboardLayout,
@@ -223,60 +221,12 @@ interface MedicationComplianceDailyResponse {
dailyCompliance: Record<string, MedicationDailyData>; dailyCompliance: Record<string, MedicationDailyData>;
} }
interface RangeDisplayConfig { /**
range: TrafficRange | null; * v1.4.19 A3 — `getRangeColorClass` / `getRangeHint` /
} * `RangeDisplayConfig` removed alongside the `<TrendCard>` tile-strip
* deletion. Those helpers were only used by the duplicate-of-dashboard
function getRangeColorClass( * tile grid; every other call site lives on the dashboard surface.
value: number | null | undefined, */
config: RangeDisplayConfig,
): string | undefined {
const range = config.range;
if (value == null || !range) return undefined;
const inGreen = value >= range.greenMin && value <= range.greenMax;
const inOrange =
!inGreen && value >= range.orangeMin && value <= range.orangeMax;
if (inGreen) return "text-green-400";
if (inOrange) return "text-orange-400";
return "text-red-400";
}
function getRangeHint(
unit: string,
config: RangeDisplayConfig,
t: (key: string) => string,
formatNumber: (value: number, fractionDigits?: number) => string,
): React.ReactNode | undefined {
const range = config.range;
if (!range) return undefined;
const format = (value: number) => formatNumber(value, 1);
return (
<>
<p>
<span className="font-bold text-green-400">
{t("charts.colorGreen")}
</span>{" "}
{format(range.greenMin)}-{format(range.greenMax)} {unit}
</p>
<p>
<span className="font-bold text-orange-400">
{t("charts.colorOrange")}
</span>{" "}
{format(range.orangeMin)}-{format(range.greenMin)} {t("common.or")}{" "}
{format(range.greenMax)}-{format(range.orangeMax)} {unit}
</p>
<p>
<span className="font-bold text-red-400">{t("charts.colorRed")}</span>{" "}
{"< "}
{format(range.orangeMin)} {t("common.or")} {"> "}
{format(range.orangeMax)} {unit}
</p>
</>
);
}
/** /**
* v1.4.16 phase B1b — pick the freshest ISO timestamp from a list so the * v1.4.16 phase B1b — pick the freshest ISO timestamp from a list so the
@@ -544,7 +494,6 @@ function getMedicationComplianceSectionStatus(input: {
export default function InsightsPage() { export default function InsightsPage() {
const { isAuthenticated, user } = useAuth(); const { isAuthenticated, user } = useAuth();
const { t, locale } = useTranslations(); const { t, locale } = useTranslations();
const fmt = useFormatters();
const STRENGTH_LABELS: Record<string, string> = { const STRENGTH_LABELS: Record<string, string> = {
stark: t("insights.strengthStrong"), stark: t("insights.strengthStrong"),
@@ -696,10 +645,10 @@ export default function InsightsPage() {
const sys = analytics?.summaries?.BLOOD_PRESSURE_SYS; const sys = analytics?.summaries?.BLOOD_PRESSURE_SYS;
const dia = analytics?.summaries?.BLOOD_PRESSURE_DIA; const dia = analytics?.summaries?.BLOOD_PRESSURE_DIA;
const p = analytics?.summaries?.PULSE; const p = analytics?.summaries?.PULSE;
const bf = analytics?.summaries?.BODY_FAT; // v1.4.19 A3 — `bf` / `showBodyFatCard` / `moodSummary` /
const showBodyFatCard = (bf?.count ?? 0) > 0; // `showMoodCard` were bookkeeping for the now-removed duplicate
const moodSummary = data?.moodSummary; // tile strip (Marc said those tiles duplicate the dashboard).
const showMoodCard = (moodSummary?.count ?? 0) > 0; // Remaining mood references read `data?.moodSummary` inline below.
const bmiDivisor = user?.heightCm ? (user.heightCm / 100) ** 2 : null; const bmiDivisor = user?.heightCm ? (user.heightCm / 100) ** 2 : null;
// bmiAvg30 and bmiSlope30 still used for overallStatus + bmiSectionStatus // bmiAvg30 and bmiSlope30 still used for overallStatus + bmiSectionStatus
const bmiAvg30 = bmiDivisor && w?.avg30 != null ? w.avg30 / bmiDivisor : null; const bmiAvg30 = bmiDivisor && w?.avg30 != null ? w.avg30 / bmiDivisor : null;
@@ -948,100 +897,14 @@ export default function InsightsPage() {
<InsightsSectionNav /> <InsightsSectionNav />
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4 xl:grid-cols-5"> {/* v1.4.19 A3 — duplicate per-metric `<TrendCard>` strip removed.
<TrendCard Up to v1.4.18 the page led with a 5-column grid of weight /
label={t("dashboard.weight")} BP-sys / BP-dia / pulse / body-fat / mood tiles — exact
latest={w?.latest ?? null} duplicates of the dashboard tile-strip. They added zero
unit="kg" information beyond what's already on the dashboard. The
avg7={w?.avg7 ?? null} recommendations grid + per-section detail cards below are
avg30={w?.avg30 ?? null} the actual value on `/insights`; the tiles only consumed
avg7ColorClass={getRangeColorClass(w?.avg7, { range: weightRange })} scroll height. */}
avg30ColorClass={getRangeColorClass(w?.avg30, { range: weightRange })}
avg7Hint={getRangeHint("kg", { range: weightRange }, t, fmt.number)}
avg30Hint={getRangeHint("kg", { range: weightRange }, t, fmt.number)}
slope30={w?.slope30 ?? null}
icon={Activity}
/>
<TrendCard
label={t("dashboard.bloodPressureSys")}
latest={sys?.latest ?? null}
unit="mmHg"
avg7={sys?.avg7 ?? null}
avg30={sys?.avg30 ?? null}
avg7ColorClass={getRangeColorClass(sys?.avg7, { range: bpSysRange })}
avg30ColorClass={getRangeColorClass(sys?.avg30, {
range: bpSysRange,
})}
avg7Hint={getRangeHint("mmHg", { range: bpSysRange }, t, fmt.number)}
avg30Hint={getRangeHint("mmHg", { range: bpSysRange }, t, fmt.number)}
slope30={sys?.slope30 ?? null}
icon={Heart}
/>
<TrendCard
label={t("dashboard.bloodPressureDia")}
latest={dia?.latest ?? null}
unit="mmHg"
avg7={dia?.avg7 ?? null}
avg30={dia?.avg30 ?? null}
avg7ColorClass={getRangeColorClass(dia?.avg7, { range: bpDiaRange })}
avg30ColorClass={getRangeColorClass(dia?.avg30, {
range: bpDiaRange,
})}
avg7Hint={getRangeHint("mmHg", { range: bpDiaRange }, t, fmt.number)}
avg30Hint={getRangeHint("mmHg", { range: bpDiaRange }, t, fmt.number)}
slope30={dia?.slope30 ?? null}
icon={Heart}
/>
<TrendCard
label={t("dashboard.pulse")}
latest={p?.latest ?? null}
unit="bpm"
avg7={p?.avg7 ?? null}
avg30={p?.avg30 ?? null}
avg7ColorClass={getRangeColorClass(p?.avg7, {
range: pulseDisplayRange,
})}
avg30ColorClass={getRangeColorClass(p?.avg30, {
range: pulseDisplayRange,
})}
avg7Hint={getRangeHint(
"bpm",
{ range: pulseDisplayRange },
t,
fmt.number,
)}
avg30Hint={getRangeHint(
"bpm",
{ range: pulseDisplayRange },
t,
fmt.number,
)}
slope30={p?.slope30 ?? null}
icon={TrendingUp}
/>
{showBodyFatCard ? (
<TrendCard
label={t("dashboard.bodyFat")}
latest={bf?.latest ?? null}
unit="%"
avg7={bf?.avg7 ?? null}
avg30={bf?.avg30 ?? null}
slope30={bf?.slope30 ?? null}
icon={Percent}
/>
) : null}
{showMoodCard ? (
<TrendCard
label={t("dashboard.mood")}
latest={moodSummary?.latest ?? null}
unit="/ 5"
avg7={moodSummary?.avg7 ?? null}
avg30={moodSummary?.avg30 ?? null}
slope30={(moodSummary?.slope30 as TrendSlope | undefined) ?? null}
icon={Smile}
/>
) : null}
</div>
<section id="section-general" className="scroll-mt-28 space-y-2"> <section id="section-general" className="scroll-mt-28 space-y-2">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">