neues Admin UI Layout eingeführt. Alle Tests auf den neusten Stand gebracht.

This commit is contained in:
Codex Agent
2025-12-30 10:24:06 +01:00
parent 902e78cae9
commit efe2f25b3e
85 changed files with 95235 additions and 19197 deletions

View File

@@ -16,6 +16,7 @@ import { useEventContext } from '../context/EventContext';
import { formatEventDate, isBrandingAllowed, resolveEngagementMode, resolveEventDisplayName } from '../lib/events';
import { isPastEvent } from './eventDate';
import { useBackNavigation } from './hooks/useBackNavigation';
import { ADMIN_ACTION_COLORS, ADMIN_MOTION, useAdminTheme } from './theme';
export default function MobileEventDetailPage() {
const { slug: slugParam } = useParams<{ slug?: string }>();
@@ -31,6 +32,7 @@ export default function MobileEventDetailPage() {
const { events, activeEvent, selectEvent } = useEventContext();
const [showEventPicker, setShowEventPicker] = React.useState(false);
const back = useBackNavigation(adminPath('/mobile/events'));
const { textStrong, text, muted, danger, accentSoft } = useAdminTheme();
React.useEffect(() => {
if (!slug) return;
@@ -105,33 +107,33 @@ export default function MobileEventDetailPage() {
headerActions={
<XStack space="$3" alignItems="center">
<HeaderActionButton onPress={() => navigate(adminPath('/mobile/settings'))} ariaLabel={t('mobileSettings.title', 'Settings')}>
<Settings size={18} color="#0f172a" />
<Settings size={18} color={textStrong} />
</HeaderActionButton>
<HeaderActionButton onPress={() => navigate(0)} ariaLabel={t('common.refresh', 'Refresh')}>
<RefreshCcw size={18} color="#0f172a" />
<RefreshCcw size={18} color={textStrong} />
</HeaderActionButton>
</XStack>
}
>
{error ? (
<MobileCard>
<Text fontWeight="700" color="#b91c1c">
<Text fontWeight="700" color={danger}>
{error}
</Text>
</MobileCard>
) : null}
<MobileCard space="$3">
<Text fontSize="$lg" fontWeight="800" color="#111827">
<Text fontSize="$lg" fontWeight="800" color={textStrong}>
{event ? renderName(event.name, t) : t('events.placeholders.untitled', 'Unbenanntes Event')}
</Text>
<XStack alignItems="center" space="$2">
<CalendarDays size={16} color="#6b7280" />
<Text fontSize="$sm" color="#4b5563">
<CalendarDays size={16} color={muted} />
<Text fontSize="$sm" color={muted}>
{formatDate(event?.event_date, t)}
</Text>
<MapPin size={16} color="#6b7280" />
<Text fontSize="$sm" color="#4b5563">
<MapPin size={16} color={muted} />
<Text fontSize="$sm" color={muted}>
{resolveLocation(event, t)}
</Text>
</XStack>
@@ -148,13 +150,13 @@ export default function MobileEventDetailPage() {
width: 44,
height: 44,
borderRadius: 22,
backgroundColor: '#e2e8f0',
backgroundColor: accentSoft,
alignItems: 'center',
justifyContent: 'center',
boxShadow: '0 6px 16px rgba(0,0,0,0.12)',
}}
>
<Pencil size={18} color="#0f172a" />
<Pencil size={18} color={textStrong} />
</Pressable>
</MobileCard>
@@ -183,7 +185,7 @@ export default function MobileEventDetailPage() {
>
<YStack space="$2">
{events.length === 0 ? (
<Text fontSize={12.5} color="#4b5563">
<Text fontSize={12.5} color={muted}>
{t('events.list.empty.description', 'Starte jetzt mit deinem ersten Event.')}
</Text>
) : (
@@ -198,12 +200,12 @@ export default function MobileEventDetailPage() {
>
<XStack alignItems="center" justifyContent="space-between" paddingVertical="$2">
<YStack space="$1">
<Text fontSize={13} fontWeight="700" color="#111827">
<Text fontSize={13} fontWeight="700" color={textStrong}>
{renderName(ev.name, t)}
</Text>
<XStack alignItems="center" space="$1.5">
<CalendarDays size={14} color="#6b7280" />
<Text fontSize={12} color="#4b5563">
<CalendarDays size={14} color={muted} />
<Text fontSize={12} color={muted}>
{formatDate(ev.event_date, t)}
</Text>
</XStack>
@@ -219,7 +221,7 @@ export default function MobileEventDetailPage() {
</MobileSheet>
<YStack space="$2">
<Text fontSize="$md" fontWeight="800" color="#111827">
<Text fontSize="$md" fontWeight="800" color={textStrong}>
{t('events.detail.managementTitle', 'Event Management')}
</Text>
<XStack flexWrap="wrap" space="$2">
@@ -230,55 +232,63 @@ export default function MobileEventDetailPage() {
? t('events.quick.tasks', 'Tasks & Checklists')
: `${t('events.quick.tasks', 'Tasks & Checklists')} (${t('common:states.disabled', 'Disabled')})`
}
color="#60a5fa"
color={ADMIN_ACTION_COLORS.tasks}
onPress={() => navigate(adminPath(`/mobile/events/${slug ?? ''}/tasks`))}
delayMs={0}
/>
<ActionTile
icon={QrCode}
label={t('events.quick.qr', 'QR Code Layouts')}
color="#fbbf24"
color={ADMIN_ACTION_COLORS.qr}
onPress={() => navigate(adminPath(`/mobile/events/${slug ?? ''}/qr`))}
delayMs={ADMIN_MOTION.tileStaggerMs}
/>
<ActionTile
icon={Image}
label={t('events.quick.images', 'Image Management')}
color="#a855f7"
color={ADMIN_ACTION_COLORS.images}
onPress={() => navigate(adminPath(`/mobile/events/${slug ?? ''}/photos`))}
delayMs={ADMIN_MOTION.tileStaggerMs * 2}
/>
<ActionTile
icon={Users}
label={t('events.quick.guests', 'Guest Management')}
color="#4ade80"
color={ADMIN_ACTION_COLORS.guests}
onPress={() => navigate(adminPath(`/mobile/events/${slug ?? ''}/members`))}
delayMs={ADMIN_MOTION.tileStaggerMs * 3}
/>
<ActionTile
icon={Megaphone}
label={t('events.quick.guestMessages', 'Guest messages')}
color="#fb923c"
color={ADMIN_ACTION_COLORS.guestMessages}
onPress={() => slug && navigate(ADMIN_EVENT_GUEST_NOTIFICATIONS_PATH(slug))}
disabled={!slug}
delayMs={ADMIN_MOTION.tileStaggerMs * 4}
/>
<ActionTile
icon={Layout}
label={t('events.quick.branding', 'Branding & Theme')}
color="#fb7185"
color={ADMIN_ACTION_COLORS.branding}
onPress={
brandingAllowed ? () => navigate(adminPath(`/mobile/events/${slug ?? ''}/branding`)) : undefined
}
disabled={!brandingAllowed}
delayMs={ADMIN_MOTION.tileStaggerMs * 5}
/>
<ActionTile
icon={Camera}
label={t('events.quick.photobooth', 'Photobooth')}
color="#38bdf8"
color={ADMIN_ACTION_COLORS.photobooth}
onPress={() => navigate(adminPath(`/mobile/events/${slug ?? ''}/photobooth`))}
delayMs={ADMIN_MOTION.tileStaggerMs * 6}
/>
{isPastEvent(event?.event_date) ? (
<ActionTile
icon={Sparkles}
label={t('events.quick.recap', 'Recap & Archive')}
color="#f59e0b"
color={ADMIN_ACTION_COLORS.recap}
onPress={() => navigate(adminPath(`/mobile/events/${slug ?? ''}/recap`))}
delayMs={ADMIN_MOTION.tileStaggerMs * 7}
/>
) : null}
</XStack>