Refresh mobile dashboard and header
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import React, { Suspense } from 'react';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import { ChevronLeft, Bell, QrCode } from 'lucide-react';
|
||||
import { ChevronLeft, Bell, QrCode, ChevronsUpDown } from 'lucide-react';
|
||||
import { YStack, XStack } from '@tamagui/stacks';
|
||||
import { SizableText as Text } from '@tamagui/text';
|
||||
import { Pressable } from '@tamagui/react-native-web-lite';
|
||||
@@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { useEventContext } from '../../context/EventContext';
|
||||
import { BottomNav, NavKey } from './BottomNav';
|
||||
import { useMobileNav } from '../hooks/useMobileNav';
|
||||
import { adminPath } from '../../constants';
|
||||
import { ADMIN_EVENTS_PATH, adminPath } from '../../constants';
|
||||
import { MobileCard, CTAButton } from './Primitives';
|
||||
import { useNotificationsBadge } from '../hooks/useNotificationsBadge';
|
||||
import { useOnlineStatus } from '../hooks/useOnlineStatus';
|
||||
@@ -31,7 +31,7 @@ type MobileShellProps = {
|
||||
};
|
||||
|
||||
export function MobileShell({ title, subtitle, children, activeTab, onBack, headerActions }: MobileShellProps) {
|
||||
const { events, activeEvent, selectEvent } = useEventContext();
|
||||
const { events, activeEvent, hasMultipleEvents, selectEvent } = useEventContext();
|
||||
const { user } = useAuth();
|
||||
const { go } = useMobileNav(activeEvent?.slug, activeTab);
|
||||
const navigate = useNavigate();
|
||||
@@ -137,7 +137,13 @@ export function MobileShell({ title, subtitle, children, activeTab, onBack, head
|
||||
}, []);
|
||||
|
||||
const pageTitle = title ?? t('header.appName', 'Event Admin');
|
||||
const eventContext = !isCompactHeader && effectiveActive ? resolveEventDisplayName(effectiveActive) : null;
|
||||
const eventContext = !isCompactHeader
|
||||
? effectiveActive
|
||||
? resolveEventDisplayName(effectiveActive)
|
||||
: hasMultipleEvents
|
||||
? t('header.selectEvent', 'Select an event')
|
||||
: null
|
||||
: null;
|
||||
const subtitleText = subtitle ?? eventContext ?? '';
|
||||
const isMember = user?.role === 'member';
|
||||
const memberPermissions = Array.isArray(effectiveActive?.member_permissions) ? effectiveActive?.member_permissions ?? [] : [];
|
||||
@@ -164,22 +170,55 @@ export function MobileShell({ title, subtitle, children, activeTab, onBack, head
|
||||
) : (
|
||||
<XStack width={28} />
|
||||
);
|
||||
const headerTitle = (
|
||||
<XStack alignItems="center" space="$1" flex={1} minWidth={0} justifyContent="flex-end">
|
||||
<YStack alignItems="flex-end" maxWidth="100%">
|
||||
<Text fontSize="$lg" fontWeight="800" fontFamily="$display" color={textColor} textAlign="right" numberOfLines={1}>
|
||||
{pageTitle}
|
||||
const headerTitleRight = (
|
||||
<YStack alignItems="flex-end" maxWidth="100%">
|
||||
<Text fontSize="$lg" fontWeight="800" fontFamily="$display" color={textColor} textAlign="right" numberOfLines={1}>
|
||||
{pageTitle}
|
||||
</Text>
|
||||
{subtitleText ? (
|
||||
<Text fontSize="$xs" color={mutedText} textAlign="right" numberOfLines={1} fontFamily="$body">
|
||||
{subtitleText}
|
||||
</Text>
|
||||
{subtitleText ? (
|
||||
<Text fontSize="$xs" color={mutedText} textAlign="right" numberOfLines={1} fontFamily="$body">
|
||||
{subtitleText}
|
||||
</Text>
|
||||
) : null}
|
||||
</YStack>
|
||||
</XStack>
|
||||
) : null}
|
||||
</YStack>
|
||||
);
|
||||
const headerTitleCenter = (
|
||||
<YStack alignItems="center" maxWidth="100%">
|
||||
<Text fontSize="$lg" fontWeight="800" fontFamily="$display" color={textColor} textAlign="center" numberOfLines={1}>
|
||||
{pageTitle}
|
||||
</Text>
|
||||
{subtitleText ? (
|
||||
<Text fontSize="$xs" color={mutedText} textAlign="center" numberOfLines={1} fontFamily="$body">
|
||||
{subtitleText}
|
||||
</Text>
|
||||
) : null}
|
||||
</YStack>
|
||||
);
|
||||
const isEventsIndex = location.pathname === ADMIN_EVENTS_PATH;
|
||||
const canSwitchEvents = hasMultipleEvents && !isEventsIndex;
|
||||
const headerActionsRow = (
|
||||
<XStack alignItems="center" space="$2">
|
||||
{canSwitchEvents ? (
|
||||
<HeaderActionButton onPress={() => navigate(ADMIN_EVENTS_PATH)} ariaLabel={t('header.switchEvent', 'Switch event')}>
|
||||
<XStack
|
||||
width={34}
|
||||
height={34}
|
||||
borderRadius={12}
|
||||
backgroundColor={actionSurface}
|
||||
borderWidth={1}
|
||||
borderColor={actionBorder}
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
style={{
|
||||
boxShadow: `0 10px 18px ${actionShadow}`,
|
||||
backdropFilter: 'blur(12px)',
|
||||
WebkitBackdropFilter: 'blur(12px)',
|
||||
}}
|
||||
>
|
||||
<ChevronsUpDown size={16} color={textColor} />
|
||||
</XStack>
|
||||
</HeaderActionButton>
|
||||
) : null}
|
||||
<HeaderActionButton
|
||||
onPress={() => navigate(adminPath('/mobile/notifications'))}
|
||||
ariaLabel={t('mobile.notifications', 'Notifications')}
|
||||
@@ -273,22 +312,28 @@ export function MobileShell({ title, subtitle, children, activeTab, onBack, head
|
||||
}}
|
||||
>
|
||||
{isCompactHeader ? (
|
||||
<YStack space="$2">
|
||||
<XStack alignItems="center" justifyContent="space-between" minHeight={48} space="$3">
|
||||
{headerBackButton}
|
||||
<XStack flex={1} minWidth={0} justifyContent="flex-end">
|
||||
{headerTitle}
|
||||
</XStack>
|
||||
<XStack
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
minHeight={48}
|
||||
space="$3"
|
||||
flexWrap="wrap"
|
||||
>
|
||||
{headerBackButton}
|
||||
<XStack flex={1} minWidth={120} justifyContent="center">
|
||||
{headerTitleCenter}
|
||||
</XStack>
|
||||
<XStack alignItems="center" justifyContent="flex-end">
|
||||
<XStack justifyContent="flex-end" flexShrink={0} style={{ marginLeft: 'auto' }}>
|
||||
{headerActionsRow}
|
||||
</XStack>
|
||||
</YStack>
|
||||
</XStack>
|
||||
) : (
|
||||
<XStack alignItems="center" justifyContent="space-between" minHeight={48} space="$3">
|
||||
{headerBackButton}
|
||||
<XStack alignItems="center" space="$2.5" flex={1} justifyContent="flex-end" minWidth={0}>
|
||||
{headerTitle}
|
||||
<XStack flex={1} minWidth={0} justifyContent="flex-end">
|
||||
{headerTitleRight}
|
||||
</XStack>
|
||||
{headerActionsRow}
|
||||
</XStack>
|
||||
</XStack>
|
||||
|
||||
Reference in New Issue
Block a user