New StammbaumCard rendered below the Namensverlauf card on
/persons/{id}/edit:
- Header with "Als Familienmitglied" toggle (form action
toggleFamilyMember → PATCH /api/persons/{id}/family-member).
- "Erscheint im Stammbaum" banner with deep-link to
/stammbaum?focus={id} when familyMember is true.
- Direct relationships list grouped by type, then year. Chip text is
direction-aware: storage subject reads "Elternteil von", storage
object reads "Kind von" (new relation_child_of i18n key in all 3
locales). Symmetric and non-family types use their own keys.
- + Beziehung hinzufügen reveals an inline form with type select
(grouped Familie / Sozial), a PersonTypeahead with the new
excludePersonId prop (self-rel prevention, Elicit blocker 1), and
Von / Bis year fields.
- Year validation lives client-side via $derived: empty/empty is OK,
Bis < Von shows a red text-red-700 error wired with aria-describedby
and disables submit (Sara blocker 3).
- Self-rel inline error mirrors the typeahead exclusion in case the
user submits the personId regardless.
- Abgeleitete Beziehungen section (top 5) collapsed by default.
+page.server.ts loads relationships + inferred relationships in the
existing parallel fetch and adds three actions: toggleFamilyMember,
addRelationship (with year-range guard), deleteRelationship.
Refs #358.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
validatePersonFields now returns a PersonValidationKey instead of a
hardcoded German string. resolveValidationMessage() translates the key
through Paraglide so English and Spanish locale users no longer see
German error text. Adds validation_last_name_required and
validation_first_name_required to all three message files.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes four independent PersonType type declarations and the duplicated
TYPES/PERSON_TYPES arrays. normalizePersonType moves from the edit route
module into the shared lib so page.server.test.ts no longer imports from a
route. Both server actions now use normalizePersonType for personType
extraction instead of an inline type cast.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New src/lib/person-validation.ts exports validatePersonFields (pure function)
- 8 unit tests covering: valid PERSON, lastName missing/undefined,
firstName missing/undefined for PERSON, non-PERSON types without firstName
- Both edit and new-person server actions now call the shared helper instead
of inline if-chains, making the logic testable and non-duplicated
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Tests now import from production code instead of a local copy, giving real
regression protection if the inline logic is changed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces raw client-side fetch with SvelteKit form actions
(addAlias, removeAlias) using the server-side API client for
proper auth handling. 10 new component tests for NameHistoryEditCard.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
NameHistoryEditCard with add form (type dropdown + name fields),
delete with confirmation modal, and IDOR-safe client-side fetch
calls. Placed between Personendaten and DangerZone cards.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New edit route with WRITE_ALL guard; PersonEditForm (6 fields), sticky
PersonEditSaveBar, collapsed PersonDangerZone with PersonMergePanel.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>