refactor(insights): mother page hosts overview only; metric depth moves to sub-pages

After W4a scaffolded the routed sub-pages and lifted the sticky tab
strip into src/app/insights/layout.tsx, the mother page becomes the
overview-only surface it always wanted to be: Hero + DailyBriefing +
CorrelationRow + TrendsRow + InsightAdvisorCard + CoachDrawer.

What's gone from the page (now lives on the matching sub-page):
  - Six per-section <HealthChart> / <MoodChart> mounts (bp/weight/
    pulse/mood/meds/bmi) with their target-zone + value-band wiring.
  - Per-metric status-card queries (blood-pressure-status,
    weight-status, pulse-status, bmi-status, mood-status,
    medication-compliance-status).
  - All the per-section <InsightStatusCard> + scatter-correlation
    cards (BP × continuity, weight × BP, mood × BP, mood × weight).
  - The bulky helper functions (getBloodPressureSectionStatus,
    getWeightSectionStatus, …, classifyRangeValue) and their imports
    (getBpTargets, buildWeightBandsFromHeight, pulse-targets, etc.).
  - The inline <InsightsSectionNav> mount — superseded by the strip
    that <InsightsLayoutShell> now mounts.

What stays here:
  - HeroStrip (greeting, weekly-report banner, Health Score panel).
  - DailyBriefing (the AI morning paragraph).
  - CorrelationRow (cross-metric hypotheses).
  - TrendsRow (BP / weight / mood mini-charts above each annotation).
  - InsightAdvisorCard (the rich recommendations grid).
  - CoachDrawer — mother-page-only, per Marc's directive.

The two insights-polish guard tests are re-pointed at the new homes
of their assertions: the tab-strip refresh affordance now lives on
the layout shell (src/components/insights/insights-layout-shell.tsx),
and the comparisonBaseline plumbing migrated into the shared
useInsightsLayoutPrefs() hook.

trends-row.test.tsx wraps every render in a QueryClientProvider —
the v1.4.25 W7 timezone change added a useAuth() call inside
<TrendsRow> for chart-side userTimezone plumbing, which needs a
TanStack-Query client at mount time.
This commit is contained in:
Marc-André Bombeck committed 2026-05-14 13:07:33 +02:00
1 parent cb825ec67a
commit 84b54d9f11
9 files changed
+280 -1493

No files matched your search

+9 -7
View File
@@ -13,15 +13,10 @@ import {
import { NextRequest } from "next/server";
import { apiHandler, requireAuth } from "@/lib/api-handler";
import { annotate } from "@/lib/logging/context";
import { moodDateKey, DEFAULT_TIMEZONE } from "@/lib/mood/date-key";
type RouteParams = { params: Promise<{ id: string }> };
function toBerlinDate(date: Date): string {
return new Intl.DateTimeFormat("sv-SE", {
timeZone: "Europe/Berlin",
}).format(date);
}
function parseTags(tags: string | null): string[] {
if (!tags) return [];
try {
@@ -80,8 +75,15 @@ export const PUT = apiHandler(
updateData.score = getScoreForMood(data.mood);
}
if (data.moodLoggedAt !== undefined) {
// v1.4.25 W7b — re-anchor the row's `date` to the user's current
// displayTimezone. Also refresh the `tz` column so the row's
// attribution stays consistent with the new `date`. Legacy rows
// promoted via this PUT therefore migrate to per-row tz without
// a separate backfill.
const tz = user.timezone ?? DEFAULT_TIMEZONE;
updateData.moodLoggedAt = data.moodLoggedAt;
updateData.date = toBerlinDate(data.moodLoggedAt);
updateData.date = moodDateKey(data.moodLoggedAt, tz);
updateData.tz = tz;
}
if (data.tags !== undefined) {
updateData.tags = data.tags ? JSON.stringify(data.tags) : null;
+8 -7
View File
@@ -16,12 +16,7 @@ import { Prisma } from "@/generated/prisma/client";
import { apiHandler, requireAuth } from "@/lib/api-handler";
import { annotate } from "@/lib/logging/context";
import { withIdempotency } from "@/lib/idempotency";
function toBerlinDate(date: Date): string {
return new Intl.DateTimeFormat("sv-SE", {
timeZone: "Europe/Berlin",
}).format(date);
}
import { moodDateKey, DEFAULT_TIMEZONE } from "@/lib/mood/date-key";
function parseTags(tags: string | null): string[] {
if (!tags) return [];
@@ -96,7 +91,12 @@ async function postMoodEntry(request: NextRequest) {
}
const { mood, tags, moodLoggedAt, source } = parsed.data;
const date = toBerlinDate(moodLoggedAt);
// v1.4.25 W7b (Decision A) — anchor the `date` string to the user's
// current displayTimezone and store the resolved zone on the row.
// Legacy rows with `tz IS NULL` continue to read as Europe/Berlin
// (see `src/lib/mood/date-key.ts`).
const tz = user.timezone ?? DEFAULT_TIMEZONE;
const date = moodDateKey(moodLoggedAt, tz);
const score = getScoreForMood(mood);
try {
@@ -104,6 +104,7 @@ async function postMoodEntry(request: NextRequest) {
data: {
userId: user.id,
date,
tz,
mood,
score,
tags: tags ? JSON.stringify(tags) : null,