main
tsx 81 lines 2.43 KB
Raw
1 "use client";
2
3 import { useEffect, useState } from "react";
4 import Link from "next/link";
5 import { useRouter } from "next/navigation";
6 import { authApi } from "../lib/portfolio-api";
7
8 type VerificationState = "VERIFYING" | "SUCCESS" | "INVALID";
9
10 export default function VerifyEmailPage() {
11 const router = useRouter();
12 const [state, setState] = useState<VerificationState>("VERIFYING");
13 const [email, setEmail] = useState("");
14 const [resendMessage, setResendMessage] = useState("");
15
16 useEffect(() => {
17 const token = new URLSearchParams(window.location.search).get("token");
18 if (!token) {
19 queueMicrotask(() => setState("INVALID"));
20 return;
21 }
22
23 let active = true;
24 let redirectTimer: number | undefined;
25 void authApi.verifyEmail(token)
26 .then(() => {
27 if (!active) return;
28 setState("SUCCESS");
29 redirectTimer = window.setTimeout(() => router.push("/"), 1500);
30 })
31 .catch(() => {
32 if (active) setState("INVALID");
33 });
34
35 return () => {
36 active = false;
37 if (redirectTimer) window.clearTimeout(redirectTimer);
38 };
39 }, [router]);
40
41 if (state === "SUCCESS") {
42 return (
43 <main className="signin-shell">
44 <section className="signin-panel">
45 <h1>Email verified</h1>
46 <p>Email verified successfully.</p>
47 <p>Redirecting you to sign in...</p>
48 <Link className="button" href="/">Sign in now</Link>
49 </section>
50 </main>
51 );
52 }
53
54 if (state === "INVALID") {
55 return (
56 <main className="signin-shell">
57 <section className="signin-panel">
58 <h1>Verification link expired</h1>
59 <p>This verification link is invalid or expired.</p>
60 <form className="signin-actions" onSubmit={(event) => {
61 event.preventDefault();
62 void authApi.resendVerification(email).then((result) => setResendMessage(result.message));
63 }}>
64 <input type="email" value={email} onChange={(event) => setEmail(event.target.value)} required placeholder="Email" />
65 <button type="submit">Resend verification email</button>
66 </form>
67 {resendMessage ? <p role="status">{resendMessage}</p> : null}
68 <Link href="/">Back to sign in</Link>
69 </section>
70 </main>
71 );
72 }
73
74 return (
75 <main className="signin-shell">
76 <section className="signin-panel">
77 <h1>Verifying your email...</h1>
78 </section>
79 </main>
80 );
81 }