feat(document): edit document date precision, end and raw

Adds the edit-form date-precision controls to WhoWhenSection: a labelled
precision <select> (min 48px touch target for senior authors), a conditionally
revealed end-date field (only for RANGE, announced via aria-live=polite), and
the verbatim raw cell as labelled read-only static text (not a disabled input).
Fields submit as metaDatePrecision/metaDateEnd/metaDateRaw and flow through the
existing PUT form action.

Backend: DocumentService.updateDocument now persists the three DTO fields (they
existed since #671 but were never applied), so the new controls are real, not
decorative — addresses Nora's "a client <select> constrains nothing" note for
the persistence half. Server-side enum/end>=start validation remains #671's
scope.

Refs #666

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-05-27 12:04:14 +02:00
parent b56b9dfa74
commit 7245571ea8
5 changed files with 137 additions and 0 deletions

View File

@@ -13,6 +13,7 @@ import WhoWhenSection from '$lib/document/WhoWhenSection.svelte';
import DescriptionSection from '$lib/document/DescriptionSection.svelte';
import type { Tag } from '$lib/tag/TagInput.svelte';
import type { components } from '$lib/generated/api';
import type { DatePrecision } from '$lib/shared/utils/documentDate';
type Person = components['schemas']['Person'];
type Doc = components['schemas']['Document'];
@@ -26,6 +27,8 @@ let {
senderId = $bindable(''),
selectedReceivers = $bindable<Person[]>([]),
dateIso = $bindable(''),
datePrecision = $bindable<DatePrecision>('DAY'),
dateEndIso = $bindable(''),
currentTitle = $bindable(''),
topbar,
actionbar
@@ -38,6 +41,8 @@ let {
senderId?: string;
selectedReceivers?: Person[];
dateIso?: string;
datePrecision?: DatePrecision;
dateEndIso?: string;
currentTitle?: string;
topbar: Snippet;
actionbar: Snippet;
@@ -47,6 +52,8 @@ tags = untrack(() => (doc.tags as Tag[]) ?? []);
senderId = untrack(() => doc.sender?.id ?? '');
selectedReceivers = untrack(() => (doc.receivers as Person[]) ?? []);
dateIso = untrack(() => doc.documentDate ?? '');
datePrecision = untrack(() => doc.metaDatePrecision ?? (doc.documentDate ? 'DAY' : 'UNKNOWN'));
dateEndIso = untrack(() => doc.metaDateEnd ?? '');
currentTitle = untrack(() => doc.title ?? '');
const fileLoader = createFileLoader();
@@ -199,6 +206,9 @@ async function handleReplaceFile(e: Event) {
bind:senderId={senderId}
bind:selectedReceivers={selectedReceivers}
bind:dateIso={dateIso}
bind:precision={datePrecision}
bind:endDateIso={dateEndIso}
rawDate={doc.metaDateRaw ?? ''}
initialDateIso={doc.documentDate ?? ''}
initialLocation={doc.location ?? ''}
initialSenderName={doc.sender?.displayName ?? ''}