import React from 'react'; import { useNavigate } from 'react-router-dom'; import { ChevronDown, ChevronLeft, Bell, QrCode } from 'lucide-react'; import { YStack, XStack } from '@tamagui/stacks'; import { SizableText as Text } from '@tamagui/text'; import { Pressable } from '@tamagui/react-native-web-lite'; import { useTranslation } from 'react-i18next'; import { useEventContext } from '../../context/EventContext'; import { BottomNav, NavKey } from './BottomNav'; import { useMobileNav } from '../hooks/useMobileNav'; import { adminPath } from '../../constants'; import { MobileSheet } from './Sheet'; import { MobileCard, PillBadge } from './Primitives'; import { useAlertsBadge } from '../hooks/useAlertsBadge'; import { formatEventDate, resolveEventDisplayName } from '../../lib/events'; import { TenantEvent } from '../../api'; type MobileShellProps = { title?: string; subtitle?: string; children: React.ReactNode; activeTab: NavKey; onBack?: () => void; headerActions?: React.ReactNode; }; export function MobileShell({ title, subtitle, children, activeTab, onBack, headerActions }: MobileShellProps) { const { events, activeEvent, hasMultipleEvents, hasEvents, selectEvent } = useEventContext(); const { go } = useMobileNav(activeEvent?.slug); const navigate = useNavigate(); const { t, i18n } = useTranslation('mobile'); const { count: alertCount } = useAlertsBadge(); const [pickerOpen, setPickerOpen] = React.useState(false); const locale = i18n.language?.startsWith('en') ? 'en-GB' : 'de-DE'; const eventTitle = title ?? (activeEvent ? resolveEventDisplayName(activeEvent) : t('header.appName', 'Event Admin')); const subtitleText = subtitle ?? (activeEvent?.event_date ? formatEventDate(activeEvent.event_date, locale) ?? '' : hasEvents ? t('header.selectEvent', 'Select an event to continue') : t('header.empty', 'Create your first event to get started')); const showEventSwitcher = hasMultipleEvents; const showQr = Boolean(activeEvent?.slug); return ( {onBack ? ( {t('actions.back', 'Back')} ) : null} setPickerOpen(true)} style={{ alignItems: 'flex-start' }} > {eventTitle} {subtitleText ? ( {subtitleText} ) : null} {showEventSwitcher ? : null} navigate(adminPath('/mobile/alerts'))}> {alertCount > 0 ? ( {alertCount > 9 ? '9+' : alertCount} ) : null} {showQr ? ( navigate(adminPath(`/mobile/events/${activeEvent?.slug}/qr`))}> {t('header.quickQr', 'Quick QR')} ) : null} {headerActions ?? null} {children} setPickerOpen(false)} title={t('header.eventSwitcher', 'Choose an event')} footer={null} bottomOffsetPx={110} > {events.length === 0 ? ( {t('header.noEventsTitle', 'Create your first event')} {t('header.noEventsBody', 'Start an event to access tasks, uploads, QR posters and more.')} navigate(adminPath('/mobile/events/new'))}> {t('header.createEvent', 'Create event')} ) : ( events.map((event) => ( { selectEvent(event.slug ?? null); setPickerOpen(false); }} > {resolveEventDisplayName(event)} {formatEventDate(event.event_date, locale) ?? t('header.noDate', 'Date tbd')} {event.slug === activeEvent?.slug ? t('header.active', 'Active') : (event.status ?? '—')} )) )} {activeEvent ? ( { selectEvent(null); setPickerOpen(false); }} > {t('header.clearSelection', 'Clear selection')} ) : null} ); } export function renderEventLocation(event?: TenantEvent | null): string { if (!event) return 'Location'; const settings = (event.settings ?? {}) as Record; const candidate = (settings.location as string | undefined) ?? (settings.address as string | undefined) ?? (settings.city as string | undefined); if (candidate && candidate.trim()) { return candidate; } return 'Location'; }