import React from 'react'; import { Button } from '@/components/ui/button'; import { createBrowserRouter, Outlet, useParams, Link } from 'react-router-dom'; import Header from './components/Header'; import BottomNav from './components/BottomNav'; import { useEventData } from './hooks/useEventData'; import { AlertTriangle, Loader2 } from 'lucide-react'; import type { FetchEventErrorCode } from './services/eventApi'; import { EventStatsProvider } from './context/EventStatsContext'; import { GuestIdentityProvider } from './context/GuestIdentityContext'; import LandingPage from './pages/LandingPage'; import ProfileSetupPage from './pages/ProfileSetupPage'; import HomePage from './pages/HomePage'; import TaskPickerPage from './pages/TaskPickerPage'; import TaskDetailPage from './pages/TaskDetailPage'; import UploadPage from './pages/UploadPage'; import UploadQueuePage from './pages/UploadQueuePage'; import GalleryPage from './pages/GalleryPage'; import PhotoLightbox from './pages/PhotoLightbox'; import AchievementsPage from './pages/AchievementsPage'; import SlideshowPage from './pages/SlideshowPage'; import SettingsPage from './pages/SettingsPage'; import LegalPage from './pages/LegalPage'; import NotFoundPage from './pages/NotFoundPage'; function HomeLayout() { const { token } = useParams(); if (!token) { return (
); } return ( ); } export const router = createBrowserRouter([ { path: '/event', element: }, { path: '/setup/:token', element: , children: [ { index: true, element: }, ], }, { path: '/e/:token', element: , children: [ { index: true, element: }, { path: 'tasks', element: }, { path: 'tasks/:taskId', element: }, { path: 'upload', element: }, { path: 'queue', element: }, { path: 'gallery', element: }, { path: 'photo/:photoId', element: }, { path: 'achievements', element: }, { path: 'slideshow', element: }, ], }, { path: '/settings', element: }, { path: '/legal/:page', element: }, { path: '*', element: }, ]); function EventBoundary({ token }: { token: string }) { const { event, status, error, errorCode } = useEventData(); if (status === 'loading') { return ; } if (status === 'error' || !event) { return ; } return (
); } function SetupLayout() { const { token } = useParams<{ token: string }>(); if (!token) return null; return (
); } function EventLoadingView() { return (

Wir prüfen deinen Zugang...

Einen Moment bitte.

); } interface EventErrorViewProps { code: FetchEventErrorCode | null; message: string | null; } function EventErrorView({ code, message }: EventErrorViewProps) { const content = getErrorContent(code, message); return (

{content.title}

{content.description}

{content.hint && (

{content.hint}

)}
{content.ctaHref && content.ctaLabel && ( )}
); } function getErrorContent( code: FetchEventErrorCode | null, message: string | null, ) { const base = (fallbackTitle: string, fallbackDescription: string, options?: { ctaLabel?: string; ctaHref?: string; hint?: string }) => ({ title: fallbackTitle, description: message ?? fallbackDescription, ctaLabel: options?.ctaLabel, ctaHref: options?.ctaHref, hint: options?.hint ?? null, }); switch (code) { case 'invalid_token': return base('Zugriffscode ungültig', 'Der eingegebene Code konnte nicht verifiziert werden.', { ctaLabel: 'Neuen Code anfordern', ctaHref: '/event', }); case 'token_revoked': return base('Zugriffscode deaktiviert', 'Dieser Code wurde zurückgezogen. Bitte fordere einen neuen Code an.', { ctaLabel: 'Neuen Code anfordern', ctaHref: '/event', }); case 'token_expired': return base('Zugriffscode abgelaufen', 'Der Code ist nicht mehr gültig. Aktualisiere deinen Code, um fortzufahren.', { ctaLabel: 'Code aktualisieren', ctaHref: '/event', }); case 'token_rate_limited': return base('Zu viele Versuche', 'Es gab zu viele Eingaben in kurzer Zeit. Warte kurz und versuche es erneut.', { hint: 'Tipp: Eine erneute Eingabe ist in wenigen Minuten möglich.', }); case 'event_not_public': return base('Event nicht öffentlich', 'Dieses Event ist aktuell nicht öffentlich zugänglich.', { hint: 'Nimm Kontakt mit den Veranstalter:innen auf, um Zugang zu erhalten.', }); case 'network_error': return base('Verbindungsproblem', 'Wir konnten keine Verbindung zum Server herstellen. Prüfe deine Internetverbindung und versuche es erneut.'); case 'server_error': return base('Server nicht erreichbar', 'Der Server reagiert derzeit nicht. Versuche es später erneut.'); default: return base('Event nicht erreichbar', 'Wir konnten dein Event nicht laden. Bitte versuche es erneut.', { ctaLabel: 'Zur Code-Eingabe', ctaHref: '/event', }); } } function SimpleLayout({ title, children }: { title: string; children: React.ReactNode }) { return (
{children}
); }