All files / components/accounts DeleteAccountDialog.tsx

96% Statements 24/25
73.33% Branches 11/15
100% Functions 4/4
100% Lines 23/23

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124                                                                  65x 65x 65x   65x 3x   3x 3x   3x 3x 2x 2x   1x 1x   3x       65x 4x 4x 4x 4x       65x   22x   22x                                                         5x                                                      
/**
 * Delete account confirmation dialog
 */
 
import { useState } from 'react';
import {
    AlertDialog,
    AlertDialogAction,
    AlertDialogCancel,
    AlertDialogContent,
    AlertDialogDescription,
    AlertDialogFooter,
    AlertDialogHeader,
    AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Loader2, AlertTriangle } from 'lucide-react';
import type { AccountListItem } from '@/services/accounts.service';
 
interface DeleteAccountDialogProps {
    open: boolean;
    onOpenChange: (open: boolean) => void;
    account: AccountListItem | null;
    onConfirm: (accountId: string) => Promise<void>;
}
 
export default function DeleteAccountDialog({
    open,
    onOpenChange,
    account,
    onConfirm,
}: DeleteAccountDialogProps) {
    const [confirmName, setConfirmName] = useState('');
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState<string | null>(null);
 
    const handleConfirm = async () => {
        Iif (!account) return;
 
        setLoading(true);
        setError(null);
 
        try {
            await onConfirm(account.id);
            setConfirmName('');
            onOpenChange(false);
        } catch (err: unknown) {
            const error = err as { response?: { data?: { detail?: string } }; message?: string };
            setError(error.response?.data?.detail || error.message || 'Failed to delete account');
        } finally {
            setLoading(false);
        }
    };
 
    const handleOpenChange = (open: boolean) => {
        Eif (!loading) {
            setConfirmName('');
            setError(null);
            onOpenChange(open);
        }
    };
 
    if (!account) return null;
 
    const isConfirmValid = confirmName === account.name;
 
    return (
        <AlertDialog open={open} onOpenChange={handleOpenChange}>
            <AlertDialogContent>
                <AlertDialogHeader>
                    <AlertDialogTitle className="flex items-center gap-2">
                        <AlertTriangle className="h-5 w-5 text-destructive" />
                        Delete Account
                    </AlertDialogTitle>
                    <AlertDialogDescription className="space-y-3">
                        <p>
                            You are about to delete account <strong>{account.name}</strong> ({account.account_code}).
                        </p>
                        <div className="bg-destructive/10 border border-destructive/20 rounded-md p-3">
                            <p className="text-sm font-medium text-destructive">
                                ⚠️ Warning: This action cannot be undone!
                            </p>
                            <ul className="text-sm text-destructive mt-2 space-y-1 list-disc list-inside">
                                <li>All {account.user_count} user(s) will be deleted</li>
                                <li>All associated data will be permanently removed</li>
                                <li>Collections and records will be deleted</li>
                            </ul>
                        </div>
                        <div className="space-y-2">
                            <Label htmlFor="confirm-name">
                                Type <strong>{account.name}</strong> to confirm:
                            </Label>
                            <Input
                                id="confirm-name"
                                value={confirmName}
                                onChange={(e) => setConfirmName(e.target.value)}
                                placeholder={account.name}
                                disabled={loading}
                            />
                        </div>
                        {error && (
                            <div className="text-sm text-destructive bg-destructive/10 p-3 rounded-md">
                                {error}
                            </div>
                        )}
                    </AlertDialogDescription>
                </AlertDialogHeader>
                <AlertDialogFooter>
                    <AlertDialogCancel disabled={loading}>Cancel</AlertDialogCancel>
                    <AlertDialogAction
                        onClick={handleConfirm}
                        disabled={!isConfirmValid || loading}
                        className="bg-destructive text-white hover:bg-destructive/90"
                    >
                        {loading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
                        Delete Account
                    </AlertDialogAction>
                </AlertDialogFooter>
            </AlertDialogContent>
        </AlertDialog>
    );
}