| 
 | 1 | +'use client';  | 
 | 2 | + | 
 | 3 | +import { useState } from 'react';  | 
 | 4 | +import { Button } from './ui/button';  | 
 | 5 | +import { AlertTriangle, Info } from 'lucide-react';  | 
 | 6 | + | 
 | 7 | +interface ConfirmationModalProps {  | 
 | 8 | +  isOpen: boolean;  | 
 | 9 | +  onClose: () => void;  | 
 | 10 | +  onConfirm: () => void;  | 
 | 11 | +  title: string;  | 
 | 12 | +  message: string;  | 
 | 13 | +  variant: 'simple' | 'danger';  | 
 | 14 | +  confirmText?: string; // What the user must type for danger variant  | 
 | 15 | +  confirmButtonText?: string;  | 
 | 16 | +  cancelButtonText?: string;  | 
 | 17 | +}  | 
 | 18 | + | 
 | 19 | +export function ConfirmationModal({  | 
 | 20 | +  isOpen,  | 
 | 21 | +  onClose,  | 
 | 22 | +  onConfirm,  | 
 | 23 | +  title,  | 
 | 24 | +  message,  | 
 | 25 | +  variant,  | 
 | 26 | +  confirmText,  | 
 | 27 | +  confirmButtonText = 'Confirm',  | 
 | 28 | +  cancelButtonText = 'Cancel'  | 
 | 29 | +}: ConfirmationModalProps) {  | 
 | 30 | +  const [typedText, setTypedText] = useState('');  | 
 | 31 | + | 
 | 32 | +  if (!isOpen) return null;  | 
 | 33 | + | 
 | 34 | +  const isDanger = variant === 'danger';  | 
 | 35 | +  const isConfirmEnabled = isDanger ? typedText === confirmText : true;  | 
 | 36 | + | 
 | 37 | +  const handleConfirm = () => {  | 
 | 38 | +    if (isConfirmEnabled) {  | 
 | 39 | +      onConfirm();  | 
 | 40 | +      setTypedText(''); // Reset for next time  | 
 | 41 | +    }  | 
 | 42 | +  };  | 
 | 43 | + | 
 | 44 | +  const handleClose = () => {  | 
 | 45 | +    onClose();  | 
 | 46 | +    setTypedText(''); // Reset when closing  | 
 | 47 | +  };  | 
 | 48 | + | 
 | 49 | +  return (  | 
 | 50 | +    <div className="fixed inset-0 backdrop-blur-sm bg-black/50 flex items-center justify-center z-50 p-4">  | 
 | 51 | +      <div className="bg-card rounded-lg shadow-xl max-w-md w-full border border-border">  | 
 | 52 | +        {/* Header */}  | 
 | 53 | +        <div className="flex items-center justify-center p-6 border-b border-border">  | 
 | 54 | +          <div className="flex items-center gap-3">  | 
 | 55 | +            {isDanger ? (  | 
 | 56 | +              <AlertTriangle className="h-8 w-8 text-red-600" />  | 
 | 57 | +            ) : (  | 
 | 58 | +              <Info className="h-8 w-8 text-blue-600" />  | 
 | 59 | +            )}  | 
 | 60 | +            <h2 className="text-2xl font-bold text-card-foreground">{title}</h2>  | 
 | 61 | +          </div>  | 
 | 62 | +        </div>  | 
 | 63 | + | 
 | 64 | +        {/* Content */}  | 
 | 65 | +        <div className="p-6">  | 
 | 66 | +          <p className="text-sm text-muted-foreground mb-6">  | 
 | 67 | +            {message}  | 
 | 68 | +          </p>  | 
 | 69 | + | 
 | 70 | +          {/* Type-to-confirm input for danger variant */}  | 
 | 71 | +          {isDanger && confirmText && (  | 
 | 72 | +            <div className="mb-6">  | 
 | 73 | +              <label className="block text-sm font-medium text-foreground mb-2">  | 
 | 74 | +                Type <code className="bg-muted px-2 py-1 rounded text-sm">{confirmText}</code> to confirm:  | 
 | 75 | +              </label>  | 
 | 76 | +              <input  | 
 | 77 | +                type="text"  | 
 | 78 | +                value={typedText}  | 
 | 79 | +                onChange={(e) => setTypedText(e.target.value)}  | 
 | 80 | +                className="w-full px-3 py-2 border border-input rounded-md bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:border-ring"  | 
 | 81 | +                placeholder={`Type "${confirmText}" here`}  | 
 | 82 | +                autoComplete="off"  | 
 | 83 | +              />  | 
 | 84 | +            </div>  | 
 | 85 | +          )}  | 
 | 86 | + | 
 | 87 | +          {/* Action Buttons */}  | 
 | 88 | +          <div className="flex flex-col sm:flex-row justify-end gap-3">  | 
 | 89 | +            <Button  | 
 | 90 | +              onClick={handleClose}  | 
 | 91 | +              variant="outline"  | 
 | 92 | +              size="default"  | 
 | 93 | +              className="w-full sm:w-auto"  | 
 | 94 | +            >  | 
 | 95 | +              {cancelButtonText}  | 
 | 96 | +            </Button>  | 
 | 97 | +            <Button  | 
 | 98 | +              onClick={handleConfirm}  | 
 | 99 | +              disabled={!isConfirmEnabled}  | 
 | 100 | +              variant={isDanger ? "destructive" : "default"}  | 
 | 101 | +              size="default"  | 
 | 102 | +              className="w-full sm:w-auto"  | 
 | 103 | +            >  | 
 | 104 | +              {confirmButtonText}  | 
 | 105 | +            </Button>  | 
 | 106 | +          </div>  | 
 | 107 | +        </div>  | 
 | 108 | +      </div>  | 
 | 109 | +    </div>  | 
 | 110 | +  );  | 
 | 111 | +}  | 
0 commit comments