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 } 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 primaryActions = React.useMemo( () => [ { to: 'tasks', label: t('home.actions.items.tasks.label'), description: t('home.actions.items.tasks.description'), icon: , }, { to: 'upload', label: t('home.actions.items.upload.label'), description: t('home.actions.items.upload.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 && ( )} } label={t('home.stats.online')} value={`${stats.onlineGuests}`} accentColor={accentColor} /> } label={t('home.stats.tasksSolved')} value={`${stats.tasksSolved}`} accentColor={accentColor} /> } label={t('home.stats.lastUpload')} value={latestUploadText} accentColor={accentColor} /> } label={t('home.stats.completedTasks')} value={`${completedCount}`} accentColor={accentColor} />

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

{t('home.actions.subtitle')}
{primaryActions.map((action) => (
{action.icon}
{action.label} {action.description}
))}
{t('home.checklist.title')} {t('home.checklist.description')} {checklistItems.map((item) => (
{item}
))}
); } function HeroCard({ name, eventName, tasksCompleted, t, branding, onDismiss, }: { name: string; eventName: string; tasksCompleted: number; t: TranslateFn; branding: EventBranding; onDismiss: () => void; }) { 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}

); } function StatTile({ icon, label, value, accentColor }: { icon: React.ReactNode; label: string; value: string; accentColor: string }) { return (
{icon}
{label} {value}
); } 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}`); }