"use client"; import { useState, useEffect, useMemo } from "react"; import { useRouter } from "next/navigation"; import { createApiClient } from "@app/lib/api"; import { useEnvContext } from "@app/hooks/useEnvContext"; import { formatAxiosError } from "@app/lib/api"; import { toast } from "@app/hooks/useToast"; import { useTranslations } from "next-intl"; import { Button } from "@app/components/ui/button"; import { Credenza, CredenzaBody, CredenzaClose, CredenzaContent, CredenzaFooter, CredenzaHeader, CredenzaTitle } from "@app/components/Credenza"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@app/components/ui/form"; import { Input } from "@app/components/ui/input"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { InputOTP, InputOTPGroup, InputOTPSlot } from "@app/components/ui/input-otp"; import { REGEXP_ONLY_DIGITS_AND_CHARS } from "input-otp"; import type { DeleteMyAccountPreviewResponse, DeleteMyAccountCodeRequestedResponse, DeleteMyAccountSuccessResponse } from "@server/routers/auth/deleteMyAccount"; import { AxiosResponse } from "axios"; type DeleteAccountConfirmDialogProps = { open: boolean; setOpen: (open: boolean) => void; }; export default function DeleteAccountConfirmDialog({ open, setOpen }: DeleteAccountConfirmDialogProps) { const { env } = useEnvContext(); const api = createApiClient({ env }); const router = useRouter(); const t = useTranslations(); const passwordSchema = useMemo( () => z.object({ password: z.string().min(1, { message: t("passwordRequired") }) }), [t] ); const codeSchema = useMemo( () => z.object({ code: z.string().length(6, { message: t("pincodeInvalid") }) }), [t] ); const [step, setStep] = useState<0 | 1 | 2>(0); const [loading, setLoading] = useState(false); const [loadingPreview, setLoadingPreview] = useState(false); const [preview, setPreview] = useState(null); const [passwordValue, setPasswordValue] = useState(""); const passwordForm = useForm>({ resolver: zodResolver(passwordSchema), defaultValues: { password: "" } }); const codeForm = useForm>({ resolver: zodResolver(codeSchema), defaultValues: { code: "" } }); useEffect(() => { if (open && step === 0 && !preview) { setLoadingPreview(true); api.post>( "/auth/delete-my-account", {} ) .then((res) => { if (res.data?.data?.preview) { setPreview(res.data.data); } }) .catch((err) => { toast({ variant: "destructive", title: t("deleteAccountError"), description: formatAxiosError( err, t("deleteAccountError") ) }); setOpen(false); }) .finally(() => setLoadingPreview(false)); } }, [open, step, preview, api, setOpen, t]); function reset() { setStep(0); setPreview(null); setPasswordValue(""); passwordForm.reset(); codeForm.reset(); } async function handleContinueToPassword() { setStep(1); } async function handlePasswordSubmit( values: z.infer ) { setLoading(true); setPasswordValue(values.password); try { const res = await api.post< | AxiosResponse | AxiosResponse >("/auth/delete-my-account", { password: values.password }); const data = res.data?.data; if (data && "codeRequested" in data && data.codeRequested) { setStep(2); } else if (data && "success" in data && data.success) { toast({ title: t("deleteAccountSuccess"), description: t("deleteAccountSuccessMessage") }); setOpen(false); reset(); router.push("/auth/login"); router.refresh(); } } catch (err) { toast({ variant: "destructive", title: t("deleteAccountError"), description: formatAxiosError(err, t("deleteAccountError")) }); } finally { setLoading(false); } } async function handleCodeSubmit(values: z.infer) { setLoading(true); try { const res = await api.post< AxiosResponse >("/auth/delete-my-account", { password: passwordValue, code: values.code }); if (res.data?.data?.success) { toast({ title: t("deleteAccountSuccess"), description: t("deleteAccountSuccessMessage") }); setOpen(false); reset(); router.push("/auth/login"); router.refresh(); } } catch (err) { toast({ variant: "destructive", title: t("deleteAccountError"), description: formatAxiosError(err, t("deleteAccountError")) }); } finally { setLoading(false); } } return ( { setOpen(val); if (!val) reset(); }} > {t("deleteAccountConfirmTitle")}
{step === 0 && ( <> {loadingPreview ? (

{t("loading")}...

) : preview ? ( <>

{t("deleteAccountConfirmMessage")}

{t( "deleteAccountPreviewAccount" )}

{preview.orgs.length > 0 && ( <>

{t( "deleteAccountPreviewOrgs" )}

    {preview.orgs.map( (org) => (
  • {org.name || org.orgId}
  • ) )}
)}

{t("cannotbeUndone")}

) : null} )} {step === 1 && (
( {t("password")} )} /> )} {step === 2 && (

{t("otpAuthDescription")}

(
{ field.onChange( value ); }} >
)} />
)}
{step === 0 && preview && !loadingPreview && ( )} {step === 1 && ( )} {step === 2 && ( )}
); }