import React from 'react'; import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; import { ArrowLeft, Loader2, Save, Sparkles, Package as PackageIcon } from 'lucide-react'; import { useQuery } from '@tanstack/react-query'; 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 { Checkbox } from '@/components/ui/checkbox'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'; import { AdminLayout } from '../components/AdminLayout'; import { createEvent, getEvent, updateEvent, getPackages } from '../api'; import { isAuthError } from '../auth/tokens'; import { ADMIN_EVENT_VIEW_PATH, ADMIN_EVENTS_PATH } from '../constants'; interface EventFormState { name: string; slug: string; date: string; package_id: number; isPublished: boolean; } export default function EventFormPage() { const params = useParams<{ slug?: string }>(); const [searchParams] = useSearchParams(); const slugParam = params.slug ?? searchParams.get('slug') ?? undefined; const isEdit = Boolean(slugParam); const navigate = useNavigate(); const [form, setForm] = React.useState({ name: '', slug: '', date: '', package_id: 1, // Default Free package isPublished: false, }); const [autoSlug, setAutoSlug] = React.useState(true); const [originalSlug, setOriginalSlug] = React.useState(null); const [loading, setLoading] = React.useState(isEdit); const [saving, setSaving] = React.useState(false); const [error, setError] = React.useState(null); const { data: packages, isLoading: packagesLoading } = useQuery({ queryKey: ['packages', 'endcustomer'], queryFn: () => getPackages('endcustomer'), }); React.useEffect(() => { let cancelled = false; if (!isEdit || !slugParam) { setLoading(false); return () => { cancelled = true; }; } (async () => { try { const event = await getEvent(slugParam); if (cancelled) return; const name = normalizeName(event.name); setForm((prev) => ({ ...prev, name, slug: event.slug, date: event.event_date ? event.event_date.slice(0, 10) : '', isPublished: event.status === 'published', })); setOriginalSlug(event.slug); setAutoSlug(false); } catch (err) { if (!isAuthError(err)) { setError('Event konnte nicht geladen werden.'); } } finally { if (!cancelled) { setLoading(false); } } })(); return () => { cancelled = true; }; }, [isEdit, slugParam]); function handleNameChange(value: string) { setForm((prev) => ({ ...prev, name: value })); if (autoSlug) { setForm((prev) => ({ ...prev, slug: slugify(value) })); } } function handleSlugChange(value: string) { setAutoSlug(false); setForm((prev) => ({ ...prev, slug: slugify(value) })); } async function handleSubmit(event: React.FormEvent) { event.preventDefault(); const trimmedName = form.name.trim(); const trimmedSlug = form.slug.trim(); if (!trimmedName) { setError('Bitte gib einen Eventnamen ein.'); return; } if (!trimmedSlug) { setError('Bitte waehle einen Slug fuer die Event-URL.'); return; } setSaving(true); setError(null); const status: 'draft' | 'published' | 'archived' = form.isPublished ? 'published' : 'draft'; const payload = { name: trimmedName, slug: trimmedSlug, package_id: form.package_id, date: form.date || undefined, status, }; try { if (isEdit) { const targetSlug = originalSlug ?? slugParam!; const updated = await updateEvent(targetSlug, payload); setOriginalSlug(updated.slug); navigate(ADMIN_EVENT_VIEW_PATH(updated.slug)); } else { const { event: created } = await createEvent(payload); navigate(ADMIN_EVENT_VIEW_PATH(created.slug)); } } catch (err) { if (!isAuthError(err)) { setError('Speichern fehlgeschlagen. Bitte pruefe deine Eingaben.'); } } finally { setSaving(false); } } const actions = ( ); return ( {error && ( Hinweis {error} )} Eventdetails Name, URL und Datum bestimmen das Auftreten deines Events im Gaesteportal. {loading ? ( ) : (
handleNameChange(e.target.value)} autoFocus />
handleSlugChange(e.target.value)} />

Das Event ist spaeter unter /e/{form.slug || 'dein-event'} erreichbar.

setForm((prev) => ({ ...prev, date: e.target.value }))} />
Package auswaehlen Waehlen Sie das Package fuer Ihr Event. Hoehere Packages bieten mehr Limits und Features.
{packages?.map((pkg) => (

{pkg.name}

{pkg.price} EUR

  • Max Fotos: {pkg.max_photos}
  • Max Gaeste: {pkg.max_guests}
  • Galerie: {pkg.gallery_days} Tage
  • Features: {Object.keys(pkg.features).filter(k => pkg.features[k]).join(', ')}
))}
setForm((prev) => ({ ...prev, isPublished: Boolean(checked) }))} />

Aktiviere diese Option, wenn Gaeste das Event direkt sehen sollen. Du kannst den Status spaeter aendern.

)}
); } function FormSkeleton() { return (
{Array.from({ length: 4 }).map((_, index) => (
))}
); } function slugify(value: string): string { return value .normalize('NFKD') .toLowerCase() .replace(/[\u0300-\u036f]/g, '') .replace(/[^a-z0-9]+/g, '-') .replace(/(^-|-$)+/g, '') .slice(0, 60); } function normalizeName(name: string | Record): string { if (typeof name === 'string') { return name; } return name.de ?? name.en ?? Object.values(name)[0] ?? ''; }