tab flows.
- Added a dynamic MobileShell with sticky header (notification bell with badge, quick QR when an event is
active, event switcher for multi-event users) and stabilized bottom tabs (home, tasks, uploads, profile)
driven by useMobileNav (resources/js/admin/mobile/components/MobileShell.tsx, components/BottomNav.tsx, hooks/
useMobileNav.ts).
- Centralized event handling now supports 0/1/many-event states without auto-selecting in multi-tenant mode and
exposes helper flags/activeSlug for consumers (resources/js/admin/context/EventContext.tsx).
- Rebuilt the mobile dashboard into explicit states: onboarding/no-event, single-event focus, and multi-event picker
with featured/secondary actions, KPI strip, and alerts (resources/js/admin/mobile/DashboardPage.tsx).
- Introduced tab entry points that respect event context and prompt selection when needed (resources/js/admin/
mobile/TasksTabPage.tsx, UploadsTabPage.tsx). Refreshed tasks/uploads detail screens to use the new shell and sync
event selection (resources/js/admin/mobile/EventTasksPage.tsx, EventPhotosPage.tsx).
- Updated mobile routes and existing screens to the new tab keys and header/footer behavior (resources/js/admin/
router.tsx, mobile/* pages, i18n nav/header strings).
80 lines
3.0 KiB
TypeScript
80 lines
3.0 KiB
TypeScript
import React from 'react';
|
|
import { Navigate, useNavigate } from 'react-router-dom';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { YStack, XStack } from '@tamagui/stacks';
|
|
import { SizableText as Text } from '@tamagui/text';
|
|
import { Pressable } from '@tamagui/react-native-web-lite';
|
|
import { MobileShell } from './components/MobileShell';
|
|
import { MobileCard, CTAButton } from './components/Primitives';
|
|
import { useEventContext } from '../context/EventContext';
|
|
import { formatEventDate, resolveEventDisplayName } from '../lib/events';
|
|
import { adminPath } from '../constants';
|
|
|
|
export default function MobileTasksTabPage() {
|
|
const { events, activeEvent, hasEvents, selectEvent } = useEventContext();
|
|
const { t, i18n } = useTranslation('management');
|
|
const navigate = useNavigate();
|
|
|
|
if (activeEvent?.slug) {
|
|
return <Navigate to={adminPath(`/mobile/events/${activeEvent.slug}/tasks`)} replace />;
|
|
}
|
|
|
|
if (!hasEvents) {
|
|
return (
|
|
<MobileShell activeTab="tasks" title={t('events.tasks.title', 'Tasks')}>
|
|
<MobileCard alignItems="flex-start" space="$3">
|
|
<Text fontSize="$lg" fontWeight="800" color="#111827">
|
|
{t('events.tasks.emptyTitle', 'Create an event first')}
|
|
</Text>
|
|
<Text fontSize="$sm" color="#4b5563">
|
|
{t('events.tasks.emptyBody', 'Start an event to add tasks, challenges, and checklists.')}
|
|
</Text>
|
|
<CTAButton
|
|
label={t('events.actions.create', 'Create Event')}
|
|
onPress={() => navigate(adminPath('/mobile/events/new'))}
|
|
/>
|
|
</MobileCard>
|
|
</MobileShell>
|
|
);
|
|
}
|
|
|
|
const locale = i18n.language?.startsWith('en') ? 'en-GB' : 'de-DE';
|
|
|
|
return (
|
|
<MobileShell activeTab="tasks" title={t('events.tasks.title', 'Tasks')}>
|
|
<YStack space="$2">
|
|
<Text fontSize="$sm" color="#111827" fontWeight="700">
|
|
{t('events.tasks.pickEvent', 'Pick an event to manage tasks')}
|
|
</Text>
|
|
{events.map((event) => (
|
|
<Pressable
|
|
key={event.slug}
|
|
onPress={() => {
|
|
selectEvent(event.slug ?? null);
|
|
if (event.slug) {
|
|
navigate(adminPath(`/mobile/events/${event.slug}/tasks`));
|
|
}
|
|
}}
|
|
>
|
|
<MobileCard borderColor="#e5e7eb" space="$2">
|
|
<XStack alignItems="center" justifyContent="space-between">
|
|
<YStack space="$1">
|
|
<Text fontSize="$md" fontWeight="800" color="#111827">
|
|
{resolveEventDisplayName(event)}
|
|
</Text>
|
|
<Text fontSize="$xs" color="#6b7280">
|
|
{formatEventDate(event.event_date, locale) ?? t('events.status.draft', 'Draft')}
|
|
</Text>
|
|
</YStack>
|
|
<Text fontSize="$sm" color="#007AFF" fontWeight="700">
|
|
{t('events.actions.open', 'Open')}
|
|
</Text>
|
|
</XStack>
|
|
</MobileCard>
|
|
</Pressable>
|
|
))}
|
|
</YStack>
|
|
</MobileShell>
|
|
);
|
|
}
|