163 lines
5.5 KiB
TypeScript
163 lines
5.5 KiB
TypeScript
import React from 'react';
|
|
import { AlertTriangle, X } from 'lucide-react';
|
|
|
|
interface ConfirmationDialogProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
onConfirm: () => void;
|
|
title: string;
|
|
message: string;
|
|
confirmText?: string;
|
|
cancelText?: string;
|
|
variant?: 'danger' | 'warning' | 'info';
|
|
isLoading?: boolean;
|
|
}
|
|
|
|
const ConfirmationDialog: React.FC<ConfirmationDialogProps> = ({
|
|
isOpen,
|
|
onClose,
|
|
onConfirm,
|
|
title,
|
|
message,
|
|
confirmText = 'Confirm',
|
|
cancelText = 'Cancel',
|
|
variant = 'info',
|
|
isLoading = false,
|
|
}) => {
|
|
if (!isOpen) return null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
<div
|
|
className="fixed inset-0 z-50 overflow-y-auto"
|
|
aria-labelledby="modal-title"
|
|
role="dialog"
|
|
aria-modal="true"
|
|
>
|
|
{}
|
|
<div
|
|
className="fixed inset-0 bg-black/60 backdrop-blur-sm transition-opacity"
|
|
onClick={onClose}
|
|
aria-hidden="true"
|
|
/>
|
|
|
|
{}
|
|
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
|
|
<div className="relative transform overflow-hidden rounded-sm bg-gradient-to-b from-white to-gray-50 text-left shadow-2xl border border-[#d4af37]/20 transition-all sm:my-8 sm:w-full sm:max-w-lg animate-fade-in">
|
|
{}
|
|
<button
|
|
onClick={onClose}
|
|
className="absolute right-4 top-4 text-gray-400 hover:text-[#d4af37] focus:outline-none focus:ring-2 focus:ring-[#d4af37]/50 rounded-sm p-1 transition-colors"
|
|
aria-label="Close"
|
|
>
|
|
<X className="w-5 h-5" />
|
|
</button>
|
|
|
|
<div className="bg-transparent px-4 pb-4 pt-5 sm:p-6 sm:pb-4">
|
|
<div className="sm:flex sm:items-start">
|
|
<div
|
|
className={`mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full ${
|
|
variant === 'danger'
|
|
? 'bg-red-100 border-2 border-red-200'
|
|
: variant === 'warning'
|
|
? 'bg-[#d4af37]/20 border-2 border-[#d4af37]/40'
|
|
: 'bg-[#d4af37]/20 border-2 border-[#d4af37]/40'
|
|
} sm:mx-0 sm:h-10 sm:w-10`}
|
|
>
|
|
<AlertTriangle
|
|
className={`h-6 w-6 ${
|
|
variant === 'danger'
|
|
? 'text-red-600'
|
|
: variant === 'warning'
|
|
? 'text-[#d4af37]'
|
|
: 'text-[#d4af37]'
|
|
}`}
|
|
aria-hidden="true"
|
|
/>
|
|
</div>
|
|
<div className="mt-3 text-center sm:ml-4 sm:mt-0 sm:text-left">
|
|
<h3
|
|
className="text-lg font-serif font-semibold leading-6 text-gray-900 tracking-tight"
|
|
id="modal-title"
|
|
>
|
|
{title}
|
|
</h3>
|
|
<div className="mt-2">
|
|
<p className="text-sm text-gray-600 font-light leading-relaxed">{message}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="bg-gray-50/50 backdrop-blur-sm px-4 py-4 sm:flex sm:flex-row-reverse sm:px-6 gap-3 border-t border-gray-200">
|
|
<button
|
|
type="button"
|
|
onClick={onConfirm}
|
|
disabled={isLoading}
|
|
className={`inline-flex w-full justify-center rounded-sm px-4 py-2.5 text-sm font-medium tracking-wide text-white shadow-lg sm:ml-3 sm:w-auto focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed transition-all ${
|
|
variant === 'danger'
|
|
? 'bg-red-600 hover:bg-red-700 focus:ring-red-500'
|
|
: variant === 'warning'
|
|
? 'bg-gradient-to-r from-[#d4af37] to-[#c9a227] hover:from-[#f5d76e] hover:to-[#d4af37] focus:ring-[#d4af37]'
|
|
: 'btn-luxury-primary focus:ring-[#d4af37]'
|
|
}`}
|
|
>
|
|
{isLoading ? (
|
|
<span className="flex items-center gap-2">
|
|
<svg
|
|
className="animate-spin h-4 w-4 text-white"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<circle
|
|
className="opacity-25"
|
|
cx="12"
|
|
cy="12"
|
|
r="10"
|
|
stroke="currentColor"
|
|
strokeWidth="4"
|
|
/>
|
|
<path
|
|
className="opacity-75"
|
|
fill="currentColor"
|
|
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
/>
|
|
</svg>
|
|
Processing...
|
|
</span>
|
|
) : (
|
|
confirmText
|
|
)}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={onClose}
|
|
disabled={isLoading}
|
|
className="mt-3 inline-flex w-full justify-center rounded-sm bg-white/80 backdrop-blur-sm px-4 py-2.5 text-sm font-medium tracking-wide text-gray-700 shadow-sm border border-gray-300 hover:bg-white hover:border-[#d4af37]/30 hover:text-[#d4af37] sm:mt-0 sm:w-auto disabled:opacity-50 disabled:cursor-not-allowed transition-all"
|
|
>
|
|
{cancelText}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ConfirmationDialog;
|
|
|