Files
HealthLog/src/lib/query-keys/vaccinations.ts
T
Marc-André Bombeck 9b58394724 feat(vaccinations): link documents to doses, with the upload suggestion
- from the record: a document link picker on the capture form, gated on the
  documents module (blanked when off, never post-filtered)
- from the upload: a VACCINATION scan offers to file against a dose recorded
  within the shared ±7-day window; a single candidate pre-selects, two offer a
  picker with nothing pre-selected (WR-8 seen red on the pre-select rule,
  reverted by content hash), zero shows nothing, and it never blocks the upload
- the suggestion rule reuses the visit moment's window constant rather than
  forking it; it registers with the shared filing module when that lands
- suggestion and link copy in six locales
2026-08-08 21:11:21 +02:00

56 lines
3.0 KiB
TypeScript

/**
* Query keys — the immunization log.
* Part of the centralized factory; aggregated in `./index.ts`.
*
* These exist before any client reads them, because the in-repo
* `healthlog/queryKey-factory` rule errors on a bare array: the first
* component that lists doses cannot compile without a slot here. Same key with
* a different `queryFn` shape silently poisons the cache, which is the whole
* reason the factory is the only legal source.
*
* There is deliberately no matching `invalidateUserVaccinations` in
* `src/lib/cache/invalidate.ts`, for the same reason the visits module next
* door has none. That module evicts SERVER-side cached payloads, and no cached
* payload reads a dose: the dashboard snapshot, the insights targets and the
* analytics buckets are computed from measurements, medications and mood.
* Adding a sweep over caches nothing reads would be a placeholder that looks
* like coverage. It belongs in the release that puts doses into one of those
* payloads, alongside the reader that makes it necessary.
*
* There is no dependent-keys bundle here yet either, and that omission is the
* same rule one layer up: a bundle with no caller is dead code, and the gate
* says so. When the capture surface lands it brings its own, and that bundle
* has to evict the preventive-care root alongside this one — logging a dose
* satisfies the booster reminders it answers, so the checkups list goes stale
* in the same tick. Evicting only the immunization list would leave a booster
* on screen that the server had already moved a decade out.
*/
export const vaccinationKeys = {
/**
* The root prefix every dose write invalidates through
* (`vaccinationDependentKeys` in `./index.ts`). TanStack's hierarchical
* prefix semantics mean evicting `["vaccinations"]` clears the list and
* every open detail in one tick, so a dose edited in a sheet and the list
* behind it never disagree.
*/
vaccinations: () => ["vaccinations"] as const,
/**
* The list. The filter is part of the key: a page showing one antigen's
* history and the page showing everything are two different answers rather
* than one answer that overwrites the other.
*/
vaccinationList: (antigenSlug?: string | null) =>
["vaccinations", "list", antigenSlug ?? null] as const,
vaccination: (id: string) => ["vaccinations", "detail", id] as const,
/** The upload suggestion for one anchor date; the anchor is part of the key. */
vaccinationSuggestion: (anchor: string) =>
["vaccinations", "suggest", anchor] as const,
/** Mutation keys — the factory is the only legal source of these too. */
vaccinationCreate: () => ["vaccinations", "create"] as const,
vaccinationUpdate: () => ["vaccinations", "update"] as const,
vaccinationDelete: () => ["vaccinations", "delete"] as const,
vaccinationRestore: () => ["vaccinations", "restore"] as const,
vaccinationBooster: () => ["vaccinations", "booster"] as const,
vaccinationLink: () => ["vaccinations", "link"] as const,
} as const;