import { useState } from 'react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { AlertCircle, AlertTriangle, Info, ChevronDown, ChevronUp, Clock, Zap, RefreshCw, Loader2 } from 'lucide-react'; import { formatDistanceToNow } from 'date-fns'; import type { GroupedAlert } from '@/hooks/admin/useGroupedAlerts'; import { useResolveAlertGroup, useSnoozeAlertGroup } from '@/hooks/admin/useAlertGroupActions'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; interface GroupedAlertsPanelProps { alerts?: GroupedAlert[]; isLoading: boolean; } const SEVERITY_CONFIG = { critical: { color: 'text-destructive', icon: AlertCircle, label: 'Critical', badge: 'bg-destructive/10 text-destructive' }, high: { color: 'text-orange-500', icon: AlertTriangle, label: 'High', badge: 'bg-orange-500/10 text-orange-500' }, medium: { color: 'text-yellow-500', icon: AlertTriangle, label: 'Medium', badge: 'bg-yellow-500/10 text-yellow-500' }, low: { color: 'text-blue-500', icon: Info, label: 'Low', badge: 'bg-blue-500/10 text-blue-500' }, }; export function GroupedAlertsPanel({ alerts, isLoading }: GroupedAlertsPanelProps) { const [expandedGroups, setExpandedGroups] = useState>(new Set()); const resolveGroup = useResolveAlertGroup(); const snoozeGroup = useSnoozeAlertGroup(); // Filter out snoozed alerts const snoozedAlerts = JSON.parse(localStorage.getItem('snoozed_alerts') || '{}'); const visibleAlerts = alerts?.filter(alert => { const snoozeUntil = snoozedAlerts[alert.group_key]; return !snoozeUntil || Date.now() > snoozeUntil; }); const handleResolveGroup = (alert: GroupedAlert) => { console.log('🔴 Resolve button clicked', { alertIds: alert.alert_ids, source: alert.source, alert, }); resolveGroup.mutate({ alertIds: alert.alert_ids, source: alert.source, }); }; const handleSnooze = (alert: GroupedAlert, durationMs: number) => { snoozeGroup.mutate({ groupKey: alert.group_key, duration: durationMs, }); }; const toggleExpanded = (groupKey: string) => { setExpandedGroups(prev => { const next = new Set(prev); if (next.has(groupKey)) { next.delete(groupKey); } else { next.add(groupKey); } return next; }); }; if (isLoading) { return ( Critical Alerts Loading alerts...
); } if (!visibleAlerts || visibleAlerts.length === 0) { return ( Critical Alerts All systems operational

No active alerts

); } const totalAlerts = visibleAlerts.reduce((sum, alert) => sum + alert.unresolved_count, 0); const recurringCount = visibleAlerts.filter(a => a.is_recurring).length; return ( Critical Alerts {visibleAlerts.length} {visibleAlerts.length === 1 ? 'group' : 'groups'} • {totalAlerts} total alerts {recurringCount > 0 && ` • ${recurringCount} recurring`} Grouped by type to reduce alert fatigue {visibleAlerts.map(alert => { const config = SEVERITY_CONFIG[alert.severity]; const Icon = config.icon; const isExpanded = expandedGroups.has(alert.group_key); return (
{config.label} {alert.source === 'system' ? 'System' : 'Rate Limit'} {alert.is_active && ( Active )} {alert.is_recurring && ( Recurring )} {alert.unresolved_count} {alert.unresolved_count === 1 ? 'alert' : 'alerts'}

{alert.alert_type || alert.metric_type || 'Alert'} {alert.function_name && • {alert.function_name}}

{alert.messages[0]}

First: {formatDistanceToNow(new Date(alert.first_seen), { addSuffix: true })} Last: {formatDistanceToNow(new Date(alert.last_seen), { addSuffix: true })}
{alert.alert_count > 1 && ( )} handleSnooze(alert, 3600000)}> 1 hour handleSnooze(alert, 14400000)}> 4 hours handleSnooze(alert, 86400000)}> 24 hours
{isExpanded && alert.messages.length > 1 && (

All messages in this group:

{alert.messages.map((message, idx) => (
{message}
))}
)}
); })}
); }