import React from 'react'; import { YStack } from '@tamagui/stacks'; import { SizableText as Text } from '@tamagui/text'; import { Camera, Heart, PartyPopper, Users } from 'lucide-react'; import { DEFAULT_EVENT_BRANDING, useOptionalEventBranding } from '@/guest/context/EventBrandingContext'; import { getContrastingTextColor } from '@/guest/lib/color'; import type { EventBranding } from '@/guest/types/event-branding'; type LogoSize = 's' | 'm' | 'l'; type EventLogoProps = { name: string; icon?: string | null; logo?: EventBranding['logo'] | null; size?: LogoSize; }; const EVENT_ICON_COMPONENTS: Record> = { heart: Heart, guests: Users, party: PartyPopper, camera: Camera, }; const LOGO_SIZE_MAP: Record = { s: { container: 32, image: 24, emoji: 16, icon: 14, text: 12 }, m: { container: 40, image: 30, emoji: 18, icon: 18, text: 14 }, l: { container: 48, image: 38, emoji: 22, icon: 22, text: 16 }, }; function isLikelyEmoji(value: string): boolean { if (!value) { return false; } const characters = Array.from(value.trim()); if (characters.length === 0 || characters.length > 2) { return false; } return characters.some((char) => { const codePoint = char.codePointAt(0) ?? 0; return codePoint > 0x2600; }); } function getInitials(name: string): string { const words = name.split(' ').filter(Boolean); if (words.length >= 2) { return `${words[0][0]}${words[1][0]}`.toUpperCase(); } return name.substring(0, 2).toUpperCase(); } export default function EventLogo({ name, icon, logo, size }: EventLogoProps) { const brandingContext = useOptionalEventBranding(); const branding = brandingContext?.branding ?? DEFAULT_EVENT_BRANDING; const resolvedLogo = logo ?? branding.logo; const logoMode = resolvedLogo?.mode ?? (branding.logoUrl ? 'upload' : 'emoticon'); const logoValue = resolvedLogo?.value ?? branding.logoUrl ?? null; const logoSize = size ?? resolvedLogo?.size ?? 'm'; const sizes = LOGO_SIZE_MAP[logoSize]; const accentColor = branding.secondaryColor || DEFAULT_EVENT_BRANDING.secondaryColor; const textColor = getContrastingTextColor(accentColor, '#ffffff', '#0f172a'); const [logoFailed, setLogoFailed] = React.useState(false); React.useEffect(() => { setLogoFailed(false); }, [logoValue]); if (logoMode === 'upload' && logoValue && !logoFailed) { return ( {name} setLogoFailed(true)} /> ); } if (logoMode === 'emoticon' && logoValue && isLikelyEmoji(logoValue)) { return ( {logoValue} ); } if (typeof icon === 'string') { const trimmed = icon.trim(); if (trimmed) { const normalized = trimmed.toLowerCase(); const IconComponent = EVENT_ICON_COMPONENTS[normalized]; if (IconComponent) { return ( ); } if (isLikelyEmoji(trimmed)) { return ( {trimmed} ); } } } return ( {getInitials(name)} ); }