Files
HealthLog/src/components/insights/metric-empty-state.tsx
T
Marc-André Bombeck 2d111fcb24 chore(release): v1.4.28
Bug-fix and consistency follow-through after the v1.4.27 mobile sweep.
The headline is a tighter dashboard and insights surface: six widgets
retire from code entirely (GLP-1 tile, dashboard `<DrugLevelChart>`
mount, GLP-1 detail-page intake history + inventory, the
`<InsightAdvisorCard>` block and its regeneration affordance, the
weekly-report route), four broken edges close (workout-edit duplicate-
timestamp 409, BD-Zielbereich tile rebuilt on the shared
`<TrendCard>` primitive, `/insights/puls` chart timeout fallback,
sticky tab-strip scroll lock), and one consistency contract lands per
maintainer directive: every medication-list row, every medication-
detail section header, every trend tile, every Coach launch glyph,
every chart-height contract reads on one shape. The HealthScore card
grows to fill its column, gains an accessible `?` tooltip explaining
the delta, and drops the placeholder "Wochenbericht erstellen"
button. iOS contracts are intact; the only `/api/*` evolution is
additive (the `aggregate=monthly` grain on `/api/measurements` and an
internal-only `/api/internal/web-vitals` beacon route).
2026-05-16 03:17:00 +02:00

74 lines
2.5 KiB
TypeScript

"use client";
import type { ReactNode } from "react";
import { CoachLaunchButton } from "@/components/insights/coach-launch-button";
import { EmptyState } from "@/components/ui/empty-state";
/**
* v1.4.28 R3d (BK-F-M1 + BK-MED-4) — shared empty-state primitive for
* the insights sub-pages.
*
* Pre-fix, every sub-page repeated the same five-line incantation:
*
* <EmptyState icon={…} title={…} description={…} ctaSize="lg" action={…} />
* <CoachLaunchButton prefill={…} />
*
* The action slot was always a `<Button asChild><Link href="…">…</Link></Button>`
* pointing into `/measurements?add=<TYPE>` (or `/mood` / `/medications`
* for the event-driven metrics). Some sub-pages forgot to mount the
* `<CoachLaunchButton>` underneath; BK-MED-4 wanted every sub-page to
* expose a Coach launch on the empty state because the conversational
* affordance is exactly the right onboarding nudge when the user hasn't
* logged data yet.
*
* This primitive consolidates both responsibilities. Consumers pass:
*
* - the `icon` + `title` + `description` strings (already localised),
* - the primary CTA node (typically a `<Button asChild>` link),
* - the optional Coach `prefill` so a tap on "Ask the Coach" seeds
* the next turn with the metric-specific context.
*
* The Coach launch always renders (BK-MED-4). Pass `coachPrefill={null}`
* to use the default prompt; pass a string to seed a metric-specific
* onboarding question.
*/
export interface MetricEmptyStateProps {
/** Icon node (typically a `lucide-react` glyph). */
icon: ReactNode;
/** Empty-state headline (already localised). */
title: string;
/** One-line scaffold beneath the headline (already localised). */
description: string;
/** Primary CTA — usually a `<Button asChild><Link/></Button>`. */
cta: ReactNode;
/**
* Optional Coach prefill. `null` falls back to the shared default
* prompt the `<CoachLaunchButton>` ships. Pass a metric-specific
* sentence ("I haven't recorded any blood pressure yet — …") to
* seed the first Coach turn with onboarding context.
*/
coachPrefill?: string | null;
}
export function MetricEmptyState({
icon,
title,
description,
cta,
coachPrefill,
}: MetricEmptyStateProps) {
return (
<>
<EmptyState
icon={icon}
title={title}
description={description}
ctaSize="lg"
action={cta}
/>
<CoachLaunchButton prefill={coachPrefill ?? undefined} />
</>
);
}