Enrich / Edit — Unified Design Spec

Keeps the current card-based layout. Applies three targeted changes to reduce friction: a required-fields progress bar above the form, required fields moved to the first row within each card, and a proper no-PDF upload state in the left panel.

enrich edit-document unified spec field reordering

1 — Field Priority Within Cards

Both cards keep their existing structure. Fields are reordered so a user can fill the essentials top-to-bottom without skipping around. Optional fields still live in the same card — they're just pushed below a thin divider.

1
WhoWhenSection — swap rows
Currently the grid is: Date | Location (row 1) → Sender | Receivers (row 2). Required fields are split across both rows. New order: Date | Sender (row 1, both required) → Receivers | Location (row 2, both optional). No code changes to the grid — just reorder the four <div> elements inside the existing grid-cols-2.
2
DescriptionSection — promote Title, push Archive Location last
Title is the most important field but currently sits below "Aufbewahrungsort" in the component's source order. New order: Title (full row, first) → Tags → Summary → Aufbewahrungsort (last, below an "Optional" divider). The divider signals that everything below it is supplementary — no need to fill it during enrichment.
3
Required-fields progress bar — above the form scroll
A 3 px strip between the top bar and the form panel's scroll area. Tracks how many required fields (Title, Date, Sender) are non-empty. Green fill grows left to right. Count badge (e.g. "2 / 3") to the right. Zero JS overhead — computed as a $derived value from existing bindable state.
WhoWhenSection
Jetzt
DatumPflicht
OrtOptional
AbsenderPflicht
EmpfängerOptional
Neu
DatumPflicht
Absender↑ hochgezogen
EmpfängerOptional
OrtOptional

Row 1 is now entirely required. A user who fills Date + Sender and moves on has completed all mandatory who/when data.

DescriptionSection
Jetzt
TitelPflicht
AufbewahrungsortOptional
SchlagworteOptional
KurzinhaltOptional
Neu
TitelPflicht
Schlagworte↑ hochgezogen
KurzinhaltOptional
AufbewahrungsortOptional

Title stays first. Tags move up to row 2 (more useful than archive location during enrichment). Archive Location drops below the "Optional" divider — it's an administrative field, not enrichment work.

2 — Full Page with PDF

The familiar split-pane layout with the reorganized form. Required-fields bar shows 2 of 3 filled; the one missing required field (Sender) is visible immediately at the top of the first card.

Dokumente Personen Anreicherung
MR
← Zur Liste
Brief an Tante Hilde, Sommer 1952
12 verbleibend
Seite 1 / 3
Pflichtfelder
2 / 3
Wer & Wann
Datum *
15.07.1952
Absender *
Person suchen …
Empfänger
Hilde Brandt ×
+
Ort
München
Beschreibung
Titel *
Brief an Tante Hilde — München 1952
Schlagworte
Familie ×
Krieg ×
+ Schlagwort
Kurzinhalt
Optional
Aufbewahrungsort
z. B. Karton 3, Regal B
Überspringen
Speichern
Speichern & Geprüft
1
Required bar at 2/3 — Datum and Titel are filled; Absender is empty. The bar gives an at-a-glance completion signal without adding visual weight to individual fields.
2
Absender focused — it's the only required field still empty, so it receives focus on load via autofocus or a Svelte $effect that targets the first empty required input. No user action needed to know where to start.
3
Aufbewahrungsort below the "Optional" divider — visually de-prioritized without being removed. Editors doing bulk enrichment can ignore it entirely; archivists who need it will still find it.

3 — No-PDF State

When a document has no file yet (status PLACEHOLDER from Excel import), the left panel shows the same dark background but with a centered upload zone. The original filename is shown if known. Drag-and-drop is supported; clicking the CTA opens the file picker. Once a file is selected it uploads and the panel transitions to the normal PDF viewer.

