61 lines
No EOL
1.6 KiB
TypeScript
61 lines
No EOL
1.6 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { CheckCircle, Loader2 } from "lucide-react";
|
|
|
|
interface LoadingModalProps {
|
|
isOpen: boolean;
|
|
title: string;
|
|
description?: string;
|
|
success?: boolean;
|
|
successMessage?: string;
|
|
onClose?: () => void;
|
|
}
|
|
|
|
export function LoadingModal({
|
|
isOpen,
|
|
title,
|
|
description,
|
|
success = false,
|
|
successMessage,
|
|
onClose
|
|
}: LoadingModalProps) {
|
|
const [showSuccess, setShowSuccess] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (success) {
|
|
setShowSuccess(true);
|
|
const timer = setTimeout(() => {
|
|
onClose?.();
|
|
}, 2000);
|
|
return () => clearTimeout(timer);
|
|
} else {
|
|
setShowSuccess(false);
|
|
}
|
|
}, [success, onClose]);
|
|
|
|
if (!isOpen) return null;
|
|
|
|
return (
|
|
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50 flex items-center justify-center">
|
|
<div className="bg-white rounded-2xl p-8 max-w-md w-full mx-4 shadow-2xl">
|
|
<div className="flex flex-col items-center text-center">
|
|
{showSuccess ? (
|
|
<>
|
|
<CheckCircle className="w-8 h-8 text-green-600 mb-4" />
|
|
<h3 className="text-lg font-medium text-gray-900 mb-2">
|
|
{successMessage || "Terminé !"}
|
|
</h3>
|
|
</>
|
|
) : (
|
|
<>
|
|
<Loader2 className="w-8 h-8 animate-spin text-blue-600 mb-4" />
|
|
<h3 className="text-lg font-medium text-gray-900 mb-2">{title}</h3>
|
|
{description && <p className="text-gray-600 text-sm">{description}</p>}
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
} |