Files
HealthLog/src
Marc-André Bombeck 97583cf891 refactor(targets): extract TargetCard + RangeBar + ConsistencyStrip + TargetCoachButton
The /targets page composed everything inline in a 790-line page.tsx.
Break it into focused primitives under src/components/targets/ so the
W3e redesign can iterate per-card without growing the page file:

- target-card.tsx — the redesigned card composition. Headline + verbal
  status pill, big-number row with inline trend chevron, range bar,
  consistency strip, recency + streak chips (both conditional on real
  data), per-card Coach CTA gated by aiEnabled, source link footer.
  MOOD_STABILITY swaps the raw σ headline for a verbal label via the
  moodStabilityLabel helper. Fixed card order is owned by the page;
  this component is presentational.
- range-bar.tsx — extracted intact from page.tsx. Same behaviour, same
  data-slot. Now carries its own test suite.
- consistency-strip.tsx — NEW. 7 dots (one per Berlin-tz day), each
  filled / amber / red / hollow per the day's band classification.
  Caption flips between "X of 7 in range" and "X of 7 logged" when
  cadence is the more informative signal. Accessible: <ul role="list">
  with per-dot aria-labels seeded from i18n. No empty-state copy
  inside the strip — Marc directive: hide entirely when insufficient.
- target-coach-button.tsx — NEW. Per-card "Ask Coach about this" CTA
  that returns null when aiEnabled is false. No greyed-out button,
  no tooltip placeholder — the gate is total per Marc's
  "no broken-button state" directive.

Supporting helpers (each unit-tested):
- src/lib/targets/mood-stability-label.ts — pure σ → verbal-label
  threshold logic (< 1.0 stable, < 2.0 variable, ≥ 2.0
  highlyVariable). Thresholds documented in the helper and confirmed
  in the W3e plan.
- src/lib/ai/coach/target-prompts.ts — 8 metric × 2 locale templates
  for the per-card Coach prefill. Falls back to a general template for
  glucose contexts. PROMPT_VERSION unchanged (the assistant-facing
  prompt does not shift; only user-side prefills do).
- src/lib/ai/coach/target-scope.ts — per-target CoachScope.sources
  mapping. Derived metrics (BMI → weight, MOOD_STABILITY → mood) point
  at the underlying source; unmapped targets return an empty array
  so the drawer falls back to defaults.

i18n keys added: targets.consistency.* (cap + dot aria + relative day
+ insufficient-data), targets.card.{lastMet,streak}, targets.relativeDay.*,
targets.summary.{weekTitle,weekTitleAll,streakHighlight},
targets.coach.cta, targets.mood.stability.* — all EN + DE.

Tests: 17 cases across 5 suites (consistency-strip render variants,
target-coach-button gate branches, range-bar zone painting,
target-card full-data + insufficient-data + aiEnabled-off +
MOOD_STABILITY verbal-headline, mood-stability-label thresholds).

Page.tsx still uses the old inline composition for now — Phase 5
wires it to the new components.
2026-05-14 12:29:02 +02:00
..
2026-05-12 22:33:35 +02:00
2026-05-12 22:33:35 +02:00