feat(person): generation dropdown on Person edit/new forms (#689)
PersonEditForm.svelte gains a G 0…G 6 select inside the {#if isPerson}
block. min-h-[44px] meets WCAG 2.5.8 / dual-audience touch target.
generationStr is initialised via $state(untrack(...)) so prop reruns
never reset an in-progress edit (same pattern as selectedType).
Both /persons/[id]/edit and /persons/new form actions read the field
without the conditional-spread idiom — generation always lands in the
PUT/POST body. G 0 is a valid family-tree-root value the spread would
silently drop, and an empty option sends null so a human can clear the
field back to "unset".
i18n adds person_label_generation / person_option_generation_unset /
person_hint_generation in de/en/es. Drops the dead stammbaum_generations
key (zero callsites after the filter-chip removal in the spec).
Tests: dropdown render + hydration in the component, generation=0/3/null
arriving in the API body in the server actions.
Refs #689
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,12 @@ let selectedType = $state<PersonType>(
|
||||
)
|
||||
);
|
||||
|
||||
// Match the selectedType initialiser pattern: untrack so a subsequent prop
|
||||
// update (e.g. load() rerun) does not reset the user's in-progress edit.
|
||||
let generationStr = $state(
|
||||
untrack(() => (person.generation == null ? '' : String(person.generation)))
|
||||
);
|
||||
|
||||
const isPerson = $derived(selectedType === 'PERSON');
|
||||
const lastNameLabel = $derived(
|
||||
selectedType === 'INSTITUTION' || selectedType === 'GROUP'
|
||||
@@ -108,6 +114,28 @@ const inputCls =
|
||||
class={inputCls}
|
||||
/>
|
||||
</div>
|
||||
<div class="md:col-span-2">
|
||||
<label for="generation" class={labelCls}>{m.person_label_generation()}</label>
|
||||
<select
|
||||
id="generation"
|
||||
name="generation"
|
||||
bind:value={generationStr}
|
||||
class="block min-h-[44px] w-full rounded border border-line bg-surface px-3 py-2 font-serif text-ink focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring"
|
||||
aria-describedby="generation-hint"
|
||||
>
|
||||
<option value="">{m.person_option_generation_unset()}</option>
|
||||
<option value="0">G 0</option>
|
||||
<option value="1">G 1</option>
|
||||
<option value="2">G 2</option>
|
||||
<option value="3">G 3</option>
|
||||
<option value="4">G 4</option>
|
||||
<option value="5">G 5</option>
|
||||
<option value="6">G 6</option>
|
||||
</select>
|
||||
<p id="generation-hint" class="mt-1 font-sans text-xs text-ink-3">
|
||||
{m.person_hint_generation()}
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="md:col-span-2">
|
||||
|
||||
Reference in New Issue
Block a user