import { useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { AlertTriangle, CheckCircle2, Info, Megaphone, X, XCircle } from 'lucide-react'; import { listActiveBanners, type Banner } from '@/lib/api-client'; import { useDemoMode } from '@/lib/demo-mode'; const DISMISSED_KEY = 'containr.dismissed-banners'; function dismissedIds(): Set { try { return new Set(JSON.parse(localStorage.getItem(DISMISSED_KEY) ?? '[]')); } catch { return new Set(); } } const levelStyle: Record = { info: { bg: 'var(--accent-primary-soft)', fg: 'var(--accent-primary)', icon: Info }, success: { bg: 'var(--success-soft)', fg: 'var(--success)', icon: CheckCircle2 }, warning: { bg: 'var(--warning-soft)', fg: 'var(--warning)', icon: AlertTriangle }, error: { bg: 'var(--error-soft)', fg: 'var(--error)', icon: XCircle }, }; export function BannerBar() { const isDemoMode = useDemoMode(); const [dismissed, setDismissed] = useState>(dismissedIds); const bannersQuery = useQuery({ queryKey: ['active-banners'], queryFn: listActiveBanners, enabled: !isDemoMode, refetchInterval: 60_000, staleTime: 30_000, }); const banners = (bannersQuery.data ?? []).filter((b) => !dismissed.has(b.id)); if (banners.length === 0) return null; const dismiss = (id: string) => { setDismissed((prev) => { const next = new Set(prev); next.add(id); localStorage.setItem(DISMISSED_KEY, JSON.stringify([...next])); return next; }); }; return (
{banners.map((banner) => { const style = levelStyle[banner.level] ?? levelStyle.info; const Icon = banner.level === 'info' ? Megaphone : style.icon; return (
{banner.title} {banner.body ? ( {banner.body} ) : null}
{banner.dismissible ? ( ) : null}
); })}
); }