import React from 'react'; import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; import { ArrowLeft, Camera, Heart, Loader2, RefreshCw, Sparkles, QrCode } from 'lucide-react'; import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { AdminLayout } from '../components/AdminLayout'; import { EventStats as TenantEventStats, getEvent, getEventStats, TenantEvent, toggleEvent, } from '../api'; import { isAuthError } from '../auth/tokens'; import { ADMIN_EVENTS_PATH, ADMIN_EVENT_EDIT_PATH, ADMIN_EVENT_PHOTOS_PATH, ADMIN_EVENT_MEMBERS_PATH, ADMIN_EVENT_TASKS_PATH, ADMIN_EVENT_TOOLKIT_PATH, ADMIN_EVENT_INVITES_PATH, } from '../constants'; interface State { event: TenantEvent | null; stats: TenantEventStats | null; error: string | null; loading: boolean; busy: boolean; } export default function EventDetailPage() { const params = useParams<{ slug?: string }>(); const [searchParams] = useSearchParams(); const slug = params.slug ?? searchParams.get('slug') ?? null; const navigate = useNavigate(); const [state, setState] = React.useState({ event: null, stats: null, error: null, loading: true, busy: false, }); const load = React.useCallback(async () => { if (!slug) { setState((prev) => ({ ...prev, loading: false, error: 'Kein Event-Slug angegeben.' })); return; } setState((prev) => ({ ...prev, loading: true, error: null })); try { const [eventData, statsData] = await Promise.all([ getEvent(slug), getEventStats(slug), ]); setState((prev) => ({ ...prev, event: eventData, stats: statsData, loading: false, })); } catch (err) { if (isAuthError(err)) return; setState((prev) => ({ ...prev, error: 'Event konnte nicht geladen werden.', loading: false })); } }, [slug]); React.useEffect(() => { load(); }, [load]); async function handleToggle() { if (!slug) return; setState((prev) => ({ ...prev, busy: true, error: null })); try { const updated = await toggleEvent(slug); setState((prev) => ({ ...prev, event: updated, stats: prev.stats ? { ...prev.stats, status: updated.status, is_active: Boolean(updated.is_active) } : prev.stats, busy: false, })); } catch (err) { if (!isAuthError(err)) { setState((prev) => ({ ...prev, error: 'Status konnte nicht angepasst werden.', busy: false })); } else { setState((prev) => ({ ...prev, busy: false })); } } } const { event, stats, error, loading, busy } = state; const eventDisplayName = event ? renderName(event.name) : ''; const activeInvitesCount = event?.active_invites_count ?? 0; const totalInvitesCount = event?.total_invites_count ?? activeInvitesCount; const actions = ( <> {event && ( <> )} ); if (!slug) { return ( Ohne gültigen Slug können wir keine Daten laden. Kehre zur Event-Liste zurück und wähle dort ein Event aus. ); } return ( {error && ( Aktion fehlgeschlagen {error} )} {loading ? ( ) : event ? (
Eventdaten Grundlegende Informationen für Gäste und Moderation.
Einladungen & QR Steuere QR-Einladungen, Layouts und Branding gesammelt auf einer eigenen Seite.

Aktive QR-Einladungen: {activeInvitesCount} · Gesamt erstellt: {totalInvitesCount}

Bereite deine Drucklayouts vor, personalisiere Texte und Logos und drucke sie direkt aus.

Du kannst bestehende Layouts duplizieren, Farben anpassen und neue PDFs generieren.

Performance Kennzahlen zu Uploads, Highlights und Interaktion.
) : ( Event nicht gefunden Bitte prüfe den Slug und versuche es erneut. )}
); } function DetailSkeleton() { return (
{Array.from({ length: 3 }).map((_, index) => (
))}
); } function InfoRow({ label, value }: { label: string; value: string }) { return (
{label} {value}
); } function StatChip({ label, value }: { label: string; value: string | number }) { return (
{label}
{value}
); } function formatDate(iso: string | null): string { if (!iso) return 'Noch kein Datum'; const date = new Date(iso); if (Number.isNaN(date.getTime())) { return 'Unbekanntes Datum'; } return date.toLocaleDateString('de-DE', { day: '2-digit', month: 'long', year: 'numeric' }); } function renderName(name: TenantEvent['name']): string { if (typeof name === 'string') { return name; } if (name && typeof name === 'object') { return name.de ?? name.en ?? Object.values(name)[0] ?? 'Unbenanntes Event'; } return 'Unbenanntes Event'; }