InnerVoice / frontend /components /AlertCard.tsx
E5K7's picture
InnerVoice Production Upgrade: Multi-channel chat, premium UI components, Whisper-small accuracy upgrade, and full-screen layout polishing
b5e8a53
"use client";
import { motion } from "framer-motion";
interface AlertCardProps {
id: string;
alert_type: string;
severity: string;
message: string;
suggested_action?: string | null;
created_at: string;
onDismiss?: (id: string) => void;
}
function getSeverityStyle(severity: string) {
const styles: Record<string, { bg: string; border: string; icon: string }> = {
low: { bg: "bg-blue-500/5", border: "border-blue-500/20", icon: "ℹ️" },
medium: { bg: "bg-yellow-500/5", border: "border-yellow-500/20", icon: "⚠️" },
high: { bg: "bg-red-500/5", border: "border-red-500/20", icon: "🚨" },
critical: { bg: "bg-red-500/10", border: "border-red-500/30", icon: "🆘" },
};
return styles[severity] ?? styles.low;
}
export default function AlertCard({
id,
alert_type,
severity,
message,
suggested_action,
created_at,
onDismiss,
}: AlertCardProps) {
const style = getSeverityStyle(severity);
const typeLabels: Record<string, string> = {
mood_decline: "Mood Decline",
low_energy: "Low Energy",
high_anxiety: "Elevated Anxiety",
burnout_risk: "Burnout Risk",
crisis: "Needs Attention",
persistent_sadness: "Persistent Sadness",
};
return (
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, x: -20 }}
className={`vercel-card p-4 ${style.bg} ${style.border} transition-all`}
>
<div className="flex items-start justify-between gap-3">
<div className="flex items-start gap-3 flex-1">
<span className="text-xl mt-0.5 shrink-0">{style.icon}</span>
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2 mb-1 flex-wrap">
<span className="text-xs font-semibold uppercase tracking-wide text-vercel-fg/50">
{typeLabels[alert_type] ?? alert_type}
</span>
<span className="text-xs text-vercel-fg/30">
{new Date(created_at).toLocaleDateString()}
</span>
</div>
<p className="text-sm text-vercel-fg/90 leading-relaxed">{message}</p>
{suggested_action && (
<p className="mt-2 text-xs text-vercel-fg/60 italic">
💡 {suggested_action}
</p>
)}
</div>
</div>
{onDismiss && (
<button
onClick={() => onDismiss(id)}
className="text-vercel-fg/30 hover:text-vercel-fg/70 transition-colors shrink-0"
title="Dismiss"
>
</button>
)}
</div>
</motion.div>
);
}