105 lines
3.6 KiB
TypeScript
105 lines
3.6 KiB
TypeScript
"use client";
|
|
|
|
import React from "react";
|
|
import { m, AnimatePresence, LazyMotion, domAnimation } from "framer-motion";
|
|
import { CheckCircle, AlertCircle, X } from "lucide-react";
|
|
import { Button } from "./Button";
|
|
|
|
interface StatusModalProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
type: "success" | "error";
|
|
title: string;
|
|
message: string;
|
|
buttonText: string;
|
|
}
|
|
|
|
export const StatusModal = ({
|
|
isOpen,
|
|
onClose,
|
|
type,
|
|
title,
|
|
message,
|
|
buttonText,
|
|
}: StatusModalProps) => {
|
|
return (
|
|
<LazyMotion features={domAnimation}>
|
|
<AnimatePresence>
|
|
{isOpen && (
|
|
<div className="fixed inset-0 z-[100] flex items-center justify-center p-4 md:p-6">
|
|
{/* Backdrop */}
|
|
<m.div
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
exit={{ opacity: 0 }}
|
|
onClick={onClose}
|
|
className="absolute inset-0 bg-slate-950/80 backdrop-blur-sm"
|
|
/>
|
|
|
|
{/* Modal Content */}
|
|
<m.div
|
|
initial={{ opacity: 0, scale: 0.9, y: 20 }}
|
|
animate={{ opacity: 1, scale: 1, y: 0 }}
|
|
exit={{ opacity: 0, scale: 0.9, y: 20 }}
|
|
transition={{ type: "spring", damping: 25, stiffness: 300 }}
|
|
className="relative w-full max-w-lg bg-white rounded-[2.5rem] border border-slate-100 shadow-2xl overflow-hidden group"
|
|
>
|
|
{/* Tech Decoration */}
|
|
<div className="absolute top-0 left-0 w-full h-2 bg-slate-100 overflow-hidden">
|
|
<m.div
|
|
initial={{ x: "-100%" }}
|
|
animate={{ x: "100%" }}
|
|
transition={{ duration: 2, repeat: Infinity, ease: "linear" }}
|
|
className={`absolute inset-0 w-1/2 ${type === "success" ? "bg-accent" : "bg-red-500"} opacity-30`}
|
|
/>
|
|
</div>
|
|
|
|
<button
|
|
onClick={onClose}
|
|
className="absolute top-6 right-6 p-2 text-slate-400 hover:text-primary transition-colors hover:bg-slate-50 rounded-xl"
|
|
>
|
|
<X size={20} />
|
|
</button>
|
|
|
|
<div className="p-8 md:p-12 text-center">
|
|
<div
|
|
className={`w-20 h-20 rounded-full ${type === "success" ? "bg-accent/10 text-accent" : "bg-red-50 text-red-500"} flex items-center justify-center mx-auto mb-8 relative`}
|
|
>
|
|
<div
|
|
className={`absolute inset-0 ${type === "success" ? "bg-accent/20" : "bg-red-500/20"} rounded-full animate-ping opacity-20`}
|
|
/>
|
|
{type === "success" ? (
|
|
<CheckCircle size={40} />
|
|
) : (
|
|
<AlertCircle size={40} />
|
|
)}
|
|
</div>
|
|
|
|
<h3 className="text-3xl font-extrabold text-primary mb-4 leading-tight">
|
|
{title}
|
|
</h3>
|
|
<p className="text-slate-600 text-lg mb-10 leading-relaxed">
|
|
{message}
|
|
</p>
|
|
|
|
<Button
|
|
onClick={onClose}
|
|
variant={type === "success" ? "accent" : "primary"}
|
|
className="w-full py-5 text-lg"
|
|
showArrow
|
|
>
|
|
{buttonText}
|
|
</Button>
|
|
</div>
|
|
|
|
{/* Decorative Corners */}
|
|
<div className="tech-corner top-4 left-4 border-t-2 border-l-2 opacity-20" />
|
|
<div className="tech-corner bottom-4 right-4 border-b-2 border-r-2 opacity-20" />
|
|
</m.div>
|
|
</div>
|
|
)}
|
|
</AnimatePresence>
|
|
</LazyMotion>
|
|
);
|
|
};
|