From 1e821a2fb474db4024ab4bccbee28707e8c8c1e1 Mon Sep 17 00:00:00 2001 From: Codex Agent Date: Sun, 18 Jan 2026 10:08:39 +0100 Subject: [PATCH] refactor(dashboard): refine setup checklist UI - Removed progress bar from hero for cleaner look - Made setup checklist collapsible (auto-collapsed when complete) - Improved checklist item styling with active/inactive states --- resources/js/admin/mobile/DashboardPage.tsx | 46 +++--- .../mobile/components/SetupChecklist.tsx | 140 ++++++++++-------- 2 files changed, 103 insertions(+), 83 deletions(-) diff --git a/resources/js/admin/mobile/DashboardPage.tsx b/resources/js/admin/mobile/DashboardPage.tsx index 9cdbad1..738b0d4 100644 --- a/resources/js/admin/mobile/DashboardPage.tsx +++ b/resources/js/admin/mobile/DashboardPage.tsx @@ -7,7 +7,6 @@ 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'; @@ -158,10 +157,6 @@ 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(() => { @@ -189,6 +184,10 @@ export default function MobileDashboardPage() { ); } + // Calculate Readiness + const readiness = useEventReadiness(activeEvent, t as any); + const phase = activeEvent ? getEventPhase(activeEvent) : 'setup'; + return ( @@ -203,8 +202,8 @@ export default function MobileDashboardPage() { readiness={readiness} /> - {/* 1b. SETUP CHECKLIST (Only in Setup Phase) */} - {phase === 'setup' && !readiness.isReady && ( + {/* 1b. SETUP CHECKLIST */} + {phase === 'setup' && ( navigate(adminPath(nextStep.targetPath)) : undefined; return ( @@ -358,17 +358,21 @@ function LifecycleHero({ event, stats, locale, navigate, onSwitch, canSwitch, re - - - - {t('management:photobooth.checklist.title', 'Setup Status')} - - {readiness.completedSteps}/{readiness.totalSteps} + {/* Main CTA if not ready */} + {!readiness.isReady && ( + } + onPress={ctaAction} + /> + )} + {readiness.isReady && ( + + + Ready for Liftoff - - - - + )} ); @@ -589,4 +593,4 @@ function EmptyState({ canManage, onCreate }: any) { {canManage && } ); -} \ No newline at end of file +} diff --git a/resources/js/admin/mobile/components/SetupChecklist.tsx b/resources/js/admin/mobile/components/SetupChecklist.tsx index 76fc04f..a3c0557 100644 --- a/resources/js/admin/mobile/components/SetupChecklist.tsx +++ b/resources/js/admin/mobile/components/SetupChecklist.tsx @@ -3,7 +3,7 @@ import { useNavigate } from 'react-router-dom'; import { YStack, XStack } from '@tamagui/stacks'; import { SizableText as Text } from '@tamagui/text'; import { Pressable } from '@tamagui/react-native-web-lite'; -import { CheckCircle2, Circle, ChevronRight, ArrowRight } from 'lucide-react'; +import { CheckCircle2, Circle, ChevronDown, ChevronUp } from 'lucide-react'; import { useAdminTheme } from '../theme'; import { ReadinessStep } from '../hooks/useEventReadiness'; import { adminPath } from '../../constants'; @@ -11,10 +11,10 @@ import { adminPath } from '../../constants'; export function SetupChecklist({ steps, title }: { steps: ReadinessStep[]; title: string }) { const theme = useAdminTheme(); const navigate = useNavigate(); + const isAllComplete = steps.every(s => s.isComplete); + const [collapsed, setCollapsed] = React.useState(isAllComplete); - if (steps.every(s => s.isComplete)) { - return null; // Don't show if all done - } + const completedCount = steps.filter(s => s.isComplete).length; return ( - - - {title} - - + setCollapsed(!collapsed)}> + + + + {title} + + {isAllComplete && ( + + )} + + + + + {completedCount}/{steps.length} + + {collapsed ? : } + + + - - {steps.map((step, index) => { - const isNext = !step.isComplete && steps.slice(0, index).every(s => s.isComplete); - - return ( - navigate(adminPath(step.targetPath))} - style={{ - backgroundColor: isNext ? theme.surface : 'transparent', - }} - > - - {step.isComplete ? ( - - ) : isNext ? ( - - ) : ( - - )} + {!collapsed && ( + + {steps.map((step, index) => { + const isNext = !step.isComplete && steps.slice(0, index).every(s => s.isComplete); + + return ( + navigate(adminPath(step.targetPath))} + style={{ + backgroundColor: isNext ? theme.surface : 'transparent', + }} + > + + {step.isComplete ? ( + + ) : isNext ? ( + + ) : ( + + )} - - - {step.label} - - {step.description && !step.isComplete && ( - - {step.description} - - )} - + + + {step.label} + + {step.description && !step.isComplete && ( + + {step.description} + + )} + - {isNext && ( - - Start - - )} - - - ); - })} - + {isNext && ( + + Start + + )} + + + ); + })} + + )} ); -} +} \ No newline at end of file