feat(documents): run the vault's months side by side by default

An account that never picked an arrangement now sees the months flowing
across the width. The layout PUT stores only the fields the person chose,
so an untouched field keeps following the default while a saved choice
stays.
This commit is contained in:
Marc-André Bombeck committed 2026-10-09 08:50:20 +02:00
1 parent 88836452eb
commit 7340cd3ab7
7 files changed
+86 -24

No files matched your search

+24 -4
View File
@@ -10,9 +10,10 @@
* and wrap, with each month's name riding inline as a small marker that does
* not break the run.
*
* Null / missing column = the defaults below (cards, stacked — the vault as it
* has always looked). The GET endpoint never lazy-writes, so the column only
* carries data once the user has changed one of the two. Mirrors
* Null / missing column = the defaults below (cards, flowing months). The GET
* endpoint never lazy-writes, and the PUT stores only the fields the user has
* actually chosen, so a default that changes later reaches every account that
* never picked that field, while a saved choice stays. Mirrors
* `medication-list-layout.ts`: tolerant resolver on read, normaliser on write,
* preserve-when-absent PUT (see the route).
*/
@@ -33,7 +34,7 @@ export interface DocumentsLayout {
export const DEFAULT_DOCUMENTS_LAYOUT: DocumentsLayout = {
version: 1,
view: "cards",
arrangement: "stacked",
arrangement: "flow",
};
function isView(value: unknown): value is DocumentsLayoutView {
@@ -68,3 +69,22 @@ export function resolveDocumentsLayout(raw: unknown): DocumentsLayout {
: DEFAULT_DOCUMENTS_LAYOUT.arrangement,
};
}
/**
* The fields a stored blob explicitly carries, each validated. Unknown or
* malformed values drop out, so the default fills them on read. The PUT
* merges into this rather than into the resolved layout, which keeps an
* untouched field following the default instead of freezing today's value.
*/
export function storedDocumentsLayoutChoices(
raw: unknown,
): Partial<Pick<DocumentsLayout, "view" | "arrangement">> {
if (raw === null || raw === undefined || typeof raw !== "object") return {};
const blob = raw as { view?: unknown; arrangement?: unknown };
return {
...(isView(blob.view) ? { view: blob.view } : {}),
...(isArrangement(blob.arrangement)
? { arrangement: blob.arrangement }
: {}),
};
}
+1 -1
View File
@@ -62,7 +62,7 @@ const documentsLayoutSchema = z
arrangement: z
.enum(DOCUMENTS_LAYOUT_ARRANGEMENTS)
.describe(
'`stacked` gives every month its own block; `flow` runs the documents across the full width and wraps, with month names inline. Default "stacked".',
'`stacked` gives every month its own block; `flow` runs the documents across the full width and wraps, with month names inline. Default "flow"; an account that never chose keeps following the default.',
),
})
.meta({