feat(dashboard): implement transparent setup roadmap and fix translations
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

- Added SetupChecklist component for clear progress visualization
- Refactored LifecycleHero to show readiness state
- Fixed remaining untranslated keys in tool grid and readiness hook
This commit is contained in:
Codex Agent
2026-01-18 10:02:59 +01:00
parent 45f0cea264
commit 48d4716ab1
3 changed files with 131 additions and 30 deletions

View File

@@ -7,6 +7,7 @@ import { YStack, XStack } from '@tamagui/stacks';
import { SizableText as Text } from '@tamagui/text';
import { Pressable } from '@tamagui/react-native-web-lite';
import { Image } from '@tamagui/image';
import { Progress } from '@tamagui/progress';
import { isSameDay, isPast, isFuture, parseISO, differenceInDays, startOfDay } from 'date-fns';
import { MobileShell } from './components/MobileShell';
@@ -19,6 +20,7 @@ import { useAdminTheme } from './theme';
import { buildLimitWarnings } from '../lib/limitWarnings';
import { withAlpha } from './components/colors';
import { useEventReadiness } from './hooks/useEventReadiness';
import { SetupChecklist } from './components/SetupChecklist';
// --- HELPERS ---
@@ -156,6 +158,10 @@ export default function MobileDashboardPage() {
},
});
// Calculate Readiness for Setup Checklist
const readiness = useEventReadiness(activeEvent, t as any);
const phase = activeEvent ? getEventPhase(activeEvent) : 'setup';
const locale = i18n.language?.startsWith('en') ? 'en-GB' : 'de-DE';
React.useEffect(() => {
@@ -194,8 +200,17 @@ export default function MobileDashboardPage() {
navigate={navigate}
onSwitch={() => setEventSwitcherOpen(true)}
canSwitch={hasMultipleEvents}
readiness={readiness}
/>
{/* 1b. SETUP CHECKLIST (Only in Setup Phase) */}
{phase === 'setup' && !readiness.isReady && (
<SetupChecklist
steps={readiness.steps}
title={t('management:photobooth.checklist.title', 'Checklist')}
/>
)}
{/* 2. PULSE STRIP */}
<PulseStrip event={activeEvent} stats={stats} />
@@ -234,10 +249,9 @@ function getEventPhase(event: TenantEvent): EventPhase {
return 'setup';
}
function LifecycleHero({ event, stats, locale, navigate, onSwitch, canSwitch }: any) {
function LifecycleHero({ event, stats, locale, navigate, onSwitch, canSwitch, readiness }: any) {
const theme = useAdminTheme();
const { t } = useTranslation(['management', 'dashboard']);
const { completedSteps, totalSteps, nextStep } = useEventReadiness(event, t as any);
if (!event) return null;
const phase = getEventPhase(event);
@@ -320,9 +334,9 @@ function LifecycleHero({ event, stats, locale, navigate, onSwitch, canSwitch }:
);
}
// SETUP
const ctaLabel = nextStep ? nextStep.ctaLabel : t('dashboard:onboarding.hero.cta', 'Setup Complete');
const ctaAction = nextStep ? () => navigate(adminPath(nextStep.targetPath)) : undefined;
// SETUP PHASE
// We removed the big button. We show high-level status.
const progressPercent = (readiness.progress ?? 0) * 100;
return (
<YStack>
@@ -344,20 +358,17 @@ function LifecycleHero({ event, stats, locale, navigate, onSwitch, canSwitch }:
<YStack height={1} backgroundColor={theme.border} />
<XStack alignItems="center" justifyContent="space-between">
<Text fontSize="$sm" color={theme.textStrong} fontWeight="600">
{t('management:photobooth.checklist.title', 'Setup Status')}
</Text>
<Text fontSize="$xs" color={theme.muted}>{completedSteps}/{totalSteps} Schritte</Text>
</XStack>
<ModernButton
label={ctaLabel}
tone={nextStep ? 'primary' : 'ghost'}
icon={nextStep ? <ArrowRight size={16} color="white" /> : <CheckCircle2 size={16} color={theme.primary} />}
onPress={ctaAction}
disabled={!nextStep}
/>
<YStack space="$1.5">
<XStack alignItems="center" justifyContent="space-between">
<Text fontSize="$sm" color={theme.textStrong} fontWeight="600">
{t('management:photobooth.checklist.title', 'Setup Status')}
</Text>
<Text fontSize="$xs" color={theme.muted}>{readiness.completedSteps}/{readiness.totalSteps}</Text>
</XStack>
<Progress value={progressPercent} max={100} size="$2" backgroundColor={theme.surfaceMuted} borderWidth={0}>
<Progress.Indicator backgroundColor={theme.primary} />
</Progress>
</YStack>
</ModernCard>
</YStack>
);
@@ -407,7 +418,7 @@ function UnifiedToolGrid({ event, navigate, permissions, isMember }: any) {
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:events.quick.tasks', 'Tasks'), icon: ListTodo, path: `/mobile/events/${slug}/tasks`, color: theme.accent },
{ 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' },
]
},
@@ -417,7 +428,7 @@ function UnifiedToolGrid({ event, navigate, permissions, isMember }: any) {
{ 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:events.branding.titleShort', 'Branding'), icon: Layout, path: `/mobile/events/${slug}/branding`, color: theme.text },
{ label: t('management:branding.titleShort', 'Branding'), icon: Layout, path: `/mobile/events/${slug}/branding`, color: theme.text },
]
},
{
@@ -578,4 +589,4 @@ function EmptyState({ canManage, onCreate }: any) {
{canManage && <ModernButton label={t('management:events.list.actions.create', 'Create Event')} onPress={onCreate} />}
</YStack>
);
}
}