feat(ui): custom confirmation dialog replacing native window.confirm
All checks were successful
Build & Publish Docker Image / build-and-push (push) Successful in 51s

Single reusable dialog with a promise-based API: confirmAction({...})
returns Promise<boolean>. Supports title, optional message body,
confirm/cancel labels, and a 'destructive' flag that paints the confirm
button red.

Accessibility: Escape cancels, Enter confirms, confirm button auto-focus,
role=dialog + aria-labelledby, backdrop click = cancel.

Rolled out to: recipe delete, domain remove, profile delete, wishlist
remove. Native confirm() is gone from the codebase.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-17 17:15:21 +02:00
parent 3b1950713f
commit 1b9928f806
7 changed files with 229 additions and 9 deletions

View File

@@ -1,5 +1,6 @@
<script lang="ts">
import { profileStore } from '$lib/client/profile.svelte';
import { confirmAction } from '$lib/client/confirm.svelte';
let newName = $state('');
let newEmoji = $state('🍳');
@@ -36,8 +37,15 @@
await profileStore.load();
}
async function remove(id: number) {
if (!confirm('Profil wirklich löschen? Bewertungen, Favoriten und Kochjournal dieses Profils werden mit gelöscht.')) return;
async function remove(id: number, name: string) {
const ok = await confirmAction({
title: `Profil „${name}" löschen?`,
message:
'Bewertungen, Favoriten und Kochjournal-Einträge dieses Profils werden mit gelöscht. Rezepte und Kommentare bleiben erhalten.',
confirmLabel: 'Löschen',
destructive: true
});
if (!ok) return;
await fetch(`/api/profiles/${id}`, { method: 'DELETE' });
if (profileStore.activeId === id) profileStore.clear();
await profileStore.load();
@@ -82,7 +90,7 @@
</div>
<div class="actions">
<button class="btn" onclick={() => rename(p.id, p.name)}>Umbenennen</button>
<button class="btn danger" onclick={() => remove(p.id)}>Löschen</button>
<button class="btn danger" onclick={() => remove(p.id, p.name)}>Löschen</button>
</div>
</li>
{/each}