Prevent double submit + stop using form

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-02-05 11:13:44 +04:00
parent 8e8288a361
commit 8df0e526ba

View File

@@ -1,14 +1,12 @@
import { formatError } from "@probo/helpers"; import { formatError } from "@probo/helpers";
import { usePageTitle } from "@probo/hooks"; import { usePageTitle } from "@probo/hooks";
import { useTranslate } from "@probo/i18n"; import { useTranslate } from "@probo/i18n";
import { Button, Field, useToast } from "@probo/ui"; import { useToast } from "@probo/ui";
import { useEffect, useRef } from "react"; import { useCallback, useEffect, useRef } from "react";
import { useMutation } from "react-relay"; import { useMutation } from "react-relay";
import { useSearchParams } from "react-router"; import { Link, useSearchParams } from "react-router";
import { graphql } from "relay-runtime"; import { graphql } from "relay-runtime";
import { z } from "zod";
import { useFormWithSchema } from "#/hooks/useFormWithSchema";
import { getPathPrefix } from "#/utils/pathPrefix"; import { getPathPrefix } from "#/utils/pathPrefix";
import type { VerifyMagicLinkPageMutation } from "./__generated__/VerifyMagicLinkPageMutation.graphql"; import type { VerifyMagicLinkPageMutation } from "./__generated__/VerifyMagicLinkPageMutation.graphql";
@@ -21,10 +19,6 @@ const verifyMagicLinkMutation = graphql`
} }
`; `;
const verifyMagicLinkSchema = z.object({
token: z.string().min(1, "Please enter a magic token"),
});
export default function VerifyMagicLinkPagePageMutation() { export default function VerifyMagicLinkPagePageMutation() {
const { __ } = useTranslate(); const { __ } = useTranslate();
const { toast } = useToast(); const { toast } = useToast();
@@ -33,22 +27,16 @@ export default function VerifyMagicLinkPagePageMutation() {
usePageTitle(__("Verify Magic Link")); usePageTitle(__("Verify Magic Link"));
const form = useFormWithSchema(verifyMagicLinkSchema, {
defaultValues: {
token: searchParams.get("token") ?? "",
},
});
const [verifyMagicLink] = useMutation<VerifyMagicLinkPageMutation>( const [verifyMagicLink] = useMutation<VerifyMagicLinkPageMutation>(
verifyMagicLinkMutation, verifyMagicLinkMutation,
); );
const handleSubmit = form.handleSubmit((data) => { const handleVerifyMagicToken = useCallback((token: string) => {
if (submittedRef.current) return;
verifyMagicLink({ verifyMagicLink({
variables: { variables: {
input: { input: { token },
token: data.token.trim(),
},
}, },
onCompleted: (_, errors) => { onCompleted: (_, errors) => {
if (errors) { if (errors) {
@@ -76,47 +64,32 @@ export default function VerifyMagicLinkPagePageMutation() {
}); });
}, },
}); });
}); }, [__, toast, verifyMagicLink]);
useEffect(() => { useEffect(() => {
if (!submittedRef.current && searchParams.get("token")) { const token = searchParams.get("token");
void handleSubmit(); if (!submittedRef.current && token) {
void handleVerifyMagicToken(token.trim());
submittedRef.current = true; submittedRef.current = true;
} }
}); }, [handleVerifyMagicToken, searchParams]);
return ( return (
<div className="space-y-6 w-full max-w-md mx-auto pt-8"> <div className="space-y-6 w-full max-w-md mx-auto pt-8">
<div className="space-y-2 text-center"> <div className="space-y-2 text-center">
<h1 className="text-3xl font-bold">{__("Email Confirmation")}</h1> <h1 className="text-3xl font-bold">{__("Email Confirmation")}</h1>
<p className="text-txt-tertiary"> <p className="text-txt-tertiary">
{__("Confirm your email address to complete registration")} {__("Confirming your email address to complete registration…")}
</p> </p>
</div> </div>
<div className="text-center mt-6 text-sm text-txt-secondary">
<form onSubmit={e => void handleSubmit(e)} className="space-y-6"> <Link
<Field to="/connect"
label={__("Confirmation Token")} className="underline hover:text-txt-primary"
type="text"
placeholder={__("Enter your confirmation token")}
{...form.register("token")}
error={form.formState.errors.token?.message}
disabled={form.formState.isSubmitting}
help={__(
"The token has been automatically filled from the URL if available",
)}
/>
<Button
type="submit"
className="w-xs h-10 mx-auto"
disabled={form.formState.isSubmitting}
> >
{form.formState.isSubmitting {__("Go back")}
? __("Confirming...") </Link>
: __("Confirm Email")} </div>
</Button>
</form>
</div> </div>
); );
} }