import React, { useState, useCallback } from 'react'; import { X, Info, AlertTriangle, AlertCircle } from 'lucide-react'; import { useGetApiV1AnnouncementsActive } from '@/services/generated/admin/admin'; import { cn } from '@/lib/utils'; interface Announcement { id: string; title: string; content: string; type: string; } const DISMISSED_KEY = 'veza-dismissed-announcements'; function loadDismissed(): Set { try { const raw = localStorage.getItem(DISMISSED_KEY); return raw ? new Set(JSON.parse(raw)) : new Set(); } catch { return new Set(); } } function saveDismissed(ids: Set) { try { localStorage.setItem(DISMISSED_KEY, JSON.stringify([...ids])); } catch { /* ignore */ } } const defaultConfig = { icon: Info, className: 'bg-primary/10 border-[var(--sumi-border-faint)] text-foreground' }; const typeConfig: Record = { info: defaultConfig, warning: { icon: AlertTriangle, className: 'bg-warning/10 border-warning/30 text-foreground' }, error: { icon: AlertCircle, className: 'bg-destructive/10 border-destructive/30 text-foreground' }, }; export function AnnouncementBanner() { const [dismissed, setDismissed] = useState>(loadDismissed); const [showAll, setShowAll] = useState(false); // Use generated hook. apiClient response interceptor unwraps the // {success, data} envelope, so at runtime announcementsData is the // payload directly — see services/api/interceptors/response.ts. const { data: announcementsData } = useGetApiV1AnnouncementsActive(); const payload = announcementsData as unknown as { announcements?: Announcement[] } | undefined; const announcements: Announcement[] = payload?.announcements ?? []; const dismiss = useCallback((id: string) => { setDismissed((prev) => { const next = new Set(prev).add(id); saveDismissed(next); return next; }); }, []); const visible = announcements.filter((a: Announcement) => !dismissed.has(a.id)); if (visible.length === 0) return null; const shown = showAll ? visible : visible.slice(0, 1); const remaining = showAll ? 0 : visible.length - shown.length; return (
{shown.map((a: Announcement) => { const config = typeConfig[a.type] ?? defaultConfig; const Icon = config.icon; return (
{a.title} {a.content}
); })} {remaining > 0 && ( )}
); }