# Ereignis-Editor & Brief-Gruppierung · Quick-Action im Dokument

Wie kuratierte Zeitstrahl-Ereignisse entstehen und wie Briefe gruppiert werden — von zwei Seiten in ein Datenmodell (`TimelineEvent.documents`): der Ereignis-Editor unter `/zeitstrahl/events/[id]/edit` (Kurator baut, verlinkt viele Briefe) und die Quick-Action im Dokument-Detail (beim Lesen schnell zuordnen). Beide bauen auf bereits ausgelieferten Komponenten auf.

Milestone #14 · Zeitstrahl Reuse: GeschichteEditor · DocumentMultiSelect · PersonMultiSelect WRITE_ALL
Familienarchiv · 2026-06-08 · Leonie Voss, UX Lead · gegründet auf Code: GeschichteEditor.svelte · DocumentMetadataDrawer.svelte · DocumentMultiSelect.svelte

## 1 · Zwei Einstiegspunkte, ein Datenmodell

Manuelle Gruppierung = ein `TimelineEvent` mit verknüpften Dokumenten. Kuratoren arbeiten in beide Richtungen — wir bauen beide, statt eine zu erzwingen.

A · Ereignis-zuerst — der Kurator baut den Zeitstrahl. `/zeitstrahl/events/new · [id]/edit` mit Dokument-Mehrfach-Picker = Bulk-Linking vieler Briefe auf einmal. Spiegelt 1:1 den `GeschichteEditor` (gleiche zwei-Spalten-Form, Sidebar-Picker, Sticky-Save-Bar).
B · Dokument-zuerst — beim Lesen eines Briefs. Quick-Action im Dokument-Detail: bestehendes Ereignis wählen oder neu anlegen, verlinkt diesen einen Brief. Spiegelt die bestehende Geschichten-Spalte im Details-Drawer (`DocumentMetadataDrawer.svelte`).

## 2 · Ereignis-Editor — `/zeitstrahl/events/[id]/edit`

Form-Actions-Muster, gegated mit `WRITE_ALL`. Layout & Verhalten 1:1 vom `GeschichteEditor` übernommen: Hauptspalte + Sidebar (`lg:grid-cols-[2fr_1fr]`), Sticky-Save-Bar, `beforeNavigate`-Warnung bei ungespeicherten Änderungen.

FamilienarchivDokumentePersonenZeitstrahlStammbaumKR
‹ Zurück zum Zeitstrahl
Ereignis bearbeiten
Briefe von der Front
② Typ
PersönlichHistorisch
③ Datum · Präzision
1915
Jahr ▾
Bei „Zeitspanne" erscheint ein zweites End-Datum-Feld. Bei „ca." / „Saison" passt sich nur das Label an.
④ Beschreibung · optional
Karls Feldpost von der Westfront, 1915 — wöchentliche Briefe an Elfriede und den neugeborenen Hans. Eine zusammenhängende Korrespondenz, die hier als Cluster gebündelt wird …
Schlichtes Textfeld (kein Rich-Text wie Geschichten) — Ereignisse sind kurze Notizen, keine Langform.

### ⑤ Verknüpfte Briefe · 24

Diese Briefe bilden den Cluster. `DocumentMultiSelect`
✉ Westfront-Brief · Mär 1915 × ✉ Feldpost Verdun · Jul 1915 × ✉ Brief an Elfriede · Sep 1915 × Brief suchen …

### ⑥ Beteiligte Personen

Treibt die Lebensweg-Ansicht & Filter. `PersonMultiSelect`
Karl Raddatz × Elfriede Raddatz × Hans Raddatz × Person suchen …
Änderungen werden erst beim Speichern übernommen.
Löschen Abbrechen Speichern
①Titel — großes Serifen-Feld, wie der Geschichten-Titel. Pflichtfeld (Validierung bei Blur).
②Typ — `PERSONAL` / `HISTORICAL` Segmented-Control. Steuert Rendering (Mint-Pille vs. Welt-Band).
③Datum + Präzision — geteilte `DatePrecisionInput` (gleiche Logik wie Dokument-Datum, `metaDatePrecision`). „Zeitspanne" blendet End-Datum ein.
④Beschreibung — optionales Textfeld (`TEXT`), bewusst schlicht.
⑤Verknüpfte Briefe — hier wird gruppiert. Wiederverwendung von `DocumentMultiSelect` (Typeahead, Chips, Hidden-Inputs).
⑥Beteiligte Personen — `PersonMultiSelect`. Bestimmt, in welchem „Lebensweg" das Ereignis auftaucht.
⑦Sticky-Save-Bar — Speichern primär, Abbrechen sekundär, Löschen nur im Edit-Modus (mit Bestätigung).
＋/new — leeres Formular. Mit `?documentId=…` ist Feld ⑤ vorbefüllt (aus der Quick-Action, §4-D).

