Adds `<RecentWorkoutsTile>` as a default-visible dashboard widget
(`recentWorkouts`). The tile reads the top three canonical workouts
through `useWorkouts({ limit: 3 })`, renders each as a deep-link
row with the sport icon + the day + the duration, and falls back
to an Apple-Health-onboarding cue when the workout list is empty.
`DASHBOARD_WIDGET_IDS` + `DEFAULT_DASHBOARD_LAYOUT.widgets` carry
the new id; `widgetIdEnum` on `/api/dashboard/widgets` picks it up
from the same source-of-truth array. The Settings → Dashboard
layout editor surfaces it under the existing widget toggle list so
users can opt out without touching the layout JSON. Six locales
updated.
Drop the standalone GLP-1 dashboard tile and its data-fetch route.
The /api/dashboard/glp1 endpoint has no consumer outside the retired
tile (no native client reads it), so the route, the tile component,
its test, the e2e spec, the locale keys, the query-key entry and the
drift-guard assertion all retire together.
The medication detail page and its bidirectional contracts stay
untouched. An opt-in dashboard widget that surfaces the same level
chart will land later in this cycle, anchored on the existing
dashboard-layout toggle list.
Lift the GLP-1 tile range strip + tab pills, the getting-started
checklist dismiss buttons, and the settings reorder + source-ladder
arrow buttons so every interactive element clears the 44 px WCAG
2.5.5 floor.
- `glp1-tile.tsx`: range-strip radio buttons gain `inline-flex
min-h-11 items-center justify-center px-3` so each preset sits at
44 px; the tab pills (level / weight) lift the same way.
- `getting-started-checklist.tsx`: dismiss-all CTA drops `size="sm"`
so it sits at the default 40 px primitive height; per-row dismiss
`X` button wraps in `inline-flex h-11 w-11`.
- `dashboard-layout-section.tsx`: reorder up + down arrows `h-5 w-5`
→ `size-11`; column-header spacer widens to `w-11` to keep the
layout grid aligned.
- `sources-section.tsx`: metric source ladder + device-type ladder
up/down arrows stack vertically on `<sm` so each button keeps the
`h-11 w-11` floor without crowding the row; sit side-by-side again
from `sm:` up to preserve the desktop layout.
W10 design-review carry-over items. M7 lifts the medication-form
day-of-week buttons, the more-horizontal trigger, and the schedule
label-input gaps to the 44 px / space-y-2 standard used by every
other settings surface. L1 pairs every animate-spin/pulse/bounce
with motion-reduce:animate-none across the component tree so users
with prefers-reduced-motion get a still surface. L3 adds the
aria-controls + panel-id pairing to the inventory + coach-evidence
<details> blocks for parity with the Health Score provenance
accordion. L4 inserts a sr-only h4 per therapy-timeline entry so
screen-reader users can jump between medication blocks.
The faint dracula-green left-seam on the outer wrapper was decoration
without a semantic tie to the schedule rows beside it. The Syringe-icon
in the title row already carries the 'active therapy' signal at a
glance.
Replace the <dl> grid with a soft-green pill bar that groups Last- and
Next-Injection as one cohesive 'therapy schedule' unit. Each pill keeps
its data-slot anchor (glp1-tile-last / glp1-tile-next) so existing
tests stay in lockstep; new test asserts the data-slot='glp1-tile-schedule'
wrapper renders and the border-l-dracula-green/60 + border-l-2 classes
no longer appear on the outer wrapper.
The GLP-1 tile previously rendered a single weight chart — a downstream
proxy for the dose-response. The maintainer-flagged headline is the
estimated drug-level curve because it surfaces the sawtooth shape of
the weekly cycle directly.
Add a two-tab segmented control (Drug-Level default / Weight) inside the
chart pane and a 7d / 30d / 90d / All range strip above. The Drug-Level
tab mounts <DrugLevelChart compact …>, which now drops its outer card
wrapper and renders at 160 px instead of 240 px when 'compact' is set,
so the dashboard tile owns the card surface. Range selections thread
through a new windowHoursBefore prop on DrugLevelChart; the sample step
scales 6/12/24/48 h with window length so 'All' mode does not paint
thousands of points. The standalone surface at /medications/[id]/history
keeps its full 21-day default and full-card chrome — both consumers
share one implementation.
New translation keys referenced (B6 sweep picks up):
- dashboard.glp1.tabLevel
- dashboard.glp1.tabWeight
- dashboard.glp1.tabsAria
- dashboard.glp1.rangeStripLabel
- dashboard.glp1.levelUnavailable
- dashboard.glp1.weightUnavailable
Test coverage extended: glp1-tile test asserts tab strip + range strip
DOM, drug-level default selection, level-unavailable hint when the
medication has no id; the existing DrugLevelChart test suite continues
to pin the standalone-surface contract.
7 conflict files resolved by taking the upstream/HEAD side (which carries
the W4d/W5/W6c/W3f feature additions). Stashed-side changes that were
genuine new features re-land in subsequent commits if any were lost.
This sweeps up the loose state the W4e+W5e+W5d combined agent left
mid-stash. Resolves develop's working tree for clean push.
Renders a dedicated tile for users on a GLP-1 receptor agonist
(Mounjaro, Ozempic, Wegovy, Zepbound, …) — the new W4d schema enum
`Medication.treatmentClass = GLP1` is the discriminator. Tile self-
hides when no active GLP-1 med exists so accounts without one see no
visual change.
The tile surfaces:
- Drug name + current dose ("Mounjaro 7.5mg") — sourced from the
`MedicationDoseChange` titration history (latest row wins), so a
Mounjaro user titrating up 2.5 → 5 → 7.5 → 10 mg sees their
current step, not the starting dose.
- Last injection date + weekday ("Sun, 05/10")
- Next injection date + weekday + countdown
("Sun, 05/17 (in 3 days)") — predicted from the existing schedule
cadence
- Weight delta since starting the therapy ("−4.2 kg since start"
/ "−4,2 kg seit Beginn") — green chip on loss, orange on gain,
muted minus on flat (within ±0.1 kg)
- A compact weight chart with vertical injection-day markers via
the new `<HealthChart verticalMarkers={…} />` prop
New server endpoint `GET /api/dashboard/glp1` aggregates the data:
the heavy lifting (current dose / last + next injection / titration
history / inventory math) is delegated to the existing
`buildGlp1SnapshotBlock` so the Coach's GLP-1-aware reply path and
the dashboard tile read from the same shape. The route adds the UI-
facing extras (weight series since first dose-change, current vs
start, injection date keys for the markers) on top.
Mount: dashboard mother page (`src/app/page.tsx`) mounts the tile
below the AI insights preview and above the chart row — high enough
that a Mounjaro user sees their dose-response without scrolling past
BP / pulse, but below the AI preview which stays the scroll-stop
hero anchor.
Constraint respected (Marc directive 2026-05-14): the chart lives on
the Dashboard tile and the Insights /medikamente sub-page only; the
Medications page itself stays chart-free.
i18n keys: dashboard.glp1.{title, lastInjection, nextInjection,
weightDelta, inDays, empty.title, empty.description} in EN + DE.
Tests pin 7 scenarios: hidden when no active GLP-1, hidden when meds
array is empty, skeleton during fetch, full render for a Mounjaro 7.5
mg weekly profile, latest titration step wins (10 mg, not 2.5 mg),
fallback to name-only when no dose history exists, German copy under
the de locale.