import React, { useEffect, useState } from 'react'; import { Page } from './_util'; import { useNavigate } from 'react-router-dom'; import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Html5Qrcode } from 'html5-qrcode'; import { readGuestName } from '../context/GuestIdentityContext'; export default function LandingPage() { const nav = useNavigate(); const [eventCode, setEventCode] = useState(''); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [isScanning, setIsScanning] = useState(false); const [scanner, setScanner] = useState(null); function extractEventKey(raw: string): string { const trimmed = raw.trim(); if (!trimmed) { return ''; } try { const url = new URL(trimmed); const inviteParam = url.searchParams.get('invite') ?? url.searchParams.get('token'); if (inviteParam) { return inviteParam; } const segments = url.pathname.split('/').filter(Boolean); const eventIndex = segments.findIndex((segment) => segment === 'e'); if (eventIndex >= 0 && segments.length > eventIndex + 1) { return decodeURIComponent(segments[eventIndex + 1]); } if (segments.length > 0) { return decodeURIComponent(segments[segments.length - 1]); } } catch { // Not a URL, treat as raw code } return trimmed; } async function join(input?: string) { const provided = input ?? eventCode; const normalized = extractEventKey(provided); if (!normalized) return; setLoading(true); setError(null); try { const res = await fetch(`/api/v1/events/${encodeURIComponent(normalized)}`); if (!res.ok) { setError('Event nicht gefunden oder geschlossen.'); return; } const data = await res.json(); const targetKey = data.join_token ?? data.slug ?? normalized; const storedName = readGuestName(targetKey); if (!storedName) { nav(`/setup/${encodeURIComponent(targetKey)}`); } else { nav(`/e/${encodeURIComponent(targetKey)}`); } } catch (e) { console.error('Join request failed', e); setError('Netzwerkfehler. Bitte spaeter erneut versuchen.'); } finally { setLoading(false); } } const qrConfig = { fps: 10, qrbox: { width: 250, height: 250 } } as const; async function startScanner() { if (scanner) { try { await scanner.start({ facingMode: 'environment' }, qrConfig, onScanSuccess, () => undefined); setIsScanning(true); } catch (err) { console.error('Scanner start failed', err); setError('Kamera-Zugriff fehlgeschlagen. Bitte erlaube den Zugriff und versuche es erneut.'); } return; } try { const newScanner = new Html5Qrcode('qr-reader'); setScanner(newScanner); await newScanner.start({ facingMode: 'environment' }, qrConfig, onScanSuccess, () => undefined); setIsScanning(true); } catch (err) { console.error('Scanner initialisation failed', err); setError('Kamera-Zugriff fehlgeschlagen. Bitte erlaube den Zugriff und versuche es erneut.'); } } function stopScanner() { if (!scanner) { setIsScanning(false); return; } scanner .stop() .then(() => { setIsScanning(false); }) .catch((err) => console.error('Scanner stop failed', err)); } async function onScanSuccess(decodedText: string) { const value = decodedText.trim(); if (!value) return; await join(value); stopScanner(); } useEffect(() => () => { if (scanner) { scanner.stop().catch(() => undefined); } }, [scanner]); return ( {error && ( {error} )}

Willkommen bei der Fotobox!

Dein Schluessel zu unvergesslichen Momenten.

Event beitreten Scanne den QR-Code oder gib den Code manuell ein.
Oder manuell eingeben
setEventCode(event.target.value)} placeholder="Event-Code eingeben" disabled={loading} />
); }