fix email verification flow

This commit is contained in:
Ben Senescu 2026-06-19 19:38:55 -04:00 committed by GitHub
parent 17c6c8f60b
commit b2931a6542
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -47,16 +47,14 @@ function getVerificationErrorMessage(error: string | undefined) {
function getVerifyEmailPageCopy({ function getVerifyEmailPageCopy({
isHostedMode, isHostedMode,
errorMessage, errorMessage,
isWaiting,
isPending, isPending,
isVerified, isRedirecting,
email, email,
}: { }: {
isHostedMode: boolean; isHostedMode: boolean;
errorMessage: string | null; errorMessage: string | null;
isWaiting: boolean;
isPending: boolean; isPending: boolean;
isVerified: boolean; isRedirecting: boolean;
email: string | undefined; email: string | undefined;
}) { }) {
if (!isHostedMode) { if (!isHostedMode) {
@ -73,12 +71,10 @@ function getVerifyEmailPageCopy({
}; };
} }
if (isWaiting) { if (isRedirecting) {
return { return {
title: "Verify your email", title: "Email confirmed",
helperText: email helperText: "You're all set. Taking you to your account now.",
? `Click the link we sent to ${email} to verify your email.`
: "Check your inbox for the link to verify your email.",
}; };
} }
@ -89,16 +85,15 @@ function getVerifyEmailPageCopy({
}; };
} }
if (isVerified) { // Default: the user just signed up (or reloaded this page) and still needs to
// click the verification link. There is never a sign-in CTA here — an
// unverified hosted user would be bounced straight back by the verification
// gate.
return { return {
title: "Email confirmed", title: "Verify your email",
helperText: "You're all set. Taking you to your account now.", helperText: email
}; ? `Click the link we sent to ${email} to verify your email.`
} : "Check your inbox for the link to verify your email.",
return {
title: "Sign in to continue",
helperText: "Sign in to continue to your account.",
}; };
} }
@ -115,23 +110,15 @@ function VerifyEmailPage() {
const email = search.email ?? session?.user?.email; const email = search.email ?? session?.user?.email;
const isVerified = !!session?.user?.emailVerified; const isVerified = !!session?.user?.emailVerified;
const [isResending, setIsResending] = useState(false); const [isResending, setIsResending] = useState(false);
// A hosted user who still needs to verify must see the resend / "check your // Verified (or bypass) users are sent on to the app by the effect below; until
// inbox" state — never a sign-in CTA, which the verification gate would // that lands we show the redirecting state instead of the resend prompt.
// immediately block (the email-verify trap). Keying off `email` (which the const isRedirecting =
// sign-up flow always passes) covers the just-signed-up case even while the isVerified || (bypassEmailVerification && Boolean(session?.user?.id));
// session is still resolving, so we never flash the sign-in fallback.
const isWaiting =
isHostedMode &&
!errorMessage &&
!bypassEmailVerification &&
!isVerified &&
(Boolean(email) || !isPending);
const pageCopy = getVerifyEmailPageCopy({ const pageCopy = getVerifyEmailPageCopy({
isHostedMode, isHostedMode,
errorMessage, errorMessage,
isWaiting,
isPending, isPending,
isVerified, isRedirecting,
email, email,
}); });
@ -229,9 +216,11 @@ function VerifyEmailPage() {
Back to sign in Back to sign in
</Link> </Link>
</div> </div>
) : isWaiting ? ( ) : isPending || isRedirecting ? (
email ? ( <div className="flex justify-center py-4">
<div className="space-y-4"> <span className="loading loading-spinner loading-md" />
</div>
) : email ? (
<button <button
type="button" type="button"
className="btn btn-soft w-full" className="btn btn-soft w-full"
@ -240,21 +229,7 @@ function VerifyEmailPage() {
> >
{isResending ? "Sending email..." : "Resend email"} {isResending ? "Sending email..." : "Resend email"}
</button> </button>
</div> ) : null}
) : null
) : isPending || isVerified ? (
<div className="flex justify-center py-4">
<span className="loading loading-spinner loading-md" />
</div>
) : (
<Link
to="/sign-in"
search={getSignInSearch(redirectTo)}
className="btn btn-soft w-full"
>
Sign in to continue
</Link>
)}
</AuthPageCard> </AuthPageCard>
</AuthPageShell> </AuthPageShell>
); );