BillTracker/client/components/data/EraseDataSection.jsx

98 lines
4.2 KiB
React
Raw Normal View History

import { useState } from 'react';
import { toast } from 'sonner';
import { ShieldAlert, Loader2, Trash2 } from 'lucide-react';
import { api } from '@/api';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import {
AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent,
AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger,
} from '@/components/ui/alert-dialog';
import { SectionCard } from './dataShared';
/**
* Danger zone: permanently erase the user's financial data. Type-to-confirm, and
* makes clear that the account/login/2FA are preserved. Reuses POST
* /api/user/erase-data (transactional, audited, re-seeds default categories).
*/
export default function EraseDataSection({ onErased, cardProps = {} }) {
const [open, setOpen] = useState(false);
const [confirm, setConfirm] = useState('');
const [busy, setBusy] = useState(false);
const canErase = confirm.trim().toUpperCase() === 'ERASE';
async function handleErase() {
if (!canErase) return;
setBusy(true);
try {
const r = await api.eraseMyData(confirm.trim());
toast.success(`Your data was erased — ${r.erased} record${r.erased === 1 ? '' : 's'} removed.`);
setOpen(false);
setConfirm('');
onErased?.();
} catch (err) {
toast.error(err.message || 'Erase failed.');
} finally {
setBusy(false);
}
}
return (
<SectionCard {...cardProps}>
<div className="space-y-4 px-6 py-5">
<div className="rounded-lg border border-rose-300/60 bg-rose-50 p-4 dark:border-rose-800/50 dark:bg-rose-950/20">
<div className="flex items-start gap-3">
<ShieldAlert className="mt-0.5 h-5 w-5 shrink-0 text-rose-600 dark:text-rose-400" />
<div className="min-w-0 text-sm">
<p className="font-medium text-rose-700 dark:text-rose-300">This permanently deletes your financial data.</p>
<p className="mt-1 text-muted-foreground">
Bills, payments, transactions, categories, bank connections, imports and rules will be erased and
cant be recovered. Your <span className="font-medium text-foreground">account, login and 2FA are kept</span>.
Consider downloading a backup first.
</p>
</div>
</div>
</div>
<AlertDialog open={open} onOpenChange={(v) => { setOpen(v); if (!v) setConfirm(''); }}>
<AlertDialogTrigger asChild>
<Button
variant="outline"
className="gap-2 border-rose-300 text-rose-600 hover:bg-rose-50 dark:border-rose-800/60 dark:text-rose-400 dark:hover:bg-rose-950/30"
>
<Trash2 className="h-4 w-4" /> Erase my data
</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Erase all your data?</AlertDialogTitle>
<AlertDialogDescription>
This permanently deletes your bills, payments, transactions, categories, bank connections and imports.
It cannot be undone. Type <span className="font-mono font-semibold text-foreground">ERASE</span> to confirm.
</AlertDialogDescription>
</AlertDialogHeader>
<Input
autoFocus
value={confirm}
onChange={(e) => setConfirm(e.target.value)}
placeholder="Type ERASE"
className="font-mono"
aria-label="Type ERASE to confirm"
/>
<AlertDialogFooter>
<AlertDialogCancel disabled={busy}>Cancel</AlertDialogCancel>
<AlertDialogAction
disabled={!canErase || busy}
onClick={(e) => { e.preventDefault(); handleErase(); }}
className="bg-rose-600 text-white hover:bg-rose-700"
>
{busy ? <><Loader2 className="mr-1.5 h-4 w-4 animate-spin" />Erasing</> : 'Permanently erase'}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</div>
</SectionCard>
);
}