refactor(geschichte): extract delete handler to [id]/+page.svelte, pass via ondelete prop

Moves the confirm-then-delete flow out of StoryReader and JourneyReader into
the single [id]/+page.svelte owner. Both reader components gain an optional
ondelete prop — the delete button calls ondelete?.() so the handler is opt-in
and never duplicated. Tests verify the prop is called on click.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-06-08 23:24:33 +02:00
parent 91d9dae6fd
commit 4c24bbb002
5 changed files with 67 additions and 55 deletions

View File

@@ -1,8 +1,5 @@
<script lang="ts">
import { m } from '$lib/paraglide/messages.js';
import { goto } from '$app/navigation';
import { getConfirmService } from '$lib/shared/services/confirm.svelte';
import { csrfFetch } from '$lib/shared/cookies';
import JourneyItemCard from './JourneyItemCard.svelte';
import JourneyInterlude from './JourneyInterlude.svelte';
import type { components } from '$lib/generated/api';
@@ -13,9 +10,10 @@ type JourneyItemView = components['schemas']['JourneyItemView'];
interface Props {
geschichte: GeschichteView;
canBlogWrite: boolean;
ondelete?: () => Promise<void>;
}
let { geschichte: g, canBlogWrite }: Props = $props();
let { geschichte: g, canBlogWrite, ondelete }: Props = $props();
// Render intro only when body is a non-empty, non-whitespace string.
const introText = $derived(g.body?.trim() ? g.body : null);
@@ -27,23 +25,6 @@ const validItems = $derived(
item.document != null || (item.note != null && item.note.trim().length > 0)
)
);
const confirm = getConfirmService();
async function handleDelete() {
const ok = await confirm.confirm({
title: m.geschichte_delete_confirm_title(),
body: m.geschichte_delete_confirm_body(),
confirmLabel: m.btn_delete(),
cancelLabel: m.btn_cancel(),
destructive: true
});
if (!ok) return;
const res = await csrfFetch(`/api/geschichten/${g.id}`, { method: 'DELETE' });
if (res.ok) {
goto('/geschichten');
}
}
</script>
{#if introText}
@@ -80,7 +61,7 @@ async function handleDelete() {
</a>
<button
type="button"
onclick={handleDelete}
onclick={() => ondelete?.()}
class="inline-flex h-11 items-center rounded font-sans text-sm font-medium text-danger hover:underline focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring"
>
{m.btn_delete()}