feat(frontend): confirmation dialogs and undo for destructive-feeling actions
Volk aufloesen, Bienenstand deaktivieren, Benutzer deaktivieren und Webhook loeschen liefen bisher ohne jede Rueckfrage direkt auf Klick. Neue wiederverwendbare ConfirmDialog-Komponente erzwingt jetzt eine bewusste Bestaetigung. Zusaetzlich zeigen Volk/Bienenstand/Benutzer nach dem Aufloesen/Deaktivieren einen Reaktivieren-Button (nutzt die neuen Backend-Endpunkte), da diese Aktionen nie ein echtes Loeschen sind und ein versehentlicher Klick bisher nicht rueckgaengig zu machen war.
This commit is contained in:
1 parent
57979f0371
commit
6ab028d1be
9 files changed
+231
-36
No files matched your search
@@ -0,0 +1,81 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Button, buttonVariants } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { VariantProps } from "class-variance-authority";
|
||||
|
||||
interface ConfirmDialogProps {
|
||||
triggerLabel: string;
|
||||
triggerVariant?: VariantProps<typeof buttonVariants>["variant"];
|
||||
triggerSize?: VariantProps<typeof buttonVariants>["size"];
|
||||
triggerClassName?: string;
|
||||
triggerDisabled?: boolean;
|
||||
title: string;
|
||||
description: string;
|
||||
confirmLabel: string;
|
||||
destructive?: boolean;
|
||||
onConfirm: () => void;
|
||||
isPending?: boolean;
|
||||
}
|
||||
|
||||
export function ConfirmDialog({
|
||||
triggerLabel,
|
||||
triggerVariant = "outline",
|
||||
triggerSize = "default",
|
||||
triggerClassName,
|
||||
triggerDisabled,
|
||||
title,
|
||||
description,
|
||||
confirmLabel,
|
||||
destructive = true,
|
||||
onConfirm,
|
||||
isPending,
|
||||
}: ConfirmDialogProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<Button
|
||||
type="button"
|
||||
variant={triggerVariant}
|
||||
size={triggerSize}
|
||||
className={cn(triggerClassName)}
|
||||
disabled={triggerDisabled}
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
{triggerLabel}
|
||||
</Button>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{title}</DialogTitle>
|
||||
<DialogDescription>{description}</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<Button type="button" variant="outline" onClick={() => setOpen(false)}>
|
||||
Abbrechen
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant={destructive ? "destructive" : "default"}
|
||||
disabled={isPending}
|
||||
onClick={() => {
|
||||
onConfirm();
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
{isPending ? "Wird ausgeführt…" : confirmLabel}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user