mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 21:10:59 +00:00
docs(planning): v1.4.34 IW-B close-out report
Captures the analytics lastSeenByType surface, the bfcache-friendly Cache-Control directive, the dashboard tile-strip staleDays wiring, the CoachLaunchProvider hoist, and the dashboard hero CTA — three commits on develop with quality gates passing across 4205 tests.
This commit is contained in:
1 parent
0729c2028b
commit
4d40454261
1 file changed
+109
@@ -0,0 +1,109 @@
|
||||
# v1.4.34 IW-B — implementation report
|
||||
|
||||
Branch: `develop`. Three commits pushed:
|
||||
|
||||
| SHA | Title |
|
||||
| ---------- | ------------------------------------------------------------------------ |
|
||||
| `9a8a9e9a` | feat(analytics): expose per-type lastSeenByType + bfcache-friendly Cache-Control |
|
||||
| `721e88df` | feat(i18n): add stale-hint week/month plurals and dashboard coach CTA |
|
||||
| `0729c202` | feat(dashboard): hoist Coach launch provider and add hero CTA |
|
||||
|
||||
## Scope deltas vs the brief
|
||||
|
||||
1. **`/api/analytics` `lastSeenByType`** — additive field on both the default
|
||||
thick path and the `?slice=summaries` slim slice. Default path captures
|
||||
the freshest `measuredAt` per `MeasurementType` in the existing per-type
|
||||
chunked walk (`.at(-1)` on the ascending-sorted series). Slim slice adds
|
||||
`measured_at` to the existing `DISTINCT ON (type)` pass — zero extra
|
||||
round-trips. Shape:
|
||||
`lastSeenByType[type] = { lastSeenAt: string, daysAgo: number } | null`.
|
||||
2. **`<TrendCard staleDays>` wiring** — 12 mounts on `src/app/page.tsx`
|
||||
pass `staleDays={tileStaleDays("<TYPE>")}` (weight, BP sys/dia, pulse,
|
||||
body-fat, sleep, steps, VO2 max, 4× glucose contexts). Mood and the
|
||||
BD-Zielbereich tile keep the default `null` because they have no
|
||||
underlying per-type freshness signal (mood reads `/api/mood/analytics`;
|
||||
BD-Ziel is an aggregate). The `tileStaleDays` helper returns the
|
||||
`daysAgo` value only when it crosses the 7-day floor — the same gate
|
||||
the `<TrendCard>` uses to decide whether to paint the caption.
|
||||
3. **`Cache-Control` on `/api/analytics`** — both slices stamp the typed
|
||||
`NO_STORE_BUT_BFCACHE` constant (`private, max-age=0, must-revalidate`)
|
||||
imported from IW-A's `src/lib/http/cache-headers.ts`. Replaces the
|
||||
framework's stock `no-store, must-revalidate` which Chromium treats as
|
||||
a hard bfcache breaker.
|
||||
4. **`<CoachLaunchProvider>` hoist** — moved from
|
||||
`src/app/insights/layout.tsx` to `src/components/layout/auth-shell.tsx`
|
||||
so the drawer is reachable from every authenticated route. The
|
||||
`<LayoutCoachMount>` rides alongside the provider on the shell;
|
||||
`<LayoutCoachFab>` stays scoped to `/insights/**` because the floating
|
||||
action would distract from the dashboard hero.
|
||||
5. **Dashboard hero CTA** — new "Frag den Coach" / "Ask the coach" button
|
||||
next to the existing "Hinzufügen" pill on `src/app/page.tsx`. Wires to
|
||||
`coachLaunch.askCoach(null)`; mobile-first via `min-h-11` (WCAG 2.5.5)
|
||||
with the matching `sm:min-h-9` desktop floor.
|
||||
|
||||
## Locale changes
|
||||
|
||||
Six locales (de, en, es, fr, it, pl) gained five additive keys each:
|
||||
|
||||
- `dashboard.staleHintWeeksOne` / `staleHintWeeksOther`
|
||||
- `dashboard.staleHintMonthsOne` / `staleHintMonthsOther`
|
||||
- `dashboard.coachCta`
|
||||
|
||||
`<TrendCard>` picks the right bucket based on `staleDays`:
|
||||
|
||||
- `8 <= staleDays <= 30` → existing `dashboard.staleHint` ("X d ago")
|
||||
- `30 < staleDays <= 60` → `staleHintWeeks*` (singular at exactly 1 week)
|
||||
- `staleDays > 60` → `staleHintMonths*` (singular at exactly 1 month)
|
||||
|
||||
Polish uses the genitive-plural form ("tygodni" / "miesięcy") that covers
|
||||
every non-1 count the bucket math can produce.
|
||||
|
||||
## Files touched
|
||||
|
||||
Source:
|
||||
- `src/app/api/analytics/route.ts`
|
||||
- `src/app/api/analytics/__tests__/route.test.ts`
|
||||
- `src/lib/analytics/summaries-slice.ts`
|
||||
- `src/lib/analytics/__tests__/summaries-slice.test.ts`
|
||||
- `src/lib/queries/use-analytics-query.ts`
|
||||
- `src/components/charts/trend-card.tsx`
|
||||
- `src/components/charts/__tests__/trend-card-stale-days.test.tsx` (new)
|
||||
- `src/app/page.tsx`
|
||||
- `src/components/layout/auth-shell.tsx`
|
||||
- `src/components/layout/__tests__/auth-shell-coach-hoist.test.ts` (new)
|
||||
- `src/app/insights/layout.tsx`
|
||||
- `src/app/__tests__/insights-polish.test.ts` (existing mount-location pin updated)
|
||||
|
||||
Locales: `messages/{de,en,es,fr,it,pl}.json`.
|
||||
|
||||
## Quality gates
|
||||
|
||||
```
|
||||
$ npx tsc --noEmit
|
||||
(clean)
|
||||
$ npx eslint <every touched file>
|
||||
(clean)
|
||||
$ npx vitest run
|
||||
Test Files 396 passed (396)
|
||||
Tests 4205 passed | 1 skipped (4206)
|
||||
```
|
||||
|
||||
Eight new test cases pin the contracts:
|
||||
- analytics route: `lastSeenByType` on both slices, bfcache header on both slices.
|
||||
- slim slice unit: `lastSeenByType` derived from the `DISTINCT ON` pass's `measured_at`.
|
||||
- trend-card: 6 cases covering the bucket-aware copy (silent, day-bucket, week-bucket, month-bucket, German singular/plural edge).
|
||||
- auth-shell hoist: provider import, drawer mount, no double-mount on insights layout.
|
||||
|
||||
## Notes for downstream
|
||||
|
||||
- The dashboard hero CTA hides cleanly when `featureFlags.coach === false`
|
||||
OR the provider context is null. Operators that disable the Coach surface
|
||||
app-wide see the existing "Hinzufügen" pill in the hero unchanged.
|
||||
- The slim slice's `lastSeenByType` is now consumed by `useAnalyticsQuery`
|
||||
callers via the optional field on `AnalyticsRawPayload`; the dashboard
|
||||
uses the thick slice today but the slim path is consumer-ready for the
|
||||
sub-page surfaces that prefetch the lightweight payload.
|
||||
- Three commits were retag-rebased mid-session because parallel agents
|
||||
share the working tree on `develop`. Final state on `origin/develop`
|
||||
carries `9a8a9e9a`, `721e88df`, and `0729c202` with my full commit
|
||||
messages intact.
|
||||
Reference in new issue
Block a user