Update admin PWA events, branding, and packages
This commit is contained in:
@@ -10,7 +10,7 @@ import { Image } from '@tamagui/image';
|
||||
import { isSameDay, isPast, isFuture, parseISO, differenceInDays, startOfDay } from 'date-fns';
|
||||
|
||||
import { MobileShell } from './components/MobileShell';
|
||||
import { adminPath } from '../constants';
|
||||
import { ADMIN_EVENTS_PATH, adminPath } from '../constants';
|
||||
import { useEventContext } from '../context/EventContext';
|
||||
import { getEventStats, EventStats, TenantEvent, getEventPhotos, TenantPhoto } from '../api';
|
||||
import { formatEventDate, resolveEventDisplayName } from '../lib/events';
|
||||
@@ -165,10 +165,21 @@ export default function MobileDashboardPage() {
|
||||
selectEvent(slugParam);
|
||||
}, [activeEvent?.slug, selectEvent, slugParam]);
|
||||
|
||||
const shouldRedirectToSelector = !isLoading && !activeEvent && !slugParam;
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!shouldRedirectToSelector) return;
|
||||
navigate(ADMIN_EVENTS_PATH, { replace: true });
|
||||
}, [navigate, shouldRedirectToSelector]);
|
||||
|
||||
const [eventSwitcherOpen, setEventSwitcherOpen] = React.useState(false);
|
||||
|
||||
// --- RENDER ---
|
||||
|
||||
if (shouldRedirectToSelector) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<MobileShell activeTab="home" title={t('mobileDashboard.title', 'Dashboard')}>
|
||||
@@ -188,6 +199,7 @@ export default function MobileDashboardPage() {
|
||||
// Calculate Readiness
|
||||
const readiness = useEventReadiness(activeEvent, t as any);
|
||||
const phase = activeEvent ? getEventPhase(activeEvent) : 'setup';
|
||||
const isCompleted = phase === 'post';
|
||||
|
||||
return (
|
||||
<MobileShell activeTab="home" title={t('mobileDashboard.title', 'Dashboard')}>
|
||||
@@ -223,6 +235,7 @@ export default function MobileDashboardPage() {
|
||||
navigate={navigate}
|
||||
permissions={memberPermissions}
|
||||
isMember={isMember}
|
||||
isCompleted={isCompleted}
|
||||
/>
|
||||
|
||||
{/* 5. RECENT PHOTOS */}
|
||||
@@ -241,6 +254,7 @@ export default function MobileDashboardPage() {
|
||||
type EventPhase = 'setup' | 'live' | 'post';
|
||||
|
||||
function getEventPhase(event: TenantEvent): EventPhase {
|
||||
if (event.status === 'archived') return 'post';
|
||||
if (!event.event_date) return 'setup';
|
||||
const today = startOfDay(new Date());
|
||||
const eventDate = parseISO(event.event_date);
|
||||
@@ -318,17 +332,23 @@ function LifecycleHero({ event, stats, locale, navigate, onSwitch, canSwitch, re
|
||||
</YStack>
|
||||
<YStack>
|
||||
<Text fontSize="$md" fontWeight="800" color={theme.textStrong}>
|
||||
{t('management:status.archived', 'Event Completed')}
|
||||
{t('events.recap.completedTitle', 'Event completed')}
|
||||
</Text>
|
||||
<Text fontSize="$xs" color={theme.muted}>{t('management:recap.galleryOpen', 'Gallery online')}</Text>
|
||||
<Text fontSize="$xs" color={theme.muted}>{t('events.recap.galleryOpen', 'Gallery online')}</Text>
|
||||
</YStack>
|
||||
</XStack>
|
||||
<ModernButton
|
||||
label={t('management:recap.downloadAll', 'Download Photos')}
|
||||
label={t('events.recap.downloadAll', 'Download photos')}
|
||||
tone="primary"
|
||||
icon={<Download size={16} color="white" />}
|
||||
onPress={() => navigate(adminPath(`/mobile/exports`))}
|
||||
/>
|
||||
<ModernButton
|
||||
label={t('events.recap.openRecap', 'Open recap')}
|
||||
tone="ghost"
|
||||
icon={<ArrowRight size={16} color={theme.text} />}
|
||||
onPress={() => navigate(adminPath(`/mobile/events/${event.slug}/recap`))}
|
||||
/>
|
||||
</ModernCard>
|
||||
</YStack>
|
||||
);
|
||||
@@ -413,40 +433,46 @@ function PulseStrip({ event, stats }: any) {
|
||||
);
|
||||
}
|
||||
|
||||
function UnifiedToolGrid({ event, navigate, permissions, isMember }: any) {
|
||||
function UnifiedToolGrid({ event, navigate, permissions, isMember, isCompleted }: any) {
|
||||
const theme = useAdminTheme();
|
||||
const { t } = useTranslation(['management', 'dashboard']);
|
||||
const slug = event?.slug;
|
||||
if (!slug) return null;
|
||||
|
||||
const experienceItems = [
|
||||
{ label: t('management:photos.gallery.title', 'Photos'), icon: ImageIcon, path: `/mobile/events/${slug}/control-room`, color: theme.primary },
|
||||
!isCompleted ? { label: t('management:events.quick.liveShowSettings', 'Slide Show'), icon: Tv, path: `/mobile/events/${slug}/live-show/settings`, color: '#F59E0B' } : null,
|
||||
!isCompleted ? { label: t('events.tasks.badge', 'Tasks'), icon: ListTodo, path: `/mobile/events/${slug}/tasks`, color: theme.accent } : null,
|
||||
!isCompleted ? { label: t('management:events.quick.photobooth', 'Photobooth'), icon: Camera, path: `/mobile/events/${slug}/photobooth`, color: '#8B5CF6' } : null,
|
||||
].filter((item): item is { label: string; icon: any; path: string; color?: string } => Boolean(item));
|
||||
|
||||
const operationsItems = [
|
||||
!isCompleted ? { label: t('management:invites.badge', 'QR Codes'), icon: QrCode, path: `/mobile/events/${slug}/qr`, color: '#10B981' } : null,
|
||||
{ label: t('management:events.quick.guests', 'Guests'), icon: Users, path: `/mobile/events/${slug}/members`, color: theme.text },
|
||||
!isCompleted ? { label: t('management:events.quick.guestMessages', 'Messages'), icon: Megaphone, path: `/mobile/events/${slug}/guest-notifications`, color: theme.text } : null,
|
||||
!isCompleted ? { label: t('events.branding.titleShort', 'Branding'), icon: Layout, path: `/mobile/events/${slug}/branding`, color: theme.text } : null,
|
||||
].filter((item): item is { label: string; icon: any; path: string; color?: string } => Boolean(item));
|
||||
|
||||
const adminItems = [
|
||||
{ label: t('management:mobileDashboard.shortcutAnalytics', 'Analytics'), icon: TrendingUp, path: `/mobile/events/${slug}/analytics` },
|
||||
!isCompleted ? { label: t('events.recap.exportTitleShort', 'Exports'), icon: Download, path: `/mobile/exports` } : null,
|
||||
{ label: t('management:mobileProfile.settings', 'Settings'), icon: Settings, path: `/mobile/events/${slug}/edit` },
|
||||
].filter((item): item is { label: string; icon: any; path: string; color?: string } => Boolean(item));
|
||||
|
||||
const sections = [
|
||||
{
|
||||
title: t('management:branding.badge', 'Experience'),
|
||||
items: [
|
||||
{ label: t('management:photos.gallery.title', 'Photos'), icon: ImageIcon, path: `/mobile/events/${slug}/control-room`, color: theme.primary },
|
||||
{ label: t('management:events.quick.liveShowSettings', 'Slide Show'), icon: Tv, path: `/mobile/events/${slug}/live-show/settings`, color: '#F59E0B' },
|
||||
{ label: t('management:tasks.badge', 'Tasks'), icon: ListTodo, path: `/mobile/events/${slug}/tasks`, color: theme.accent },
|
||||
{ label: t('management:events.quick.photobooth', 'Photobooth'), icon: Camera, path: `/mobile/events/${slug}/photobooth`, color: '#8B5CF6' },
|
||||
]
|
||||
items: experienceItems,
|
||||
},
|
||||
{
|
||||
title: t('management:workspace.hero.badge', 'Operations'),
|
||||
items: [
|
||||
{ label: t('management:invites.badge', 'QR Codes'), icon: QrCode, path: `/mobile/events/${slug}/qr`, color: '#10B981' },
|
||||
{ label: t('management:events.quick.guests', 'Guests'), icon: Users, path: `/mobile/events/${slug}/members`, color: theme.text },
|
||||
{ label: t('management:events.quick.guestMessages', 'Messages'), icon: Megaphone, path: `/mobile/events/${slug}/guest-notifications`, color: theme.text },
|
||||
{ label: t('management:branding.titleShort', 'Branding'), icon: Layout, path: `/mobile/events/${slug}/branding`, color: theme.text },
|
||||
]
|
||||
items: operationsItems,
|
||||
},
|
||||
{
|
||||
title: t('management:settings.hero.badge', 'Admin'),
|
||||
items: [
|
||||
{ label: t('management:mobileDashboard.shortcutAnalytics', 'Analytics'), icon: TrendingUp, path: `/mobile/events/${slug}/analytics` },
|
||||
{ label: t('management:recap.exportTitle', 'Exports'), icon: Download, path: `/mobile/exports` },
|
||||
{ label: t('management:mobileProfile.settings', 'Settings'), icon: Settings, path: `/mobile/events/${slug}/edit` },
|
||||
]
|
||||
items: adminItems,
|
||||
}
|
||||
];
|
||||
].filter((section) => section.items.length > 0);
|
||||
|
||||
return (
|
||||
<YStack space="$4">
|
||||
|
||||
Reference in New Issue
Block a user