diff --git a/src/components/auth/auth-form.tsx b/src/components/auth/auth-form.tsx index 601cefb..cddebdb 100644 --- a/src/components/auth/auth-form.tsx +++ b/src/components/auth/auth-form.tsx @@ -1,7 +1,7 @@ "use client"; import { z } from "zod"; -import { ReactElement, useState } from "react"; +import { ReactElement, useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { Input } from "@/components/ui/input"; @@ -84,8 +84,14 @@ const inputAnimationVariants = { * @return the form jsx */ const AuthForm = (): ReactElement => { + const turnstile: TurnstileObject = useTurnstile(); + const cookies: Cookies = useCookies(); + const router: AppRouterInstance = useRouter(); + const [stage, setStage] = useState<"email" | "register" | "login">("email"); const [loading, setLoading] = useState(false); + + const [awaitingCaptcha, setAwaitingCaptcha] = useState(true); const [captchaResponse, setCaptchaResponse] = useState( undefined ); @@ -94,9 +100,6 @@ const AuthForm = (): ReactElement => { const [tfaPin, setTfaPin] = useState(); const [error, setError] = useState(undefined); - const turnstile: TurnstileObject = useTurnstile(); - const cookies: Cookies = useCookies(); - const router: AppRouterInstance = useRouter(); // Build the form const { @@ -113,6 +116,12 @@ const AuthForm = (): ReactElement => { ), }); + // Received the captcha response + useEffect(() => { + console.log("Received new captcha response"); + setAwaitingCaptcha(false); + }, [captchaResponse]); + /** * Handle submitting the form. */ @@ -122,6 +131,10 @@ const AuthForm = (): ReactElement => { password, passwordConfirmation, }: any) => { + // Prevent submitting when the captcha is being fetched + if (awaitingCaptcha) { + return; + } setLoading(true); if (stage === "email") { const { data, error } = await apiRequest<{ exists: boolean }>({ @@ -134,6 +147,7 @@ const AuthForm = (): ReactElement => { } else { setStage(data?.exists ? "login" : "register"); } + setAwaitingCaptcha(true); turnstile.reset(); } else { const registering: boolean = stage === "register"; @@ -161,6 +175,7 @@ const AuthForm = (): ReactElement => { setLoading(false); setBorderCrossing(true); setError(undefined); + setAwaitingCaptcha(true); turnstile.reset(); return; } @@ -168,6 +183,7 @@ const AuthForm = (): ReactElement => { // Reset the captcha if auth fails if (error) { + setAwaitingCaptcha(true); turnstile.reset(); } else { // Otherwise store the session and redirect to the dashboard @@ -240,6 +256,7 @@ const AuthForm = (): ReactElement => { className="pl-8 rounded-lg" type="password" placeholder="Password" + disabled={awaitingCaptcha} {...register("password")} /> @@ -303,7 +320,7 @@ const AuthForm = (): ReactElement => {