feat(events): wire workbench detail overlay via ViewProps

Events ListView and DetailView now use the standard ViewProps interface
(navigate/goBack/params) instead of the custom onOpenEvent callback.
Adds paramKey to the events app registration so the workbench overlay
knows which param carries the event ID. Clicking an event card now
opens the detail overlay with prev/next sibling navigation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-04-10 17:36:40 +02:00
parent f1a7f35d66
commit 05f4da5db3
5 changed files with 37 additions and 33 deletions

View file

@ -715,6 +715,7 @@ registerApp({
list: { load: () => import('$lib/modules/events/ListView.svelte') },
detail: { load: () => import('$lib/modules/events/views/DetailView.svelte') },
},
paramKey: 'eventId',
});
registerApp({

View file

@ -5,12 +5,9 @@
import { drainTombstones } from './tombstones';
import EventCard from './components/EventCard.svelte';
import type { SocialEvent } from './types';
import type { ViewProps } from '$lib/app-registry';
interface Props {
onOpenEvent?: (id: string) => void;
}
let { onOpenEvent }: Props = $props();
let { navigate, goBack, params }: ViewProps = $props();
const upcoming = useUpcomingEvents();
const past = usePastEvents();
@ -44,12 +41,17 @@
newDate = '';
newLocation = '';
showCreate = false;
onOpenEvent?.(result.id);
open({ id: result.id } as SocialEvent);
}
}
function open(event: SocialEvent) {
onOpenEvent?.(event.id);
const ids = [...(upcoming.value ?? []), ...(past.value ?? [])].map((e) => e.id);
navigate('detail', {
eventId: event.id,
_siblingIds: ids,
_siblingKey: 'eventId',
});
}
</script>
@ -59,12 +61,9 @@
<div class="events-page">
<header class="events-header">
<div>
<h1 class="page-title">Events</h1>
<p class="page-subtitle">
{(upcoming.value ?? []).length} bevorstehend · {(past.value ?? []).length} vergangen
</p>
</div>
<p class="page-subtitle">
{(upcoming.value ?? []).length} bevorstehend · {(past.value ?? []).length} vergangen
</p>
<button class="new-btn" onclick={() => (showCreate = !showCreate)}>
{showCreate ? 'Abbrechen' : '+ Neues Event'}
</button>
@ -127,12 +126,6 @@
align-items: flex-start;
justify-content: space-between;
}
.page-title {
margin: 0;
font-size: 1.5rem;
font-weight: 700;
color: hsl(var(--color-foreground));
}
.page-subtitle {
margin: 0.25rem 0 0;
font-size: 0.875rem;

View file

@ -5,13 +5,11 @@
import RsvpSummaryView from '../components/RsvpSummary.svelte';
import PublicRsvpList from '../components/PublicRsvpList.svelte';
import BringListEditor from '../components/BringListEditor.svelte';
import type { ViewProps } from '$lib/app-registry';
interface Props {
eventId: string;
onBack?: () => void;
}
let { navigate, goBack, params }: ViewProps = $props();
let { eventId, onBack }: Props = $props();
let eventId = $derived((params.eventId as string) ?? '');
const eventQuery = useEvent(() => eventId);
const guests = useEventGuests(() => eventId);
@ -84,7 +82,7 @@
if (!event) return;
if (!confirm(`Event "${event.title}" wirklich löschen?`)) return;
await eventsStore.deleteEvent(event.id);
onBack?.();
goBack();
}
function copyShareLink() {
@ -99,9 +97,7 @@
{:else}
<div class="detail">
<header class="detail-header">
{#if onBack}
<button class="back-btn" onclick={onBack}> Zurück</button>
{/if}
<button class="back-btn" onclick={goBack}> Zurück</button>
<div class="header-actions">
<button class="action-btn" onclick={startEdit}>Bearbeiten</button>
<button class="action-btn danger" onclick={handleDelete}>Löschen</button>

View file

@ -2,9 +2,15 @@
import { goto } from '$app/navigation';
import ListView from '$lib/modules/events/ListView.svelte';
function handleOpen(id: string) {
goto(`/events/${id}`);
function navigate(viewName: string, params: Record<string, unknown> = {}) {
if (viewName === 'detail' && params.eventId) {
goto(`/events/${params.eventId}`);
}
}
function goBack() {
goto('/events');
}
</script>
<ListView onOpenEvent={handleOpen} />
<ListView {navigate} {goBack} params={{}} />

View file

@ -5,9 +5,17 @@
const eventId = $derived($page.params.id ?? '');
function handleBack() {
function navigate(viewName: string, navParams: Record<string, unknown> = {}) {
if (viewName === 'detail' && navParams.eventId) {
goto(`/events/${navParams.eventId}`);
} else if (viewName === 'list') {
goto('/events');
}
}
function goBack() {
goto('/events');
}
</script>
<DetailView {eventId} onBack={handleBack} />
<DetailView {navigate} {goBack} params={{ eventId }} />