import React from 'react'; import { Link, useParams } from 'react-router-dom'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Separator } from '@/components/ui/separator'; import EmotionPicker from '../components/EmotionPicker'; import GalleryPreview from '../components/GalleryPreview'; import { useGuestIdentity } from '../context/GuestIdentityContext'; import { useEventStats } from '../context/EventStatsContext'; import { useEventData } from '../hooks/useEventData'; import { useGuestTaskProgress } from '../hooks/useGuestTaskProgress'; import { Sparkles, UploadCloud, Images, CheckCircle2, Users, TimerReset, X, Camera, ArrowUpRight } from 'lucide-react'; import { useTranslation, type TranslateFn } from '../i18n/useTranslation'; import { useEventBranding } from '../context/EventBrandingContext'; import type { EventBranding } from '../types/event-branding'; export default function HomePage() { const { token } = useParams<{ token: string }>(); const { name, hydrated } = useGuestIdentity(); const stats = useEventStats(); const { event } = useEventData(); const { completedCount } = useGuestTaskProgress(token); const { t } = useTranslation(); const { branding } = useEventBranding(); const heroStorageKey = token ? `guestHeroDismissed_${token}` : 'guestHeroDismissed'; const [heroVisible, setHeroVisible] = React.useState(() => { if (typeof window === 'undefined') { return true; } try { return window.sessionStorage.getItem(heroStorageKey) !== '1'; } catch { return true; } }); React.useEffect(() => { if (typeof window === 'undefined') { return; } try { setHeroVisible(window.sessionStorage.getItem(heroStorageKey) !== '1'); } catch { setHeroVisible(true); } }, [heroStorageKey]); const dismissHero = React.useCallback(() => { setHeroVisible(false); if (typeof window === 'undefined') { return; } try { window.sessionStorage.setItem(heroStorageKey, '1'); } catch { // ignore storage exceptions (e.g. private mode) } }, [heroStorageKey]); const displayName = hydrated && name ? name : t('home.fallbackGuestName'); const eventNameDisplay = event?.name ?? t('home.hero.defaultEventName'); const latestUploadText = formatLatestUpload(stats.latestPhotoAt, t); const accentColor = branding.primaryColor; const secondaryAccent = branding.secondaryColor; const statItems = React.useMemo( () => [ { icon: , label: t('home.stats.online'), value: `${stats.onlineGuests}`, }, { icon: , label: t('home.stats.tasksSolved'), value: `${stats.tasksSolved}`, }, { icon: , label: t('home.stats.lastUpload'), value: latestUploadText, }, { icon: , label: t('home.stats.completedTasks'), value: `${completedCount}`, }, ], [completedCount, latestUploadText, stats.onlineGuests, stats.tasksSolved, t], ); const quickActions = React.useMemo( () => [ { to: 'upload', label: t('home.actions.items.upload.label'), description: t('home.actions.items.upload.description'), icon: , highlight: true, }, { to: 'tasks', label: t('home.actions.items.tasks.label'), description: t('home.actions.items.tasks.description'), icon: , }, { to: 'gallery', label: t('home.actions.items.gallery.label'), description: t('home.actions.items.gallery.description'), icon: , }, ], [t], ); const checklistItems = React.useMemo( () => [ t('home.checklist.steps.first'), t('home.checklist.steps.second'), t('home.checklist.steps.third'), ], [t], ); if (!token) { return null; } return (
{heroVisible && ( )}

{t('home.actions.title')}

{t('home.actions.subtitle')}

{quickActions.map((action) => ( ))}
{t('home.checklist.title')} {t('home.checklist.description')} {checklistItems.map((item) => (
{item}
))}
); } function HeroCard({ name, eventName, tasksCompleted, t, branding, onDismiss, ctaLabel, ctaHref, }: { name: string; eventName: string; tasksCompleted: number; t: TranslateFn; branding: EventBranding; onDismiss: () => void; ctaLabel?: string; ctaHref?: string; }) { const heroTitle = t('home.hero.title').replace('{name}', name); const heroDescription = t('home.hero.description').replace('{eventName}', eventName); const progressMessage = tasksCompleted > 0 ? t('home.hero.progress.some').replace('{count}', `${tasksCompleted}`) : t('home.hero.progress.none'); const style = React.useMemo(() => ({ background: `linear-gradient(135deg, ${branding.primaryColor}, ${branding.secondaryColor})`, color: '#ffffff', fontFamily: branding.fontFamily ?? undefined, }), [branding.fontFamily, branding.primaryColor, branding.secondaryColor]); return ( {t('home.hero.subtitle')} {heroTitle}

{heroDescription}

{progressMessage}

{ctaHref && ctaLabel && ( )}
); } function StatsRibbon({ items, accentColor, fontFamily, }: { items: { icon: React.ReactNode; label: string; value: string }[]; accentColor: string; fontFamily?: string | null; }) { return (
{items.map((item) => (
{item.icon}
{item.label} {item.value}
))}
); } function QuickActionCard({ action, accentColor, secondaryAccent, }: { action: { to: string; label: string; description: string; icon: React.ReactNode; highlight?: boolean }; accentColor: string; secondaryAccent: string; }) { const highlightStyle = action.highlight ? { background: `linear-gradient(120deg, ${accentColor}, ${secondaryAccent})`, color: '#fff', } : undefined; return (
{action.icon}
{action.label} {action.description}
); } function formatLatestUpload(isoDate: string | null, t: TranslateFn) { if (!isoDate) { return t('home.latestUpload.none'); } const date = new Date(isoDate); if (Number.isNaN(date.getTime())) { return t('home.latestUpload.invalid'); } const diffMs = Date.now() - date.getTime(); const diffMinutes = Math.round(diffMs / 60000); if (diffMinutes < 1) { return t('home.latestUpload.justNow'); } if (diffMinutes < 60) { return t('home.latestUpload.minutes').replace('{count}', `${diffMinutes}`); } const diffHours = Math.round(diffMinutes / 60); if (diffHours < 24) { return t('home.latestUpload.hours').replace('{count}', `${diffHours}`); } const diffDays = Math.round(diffHours / 24); return t('home.latestUpload.days').replace('{count}', `${diffDays}`); }