"use client"; import { Alert, AlertType } from "@/components/alert"; import { handleServerActionResponse } from "@/lib/client-utils"; import { UNKNOWN_USER_ID } from "@/lib/constants"; import { initialSendVerification, resendVerification, sendVerification } from "@/lib/server/verify"; import { useTranslations } from "next-intl"; import { useRouter } from "next/navigation"; import { useCallback, useEffect, useRef, useState } from "react"; import { useForm } from "react-hook-form"; import { AutoSubmitForm } from "./auto-submit-form"; import { BackButton } from "./back-button"; import { Button, ButtonVariants } from "./button"; import { TextInput } from "./input"; import { Spinner } from "./spinner"; import { Translated } from "./translated"; type Inputs = { code: string; }; type Props = { userId: string; loginName?: string; organization?: string; code?: string; isInvite: boolean; requestId?: string; submit: boolean; doSend?: boolean; }; export function VerifyForm({ userId, loginName, organization, requestId, code, isInvite, submit, doSend }: Props) { const router = useRouter(); const { register, handleSubmit, formState } = useForm({ mode: "onChange", defaultValues: { code: code ?? "", }, }); const t = useTranslations("verify"); const [error, setError] = useState(""); const [samlData, setSamlData] = useState<{ url: string; fields: Record } | null>(null); const [loading, setLoading] = useState(false); const initialSendDone = useRef(false); const [initialSendError, setInitialSendError] = useState(""); const [codeSent, setCodeSent] = useState(false); useEffect(() => { if (doSend && userId && userId !== UNKNOWN_USER_ID && !initialSendDone.current) { initialSendDone.current = true; setError(""); initialSendVerification({ userId, isInvite, requestId }) .then(() => { setCodeSent(true); }) .catch(() => { setInitialSendError(isInvite ? t("errors.couldNotResendInvite") : t("errors.couldNotResendEmail")); }); } }, [doSend, userId, isInvite, requestId, t]); async function resendCode() { setError(""); setInitialSendError(""); setLoading(true); // do not send code for dummy userid that is set to prevent user enumeration if (userId === UNKNOWN_USER_ID) { await new Promise((resolve) => setTimeout(resolve, 1000)); setLoading(false); return; } const response = await resendVerification({ userId, isInvite: isInvite, requestId: requestId, }) .catch(() => { setError(t("errors.couldNotResendEmail")); return; }) .finally(() => { setLoading(false); }); if (response && "error" in response && response?.error) { setError(response.error); return; } return response; } const processedCode = useRef(undefined); const fcn = useCallback( async function submitCodeAndContinue(value: Inputs): Promise { setError(""); setInitialSendError(""); setLoading(true); try { const response = await sendVerification({ code: value.code, userId, isInvite: isInvite, loginName: loginName, organization: organization, requestId: requestId, }); handleServerActionResponse(response, router, setSamlData, setError); } catch { setError(t("errors.couldNotVerifyUser")); } finally { setLoading(false); } }, [isInvite, userId, loginName, organization, requestId, router, t], ); useEffect(() => { if (submit && code && code !== processedCode.current) { processedCode.current = code; fcn({ code }); } }, [submit, code, fcn]); return ( <> {samlData && } {codeSent && !initialSendError && (
)}
{(error || initialSendError) && (
{error || initialSendError}
)}
); }