mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 22:02:16 +00:00
Carves the v1.4.24 monolithic /insights page into routed sub-pages
under /insights/{blutdruck,gewicht,puls,stimmung,medikamente,bmi}.
Each sub-page renders its metric chart with the per-chart cog
(chartKey from CHART_OVERLAY_KEYS) and the existing AI status card;
empty states surface a CTA where the chart can't compute (BMI without
height, mood with zero entries, medication adherence without a tracked
medication).
The sticky tab strip moves into src/app/insights/layout.tsx via the
new <InsightsLayoutShell>, which also owns the advisor query so the
regenerate affordance stays reachable from every Insights surface.
The tab strip itself is now route-aware (<Link> + usePathname()) and
exposes an "Overview" pill for the mother page. The CoachDrawer stays
in the mother-page body only — per Marc's directive, navigating to a
sub-page must unmount the drawer.
Shared infrastructure:
- src/lib/insights/sub-page-metric.ts: slug → MeasurementType[] map
+ SUB_PAGE_SLUGS canonical order.
- src/hooks/use-insights-layout-prefs.ts: reader for the dashboard-
layout payload so every sub-page picks up the comparisonBaseline
without re-fetching.
- src/components/insights/sub-page-shell.tsx: title + optional badge
+ focusable h1 (a11y — screen-reader focus restoration on tab
navigation).
- src/components/insights/insights-layout-shell.tsx: the layout's
client shell that mounts the strip + threads the regenerate handler.
The 7th sub-page (/insights/schlaf) ships in the follow-up W4c commit
together with its sleep-stage chart components.
37 lines
1.3 KiB
TypeScript
37 lines
1.3 KiB
TypeScript
"use client";
|
|
|
|
import type { ReactNode } from "react";
|
|
|
|
import { useAuth } from "@/hooks/use-auth";
|
|
import { InsightsTabStrip } from "@/components/insights/insights-tab-strip";
|
|
import { useInsightsAdvisorQuery } from "@/components/insights/use-insights-advisor";
|
|
|
|
/**
|
|
* v1.4.25 W4 — client shell for `src/app/insights/layout.tsx`.
|
|
*
|
|
* Owns the advisor query so the regenerate button on the sticky tab
|
|
* strip works from every Insights surface (mother + the seven sub-
|
|
* pages). TanStack Query dedup keeps the cost negligible: the mother
|
|
* page's own `useInsightsAdvisorQuery` consumer shares the same
|
|
* `queryKeys.insightsAdvisor()` key, so the two consumers reuse the
|
|
* same cache entry without extra network traffic.
|
|
*
|
|
* CRITICAL — the `<CoachDrawer>` does NOT mount here. It lives only in
|
|
* `src/app/insights/page.tsx` body so navigating into a sub-page
|
|
* unmounts the drawer.
|
|
*/
|
|
export function InsightsLayoutShell({ children }: { children: ReactNode }) {
|
|
const { isAuthenticated } = useAuth();
|
|
const advisor = useInsightsAdvisorQuery(isAuthenticated);
|
|
|
|
return (
|
|
<div className="space-y-8">
|
|
<InsightsTabStrip
|
|
onRegenerate={isAuthenticated ? advisor.regenerate : undefined}
|
|
regenerating={advisor.isRegenerating}
|
|
/>
|
|
{children}
|
|
</div>
|
|
);
|
|
}
|