Files
MSP-CAS/src/components/alerts/AlertCard.tsx

101 lines
2.8 KiB
TypeScript

'use client'
import { cn, formatRelativeTime } from '@/lib/utils'
export type AlertSeverity = 'CRITICAL' | 'WARNING' | 'INFO'
export type AlertStatus = 'ACTIVA' | 'RECONOCIDA' | 'RESUELTA'
export interface AlertCardData {
id: string
title: string
device: string
description: string
severity: AlertSeverity
timestamp: Date | string
status: AlertStatus
}
interface AlertCardProps {
alert: AlertCardData
onAcknowledge?: (id: string) => void
onResolve?: (id: string) => void
}
const severityStyles = {
CRITICAL: {
bar: 'bg-red-500',
badge: 'bg-red-500/20 text-red-400 border-red-500/40',
label: 'CRÍTICO',
},
WARNING: {
bar: 'bg-amber-500',
badge: 'bg-amber-500/20 text-amber-400 border-amber-500/40',
label: 'ADVERTENCIA',
},
INFO: {
bar: 'bg-blue-500',
badge: 'bg-blue-500/20 text-blue-400 border-blue-500/40',
label: 'INFO',
},
}
export default function AlertCard({ alert, onAcknowledge, onResolve }: AlertCardProps) {
const style = severityStyles[alert.severity]
const ts = typeof alert.timestamp === 'string' ? new Date(alert.timestamp) : alert.timestamp
return (
<div
className={cn(
'rounded-xl border border-slate-700/60 bg-slate-800/50 shadow-sm',
'p-5 transition-all duration-200 hover:border-slate-600 hover:shadow-md',
'flex gap-4'
)}
>
<div className={cn('w-1 shrink-0 rounded-full', style.bar)} aria-hidden />
<div className="min-w-0 flex-1">
<h4 className="font-semibold text-slate-100 text-base leading-tight">
{alert.title}
</h4>
<p className="mt-1 text-sm text-slate-400">{alert.device}</p>
<p className="mt-2 text-sm text-slate-500 line-clamp-2">{alert.description}</p>
<p className="mt-2 text-xs text-slate-600">{formatRelativeTime(ts)}</p>
</div>
<div className="flex shrink-0 flex-col items-end justify-between gap-3">
<span
className={cn(
'rounded-md border px-2 py-0.5 text-xs font-medium',
style.badge
)}
>
{style.label}
</span>
{alert.status === 'ACTIVA' && (
<div className="flex gap-2">
<button
type="button"
onClick={() => onAcknowledge?.(alert.id)}
className="btn btn-secondary btn-sm"
>
Marcar leído
</button>
<button
type="button"
onClick={() => onResolve?.(alert.id)}
className="btn btn-ghost btn-sm"
>
Descartar
</button>
</div>
)}
{alert.status !== 'ACTIVA' && (
<span className="text-xs text-slate-500">
{alert.status === 'RECONOCIDA' ? 'Leída' : 'Resuelta'}
</span>
)}
</div>
</div>
)
}