import React, { createContext, useContext, useEffect, useMemo } from 'react'; import type { EventBranding } from '../types/event-branding'; type EventBrandingContextValue = { branding: EventBranding; isCustom: boolean; }; export const DEFAULT_EVENT_BRANDING: EventBranding = { primaryColor: '#f43f5e', secondaryColor: '#fb7185', backgroundColor: '#ffffff', fontFamily: null, logoUrl: null, }; const DEFAULT_PRIMARY = DEFAULT_EVENT_BRANDING.primaryColor.toLowerCase(); const DEFAULT_SECONDARY = DEFAULT_EVENT_BRANDING.secondaryColor.toLowerCase(); const DEFAULT_BACKGROUND = DEFAULT_EVENT_BRANDING.backgroundColor.toLowerCase(); const EventBrandingContext = createContext(undefined); function normaliseHexColor(value: string | null | undefined, fallback: string): string { if (typeof value !== 'string') { return fallback; } const trimmed = value.trim(); return /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(trimmed) ? trimmed : fallback; } function resolveBranding(input?: EventBranding | null): EventBranding { if (!input) { return DEFAULT_EVENT_BRANDING; } return { primaryColor: normaliseHexColor(input.primaryColor, DEFAULT_EVENT_BRANDING.primaryColor), secondaryColor: normaliseHexColor(input.secondaryColor, DEFAULT_EVENT_BRANDING.secondaryColor), backgroundColor: normaliseHexColor(input.backgroundColor, DEFAULT_EVENT_BRANDING.backgroundColor), fontFamily: input.fontFamily?.trim() || null, logoUrl: input.logoUrl?.trim() || null, }; } function applyCssVariables(branding: EventBranding) { if (typeof document === 'undefined') { return; } const root = document.documentElement; root.style.setProperty('--guest-primary', branding.primaryColor); root.style.setProperty('--guest-secondary', branding.secondaryColor); root.style.setProperty('--guest-background', branding.backgroundColor); if (branding.fontFamily) { root.style.setProperty('--guest-font-family', branding.fontFamily); } else { root.style.removeProperty('--guest-font-family'); } } function resetCssVariables() { if (typeof document === 'undefined') { return; } const root = document.documentElement; root.style.removeProperty('--guest-primary'); root.style.removeProperty('--guest-secondary'); root.style.removeProperty('--guest-background'); root.style.removeProperty('--guest-font-family'); } export function EventBrandingProvider({ branding, children, }: { branding?: EventBranding | null; children: React.ReactNode; }) { const resolved = useMemo(() => resolveBranding(branding), [branding]); useEffect(() => { applyCssVariables(resolved); return () => { resetCssVariables(); applyCssVariables(DEFAULT_EVENT_BRANDING); }; }, [resolved]); const value = useMemo(() => ({ branding: resolved, isCustom: resolved.primaryColor.toLowerCase() !== DEFAULT_PRIMARY || resolved.secondaryColor.toLowerCase() !== DEFAULT_SECONDARY || resolved.backgroundColor.toLowerCase() !== DEFAULT_BACKGROUND, }), [resolved]); return {children}; } export function useEventBranding(): EventBrandingContextValue { const context = useContext(EventBrandingContext); if (!context) { throw new Error('useEventBranding must be used within an EventBrandingProvider'); } return context; } export function useOptionalEventBranding(): EventBrandingContextValue | undefined { return useContext(EventBrandingContext); }