Files
fotospiel-app/resources/js/admin/mobile/components/SetupChecklist.tsx
Codex Agent 1e821a2fb4
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled
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
2026-01-18 10:08:39 +01:00

107 lines
4.1 KiB
TypeScript

import React from 'react';
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, ChevronDown, ChevronUp } from 'lucide-react';
import { useAdminTheme } from '../theme';
import { ReadinessStep } from '../hooks/useEventReadiness';
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);
const completedCount = steps.filter(s => s.isComplete).length;
return (
<YStack
backgroundColor={theme.surface}
borderRadius={16}
borderWidth={1}
borderColor={theme.border}
padding="$0"
overflow="hidden"
style={{ boxShadow: `0 2px 8px ${theme.shadow}` }}
>
<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}>
{title}
</Text>
{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>
{steps.map((step, index) => {
const isNext = !step.isComplete && steps.slice(0, index).every(s => s.isComplete);
return (
<Pressable
key={step.id}
onPress={() => navigate(adminPath(step.targetPath))}
style={{
backgroundColor: isNext ? theme.surface : 'transparent',
}}
>
<XStack
paddingHorizontal="$3.5"
paddingVertical="$3"
alignItems="center"
space="$3"
borderTopWidth={1}
borderColor={theme.border}
>
{step.isComplete ? (
<CheckCircle2 size={20} color={theme.successText} />
) : isNext ? (
<Circle size={20} color={theme.primary} strokeWidth={2.5} />
) : (
<Circle size={20} color={theme.border} />
)}
<YStack flex={1} space="$0.5">
<Text
fontSize="$sm"
fontWeight={isNext ? "700" : "500"}
color={step.isComplete ? theme.muted : theme.textStrong}
textDecorationLine={step.isComplete ? 'line-through' : 'none'}
>
{step.label}
</Text>
{step.description && !step.isComplete && (
<Text fontSize="$xs" color={theme.muted}>
{step.description}
</Text>
)}
</YStack>
{isNext && (
<YStack backgroundColor={theme.primary} borderRadius={999} paddingHorizontal="$2.5" paddingVertical="$1.5">
<Text fontSize="$xs" color="white" fontWeight="700">Start</Text>
</YStack>
)}
</XStack>
</Pressable>
);
})}
</YStack>
)}
</YStack>
);
}