diff --git a/frontend/src/lib/document/DocumentMultiSelect.svelte b/frontend/src/lib/document/DocumentMultiSelect.svelte index dcb4ecca..fbfd59a9 100644 --- a/frontend/src/lib/document/DocumentMultiSelect.svelte +++ b/frontend/src/lib/document/DocumentMultiSelect.svelte @@ -5,11 +5,20 @@ import { clickOutside } from '$lib/shared/actions/clickOutside'; import { formatDocumentDate, type DatePrecision } from '$lib/shared/utils/documentDate'; import { getLocale } from '$lib/paraglide/runtime.js'; -type Document = components['schemas']['Document']; type DocumentListItem = components['schemas']['DocumentListItem']; +/** + * Exactly the fields this picker reads — id for selection/dedup, the rest for + * the honest date label. A full `Document` and a `DocumentListItem` are both + * structurally assignable, so the search results need no cast. + */ +type DocumentOption = Pick< + DocumentListItem, + 'id' | 'title' | 'documentDate' | 'metaDatePrecision' | 'metaDateEnd' +>; + interface Props { - selectedDocuments?: Document[]; + selectedDocuments?: DocumentOption[]; placeholder?: string; hiddenInputName?: string; } @@ -21,7 +30,7 @@ let { }: Props = $props(); let searchTerm = $state(''); -let results: Document[] = $state([]); +let results: DocumentOption[] = $state([]); let showDropdown = $state(false); let loading = $state(false); let debounceTimer: ReturnType; @@ -47,13 +56,13 @@ function handleInput() { const res = await fetch(`/api/documents/search?q=${encodeURIComponent(searchTerm)}&size=10`); if (res.ok) { const body: { items: DocumentListItem[] } = await res.json(); - const docs = body.items.map((it) => ({ + const docs: DocumentOption[] = body.items.map((it) => ({ id: it.id, title: it.title, documentDate: it.documentDate, metaDatePrecision: it.metaDatePrecision, metaDateEnd: it.metaDateEnd - })) as unknown as Document[]; + })); results = docs.filter((d) => !selectedDocuments.some((s) => s.id === d.id)); } } catch { @@ -64,7 +73,7 @@ function handleInput() { }, 300); } -function selectDocument(doc: Document) { +function selectDocument(doc: DocumentOption) { selectedDocuments = [...selectedDocuments, doc]; searchTerm = ''; showDropdown = false; @@ -75,10 +84,15 @@ function removeDocument(id: string | undefined) { selectedDocuments = selectedDocuments.filter((d) => d.id !== id); } -function formatDocLabel(doc: Document): string { +function formatDocLabel(doc: DocumentOption): string { if (!doc.documentDate) return doc.title; - const precision = (doc.metaDatePrecision as DatePrecision | undefined) ?? 'DAY'; - const label = formatDocumentDate(doc.documentDate, precision, doc.metaDateEnd, null, getLocale()); + const label = formatDocumentDate( + doc.documentDate, + doc.metaDatePrecision as DatePrecision, + doc.metaDateEnd, + null, + getLocale() + ); return `${doc.title} · ${label}`; }