## 3 · Brief-Gruppierung im Editor — der Dokument-Picker

Feld ⑤ ist der unveränderte `DocumentMultiSelect`: Tippen sucht über `/api/documents/search?q=…` (debounced 300 ms), Treffer mit ehrlichem Datums-Label, bereits gewählte werden gefiltert. Jeder Klick fügt einen Brief zum Cluster.

Suche aktiv — DropdownDocumentMultiSelect
✉ Westfront-Brief · Mär 1915 × ✉ Feldpost Verdun · Jul 1915 × Verdun▏
Feldpost aus Verdun · Brief · Juli 1915
Brief aus dem Verdun-Lazarett · Brief · August 1916
Rückkehr aus Verdun · Brief · ca. 1917
Label = `title · formatDocumentDate(precision)`. Bereits verknüpfte Briefe erscheinen nicht in den Treffern (Dedup).
Inline „＋ Ereignis" am Jahres-BandZeitstrahl
1915
✉ 24 Briefe
Monats-Dichte ▾
Kuratoren können auch direkt im Zeitstrahl ein Ereignis anlegen — öffnet denselben Editor, Jahr & Briefe des Bandes vorbefüllt.

## 4 · Quick-Action im Dokument-Detail — wo sie lebt

Die Dokument-Detailseite ist ein vollflächiger Viewer ohne Sidebar (`fixed inset`). Aktions-Flächen gibt es nur zwei: die `DocumentTopBar` und den aufklappbaren Details-Drawer. Die Quick-Action lebt an beiden — primär als „Zeitstrahl"-Spalte im Drawer (spiegelt die Geschichten-Spalte), plus ein Top-Bar-Button für den Ein-Klick-Weg.

Warum der Details-Drawer der richtige Ort ist: Er zeigt heute schon, wozu ein Brief gehört — Personen, Schlagwörter und Geschichten (mit „Zuordnen"-Aktion, gegated über `canBlogWrite`, `DocumentMetadataDrawer.svelte:210`). Zeitstrahl-Ereignisse sind strukturell identisch („dieser Brief gehört zu diesen Ereignissen") und bekommen daher eine gleichwertige vierte/fünfte Spalte. Konsistent & auffindbar dort, wo Nutzer ohnehin „Zugehörigkeit" suchen.
‹
Brief über die Lage an der Westfront
März 1915
KR→ER
Details ▴
✎ Transkribieren ⊕ Zeitstrahl ⤓
Details
Datum
März 1915
Ort
Westfront
Status
Transkribiert
Personen
KRKarl Raddatz
ERElfriede Raddatz
Schlagwörter
KriegBriefe von der Front
Zeitstrahl + Zuordnen
Briefe von der Front×
1915 · 24 Briefe · persönlich
Krieg
Ereignis suchen … ＋ Neu
↓ PDF-Viewer (Brief-Scan) …
ATop-Bar-Button „⊕ Zeitstrahl" — Mint-Akzent im Aktions-Cluster (`DocumentTopBarActions`). Öffnet ein kleines Popover zum Ein-Klick-Zuordnen, ohne den Drawer zu öffnen. Im Mobile-Menü als Eintrag.
B„Zeitstrahl"-Spalte im Details-Drawer — neue Spalte neben Geschichten. Zeigt verknüpfte Ereignisse (Titel · Datum · Tag-Chip), Unlink über `×`, plus Quick-Add-Zeile. Nur sichtbar/aktiv bei `canWrite`.
CQuick-Add-Zeile — Typeahead „Ereignis suchen …" (sofortiges Verlinken, keine Navigation) + „＋ Neu".
D„＋ Neu" → `/zeitstrahl/events/new?documentId={id}` — öffnet den Editor (§2) mit diesem Brief in Feld ⑤ vorbefüllt. Spiegelt `/geschichten/new?documentId=`.

## 5 · Quick-Action — Zustände

