diff --git a/CHANGELOG.md b/CHANGELOG.md index e96d83735..e1f4e17ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,336 @@ # Changelog +## [1.4.28] — 2026-05-16 + +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 `` +mount, GLP-1 detail-page intake history + inventory, the +`` 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 +`` 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). + +### Removed + +- **GLP-1 dashboard tile.** `src/components/dashboard/glp1-tile.tsx` + and every reference (`dashboard-layout.ts` entry, the + `dashboard.glp1.*` i18n keys, the test fixtures) retire. The tile + is gone from `/`; the recovered vertical real estate flows to the + trends row + HealthScore column. +- **Dashboard `` mount.** The standalone Drug-Level + pane retired from `/`. The component itself stays — it serves the + `/medications/[id]/history` page exclusively. The `compact` mode + and `windowHoursBefore` override drop with the dashboard mount; the + history-page recipe paints the chart inside + `` on the same heading scale as every + other section on the page. +- **`` surface.** The "Persönlicher Berater" + card at the bottom of `/insights` and its "Insights aktualisieren" + regeneration button retire. The Coach drawer is the single + assistant entry point. Component, mounts, test fixtures, i18n + keys, and the cached-advisor query all retire together. +- **Weekly-report route.** `/insights/report/[week]` and the + `` mount on the hero retire. No remaining + consumer; the Coach drawer covers the equivalent ask. +- **GLP-1 detail-page intake history + inventory.** The "Dosis- + Historie" disclosure and "Bestand" section retire from the GLP-1 + medication detail page. The page now collapses to header, + schedule, dose-titration ladder, and side-effects — every section + the maintainer flagged as wanted; every section flagged as + unwanted is gone. Inventory tracking remains opt-in for a future + release. +- **Hero "Wochenbericht erstellen" button.** The placeholder + affordance retires from the `/insights` action row. The row now + carries a single "Coach fragen" button so the HealthScore card on + the opposite column has the height to reach the last suggested + prompt. + +### Fixed + +- **Workout edit raised a 500 on duplicate timestamps.** The save + path on `PUT /api/measurements/[id]` returned a generic 500 when a + sport-typed sample (`ACTIVE_ENERGY_BURNED`, `FLIGHTS_CLIMBED`, + `WALKING_RUNNING_DISTANCE`, `EXERCISE_TIME`) collided with an + existing row on the same `(type, measuredAt)` natural key. Returns + 409 with a `measurements.duplicateTimestamp` translation key now; + the iOS native client and the web measurement-form both surface + the conflict to the user instead of a generic toast. +- **BD-Zielbereich tile rendered "1.1." instead of numbers.** The + tile's bespoke rendering path read the schedule date through + `Intl.DateTimeFormat` and missed the underlying value. Tile + rebuilt on the shared `` primitive so the chrome, the + state shape, the prop API, and the fallback behaviour match the + Weight and BP siblings. The divergence has been the open finding + across v1.4.22, v1.4.25, v1.4.26 patches — this release rewrites + the tile instead of patching. +- **`/insights/puls` hung waiting on the assessment provider.** The + pulse status card called the language-model provider with no + client-side timeout. A timeout helper (`with-timeout.ts`) caps + every status-card provider call at 20 s and returns the rule-based + fallback string on timeout; the page renders the chart immediately + and the assessment line resolves async. +- **Scroll stuck on `/insights` mother-page navigation.** The sticky + tab-strip's intersection-observer was fighting the focus-on-mount + logic so the page sometimes refused to scroll past the tab row. + The observer rebinds on route change and the focus-on-mount + effect now waits for the next animation frame so the scroll + position is locked in before the observer fires. +- **`` paint exceeded the active range window.** The + chart fetched every dose-event in history regardless of the + selected range. Now bounded to the active range — 30 days / 90 + days / all-time — so the wire payload and the recharts render + scale linearly with the visible window. +- **Mood trend tile painted a residual `rounded-xl` border.** The + shadcn `` default paints `rounded-xl` while the trends row + needs `rounded-md` to match the `` shape. Mini- + mode override adds `rounded-md`; the visual rhythm of the row + reads on one envelope. +- **Side-effects card overflowed at 320 px.** The "Nebenwirkungen + erfassen" CTA chip ran past the section header. The qualifier + drops from every locale ("Erfassen" / "Log" / "Consigner" / + "Registrar" / "Registra" / "Dodaj"); the section title carries + the context. The date column on the entry rows narrows from 88 px + to 56 px so the free-text slot recovers 32 px of wrap headroom. +- **Medication-list row shape diverged for GLP-1 entries.** The + GLP-1 row painted with a brand icon and a middle-dot separator; + every other row painted two-line without an icon. Both routes + through a shared `` now — line 1 is `{name} + {dose}`, line 2 is the class label plus state badges. The GLP-1 + outlier shape is gone. +- **HealthScore card came up short below the action+prompts column.** + The card now opts into `flex h-full flex-col` with the disclaimer + footer pinned via `mt-auto`; the hero row switches to + `md:items-stretch` on `md+` so the score column reaches the + bottom of the suggested-prompt rail. Equal-height contract across + the hero strip. +- **`/measurements` aggregation truncated long-window queries.** The + `take` cap applied before bucketising, so a 365-day daily-grain + query returned only the first N raw rows. Aggregation now runs + as a Postgres `date_trunc` GROUP BY and the cap applies to the + bucketised result; a 1-year window returns up to 365 daily + buckets. The all-time chart range resolves to monthly grain (24- + bucket ceiling) or weekly when history is under two years. +- **Schlaf sub-page missed the per-section assessment slot.** Six of + seven insights sub-pages mount `` underneath + the chart; Sleep did not. Documented as the intentional skip + with a `// no per-section assessment yet` marker so future + contributors do not re-flag it. +- **Insights-targets locale strings missed on FR / ES / IT / PL.** + `measurements.duplicateTimestamp` and `insights.sleep.description` + now carry native translations in every locale. + +### Changed + +- **BD-Zielbereich tile aligned to ``.** Tile chrome, + state shape, prop API, and fallback states all match Weight and + BP. The Z-value rounds to one decimal at the boundary, the legend + carries the same micro labels across siblings, the empty state + reads the same copy with the same CTA shape. +- **Medication-list rows route through ``.** + GLP-1 and standard rows both render `{name} {dose}` on line 1 and + class label plus state badges on line 2. State badges break onto + their own row at 320 px so the two-line shape holds. +- **Medications detail-page chrome collapsed to one heading scale.** + Every section on `/medications/[id]` mounts through + `` (`text-base font-semibold leading-6 + tracking-tight`). DrugLevelChart's standalone header migrates to + `

` with the same classes. Micro labels lift from + `text-[10px]` / `text-[11px]` to `text-xs` across Scheduling, + Titration, SideEffects. Three scales survive the page: heading, + body (`text-sm`), micro (`text-xs`). +- **Coach launch shape consolidated to three primitives.** A single + `` mounts once per Insights surface (FAB on `