Compact dashboard overview
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

This commit is contained in:
Codex Agent
2026-01-22 16:51:05 +01:00
parent 64c9d7357a
commit 66193a6461
2 changed files with 43 additions and 30 deletions

View File

@@ -199,16 +199,15 @@ export default function MobileDashboardPage() {
return (
<MobileShell activeTab="home" title={t('mobileDashboard.title', 'Dashboard')}>
<DashboardCard padding="$0">
<YStack padding="$3.5" space="$2">
<YStack padding="$3" space="$2">
<SectionHeader
title={t('dashboard:overview.title', 'At a glance')}
subtitle={t('dashboard:overview.description', 'Key customer metrics at a glance.')}
showSeparator={false}
compact
/>
</YStack>
<Separator backgroundColor={theme.border} opacity={0.6} />
<YStack padding="$3.5" space="$2.5">
<YStack padding="$3" space="$2.5">
{/* 1. LIFECYCLE HERO */}
<LifecycleHero
event={activeEvent}
@@ -223,12 +222,13 @@ export default function MobileDashboardPage() {
{phase === 'setup' && (
<SetupChecklist
steps={readiness.steps}
title={t('management:photobooth.checklist.title', 'Checklist')}
title={t('dashboard:readiness.title', 'Bereit für den Eventstart')}
variant="embedded"
/>
)}
{/* 2. PULSE STRIP */}
<Separator backgroundColor={theme.border} opacity={0.6} />
<PulseStrip event={activeEvent} stats={stats} />
</YStack>
</DashboardCard>
@@ -400,6 +400,7 @@ function LifecycleHero({ event, stats, locale, navigate, readiness, variant = 'd
const nextStep = readiness.nextStep;
const ctaLabel = nextStep ? nextStep.ctaLabel : t('dashboard:onboarding.hero.cta', 'Setup Complete');
const ctaAction = nextStep ? () => navigate(adminPath(nextStep.targetPath)) : undefined;
const showCta = Boolean(nextStep);
return (
<YStack space="$2">
@@ -423,9 +424,9 @@ function LifecycleHero({ event, stats, locale, navigate, readiness, variant = 'd
</YStack>
</XStack>
<Separator backgroundColor={theme.border} opacity={0.6} />
{showCta ? <Separator backgroundColor={theme.border} opacity={0.6} /> : null}
{!readiness.isReady ? (
{showCta ? (
<Button
onPress={ctaAction}
backgroundColor={theme.primary}
@@ -440,14 +441,7 @@ function LifecycleHero({ event, stats, locale, navigate, readiness, variant = 'd
<ChevronRight size={16} color="white" />
</XStack>
</Button>
) : (
<XStack alignItems="center" space="$2">
<CheckCircle2 size={18} color={theme.successText} />
<Text fontSize="$sm" color={theme.successText} fontWeight="700">
{t('management:mobileDashboard.readyForLiftoff', 'Ready for Liftoff')}
</Text>
</XStack>
)}
) : null}
</YStack>
</DashboardCard>
</YStack>

View File

@@ -1,8 +1,10 @@
import React from 'react';
import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { Card } from '@tamagui/card';
import { YGroup } from '@tamagui/group';
import { ListItem } from '@tamagui/list-item';
import { Progress } from '@tamagui/progress';
import { YStack, XStack } from '@tamagui/stacks';
import { SizableText as Text } from '@tamagui/text';
import { Pressable } from '@tamagui/react-native-web-lite';
@@ -23,12 +25,15 @@ export function SetupChecklist({
variant?: 'card' | 'embedded';
}) {
const theme = useAdminTheme();
const { t } = useTranslation('dashboard');
const navigate = useNavigate();
const isAllComplete = steps.every(s => s.isComplete);
const [collapsed, setCollapsed] = React.useState(isAllComplete);
const isEmbedded = variant === 'embedded';
const completedCount = steps.filter(s => s.isComplete).length;
const totalSteps = steps.length;
const progressValue = totalSteps > 0 ? Math.round((completedCount / totalSteps) * 100) : 0;
return (
<Card
@@ -44,23 +49,37 @@ export function SetupChecklist({
shadowOffset={isEmbedded ? { width: 0, height: 0 } : { width: 0, height: 10 }}
>
<Pressable onPress={() => setCollapsed(!collapsed)}>
<XStack padding="$3" paddingVertical="$2.5" alignItems="center" justifyContent="space-between">
<XStack alignItems="center" space="$2">
<Text fontSize="$xs" fontWeight="700" color={theme.muted} textTransform="uppercase" letterSpacing={1}>
<YStack padding="$3" paddingVertical="$2.5" space="$2">
<XStack 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>
</Text>
<PillBadge tone={isAllComplete ? 'success' : 'warning'}>
{isAllComplete ? t('readiness.complete', 'Erledigt') : t('readiness.pending', 'Noch offen')}
</PillBadge>
</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>
<Progress
value={progressValue}
size="$1"
backgroundColor={theme.surfaceMuted}
height={6}
>
<Progress.Indicator
backgroundColor={isAllComplete ? theme.success : theme.primary}
animation="bouncy"
/>
</Progress>
</YStack>
</Pressable>
{!collapsed && (