Files
familienarchiv/frontend/src/routes/persons/[id]/PersonMergePanel.svelte
Marcel f11d8a38ed feat(frontend): replace all name concatenation with displayName
- Add displayName default method to PersonSummaryDTO
- Update native SQL queries to include title, person_type columns
- Add getInitials() utility to personFormat.ts
- Update abbreviateName/abbreviateCompact for nullable firstName
- Replace firstName+lastName concatenation with displayName in all
  person-displaying components and server load files
- Regenerate API types with displayName on Person and PersonSummaryDTO

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 12:22:30 +02:00

84 lines
2.4 KiB
Svelte

<script lang="ts">
import { enhance } from '$app/forms';
import PersonTypeahead from '$lib/components/PersonTypeahead.svelte';
import { m } from '$lib/paraglide/messages.js';
let {
person,
form
}: {
person: { displayName: string };
form?: { mergeError?: string } | null;
} = $props();
let mergeTargetId = $state('');
let showMergeConfirm = $state(false);
</script>
<div class="mb-10 overflow-hidden rounded-sm border border-line bg-surface shadow-sm">
<div class="p-6 md:p-8">
<h2 class="mb-1 font-serif text-lg text-ink">{m.person_merge_heading()}</h2>
<p class="mb-5 font-sans text-sm text-ink-2">
{m.person_merge_description()}
</p>
{#if form?.mergeError}
<p class="mb-4 rounded border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-600">
{form.mergeError}
</p>
{/if}
<form method="POST" action="?/merge" use:enhance>
<input type="hidden" name="targetPersonId" bind:value={mergeTargetId} />
<div class="flex flex-col items-end gap-3 sm:flex-row">
<div class="flex-1">
<PersonTypeahead
name="_targetPersonDisplay"
label={m.person_merge_target_label()}
value={mergeTargetId}
onchange={(value) => {
mergeTargetId = value;
showMergeConfirm = false;
}}
/>
</div>
{#if !showMergeConfirm}
<button
type="button"
disabled={!mergeTargetId}
onclick={() => (showMergeConfirm = true)}
class="rounded border border-red-300 px-4 py-2 text-sm font-bold tracking-widest text-red-600 uppercase transition-colors hover:bg-red-50 disabled:cursor-not-allowed disabled:opacity-40"
>
{m.person_btn_merge()}
</button>
{:else}
<div class="flex gap-2">
<button
type="submit"
class="rounded bg-red-600 px-4 py-2 text-sm font-bold tracking-widest text-white uppercase transition-colors hover:bg-red-700"
>
{m.person_btn_merge_confirm()}
</button>
<button
type="button"
onclick={() => (showMergeConfirm = false)}
class="rounded border border-line px-4 py-2 text-sm font-bold tracking-widest text-ink-2 uppercase transition-colors hover:bg-muted"
>
{m.btn_cancel()}
</button>
</div>
{/if}
</div>
{#if showMergeConfirm}
<p class="mt-3 rounded border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700">
{m.person_merge_warning()} <strong>{person.displayName}</strong>
{m.person_merge_will_be_deleted()}
</p>
{/if}
</form>
</div>
</div>