// frontend/src/components/alerts/AlertCard.tsx /** * Individual alert/recommendation card component * Displays alert details with appropriate styling and actions */ import React, { useState } from 'react'; import { AlertItem, ItemSeverity, ItemType } from '../../types/alerts'; import { formatDistanceToNow } from 'date-fns'; import { es } from 'date-fns/locale'; interface AlertCardProps { item: AlertItem; onAcknowledge: (itemId: string) => void; onResolve: (itemId: string) => void; compact?: boolean; showActions?: boolean; } const getSeverityConfig = (severity: ItemSeverity, itemType: ItemType) => { if (itemType === 'recommendation') { switch (severity) { case 'high': return { color: 'bg-blue-50 border-blue-200 text-blue-900', icon: '💡', badge: 'bg-blue-100 text-blue-800' }; case 'medium': return { color: 'bg-blue-50 border-blue-100 text-blue-800', icon: '💡', badge: 'bg-blue-50 text-blue-600' }; case 'low': return { color: 'bg-gray-50 border-gray-200 text-gray-700', icon: '💡', badge: 'bg-gray-100 text-gray-600' }; default: return { color: 'bg-blue-50 border-blue-200 text-blue-900', icon: '💡', badge: 'bg-blue-100 text-blue-800' }; } } else { switch (severity) { case 'urgent': return { color: 'bg-red-50 border-red-300 text-red-900', icon: '🚨', badge: 'bg-red-100 text-red-800', pulse: true }; case 'high': return { color: 'bg-orange-50 border-orange-200 text-orange-900', icon: '⚠️', badge: 'bg-orange-100 text-orange-800' }; case 'medium': return { color: 'bg-yellow-50 border-yellow-200 text-yellow-900', icon: '🔔', badge: 'bg-yellow-100 text-yellow-800' }; case 'low': return { color: 'bg-green-50 border-green-200 text-green-900', icon: 'ℹ️', badge: 'bg-green-100 text-green-800' }; default: return { color: 'bg-gray-50 border-gray-200 text-gray-700', icon: '📋', badge: 'bg-gray-100 text-gray-600' }; } } }; const getStatusConfig = (status: string) => { switch (status) { case 'acknowledged': return { color: 'bg-blue-100 text-blue-800', label: 'Reconocido' }; case 'resolved': return { color: 'bg-green-100 text-green-800', label: 'Resuelto' }; default: return { color: 'bg-gray-100 text-gray-800', label: 'Activo' }; } }; export const AlertCard: React.FC = ({ item, onAcknowledge, onResolve, compact = false, showActions = true }) => { const [isExpanded, setIsExpanded] = useState(false); const [actionLoading, setActionLoading] = useState(null); const severityConfig = getSeverityConfig(item.severity, item.item_type); const statusConfig = getStatusConfig(item.status); const handleAction = async (action: () => void, actionType: string) => { setActionLoading(actionType); try { await action(); } finally { setActionLoading(null); } }; const timeAgo = formatDistanceToNow(new Date(item.timestamp), { addSuffix: true, locale: es }); return (
{/* Header */}
{/* Icon and Type Badge */}
{severityConfig.icon}
{/* Title and Badges */}

{item.title}

{item.item_type === 'alert' ? 'Alerta' : 'RecomendaciĂłn'} - {item.severity} {statusConfig.label} {item.service}
{/* Expand Button */} {!compact && ( )}
{/* Message */}

{item.message}

{/* Timestamp */}

{timeAgo} • {new Date(item.timestamp).toLocaleString('es-ES')}

{/* Quick Actions */} {showActions && item.status === 'active' && (
)}
{/* Expanded Details */} {isExpanded && (
{/* Actions */} {item.actions.length > 0 && (

Acciones sugeridas:

    {item.actions.map((action, index) => (
  • {action}
  • ))}
)} {/* Metadata */} {Object.keys(item.metadata).length > 0 && (

Detalles técnicos:

{Object.entries(item.metadata).map(([key, value]) => (
{key}:{' '} {typeof value === 'object' ? JSON.stringify(value) : String(value)}
))}
)} {/* Acknowledgment/Resolution Info */} {(item.acknowledged_at || item.resolved_at) && (
{item.acknowledged_at && (

Reconocido: {new Date(item.acknowledged_at).toLocaleString('es-ES')} {item.acknowledged_by && ` por ${item.acknowledged_by}`}

)} {item.resolved_at && (

Resuelto: {new Date(item.resolved_at).toLocaleString('es-ES')} {item.resolved_by && ` por ${item.resolved_by}`}

)}
)}
)}
); };