feat(person): date + precision controls on person new/edit forms
New PersonLifeDateField (German date input + hidden ISO + DAY/MONTH/YEAR precision select, min-h-44px, sm: side-by-side) used for birth and death in both forms. Legacy APPROX precision seeds the select as YEAR so an untouched save never claims DAY. Server actions send date+precision pairs or omit both; obsolete year i18n keys removed, 9 form keys added. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -174,12 +174,18 @@
|
||||
"person_merge_warning": "Achtung: Diese Aktion ist nicht rückgängig zu machen.",
|
||||
"person_label_notes": "Notizen",
|
||||
"person_placeholder_notes": "Biographische Hinweise, Besonderheiten…",
|
||||
"person_label_birth_year": "Geburtsjahr",
|
||||
"person_label_death_year": "Todesjahr",
|
||||
"person_label_birth_date": "Geburtsdatum",
|
||||
"person_label_death_date": "Sterbedatum",
|
||||
"person_label_birth_date_precision": "Genauigkeit",
|
||||
"person_label_death_date_precision": "Genauigkeit",
|
||||
"person_precision_hint": "Wie genau ist dieses Datum bekannt?",
|
||||
"person_precision_day": "Genaues Datum (Tag)",
|
||||
"person_precision_month": "Monat bekannt",
|
||||
"person_precision_year": "Nur Jahreszahl",
|
||||
"person_date_placeholder_hint": "Leer lassen, wenn unbekannt",
|
||||
"person_label_generation": "Generation",
|
||||
"person_option_generation_unset": "(keine)",
|
||||
"person_hint_generation": "Generation in der Familie (G 0 = älteste Generation)",
|
||||
"person_placeholder_year": "z.B. 1923",
|
||||
"person_year_error": "Bitte eine vierstellige Jahreszahl eingeben",
|
||||
"person_years_error_order": "Geburtsjahr muss vor dem Todesjahr liegen",
|
||||
"person_docs_heading": "Gesendete Dokumente",
|
||||
|
||||
@@ -174,12 +174,18 @@
|
||||
"person_merge_warning": "Warning: This action cannot be undone.",
|
||||
"person_label_notes": "Notes",
|
||||
"person_placeholder_notes": "Biographical notes, remarks…",
|
||||
"person_label_birth_year": "Birth year",
|
||||
"person_label_death_year": "Death year",
|
||||
"person_label_birth_date": "Date of birth",
|
||||
"person_label_death_date": "Date of death",
|
||||
"person_label_birth_date_precision": "Precision",
|
||||
"person_label_death_date_precision": "Precision",
|
||||
"person_precision_hint": "How precisely is this date known?",
|
||||
"person_precision_day": "Exact date (day)",
|
||||
"person_precision_month": "Month known",
|
||||
"person_precision_year": "Year only",
|
||||
"person_date_placeholder_hint": "Leave empty if unknown",
|
||||
"person_label_generation": "Generation",
|
||||
"person_option_generation_unset": "(none)",
|
||||
"person_hint_generation": "Generation within the family (G 0 = oldest generation)",
|
||||
"person_placeholder_year": "e.g. 1923",
|
||||
"person_year_error": "Please enter a four-digit year",
|
||||
"person_years_error_order": "Birth year must be before death year",
|
||||
"person_docs_heading": "Sent documents",
|
||||
|
||||
@@ -174,12 +174,18 @@
|
||||
"person_merge_warning": "Atención: Esta acción no se puede deshacer.",
|
||||
"person_label_notes": "Notas",
|
||||
"person_placeholder_notes": "Notas biográficas, observaciones…",
|
||||
"person_label_birth_year": "Año de nacimiento",
|
||||
"person_label_death_year": "Año de fallecimiento",
|
||||
"person_label_birth_date": "Fecha de nacimiento",
|
||||
"person_label_death_date": "Fecha de defunción",
|
||||
"person_label_birth_date_precision": "Precisión",
|
||||
"person_label_death_date_precision": "Precisión",
|
||||
"person_precision_hint": "¿Con qué precisión se conoce esta fecha?",
|
||||
"person_precision_day": "Fecha exacta (día)",
|
||||
"person_precision_month": "Mes conocido",
|
||||
"person_precision_year": "Solo año",
|
||||
"person_date_placeholder_hint": "Dejar vacío si es desconocido",
|
||||
"person_label_generation": "Generación",
|
||||
"person_option_generation_unset": "(ninguna)",
|
||||
"person_hint_generation": "Generación dentro de la familia (G 0 = generación más antigua)",
|
||||
"person_placeholder_year": "p.ej. 1923",
|
||||
"person_year_error": "Introduzca un año de cuatro dígitos",
|
||||
"person_years_error_order": "El año de nacimiento debe ser anterior al año de fallecimiento",
|
||||
"person_docs_heading": "Documentos enviados",
|
||||
|
||||
96
frontend/src/lib/person/PersonLifeDateField.svelte
Normal file
96
frontend/src/lib/person/PersonLifeDateField.svelte
Normal file
@@ -0,0 +1,96 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { m } from '$lib/paraglide/messages.js';
|
||||
import { isoToGerman, handleGermanDateInput } from '$lib/shared/utils/date';
|
||||
import type { DatePrecision } from '$lib/shared/utils/documentDate';
|
||||
|
||||
// Only DAY / MONTH / YEAR are offered for life dates: RANGE and SEASON make no
|
||||
// sense for a birth or death, and APPROX stays display-only for legacy imports (#773).
|
||||
const PERSON_DATE_PRECISIONS: { value: DatePrecision; label: () => string }[] = [
|
||||
{ value: 'DAY', label: m.person_precision_day },
|
||||
{ value: 'MONTH', label: m.person_precision_month },
|
||||
{ value: 'YEAR', label: m.person_precision_year }
|
||||
];
|
||||
|
||||
let {
|
||||
name,
|
||||
legend,
|
||||
precisionLabel,
|
||||
initialIso = '',
|
||||
initialPrecision = null
|
||||
}: {
|
||||
name: string;
|
||||
legend: string;
|
||||
precisionLabel: string;
|
||||
initialIso?: string | null;
|
||||
initialPrecision?: string | null;
|
||||
} = $props();
|
||||
|
||||
let display = $state('');
|
||||
let iso = $state('');
|
||||
let precision = $state<DatePrecision>('DAY');
|
||||
|
||||
// Seed once at mount (WhoWhenSection pattern): a later load() rerun must not
|
||||
// stomp the user's in-progress edit.
|
||||
onMount(() => {
|
||||
if (initialIso) {
|
||||
iso = initialIso;
|
||||
display = isoToGerman(initialIso);
|
||||
}
|
||||
const offered = PERSON_DATE_PRECISIONS.some((p) => p.value === initialPrecision);
|
||||
if (offered) {
|
||||
precision = initialPrecision as DatePrecision;
|
||||
} else if (initialIso) {
|
||||
// Legacy APPROX/SEASON/RANGE precision is not editable here — seed YEAR so an
|
||||
// untouched save does not silently claim DAY precision for the stored date.
|
||||
precision = 'YEAR';
|
||||
}
|
||||
});
|
||||
|
||||
function handleInput(e: Event) {
|
||||
const result = handleGermanDateInput(e);
|
||||
display = result.display;
|
||||
iso = result.iso;
|
||||
}
|
||||
|
||||
const controlCls =
|
||||
'block min-h-[44px] w-full rounded border border-line px-3 py-2 font-serif text-ink focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring';
|
||||
</script>
|
||||
|
||||
<fieldset>
|
||||
<legend class="mb-1 block text-xs font-bold tracking-widest text-ink-3 uppercase">
|
||||
{legend}
|
||||
</legend>
|
||||
<div class="flex flex-col gap-2 sm:flex-row">
|
||||
<div class="flex-1">
|
||||
<input
|
||||
id={name}
|
||||
type="text"
|
||||
inputmode="numeric"
|
||||
placeholder="TT.MM.JJJJ"
|
||||
maxlength="10"
|
||||
aria-label={legend}
|
||||
value={display}
|
||||
oninput={handleInput}
|
||||
class={controlCls}
|
||||
/>
|
||||
<input type="hidden" name={name} value={iso} />
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<select
|
||||
id="{name}Precision"
|
||||
name="{name}Precision"
|
||||
aria-label="{legend}: {precisionLabel}"
|
||||
bind:value={precision}
|
||||
class="{controlCls} bg-surface"
|
||||
>
|
||||
{#each PERSON_DATE_PRECISIONS as p (p.value)}
|
||||
<option value={p.value}>{p.label()}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-1 font-sans text-xs text-ink-3">
|
||||
{m.person_precision_hint()} · {m.person_date_placeholder_hint()}
|
||||
</p>
|
||||
</fieldset>
|
||||
@@ -9,8 +9,10 @@ export type PersonFormData = {
|
||||
firstName?: string | null;
|
||||
lastName: string;
|
||||
alias?: string | null;
|
||||
birthYear?: number | null;
|
||||
deathYear?: number | null;
|
||||
birthDate?: string | null;
|
||||
birthDatePrecision?: string | null;
|
||||
deathDate?: string | null;
|
||||
deathDatePrecision?: string | null;
|
||||
generation?: number | null;
|
||||
notes?: string | null;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { error, fail, redirect } from '@sveltejs/kit';
|
||||
import { createApiClient, extractErrorCode } from '$lib/shared/api.server';
|
||||
import { getErrorMessage } from '$lib/shared/errors';
|
||||
import type { DatePrecision } from '$lib/shared/utils/documentDate';
|
||||
import {
|
||||
normalizePersonType,
|
||||
validatePersonFields,
|
||||
@@ -47,10 +48,17 @@ export const actions = {
|
||||
const lastName = formData.get('lastName')?.toString().trim();
|
||||
const alias = formData.get('alias')?.toString().trim() || undefined;
|
||||
const notes = formData.get('notes')?.toString().trim() || undefined;
|
||||
const birthYearStr = formData.get('birthYear')?.toString().trim();
|
||||
const deathYearStr = formData.get('deathYear')?.toString().trim();
|
||||
const birthYear = birthYearStr ? parseInt(birthYearStr, 10) : undefined;
|
||||
const deathYear = deathYearStr ? parseInt(deathYearStr, 10) : undefined;
|
||||
// Empty date input → omit date AND precision: the backend normalises the
|
||||
// absent pair to null/UNKNOWN, and a lone precision would fail the
|
||||
// coherence check (INVALID_DATE_PRECISION).
|
||||
const birthDate = formData.get('birthDate')?.toString().trim() || undefined;
|
||||
const birthDatePrecision = birthDate
|
||||
? (formData.get('birthDatePrecision')?.toString() as DatePrecision)
|
||||
: undefined;
|
||||
const deathDate = formData.get('deathDate')?.toString().trim() || undefined;
|
||||
const deathDatePrecision = deathDate
|
||||
? (formData.get('deathDatePrecision')?.toString() as DatePrecision)
|
||||
: undefined;
|
||||
// Must NOT use the conditional-spread idiom for generation: G 0 is a
|
||||
// valid family-tree-root value. The key always travels in the body so
|
||||
// an explicit clear (empty option) reaches the backend as null.
|
||||
@@ -73,8 +81,8 @@ export const actions = {
|
||||
lastName,
|
||||
...(alias ? { alias } : {}),
|
||||
...(notes ? { notes } : {}),
|
||||
...(birthYear ? { birthYear } : {}),
|
||||
...(deathYear ? { deathYear } : {}),
|
||||
...(birthDate ? { birthDate, birthDatePrecision } : {}),
|
||||
...(deathDate ? { deathDate, deathDatePrecision } : {}),
|
||||
generation
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { untrack } from 'svelte';
|
||||
import { m } from '$lib/paraglide/messages.js';
|
||||
import PersonLifeDateField from '$lib/person/PersonLifeDateField.svelte';
|
||||
import PersonTypeSelector from '$lib/person/PersonTypeSelector.svelte';
|
||||
import {
|
||||
PERSON_TYPES as TYPES,
|
||||
@@ -88,32 +89,20 @@ const inputCls =
|
||||
<label for="alias" class={labelCls}>{m.form_label_alias()}</label>
|
||||
<input id="alias" name="alias" type="text" value={person.alias ?? ''} class={inputCls} />
|
||||
</div>
|
||||
<div>
|
||||
<label for="birthYear" class={labelCls}>{m.person_label_birth_year()}</label>
|
||||
<input
|
||||
id="birthYear"
|
||||
name="birthYear"
|
||||
type="number"
|
||||
min="1"
|
||||
max="2100"
|
||||
placeholder={m.person_placeholder_year()}
|
||||
value={person.birthYear ?? ''}
|
||||
class={inputCls}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="deathYear" class={labelCls}>{m.person_label_death_year()}</label>
|
||||
<input
|
||||
id="deathYear"
|
||||
name="deathYear"
|
||||
type="number"
|
||||
min="1"
|
||||
max="2100"
|
||||
placeholder={m.person_placeholder_year()}
|
||||
value={person.deathYear ?? ''}
|
||||
class={inputCls}
|
||||
/>
|
||||
</div>
|
||||
<PersonLifeDateField
|
||||
name="birthDate"
|
||||
legend={m.person_label_birth_date()}
|
||||
precisionLabel={m.person_label_birth_date_precision()}
|
||||
initialIso={person.birthDate ?? ''}
|
||||
initialPrecision={person.birthDatePrecision ?? null}
|
||||
/>
|
||||
<PersonLifeDateField
|
||||
name="deathDate"
|
||||
legend={m.person_label_death_date()}
|
||||
precisionLabel={m.person_label_death_date_precision()}
|
||||
initialIso={person.deathDate ?? ''}
|
||||
initialPrecision={person.deathDatePrecision ?? null}
|
||||
/>
|
||||
<div class="md:col-span-2">
|
||||
<label for="generation" class={labelCls}>{m.person_label_generation()}</label>
|
||||
<select
|
||||
|
||||
@@ -12,8 +12,10 @@ const personPersonal = {
|
||||
firstName: 'Anna',
|
||||
lastName: 'Schmidt',
|
||||
alias: 'Anni',
|
||||
birthYear: 1899 as number | null,
|
||||
deathYear: 1972 as number | null,
|
||||
birthDate: '1899-03-14' as string | null,
|
||||
birthDatePrecision: 'DAY' as string | null,
|
||||
deathDate: '1972-01-01' as string | null,
|
||||
deathDatePrecision: 'YEAR' as string | null,
|
||||
notes: 'Wohnte in Berlin.'
|
||||
};
|
||||
|
||||
@@ -24,8 +26,10 @@ const personInstitution = {
|
||||
firstName: null,
|
||||
lastName: 'Acme GmbH',
|
||||
alias: null,
|
||||
birthYear: null,
|
||||
deathYear: null,
|
||||
birthDate: null,
|
||||
birthDatePrecision: null,
|
||||
deathDate: null,
|
||||
deathDatePrecision: null,
|
||||
notes: null
|
||||
};
|
||||
|
||||
@@ -42,14 +46,14 @@ describe('PersonEditForm', () => {
|
||||
await expect.element(page.getByLabelText(/titel/i)).toBeVisible();
|
||||
});
|
||||
|
||||
it('hides the firstName / title / alias / year fields for INSTITUTION', async () => {
|
||||
it('hides the firstName / title / alias / life-date fields for INSTITUTION', async () => {
|
||||
render(PersonEditForm, { props: { person: personInstitution } });
|
||||
|
||||
await expect.element(page.getByLabelText(/vorname/i)).not.toBeInTheDocument();
|
||||
await expect.element(page.getByLabelText(/^titel$/i)).not.toBeInTheDocument();
|
||||
await expect.element(page.getByLabelText(/rufname/i)).not.toBeInTheDocument();
|
||||
await expect.element(page.getByLabelText(/geburtsjahr/i)).not.toBeInTheDocument();
|
||||
await expect.element(page.getByLabelText(/todesjahr/i)).not.toBeInTheDocument();
|
||||
await expect.element(page.getByLabelText(/^geburtsdatum$/i)).not.toBeInTheDocument();
|
||||
await expect.element(page.getByLabelText(/^sterbedatum$/i)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('uses the "Nachname" label for PERSON', async () => {
|
||||
@@ -77,13 +81,63 @@ describe('PersonEditForm', () => {
|
||||
expect(title.value).toBe('Frau Dr.');
|
||||
});
|
||||
|
||||
it('renders birthYear and deathYear inputs with prior values', async () => {
|
||||
it('renders an existing DAY-precision birth date as dd.mm.yyyy in the date input', async () => {
|
||||
render(PersonEditForm, { props: { person: personPersonal } });
|
||||
|
||||
const birthYear = (await page.getByLabelText(/geburtsjahr/i).element()) as HTMLInputElement;
|
||||
const deathYear = (await page.getByLabelText(/todesjahr/i).element()) as HTMLInputElement;
|
||||
expect(birthYear.value).toBe('1899');
|
||||
expect(deathYear.value).toBe('1972');
|
||||
const birthInput = (await page.getByLabelText(/^geburtsdatum$/i).element()) as HTMLInputElement;
|
||||
expect(birthInput.value).toBe('14.03.1899');
|
||||
});
|
||||
|
||||
it('submits the ISO date via the hidden birthDate input', async () => {
|
||||
const { container } = render(PersonEditForm, { props: { person: personPersonal } });
|
||||
|
||||
const hidden = container.querySelector('input[type="hidden"][name="birthDate"]');
|
||||
expect((hidden as HTMLInputElement).value).toBe('1899-03-14');
|
||||
});
|
||||
|
||||
it('offers only DAY / MONTH / YEAR precisions for life dates', async () => {
|
||||
const { container } = render(PersonEditForm, { props: { person: personPersonal } });
|
||||
|
||||
const select = container.querySelector(
|
||||
'select[name="birthDatePrecision"]'
|
||||
) as HTMLSelectElement;
|
||||
const values = Array.from(select.options).map((o) => o.value);
|
||||
expect(values).toEqual(['DAY', 'MONTH', 'YEAR']);
|
||||
});
|
||||
|
||||
it('hydrates the precision selects from the person prop', async () => {
|
||||
const { container } = render(PersonEditForm, { props: { person: personPersonal } });
|
||||
|
||||
const birth = container.querySelector('select[name="birthDatePrecision"]') as HTMLSelectElement;
|
||||
const death = container.querySelector('select[name="deathDatePrecision"]') as HTMLSelectElement;
|
||||
expect(birth.value).toBe('DAY');
|
||||
expect(death.value).toBe('YEAR');
|
||||
});
|
||||
|
||||
it('seeds a non-form precision (APPROX legacy import) as YEAR instead of DAY', async () => {
|
||||
const { container } = render(PersonEditForm, {
|
||||
props: {
|
||||
person: { ...personPersonal, birthDate: '1899-01-01', birthDatePrecision: 'APPROX' }
|
||||
}
|
||||
});
|
||||
|
||||
const birth = container.querySelector('select[name="birthDatePrecision"]') as HTMLSelectElement;
|
||||
expect(birth.value).toBe('YEAR');
|
||||
});
|
||||
|
||||
it('stacks the date input and precision select without overflow at 320px', async () => {
|
||||
await page.viewport(320, 640);
|
||||
const { container } = render(PersonEditForm, { props: { person: personPersonal } });
|
||||
|
||||
const input = container.querySelector('#birthDate') as HTMLElement;
|
||||
const select = container.querySelector('select[name="birthDatePrecision"]') as HTMLElement;
|
||||
expect(input.getBoundingClientRect().right).toBeLessThanOrEqual(320);
|
||||
expect(select.getBoundingClientRect().right).toBeLessThanOrEqual(320);
|
||||
// Stacked, not side by side: the select starts below the input.
|
||||
expect(select.getBoundingClientRect().top).toBeGreaterThanOrEqual(
|
||||
input.getBoundingClientRect().bottom
|
||||
);
|
||||
await page.viewport(1280, 720);
|
||||
});
|
||||
|
||||
it('renders the notes textarea pre-filled with prior content', async () => {
|
||||
@@ -103,15 +157,23 @@ describe('PersonEditForm', () => {
|
||||
|
||||
it('renders empty inputs when nullable fields are null', async () => {
|
||||
render(PersonEditForm, {
|
||||
props: { person: { ...personPersonal, title: null, alias: null, birthYear: null } }
|
||||
props: {
|
||||
person: {
|
||||
...personPersonal,
|
||||
title: null,
|
||||
alias: null,
|
||||
birthDate: null,
|
||||
birthDatePrecision: null
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const title = (await page.getByLabelText(/^titel/i).element()) as HTMLInputElement;
|
||||
const alias = (await page.getByLabelText(/rufname/i).element()) as HTMLInputElement;
|
||||
const birthYear = (await page.getByLabelText(/geburtsjahr/i).element()) as HTMLInputElement;
|
||||
const birthInput = (await page.getByLabelText(/^geburtsdatum$/i).element()) as HTMLInputElement;
|
||||
expect(title.value).toBe('');
|
||||
expect(alias.value).toBe('');
|
||||
expect(birthYear.value).toBe('');
|
||||
expect(birthInput.value).toBe('');
|
||||
});
|
||||
|
||||
// ─── generation dropdown (#689) ─────────────────────────────────────────────
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { error, fail, redirect } from '@sveltejs/kit';
|
||||
import { createApiClient, extractErrorCode } from '$lib/shared/api.server';
|
||||
import { getErrorMessage } from '$lib/shared/errors';
|
||||
import type { DatePrecision } from '$lib/shared/utils/documentDate';
|
||||
import {
|
||||
normalizePersonType,
|
||||
validatePersonFields,
|
||||
@@ -23,8 +24,17 @@ export const actions = {
|
||||
const firstName = formData.get('firstName')?.toString().trim();
|
||||
const lastName = formData.get('lastName')?.toString().trim();
|
||||
const alias = formData.get('alias')?.toString().trim() || undefined;
|
||||
const birthYearStr = formData.get('birthYear')?.toString().trim();
|
||||
const deathYearStr = formData.get('deathYear')?.toString().trim();
|
||||
// Empty date input → omit date AND precision: the backend normalises the
|
||||
// absent pair to null/UNKNOWN, and a lone precision would fail the
|
||||
// coherence check (INVALID_DATE_PRECISION).
|
||||
const birthDate = formData.get('birthDate')?.toString().trim() || undefined;
|
||||
const birthDatePrecision = birthDate
|
||||
? (formData.get('birthDatePrecision')?.toString() as DatePrecision)
|
||||
: undefined;
|
||||
const deathDate = formData.get('deathDate')?.toString().trim() || undefined;
|
||||
const deathDatePrecision = deathDate
|
||||
? (formData.get('deathDatePrecision')?.toString() as DatePrecision)
|
||||
: undefined;
|
||||
const notes = formData.get('notes')?.toString().trim() || undefined;
|
||||
// Must NOT use the conditional-spread idiom for generation: G 0 is a
|
||||
// valid family-tree-root value. Always travels in the body so an
|
||||
@@ -45,9 +55,6 @@ export const actions = {
|
||||
});
|
||||
}
|
||||
|
||||
const birthYear = birthYearStr ? parseInt(birthYearStr, 10) : undefined;
|
||||
const deathYear = deathYearStr ? parseInt(deathYearStr, 10) : undefined;
|
||||
|
||||
const api = createApiClient(fetch);
|
||||
const result = await api.POST('/api/persons', {
|
||||
body: {
|
||||
@@ -56,8 +63,8 @@ export const actions = {
|
||||
...(firstName ? { firstName } : {}),
|
||||
lastName: lastName!,
|
||||
...(alias ? { alias } : {}),
|
||||
...(birthYear ? { birthYear } : {}),
|
||||
...(deathYear ? { deathYear } : {}),
|
||||
...(birthDate ? { birthDate, birthDatePrecision } : {}),
|
||||
...(deathDate ? { deathDate, deathDatePrecision } : {}),
|
||||
...(notes ? { notes } : {}),
|
||||
generation
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { untrack } from 'svelte';
|
||||
import { m } from '$lib/paraglide/messages.js';
|
||||
import BackButton from '$lib/shared/primitives/BackButton.svelte';
|
||||
import PersonLifeDateField from '$lib/person/PersonLifeDateField.svelte';
|
||||
import PersonTypeSelector from '$lib/person/PersonTypeSelector.svelte';
|
||||
import { PERSON_TYPES as TYPES, type PersonType } from '$lib/person/person-validation';
|
||||
|
||||
@@ -102,30 +103,16 @@ const labelCls = 'mb-1 block text-sm font-medium text-ink-2';
|
||||
class={inputCls}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="birthYear" class={labelCls}>{m.person_label_birth_year()}</label>
|
||||
<input
|
||||
id="birthYear"
|
||||
name="birthYear"
|
||||
type="number"
|
||||
min="1"
|
||||
max="2100"
|
||||
placeholder={m.person_placeholder_year()}
|
||||
class={inputCls}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="deathYear" class={labelCls}>{m.person_label_death_year()}</label>
|
||||
<input
|
||||
id="deathYear"
|
||||
name="deathYear"
|
||||
type="number"
|
||||
min="1"
|
||||
max="2100"
|
||||
placeholder={m.person_placeholder_year()}
|
||||
class={inputCls}
|
||||
/>
|
||||
</div>
|
||||
<PersonLifeDateField
|
||||
name="birthDate"
|
||||
legend={m.person_label_birth_date()}
|
||||
precisionLabel={m.person_label_birth_date_precision()}
|
||||
/>
|
||||
<PersonLifeDateField
|
||||
name="deathDate"
|
||||
legend={m.person_label_death_date()}
|
||||
precisionLabel={m.person_label_death_date_precision()}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<div class="md:col-span-2">
|
||||
|
||||
Reference in New Issue
Block a user