Spaces:
Sleeping
Sleeping
| import React from 'react'; | |
| import { X, AlertCircle } from 'lucide-react'; | |
| import { Button } from '@/components/ui/button'; | |
| interface CustomConfirmDialogProps { | |
| isOpen: boolean; | |
| onClose: () => void; | |
| onConfirm: () => void; | |
| title: string; | |
| description?: string | React.ReactNode; | |
| confirmText?: string; | |
| cancelText?: string; | |
| variant?: 'destructive' | 'default' | 'outline' | 'secondary' | 'ghost' | 'link'; | |
| isLoading?: boolean; | |
| } | |
| const CustomConfirmDialog: React.FC<CustomConfirmDialogProps> = ({ | |
| isOpen, | |
| onClose, | |
| onConfirm, | |
| title, | |
| description, | |
| confirmText = 'Confirm', | |
| cancelText = 'Cancel', | |
| variant = 'destructive', | |
| isLoading = false, | |
| }) => { | |
| if (!isOpen) return null; | |
| const handleOverlayClick = (e: React.MouseEvent) => { | |
| // Only allow closing if not in loading state | |
| if (!isLoading && e.target === e.currentTarget) { | |
| onClose(); | |
| } | |
| }; | |
| return ( | |
| <div className="fixed inset-0 z-[999] flex items-center justify-center overflow-y-auto p-4"> | |
| {/* Overlay */} | |
| <div | |
| className="fixed inset-0 bg-black/80 backdrop-blur-sm" | |
| onClick={handleOverlayClick} | |
| /> | |
| {/* Modal Content */} | |
| <div className="relative z-[1000] w-full max-w-md rounded-lg border bg-background p-6 shadow-lg"> | |
| <div className="flex gap-4 items-start mb-4"> | |
| {variant === 'destructive' && ( | |
| <div className="flex h-10 w-10 items-center justify-center rounded-full bg-destructive/20 text-destructive"> | |
| <AlertCircle className="h-5 w-5" /> | |
| </div> | |
| )} | |
| <div className="flex-1"> | |
| <h2 className="text-lg font-semibold">{title}</h2> | |
| {description && ( | |
| typeof description === 'string' | |
| ? <p className="text-sm text-muted-foreground mt-1">{description}</p> | |
| : <div className="mt-2">{description}</div> | |
| )} | |
| </div> | |
| </div> | |
| <div className="flex justify-end space-x-2 mt-6"> | |
| <Button | |
| variant="outline" | |
| onClick={onClose} | |
| disabled={isLoading} | |
| > | |
| {cancelText} | |
| </Button> | |
| <Button | |
| variant={variant} | |
| onClick={onConfirm} | |
| disabled={isLoading} | |
| > | |
| {isLoading ? 'Processing...' : confirmText} | |
| </Button> | |
| </div> | |
| {/* Close button */} | |
| {!isLoading && ( | |
| <button | |
| onClick={onClose} | |
| className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none" | |
| > | |
| <X className="h-4 w-4" /> | |
| <span className="sr-only">Close</span> | |
| </button> | |
| )} | |
| </div> | |
| </div> | |
| ); | |
| }; | |
| export default CustomConfirmDialog; |