feat(mobile): implement event switcher sheet in header
- Replaced direct navigation with a bottom sheet for event switching - Created reusable EventSwitcherSheet component - Preserves context when switching events
This commit is contained in:
86
resources/js/admin/mobile/components/EventSwitcherSheet.tsx
Normal file
86
resources/js/admin/mobile/components/EventSwitcherSheet.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
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 } from 'lucide-react';
|
||||
import { MobileSheet } from './Sheet';
|
||||
import { useAdminTheme } from '../theme';
|
||||
import { TenantEvent } from '../../api';
|
||||
import { resolveEventDisplayName, formatEventDate } from '../../lib/events';
|
||||
import { adminPath } from '../../constants';
|
||||
|
||||
export function EventSwitcherSheet({
|
||||
open,
|
||||
onClose,
|
||||
events,
|
||||
activeSlug,
|
||||
}: {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
events: TenantEvent[];
|
||||
activeSlug: string | null;
|
||||
}) {
|
||||
const { t, i18n } = useTranslation(['management', 'mobile']);
|
||||
const navigate = useNavigate();
|
||||
const theme = useAdminTheme();
|
||||
|
||||
const locale = i18n.language;
|
||||
|
||||
const handleSelect = (slug: string) => {
|
||||
onClose();
|
||||
// Navigate to the dashboard of the selected event
|
||||
navigate(adminPath(`/mobile/events/${slug}`));
|
||||
};
|
||||
|
||||
return (
|
||||
<MobileSheet
|
||||
open={open}
|
||||
title={t('mobile:header.eventSwitcher', 'Switch Event')}
|
||||
onClose={onClose}
|
||||
snapPoints={[65]}
|
||||
>
|
||||
<YStack space="$2">
|
||||
{events.map((event) => {
|
||||
const isActive = event.slug === activeSlug;
|
||||
return (
|
||||
<Pressable key={event.slug} onPress={() => handleSelect(event.slug)}>
|
||||
<XStack
|
||||
alignItems="center"
|
||||
space="$3"
|
||||
padding="$3"
|
||||
borderRadius={14}
|
||||
backgroundColor={isActive ? theme.surfaceMuted : 'transparent'}
|
||||
borderWidth={1}
|
||||
borderColor={isActive ? theme.border : 'transparent'}
|
||||
>
|
||||
<YStack flex={1}>
|
||||
<Text fontSize="$sm" fontWeight="700" color={theme.textStrong}>
|
||||
{resolveEventDisplayName(event)}
|
||||
</Text>
|
||||
<Text fontSize="$xs" color={theme.muted}>
|
||||
{formatEventDate(event.event_date, locale)}
|
||||
</Text>
|
||||
</YStack>
|
||||
{isActive ? (
|
||||
<CheckCircle2 size={20} color={theme.primary} />
|
||||
) : (
|
||||
<Circle size={20} color={theme.border} />
|
||||
)}
|
||||
</XStack>
|
||||
</Pressable>
|
||||
);
|
||||
})}
|
||||
|
||||
<Pressable onPress={() => { onClose(); navigate(adminPath('/mobile/events/new')); }}>
|
||||
<XStack padding="$3" justifyContent="center">
|
||||
<Text fontSize="$sm" fontWeight="700" color={theme.primary}>
|
||||
{t('mobile:header.createEvent', 'Create Event')}
|
||||
</Text>
|
||||
</XStack>
|
||||
</Pressable>
|
||||
</YStack>
|
||||
</MobileSheet>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user