Kein Dokument hochgeladen
Anreicherung
MR
← Zur Liste
scan-2024-03-15-brief.pdf
12 verbleibend
scan-2024-03-15-brief.pdf
Noch keine Datei hochgeladen
Datei auswählen
oder Datei hier ablegen
Pflichtfelder
0 / 3
Wer & Wann
Datum *
TT.MM.JJJJ
Absender *
Person suchen …
Überspringen
Speichern
Speichern & Geprüft
Datei wird hochgeladen
Anreicherung
MR
← Zur Liste
scan-2024-03-15-brief.pdf
12 verbleibend
scan-2024-03-15-brief.pdf
Wird hochgeladen …
Abbrechen
Pflichtfelder
0 / 3
Wer & Wann
Datum *
TT.MM.JJJJ
Absender *
Person suchen …
Überspringen
Speichern
Speichern & Geprüft
1
Dark background is consistent — the same dark panel color as the loading state prevents a jarring flash when the PDF loads. No separate empty-state design needed for the panel chrome.
2
Filename always visibledoc.originalFilename is always populated. Showing it in the upload zone reassures the user they're uploading the right file, and in the top bar title it gives context while the form is empty.
3
Form stays usable during upload — metadata can be filled while the file uploads in parallel. The upload and form save are independent operations; both are sent on "Speichern".
4
Replace file (edit mode) — when a file already exists and the user is on the edit page, the left panel shows the PDF normally. A "Datei ersetzen" ghost button sits in the PDF toolbar — same panel, just an additional toolbar action.

Implementation Reference

Exact Tailwind classes and component-level changes. All three improvements are additive — no existing card structure or component API needs to change.
Element File Change Tailwind / Code
WhoWhenSection field order WhoWhenSection.svelte Reorder the four <div> children of the grid-cols-2 container: Date → Sender → Receivers → Location No class changes. Grid order is source order.
DescriptionSection field order DescriptionSection.svelte Move documentLocation field to last. Move Tags before Summary. No class changes to existing fields.
Optional divider inside DescriptionSection DescriptionSection.svelte Add divider element before documentLocation field. <div class="flex items-center gap-2 my-3"><div class="flex-1 border-t border-line"></div><span class="text-[9px] font-bold uppercase tracking-widest text-ink-3">Optional</span><div class="flex-1 border-t border-line"></div></div>
Required-fields progress bar enrich/[id]/+page.svelte Add strip between .enrich-bar and the split pane. Derive count from bindable state already in scope. Strip: flex items-center gap-3 border-b border-line bg-surface px-6 py-1.5. Track: h-0.5 flex-1 rounded-full bg-line. Fill: h-full rounded-full bg-brand-navy transition-all duration-300 with style="width:{pct}%".
Required fields derivation enrich/[id]/+page.svelte Derive from existing state variables, no new props needed. const requiredFilled = $derived([doc.title || titleValue, dateIso, senderId].filter(Boolean).length); — 3 total required fields in enrich mode.
Auto-focus first empty required field WhoWhenSection.svelte Add autofocus on the Date input when initialDateIso is empty; on the Sender PersonTypeahead otherwise. {#if !initialDateIso}<input ... autofocus />{:else}<PersonTypeahead ... autofocus />{/if}
No-PDF upload zone enrich/[id]/+page.svelte (new conditional block) Conditionally render upload zone in the left panel when !doc.filePath. Zone: flex-1 flex items-center justify-center bg-[#4A4846]. Inner: border border-dashed border-white/20 rounded-sm p-8 flex flex-col items-center gap-3 text-center.
Upload zone drag-and-drop enrich/[id]/+page.svelte Add ondragover / ondrop to zone element. On drop, trigger same upload action as the file input. ondragover={(e) => { e.preventDefault(); isDragging = true; }} + ondrop={(e) => { e.preventDefault(); handleFile(e.dataTransfer?.files[0]); }}. Dragging state: border-brand-mint bg-mint/5 transition.
Upload zone — original filename enrich/[id]/+page.svelte Show doc.originalFilename inside the zone as a label. Always available from the load function. <p class="text-xs font-medium text-white/50 truncate max-w-[200px]">{doc.originalFilename}</p>
Uploading / progress state enrich/[id]/+page.svelte Use existing FileLoader hook's isLoading state. Show indeterminate progress bar when loading. Progress track: w-full h-0.5 bg-white/10 rounded-full overflow-hidden. Fill: h-full bg-brand-mint/70 animate-[slide_1.4s_ease-in-out_infinite].
Replace file button (edit mode) FileSectionEdit.svelte Move "Datei ersetzen" from the card in the form scroll to a ghost button in the PDF toolbar. Toolbar is visible in both states. Button: ml-auto text-[10px] font-bold uppercase tracking-widest text-white/40 hover:text-white/70 transition-colors. Label: "Datei ersetzen". Hidden input triggers file picker.