mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 21:32:18 +00:00
The illness-episode detail gains a Dokumente card: the episode's most recent linked documents as compact rows (deep-linking into the vault, where ?doc= now opens the detail sheet directly), a link-existing picker (searchable, toggle rows driving the idempotent bulk link/unlink), an upload entry that lands pre-linked via the episode filter, and a filtered show-all view. Module-gated — accounts without the documents module see nothing. An episode without documents keeps a quiet one-line affordance instead of an empty card. The preview and picker reads get their own query keys; reusing the vault list key would collide with the infinite-query shape. Refs: document-vault plan W3-T4
62 lines
2.9 KiB
TypeScript
62 lines
2.9 KiB
TypeScript
/**
|
|
* Query keys — the Dokumente vault: the filtered timeline list (keyset-
|
|
* paginated), a single document's detail, and the usage/limits read the
|
|
* upload path pre-flights against. Part of the centralized factory;
|
|
* aggregated in `./index.ts`. Any document write (upload / edit / link /
|
|
* delete / restore / bulk) invalidates the `["documents"]` prefix so the
|
|
* timeline, an open detail sheet, and the quota bar repaint in lockstep.
|
|
*/
|
|
import type { InboundDocumentKindValue } from "@/lib/validations/inbound-documents";
|
|
|
|
/**
|
|
* The parameter set that distinguishes one vault timeline view from another —
|
|
* mirrors the URL facets (`?q&kind&episode&year`) one-to-one so a deep link
|
|
* and an in-page filter change resolve to the same cache bucket. `undefined`
|
|
* fields are dropped by TanStack's stable hash, so an all-defaults view and
|
|
* an explicit `{ q: undefined, … }` share a key. Sort is pinned server-side
|
|
* (filing date, newest first) and is deliberately NOT part of the key.
|
|
*/
|
|
export interface DocumentVaultFilters {
|
|
q?: string;
|
|
/** Type facet — OR inside the facet, sorted before keying by the caller. */
|
|
kinds?: InboundDocumentKindValue[];
|
|
/** Only documents linked to this illness/condition episode. */
|
|
episodeId?: string;
|
|
/** Only documents whose filing date falls in this calendar year. */
|
|
year?: number;
|
|
}
|
|
|
|
export const documentKeys = {
|
|
documents: () => ["documents"] as const,
|
|
inboundDocuments: () => ["documents", "inbound"] as const,
|
|
/**
|
|
* The parameterised vault list (keyset-paginated via `useInfiniteQuery`).
|
|
* The literal `"list"` segment keeps it distinct from a single-document key
|
|
* (`inboundDocument(id)`); cuid ids never collide with it. Stays under the
|
|
* `["documents", "inbound"]` prefix so prefix invalidation still reaches it.
|
|
*/
|
|
inboundDocumentList: (filters: DocumentVaultFilters) =>
|
|
["documents", "inbound", "list", filters] as const,
|
|
inboundDocument: (id: string) => ["documents", "inbound", id] as const,
|
|
/**
|
|
* The illness-episode detail's compact document preview (single page,
|
|
* small limit). Deliberately NOT `inboundDocumentList({ episodeId })` —
|
|
* that key belongs to the vault's `useInfiniteQuery` and a plain query
|
|
* under the same key would poison the cache with a different shape.
|
|
*/
|
|
inboundDocumentEpisodePreview: (episodeId: string) =>
|
|
["documents", "inbound", "episode-preview", episodeId] as const,
|
|
/**
|
|
* The link-existing-documents picker (searchable single page). Own key
|
|
* for the same shape-collision reason as the episode preview.
|
|
*/
|
|
inboundDocumentPicker: (q: string) =>
|
|
["documents", "inbound", "picker", q] as const,
|
|
/**
|
|
* Storage usage + effective limits (`GET /api/documents/inbound/usage`).
|
|
* Invalidated through the `["documents"]` prefix after every upload /
|
|
* delete so the quota bar tracks reality.
|
|
*/
|
|
inboundDocumentUsage: () => ["documents", "inbound", "usage"] as const,
|
|
};
|