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
This commit is contained in:
@@ -7,7 +7,6 @@ import { YStack, XStack } from '@tamagui/stacks';
|
|||||||
import { SizableText as Text } from '@tamagui/text';
|
import { SizableText as Text } from '@tamagui/text';
|
||||||
import { Pressable } from '@tamagui/react-native-web-lite';
|
import { Pressable } from '@tamagui/react-native-web-lite';
|
||||||
import { Image } from '@tamagui/image';
|
import { Image } from '@tamagui/image';
|
||||||
import { Progress } from '@tamagui/progress';
|
|
||||||
import { isSameDay, isPast, isFuture, parseISO, differenceInDays, startOfDay } from 'date-fns';
|
import { isSameDay, isPast, isFuture, parseISO, differenceInDays, startOfDay } from 'date-fns';
|
||||||
|
|
||||||
import { MobileShell } from './components/MobileShell';
|
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';
|
const locale = i18n.language?.startsWith('en') ? 'en-GB' : 'de-DE';
|
||||||
|
|
||||||
React.useEffect(() => {
|
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 (
|
return (
|
||||||
<MobileShell activeTab="home" title={t('mobileDashboard.title', 'Dashboard')}>
|
<MobileShell activeTab="home" title={t('mobileDashboard.title', 'Dashboard')}>
|
||||||
|
|
||||||
@@ -203,8 +202,8 @@ export default function MobileDashboardPage() {
|
|||||||
readiness={readiness}
|
readiness={readiness}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 1b. SETUP CHECKLIST (Only in Setup Phase) */}
|
{/* 1b. SETUP CHECKLIST */}
|
||||||
{phase === 'setup' && !readiness.isReady && (
|
{phase === 'setup' && (
|
||||||
<SetupChecklist
|
<SetupChecklist
|
||||||
steps={readiness.steps}
|
steps={readiness.steps}
|
||||||
title={t('management:photobooth.checklist.title', 'Checklist')}
|
title={t('management:photobooth.checklist.title', 'Checklist')}
|
||||||
@@ -334,9 +333,10 @@ function LifecycleHero({ event, stats, locale, navigate, onSwitch, canSwitch, re
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SETUP PHASE
|
// SETUP
|
||||||
// We removed the big button. We show high-level status.
|
const nextStep = readiness.nextStep;
|
||||||
const progressPercent = (readiness.progress ?? 0) * 100;
|
const ctaLabel = nextStep ? nextStep.ctaLabel : t('dashboard:onboarding.hero.cta', 'Setup Complete');
|
||||||
|
const ctaAction = nextStep ? () => navigate(adminPath(nextStep.targetPath)) : undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<YStack>
|
<YStack>
|
||||||
@@ -358,17 +358,21 @@ function LifecycleHero({ event, stats, locale, navigate, onSwitch, canSwitch, re
|
|||||||
|
|
||||||
<YStack height={1} backgroundColor={theme.border} />
|
<YStack height={1} backgroundColor={theme.border} />
|
||||||
|
|
||||||
<YStack space="$1.5">
|
{/* Main CTA if not ready */}
|
||||||
<XStack alignItems="center" justifyContent="space-between">
|
{!readiness.isReady && (
|
||||||
<Text fontSize="$sm" color={theme.textStrong} fontWeight="600">
|
<ModernButton
|
||||||
{t('management:photobooth.checklist.title', 'Setup Status')}
|
label={ctaLabel}
|
||||||
</Text>
|
tone='primary'
|
||||||
<Text fontSize="$xs" color={theme.muted}>{readiness.completedSteps}/{readiness.totalSteps}</Text>
|
icon={<ArrowRight size={16} color="white" />}
|
||||||
|
onPress={ctaAction}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{readiness.isReady && (
|
||||||
|
<XStack alignItems="center" space="$2">
|
||||||
|
<CheckCircle2 size={18} color={theme.successText} />
|
||||||
|
<Text fontSize="$sm" color={theme.successText} fontWeight="700">Ready for Liftoff</Text>
|
||||||
</XStack>
|
</XStack>
|
||||||
<Progress value={progressPercent} max={100} size="$2" backgroundColor={theme.surfaceMuted} borderWidth={0}>
|
)}
|
||||||
<Progress.Indicator backgroundColor={theme.primary} />
|
|
||||||
</Progress>
|
|
||||||
</YStack>
|
|
||||||
</ModernCard>
|
</ModernCard>
|
||||||
</YStack>
|
</YStack>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { useNavigate } from 'react-router-dom';
|
|||||||
import { YStack, XStack } from '@tamagui/stacks';
|
import { YStack, XStack } from '@tamagui/stacks';
|
||||||
import { SizableText as Text } from '@tamagui/text';
|
import { SizableText as Text } from '@tamagui/text';
|
||||||
import { Pressable } from '@tamagui/react-native-web-lite';
|
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 { useAdminTheme } from '../theme';
|
||||||
import { ReadinessStep } from '../hooks/useEventReadiness';
|
import { ReadinessStep } from '../hooks/useEventReadiness';
|
||||||
import { adminPath } from '../../constants';
|
import { adminPath } from '../../constants';
|
||||||
@@ -11,10 +11,10 @@ import { adminPath } from '../../constants';
|
|||||||
export function SetupChecklist({ steps, title }: { steps: ReadinessStep[]; title: string }) {
|
export function SetupChecklist({ steps, title }: { steps: ReadinessStep[]; title: string }) {
|
||||||
const theme = useAdminTheme();
|
const theme = useAdminTheme();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const isAllComplete = steps.every(s => s.isComplete);
|
||||||
|
const [collapsed, setCollapsed] = React.useState(isAllComplete);
|
||||||
|
|
||||||
if (steps.every(s => s.isComplete)) {
|
const completedCount = steps.filter(s => s.isComplete).length;
|
||||||
return null; // Don't show if all done
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<YStack
|
<YStack
|
||||||
@@ -26,12 +26,27 @@ export function SetupChecklist({ steps, title }: { steps: ReadinessStep[]; title
|
|||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
style={{ boxShadow: `0 2px 8px ${theme.shadow}` }}
|
style={{ boxShadow: `0 2px 8px ${theme.shadow}` }}
|
||||||
>
|
>
|
||||||
<YStack padding="$3.5" paddingBottom="$2">
|
<Pressable onPress={() => setCollapsed(!collapsed)}>
|
||||||
|
<XStack padding="$3.5" paddingVertical="$3" alignItems="center" justifyContent="space-between">
|
||||||
|
<XStack alignItems="center" space="$2">
|
||||||
<Text fontSize="$xs" fontWeight="700" color={theme.muted} textTransform="uppercase" letterSpacing={1}>
|
<Text fontSize="$xs" fontWeight="700" color={theme.muted} textTransform="uppercase" letterSpacing={1}>
|
||||||
{title}
|
{title}
|
||||||
</Text>
|
</Text>
|
||||||
</YStack>
|
{isAllComplete && (
|
||||||
|
<CheckCircle2 size={14} color={theme.successText} />
|
||||||
|
)}
|
||||||
|
</XStack>
|
||||||
|
|
||||||
|
<XStack alignItems="center" space="$2">
|
||||||
|
<Text fontSize="$xs" color={theme.muted} fontWeight="600">
|
||||||
|
{completedCount}/{steps.length}
|
||||||
|
</Text>
|
||||||
|
{collapsed ? <ChevronDown size={16} color={theme.muted} /> : <ChevronUp size={16} color={theme.muted} />}
|
||||||
|
</XStack>
|
||||||
|
</XStack>
|
||||||
|
</Pressable>
|
||||||
|
|
||||||
|
{!collapsed && (
|
||||||
<YStack>
|
<YStack>
|
||||||
{steps.map((step, index) => {
|
{steps.map((step, index) => {
|
||||||
const isNext = !step.isComplete && steps.slice(0, index).every(s => s.isComplete);
|
const isNext = !step.isComplete && steps.slice(0, index).every(s => s.isComplete);
|
||||||
@@ -86,6 +101,7 @@ export function SetupChecklist({ steps, title }: { steps: ReadinessStep[]; title
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</YStack>
|
</YStack>
|
||||||
|
)}
|
||||||
</YStack>
|
</YStack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user