Der Typeahead in der Zeitstrahl-Spalte (oder im Top-Bar-Popover). Gleiches Muster wie `DocumentMultiSelect`, nur sucht es Ereignisse statt Dokumente.

A · Nicht zugeordnet
Noch keinem Ereignis zugeordnet.
Ereignis suchen …＋ Neu
B · Suche — Treffer
Front▏
Briefe von der Front · 1915 · 24 Briefe
Kriegsausbruch · 1914 · 6 Briefe
＋ „Front" als neues Ereignis anlegen
C · Zugeordnet
Briefe von der Front✓ verknüpft ×
Krieg
Sofortiges Verlinken (POST). Toast „Zum Ereignis hinzugefügt", `aria-live`. Unlink über `×` (DELETE).
D · Mehrfach zugeordnet
Briefe von der Front×
Weihnachten 1915×
Ein Brief darf zu mehreren Ereignissen gehören (ManyToMany) — alle werden gelistet.

## 6 · Wiederverwendete Bausteine & Tokens

Maximal wiederverwenden: `DocumentMultiSelect` (Brief-Gruppierung, unverändert) · `PersonMultiSelect` (Beteiligte) · `GeschichteEditor`-Layout (zwei Spalten, Sticky-Save, `beforeNavigate`) · `DocumentMetadataDrawer`-Spaltenmuster (Quick-Action) · `useUnsavedWarning` · `formatDocumentDate` / `DatePrecision`. Brand-Tokens wie im Zeitstrahl-Spec: Navy `#012851`, Mint `#a1dcd8`, Linie `#e4e2d7`, ink-3 `#6b7280`, danger `#c0392b`; Serifen-Titel (Tinos), Sans-Chrome (Montserrat).

## 7 · Implementierungs-Referenz & Barrierefreiheit

Baustein | Datei / Endpoint | Verantwortung
--- | --- | ---
Editor-Route (neu) | `/zeitstrahl/events/new · [id]/edit` | `+page.server.ts` (Form-Actions, `WRITE_ALL`) + `+page.svelte`; `?documentId=` vorbefüllt Feld ⑤
Editor-Komponente (neu) | `TimelineEventEditor.svelte` | Spiegelt `GeschichteEditor`: Titel, Typ, Datum+Präzision, Beschreibung; Sidebar-Picker; Sticky-Save; `beforeNavigate`
Brief-Gruppierung (reuse) | `DocumentMultiSelect.svelte` | Unverändert — Typeahead `/api/documents/search`, Chips, Hidden-Inputs `documentIds`
Personen (reuse) | `PersonMultiSelect.svelte` | Unverändert — Beteiligte Personen
Datum + Präzision | `DatePrecisionInput` (geteilt) | Wie Dokument-Datum (`metaDatePrecision`); „Zeitspanne" → End-Datum; `formatDocumentDate` fürs Label
Quick-Action-Spalte (neu) | `DocumentTimelineColumn.svelte` | Im `DocumentMetadataDrawer` neben Geschichten; verknüpfte Ereignisse + Quick-Add; nur bei `canWrite`
Quick-Add-Picker (neu) | `DocumentTimelineEventPicker.svelte` | Ereignis-Typeahead; sofort verlinken oder `?documentId=` zum Editor; auch im Top-Bar-Popover
Top-Bar-Button (neu) | `DocumentTopBarActions` · `DocumentMobileMenu` | „⊕ Zeitstrahl"-Button (canWrite); öffnet Quick-Add-Popover
Backend — CRUD | `POST · PUT · DELETE /api/timeline/events` | `TimelineEventController`, `WRITE_ALL`; `TimelineEventRequest` mit `documentIds` / `personIds`
Backend — Link/Unlink | `PUT /api/timeline/events/{id}` | Verlinken/Lösen läuft über das Event-Update (`documents`-Set); kein neuer ErrorCode nötig
Barrierefreiheit | — | Picker-Dropdowns Tastatur-navigierbar (↑↓↵), `aria-live` für „verknüpft/gelöst"; 44px-Ziele; sichtbarer Fokus-Ring; Löschen/Unlink mit Bestätigung

Offene Designentscheidung: Soll der Top-Bar-Button (A) MVP sein oder reicht zunächst die Drawer-Spalte (B)? Empfehlung: B als MVP (spiegelt Geschichten exakt, geringster Aufwand), A als schneller Nachzug.