ge-tool/components/ConfirmModal.tsx

70 lines
2.7 KiB
TypeScript
Raw Normal View History

2025-12-10 06:41:43 +00:00
import React from 'react';
interface ConfirmModalProps {
isOpen: boolean;
title?: string;
message: React.ReactNode;
confirmText?: string;
cancelText?: string;
confirmButtonClass?: string;
onConfirm: () => void;
onCancel: () => void;
isLoading?: boolean;
}
const ConfirmModal: React.FC<ConfirmModalProps> = ({
isOpen,
title = 'Xác nhận',
message,
confirmText = 'Xác nhận',
cancelText = 'Huỷ',
confirmButtonClass = 'bg-rose-600 hover:bg-rose-700',
onConfirm,
onCancel,
isLoading = false,
}) => {
if (!isOpen) return null;
return (
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center p-4 z-[60]">
<div className="bg-slate-800 rounded-xl shadow-2xl border border-slate-700 max-w-md w-full">
{/* Header */}
<div className="p-6 border-b border-slate-700">
<h3 className="text-lg font-semibold text-white">{title}</h3>
</div>
{/* Content */}
<div className="p-6">
<div className="text-slate-300">{message}</div>
</div>
{/* Footer */}
<div className="flex justify-end gap-3 p-6 border-t border-slate-700">
<button
onClick={onCancel}
disabled={isLoading}
className="px-4 py-2 bg-slate-700 hover:bg-slate-600 text-white rounded-lg font-medium transition-colors disabled:opacity-50"
>
{cancelText}
</button>
<button
onClick={onConfirm}
disabled={isLoading}
className={`px-4 py-2 text-white rounded-lg font-medium transition-colors disabled:opacity-50 flex items-center gap-2 ${confirmButtonClass}`}
>
{isLoading && (
<svg className="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<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"></path>
</svg>
)}
{confirmText}
</button>
</div>
</div>
</div>
);
};
export default ConfirmModal;