mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-04-04 04:01:27 +00:00
86 lines
2.5 KiB
JavaScript
86 lines
2.5 KiB
JavaScript
import { useEffect, useState } from 'react';
|
|
import { motion } from 'framer-motion';
|
|
import { X, CheckCircle, AlertCircle, Info, AlertTriangle } from 'lucide-react';
|
|
import { errorMessages } from '@/utils/errorCodes';
|
|
|
|
const typeStyles = {
|
|
success: {
|
|
icon: <CheckCircle className="h-6 w-6 text-green-500" />,
|
|
bg: 'bg-green-300',
|
|
},
|
|
error: {
|
|
icon: <AlertCircle className="h-6 w-6 text-red-500" />,
|
|
bg: 'bg-red-300',
|
|
},
|
|
info: {
|
|
icon: <Info className="h-6 w-6 text-blue-500" />,
|
|
bg: 'bg-blue-300',
|
|
},
|
|
warning: {
|
|
icon: <AlertTriangle className="h-6 w-6 text-yellow-500" />,
|
|
bg: 'bg-yellow-300',
|
|
},
|
|
};
|
|
|
|
export default function FlashNotification({
|
|
displayPeriod = 5000,
|
|
title,
|
|
message,
|
|
type = 'info',
|
|
errorCode,
|
|
onClose,
|
|
}) {
|
|
const [isVisible, setIsVisible] = useState(true);
|
|
|
|
useEffect(() => {
|
|
setIsVisible(true);
|
|
}, [message, type, errorCode, onClose]);
|
|
|
|
useEffect(() => {
|
|
if (type !== 'error') {
|
|
const timer = setTimeout(() => {
|
|
setIsVisible(false); // Déclenche la disparition
|
|
setTimeout(onClose, 300); // Appelle onClose après l'animation
|
|
}, displayPeriod);
|
|
return () => clearTimeout(timer);
|
|
}
|
|
// Pour les erreurs, pas de timeout : la notification reste affichée
|
|
}, [onClose, displayPeriod, type]);
|
|
|
|
if (!message || !isVisible) return null;
|
|
|
|
const { icon, bg } = typeStyles[type] || typeStyles.info;
|
|
|
|
return (
|
|
<motion.div
|
|
initial={{ opacity: 0, x: 50 }} // Animation d'entrée
|
|
animate={{ opacity: 1, x: 0 }} // Animation visible
|
|
exit={{ opacity: 0, x: 50 }} // Animation de sortie
|
|
transition={{ duration: 0.3 }} // Durée des animations
|
|
className="fixed top-5 right-5 flex items-stretch rounded-lg shadow-lg bg-white z-50 border border-gray-200"
|
|
>
|
|
{/* Rectangle gauche avec l'icône */}
|
|
<div className={`flex items-center justify-center w-14 ${bg}`}>
|
|
{icon}
|
|
</div>
|
|
{/* Zone de texte */}
|
|
<div className="flex-1 w-96 p-4">
|
|
<p className="font-bold text-black">{title}</p>
|
|
<p className="text-gray-700">{message}</p>
|
|
{type === 'error' && errorCode && (
|
|
<div className="mt-2 text-xs text-gray-500">
|
|
Code : <span className="font-mono font-bold">{errorCode}</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
{/* Bouton de fermeture */}
|
|
<button
|
|
onClick={() => setIsVisible(false)}
|
|
className="text-gray-500 hover:text-gray-700 focus:outline-none p-2"
|
|
>
|
|
<X className="h-5 w-5" />
|
|
</button>
|
|
</motion.div>
|
|
);
|
|
}
|