"use client"; import React, { useCallback, useEffect, useState } from "react"; import { AlertCircle, CheckCircle2, X } from "lucide-react"; interface SuccessModalProps { isOpen: boolean; onClose: () => void; title: string; message: string; duration?: number; /** * `error` change l'icône, l'accent et **désactive la fermeture automatique** : * un message d'échec doit rester à l'écran le temps d'être lu, et il ne doit * pas s'afficher sous une coche verte de succès. */ variant?: "success" | "error"; /** Action secondaire optionnelle (ex. « Recharger la page »). */ action?: { label: string; onClick: () => void }; } /** Durée de l'animation de sortie, alignée sur les classes `animate-out`. */ const EXIT_MS = 200; export function SuccessModal({ isOpen, onClose, title, message, duration = 3000, variant = "success", action, }: SuccessModalProps) { // Seul l'état de SORTIE est porté par un state : l'entrée est jouée par CSS // au montage (`animate-in`), ce qui évite un setState synchrone dans l'effet. const [closing, setClosing] = useState(false); const isError = variant === "error"; const handleClose = useCallback(() => { setClosing(true); setTimeout(() => { setClosing(false); onClose(); }, EXIT_MS); }, [onClose]); useEffect(() => { // Une erreur ne disparaît pas toute seule : l'utilisateur la ferme. if (!isOpen || isError) return; const timer = setTimeout(() => handleClose(), duration); return () => clearTimeout(timer); }, [isOpen, duration, isError, handleClose]); if (!isOpen) return null; const state = closing ? "closed" : "open"; const Icon = isError ? AlertCircle : CheckCircle2; return (
{message}
{action && ( )}