mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
Add a CoachPlan model: durable, user-scoped if-then implementation plans the Coach proposes and the user confirms. The background memory-refresh pass extracts plans the user agreed to and writes them as "proposed"; only the user-facing PATCH on /api/coach/plans/[id] activates one. The free-text cue / action / target are encrypted at rest with the shared Bytes codec; metric, status and dates stay plain so the injection picker ranks without a per-row decrypt. Active plans fold into the Coach snapshot's memory block and survive the prompt-budget drop alongside facts. List, confirm and soft-delete routes are Coach-gated and narrow the owner from the session. Key the dashboard-snapshot query cell by locale so a locale switch reads freshly localised tile copy on its own cell instead of serving the prior locale's prose until the slot goes stale. The zero-arg key stays byte-identical, so every prefix-based invalidation keeps reaching the locale-keyed cells; the offline-banner and preloader match on the prefix. Migration 0194 (additive CREATE TABLE). Encryption-rotation registry and script cover the three new Bytes columns.
61 lines
3.0 KiB
TypeScript
61 lines
3.0 KiB
TypeScript
/**
|
|
* Query keys — dashboard snapshot, widget layout, and analytics reads.
|
|
* Part of the centralized factory; aggregated in `./index.ts`.
|
|
*/
|
|
export const dashboardKeys = {
|
|
/**
|
|
* v1.4.33 IW2 — the analytics queryKey now optionally carries a
|
|
* `slice` discriminator so the dashboard tile-strip can subscribe to
|
|
* the slim `?slice=summaries` server slice (IW1 / C1) without
|
|
* colliding with the thick-payload consumers on the Insights tree.
|
|
* Calling `queryKeys.analytics()` without a slice keeps the legacy
|
|
* shape `["analytics"]` so mutation invalidations and the bulk-key
|
|
* lists stay byte-identical.
|
|
*/
|
|
analytics: (slice?: "summaries") =>
|
|
slice ? (["analytics", slice] as const) : (["analytics"] as const),
|
|
/**
|
|
* v1.9.0 — single-metric period-over-period range read
|
|
* (`GET /api/analytics/range`). A dedicated cache slot per `(type, range)`
|
|
* so switching the time-range pills is a cheap cache hit after the first
|
|
* fetch and never collides with the shared `["analytics", "summaries"]`
|
|
* slot the dashboard tile-strip subscribes to. `["analytics"]` is a prefix
|
|
* so a blanket `queryKeys.analytics()` invalidation still reaches it.
|
|
*/
|
|
analyticsRange: (type: string, range: string) =>
|
|
["analytics", "range", type, range] as const,
|
|
|
|
/**
|
|
* v1.7.0 W6 — unified dashboard first-paint snapshot. One client cell
|
|
* hydrates every above-the-fold tile from `GET /api/dashboard/snapshot`,
|
|
* replacing the four independent analytics-slim / analytics-thick /
|
|
* mood / widget-layout cells. A measurement / mood / medication /
|
|
* widget / insight write evicts the matching server cache bucket via
|
|
* `src/lib/cache/invalidate.ts`; the client read carries the same
|
|
* 60 s `staleTime` as `DASHBOARD_QUERY_OPTS` so a warm return-to-
|
|
* dashboard is a free cache hit.
|
|
*
|
|
* v1.21.3 (b) — optional `locale` segment so a locale switch lands the
|
|
* server-rendered prose (the snapshot carries localised tile copy /
|
|
* narrative text) on its own cache cell instead of serving the prior
|
|
* locale's prose until the slot goes stale. Mirrors the `analytics(slice?)`
|
|
* optional-segment precedent above: a ZERO-ARG call stays byte-identical to
|
|
* the legacy `["dashboard","snapshot"]` literal, so every prefix-based
|
|
* invalidation bundle (`measurementDependentKeys`, `medicationDependentKeys`)
|
|
* and zero-arg reader keeps prefix-matching the locale-keyed cells.
|
|
*/
|
|
dashboardSnapshot: (locale?: string) =>
|
|
locale
|
|
? (["dashboard", "snapshot", locale] as const)
|
|
: (["dashboard", "snapshot"] as const),
|
|
|
|
/**
|
|
* v1.4.22 W5 reconcile (Code-LOW-5) — `["user", "dashboardWidgets"]`
|
|
* was duplicated as a literal at three call sites (dashboard,
|
|
* insights, settings/dashboard-layout). One typo turns into a
|
|
* silent cache miss + extra fetch; the centralised key defends
|
|
* against the same query-key-collision class as `analytics()`.
|
|
*/
|
|
dashboardWidgets: () => ["user", "dashboardWidgets"] as const,
|
|
};
|