import { useState, useCallback, createContext, useContext } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { CheckCircle, AlertTriangle, Info, X, Zap } from 'lucide-react'; import { cn } from '@/lib/utils'; type ToastType = 'success' | 'error' | 'info' | 'warning'; interface Toast { id: number; message: string; type: ToastType; } interface ToastContextValue { toast: (message: string, type?: ToastType) => void; } const ToastContext = createContext({ toast: () => {} }); export function useToast() { return useContext(ToastContext); } let nextId = 0; export function ToastProvider({ children }: { children: React.ReactNode }) { const [toasts, setToasts] = useState([]); const addToast = useCallback((message: string, type: ToastType = 'info') => { const id = ++nextId; setToasts((prev) => [...prev, { id, message, type }]); setTimeout(() => { setToasts((prev) => prev.filter((t) => t.id !== id)); }, 4000); }, []); const removeToast = useCallback((id: number) => { setToasts((prev) => prev.filter((t) => t.id !== id)); }, []); return ( {children}
{toasts.map((t) => ( removeToast(t.id)} /> ))}
); } const icons: Record = { success: , error: , info: , warning: , }; const borderColors: Record = { success: 'border-lab-manager/40', error: 'border-destructive/40', info: 'border-primary/40', warning: 'border-judge/40', }; function ToastItem({ toast, onDismiss }: { toast: Toast; onDismiss: () => void }) { return ( {icons[toast.type]} {toast.message} ); }