From 845ccf1ad46c8635782f8e10280b07c48c08eaf5 Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Sun, 13 Jul 2025 09:54:51 +0000 Subject: feat: Add delete account support --- apps/web/components/settings/DeleteAccount.tsx | 182 +++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 apps/web/components/settings/DeleteAccount.tsx (limited to 'apps/web/components') diff --git a/apps/web/components/settings/DeleteAccount.tsx b/apps/web/components/settings/DeleteAccount.tsx new file mode 100644 index 00000000..6ebafff9 --- /dev/null +++ b/apps/web/components/settings/DeleteAccount.tsx @@ -0,0 +1,182 @@ +"use client"; + +import { useState } from "react"; +import { useRouter } from "next/navigation"; +import { ActionButton } from "@/components/ui/action-button"; +import ActionConfirmingDialog from "@/components/ui/action-confirming-dialog"; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { toast } from "@/components/ui/use-toast"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { AlertTriangle, Eye, EyeOff, Trash2 } from "lucide-react"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; + +import { + useDeleteAccount, + useWhoAmI, +} from "@karakeep/shared-react/hooks/users"; + +import { Button } from "../ui/button"; +import { Card, CardContent, CardHeader, CardTitle } from "../ui/card"; + +const createDeleteAccountSchema = (isLocalUser: boolean) => + z.object({ + password: isLocalUser + ? z.string().min(1, "Password is required") + : z.string().optional(), + }); + +export function DeleteAccount() { + const router = useRouter(); + const [showPassword, setShowPassword] = useState(false); + const [isDialogOpen, setIsDialogOpen] = useState(false); + const { data: user } = useWhoAmI(); + + const isLocalUser = user?.localUser ?? false; + const deleteAccountSchema = createDeleteAccountSchema(isLocalUser); + + const form = useForm>({ + resolver: zodResolver(deleteAccountSchema), + defaultValues: { + password: "", + }, + }); + + const deleteAccountMutation = useDeleteAccount({ + onSuccess: () => { + toast({ + description: "Your account has been successfully deleted.", + }); + // Redirect to home page after successful deletion + router.push("/"); + setIsDialogOpen(false); + }, + onError: (error) => { + if (error.data?.code === "UNAUTHORIZED") { + toast({ + description: "Invalid password. Please try again.", + variant: "destructive", + }); + } else { + toast({ + description: "Failed to delete account. Please try again.", + variant: "destructive", + }); + } + }, + }); + + const onSubmit = (values: z.infer) => { + deleteAccountMutation.mutate({ password: values.password }); + }; + + return ( + + + + + Danger Zone + + + +
+

Delete Account

+

+ Permanently delete your account and all associated data. This action + cannot be undone. +

+
+ + +
+ +
+

+ This action is irreversible +

+

+ All your bookmarks, lists, tags, highlights, and other data + will be permanently deleted. This cannot be undone. +

+
+
+ +
+ + {isLocalUser && ( + ( + + + Enter your password to confirm deletion + +
+ + + + +
+ +
+ )} + /> + )} + + + + } + actionButton={() => ( + + + Delete Account + + )} + > + +
+
+
+ ); +} -- cgit v1.2.3-70-g09d2