import React from 'react'; import { YStack } from '@tamagui/stacks'; import { Trophy, UploadCloud, Sparkles, Cast, Share2, Compass, Image, Camera, Settings, Home } from 'lucide-react'; import { useLocation, useNavigate } from 'react-router-dom'; import TopBar from './TopBar'; import BottomDock from './BottomDock'; import FloatingActionButton from './FloatingActionButton'; import FabActionSheet from './FabActionSheet'; import CompassHub, { type CompassAction } from './CompassHub'; import AmbientBackground from './AmbientBackground'; import NotificationSheet from './NotificationSheet'; import SettingsSheet from './SettingsSheet'; import GuestAnalyticsNudge from './GuestAnalyticsNudge'; import { useEventData } from '../context/EventDataContext'; import { buildEventPath } from '../lib/routes'; import { useOptionalNotificationCenter } from '@/guest/context/NotificationCenterContext'; import { useTranslation } from '@/guest/i18n/useTranslation'; import { useAppearance } from '@/hooks/use-appearance'; type AppShellProps = { children: React.ReactNode; }; export default function AppShell({ children }: AppShellProps) { const [sheetOpen, setSheetOpen] = React.useState(false); const [compassOpen, setCompassOpen] = React.useState(false); const [notificationsOpen, setNotificationsOpen] = React.useState(false); const [settingsOpen, setSettingsOpen] = React.useState(false); const { tasksEnabled, event, token } = useEventData(); const notificationCenter = useOptionalNotificationCenter(); const navigate = useNavigate(); const location = useLocation(); const { t } = useTranslation(); const { resolved } = useAppearance(); const isDark = resolved === 'dark'; const actionIconColor = isDark ? '#F8FAFF' : '#0F172A'; const matomoEnabled = typeof window !== 'undefined' && Boolean((window as any).__MATOMO_GUEST__?.enabled); const showFab = !/\/photo\/\d+/.test(location.pathname); const goTo = (path: string) => () => { setSheetOpen(false); setCompassOpen(false); setNotificationsOpen(false); setSettingsOpen(false); navigate(buildEventPath(token, path)); }; const openSheet = () => { setCompassOpen(false); setNotificationsOpen(false); setSettingsOpen(false); setSheetOpen(true); }; const openCompass = () => { setSheetOpen(false); setNotificationsOpen(false); setSettingsOpen(false); setCompassOpen(true); }; const actions = [ { key: 'upload', label: t('appShell.actions.upload.label', 'Upload / Take photo'), description: t('appShell.actions.upload.description', 'Add a moment from your device or camera.'), icon: , onPress: goTo('/upload'), }, { key: 'compass', label: t('appShell.actions.compass.label', 'Compass hub'), description: t('appShell.actions.compass.description', 'Quick jump to key areas.'), icon: , onPress: () => { setSheetOpen(false); openCompass(); }, }, tasksEnabled ? { key: 'task', label: t('appShell.actions.task.label', 'Start a task'), description: t('appShell.actions.task.description', 'Pick a challenge and capture it now.'), icon: , onPress: goTo('/tasks'), } : null, { key: 'live', label: t('appShell.actions.live.label', 'Live show'), description: t('appShell.actions.live.description', 'See the real-time highlight stream.'), icon: , onPress: () => { setSheetOpen(false); setCompassOpen(false); setNotificationsOpen(false); setSettingsOpen(false); if (token) { navigate(`/show/${encodeURIComponent(token)}`); } }, }, { key: 'slideshow', label: t('appShell.actions.slideshow.label', 'Slideshow'), description: t('appShell.actions.slideshow.description', 'Lean back and watch the gallery roll.'), icon: , onPress: goTo('/slideshow'), }, { key: 'share', label: t('appShell.actions.share.label', 'Share invite'), description: t('appShell.actions.share.description', 'Send the event link or QR code.'), icon: , onPress: goTo('/share'), }, tasksEnabled ? { key: 'achievements', label: t('appShell.actions.achievements.label', 'Achievements'), description: t('appShell.actions.achievements.description', 'Track your photo streaks.'), icon: , onPress: goTo('/achievements'), } : null, ].filter(Boolean) as Array<{ key: string; label: string; description: string; icon: React.ReactNode; onPress?: () => void; }>; const compassQuadrants: [CompassAction, CompassAction, CompassAction, CompassAction] = [ { key: 'home', label: t('navigation.home', 'Home'), icon: , onPress: goTo('/'), }, { key: 'gallery', label: t('navigation.gallery', 'Gallery'), icon: , onPress: goTo('/gallery'), }, tasksEnabled ? { key: 'tasks', label: t('navigation.tasks', 'Tasks'), icon: , onPress: goTo('/tasks'), } : { key: 'settings', label: t('settings.title', 'Settings'), icon: , onPress: goTo('/settings'), }, { key: 'share', label: t('navigation.share', 'Share'), icon: , onPress: goTo('/share'), }, ]; return ( { setNotificationsOpen(false); setSheetOpen(false); setCompassOpen(false); setSettingsOpen(true); }} onNotificationsPress={() => { setSettingsOpen(false); setSheetOpen(false); setCompassOpen(false); setNotificationsOpen(true); }} notificationCount={notificationCenter?.unreadCount ?? 0} /> {children} {showFab ? : null} setSheetOpen(next)} title={t('appShell.fab.title', 'Create a moment')} actions={actions} /> , onPress: goTo('/upload'), }} quadrants={compassQuadrants} /> ); }