130 lines
4.1 KiB
TypeScript
130 lines
4.1 KiB
TypeScript
import React from 'react';
|
|
import { XStack } from '@tamagui/stacks';
|
|
import { SizableText as Text } from '@tamagui/text';
|
|
import { Button } from '@tamagui/button';
|
|
import { Bell, Settings } from 'lucide-react';
|
|
import { DEFAULT_EVENT_BRANDING, useOptionalEventBranding } from '@/guest/context/EventBrandingContext';
|
|
import EventLogo from './EventLogo';
|
|
import { useGuestThemeVariant } from '../lib/guestTheme';
|
|
|
|
type TopBarProps = {
|
|
eventName: string;
|
|
eventIcon?: string | null;
|
|
onProfilePress?: () => void;
|
|
onNotificationsPress?: () => void;
|
|
notificationCount?: number;
|
|
};
|
|
|
|
export default function TopBar({
|
|
eventName,
|
|
eventIcon,
|
|
onProfilePress,
|
|
onNotificationsPress,
|
|
notificationCount = 0,
|
|
}: TopBarProps) {
|
|
const { isDark } = useGuestThemeVariant();
|
|
const brandingContext = useOptionalEventBranding();
|
|
const branding = brandingContext?.branding ?? DEFAULT_EVENT_BRANDING;
|
|
const logoPosition = branding.logo?.position ?? 'left';
|
|
const [animationKey, setAnimationKey] = React.useState(0);
|
|
|
|
React.useEffect(() => {
|
|
setAnimationKey((prev) => prev + 1);
|
|
}, [eventName]);
|
|
|
|
const identityDirection = logoPosition === 'right'
|
|
? 'row-reverse'
|
|
: logoPosition === 'center'
|
|
? 'column'
|
|
: 'row';
|
|
const identityAlign = logoPosition === 'center' ? 'center' : 'flex-start';
|
|
|
|
return (
|
|
<XStack
|
|
alignItems="center"
|
|
justifyContent="space-between"
|
|
paddingHorizontal="$4"
|
|
paddingVertical="$3"
|
|
style={{
|
|
backgroundColor: 'transparent',
|
|
backdropFilter: 'saturate(120%) blur(8px)',
|
|
WebkitBackdropFilter: 'saturate(120%) blur(8px)',
|
|
}}
|
|
>
|
|
<XStack
|
|
key={animationKey}
|
|
alignItems={identityAlign}
|
|
gap="$2"
|
|
flexDirection={identityDirection}
|
|
flexShrink={1}
|
|
minWidth={0}
|
|
>
|
|
<EventLogo name={eventName} icon={eventIcon} logo={branding.logo} size="s" />
|
|
<Text
|
|
fontSize="$8"
|
|
fontFamily="$display"
|
|
fontWeight="$8"
|
|
numberOfLines={1}
|
|
className="guest-topbar-title"
|
|
textAlign={logoPosition === 'center' ? 'center' : 'left'}
|
|
flexShrink={1}
|
|
minWidth={0}
|
|
style={{ fontSize: 'clamp(20px, 4.6vw, 30px)', lineHeight: '1.1' }}
|
|
>
|
|
{eventName}
|
|
</Text>
|
|
</XStack>
|
|
<XStack gap="$2" alignItems="center">
|
|
<Button
|
|
size="$3"
|
|
circular
|
|
borderWidth={1}
|
|
borderColor={isDark ? 'rgba(255, 255, 255, 0.14)' : 'rgba(15, 23, 42, 0.14)'}
|
|
style={{
|
|
backgroundColor: isDark ? 'rgba(255, 255, 255, 0.08)' : 'rgba(15, 23, 42, 0.06)',
|
|
boxShadow: isDark ? '0 8px 18px rgba(2, 6, 23, 0.4)' : '0 8px 18px rgba(15, 23, 42, 0.12)',
|
|
position: 'relative',
|
|
}}
|
|
onPress={onNotificationsPress}
|
|
>
|
|
<Bell size={16} color={isDark ? '#F8FAFF' : '#0F172A'} />
|
|
{notificationCount > 0 ? (
|
|
<span
|
|
style={{
|
|
position: 'absolute',
|
|
top: -2,
|
|
right: -2,
|
|
width: 18,
|
|
height: 18,
|
|
borderRadius: 999,
|
|
backgroundColor: '#F97316',
|
|
color: '#0B101E',
|
|
fontSize: 10,
|
|
fontWeight: 700,
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
}}
|
|
>
|
|
{notificationCount > 9 ? '9+' : notificationCount}
|
|
</span>
|
|
) : null}
|
|
</Button>
|
|
<Button
|
|
size="$3"
|
|
circular
|
|
borderWidth={1}
|
|
borderColor={isDark ? 'rgba(255, 255, 255, 0.14)' : 'rgba(15, 23, 42, 0.14)'}
|
|
style={{
|
|
backgroundColor: isDark ? 'rgba(255, 255, 255, 0.08)' : 'rgba(15, 23, 42, 0.06)',
|
|
boxShadow: isDark ? '0 8px 18px rgba(2, 6, 23, 0.4)' : '0 8px 18px rgba(15, 23, 42, 0.12)',
|
|
}}
|
|
onPress={onProfilePress}
|
|
>
|
|
<Settings size={16} color={isDark ? '#F8FAFF' : '#0F172A'} />
|
|
</Button>
|
|
</XStack>
|
|
</XStack>
|
|
);
|
|
}
|