pr_01m47d15m3e54sn21z27rpy5n9/apps/web/app/routes/verify.tsx

64 lines2,258 bytesCodeBlame
1import { CircleCheck, MailWarning } from "lucide-react";
2import { redirect } from "react-router";
3
4import type { Route } from "./+types/verify";
5import { ButtonLink } from "../components/ui";
6import { identity } from "../lib/services.server";
7import { assertSameOrigin, requireUser } from "../lib/session.server";
8
9export function meta({}: Route.MetaArgs) {
10 return [{ title: "Confirm your email · g1t" }];
11}
12
13/** Follows the link from the confirmation email. */
14export async function loader({ request }: Route.LoaderArgs) {
15 const token = new URL(request.url).searchParams.get("token") ?? "";
16 const result = await identity.verifyEmail(token);
17 return result.ok
18 ? { ok: true as const, username: result.value.username }
19 : { ok: false as const, message: result.error.message };
20}
21
22/** "Resend" from the banner shown to unconfirmed accounts. */
23export async function action({ request, context }: Route.ActionArgs) {
24 assertSameOrigin(request);
25 await identity.resendVerification(requireUser(context, request));
26 throw redirect("/?sent=1");
27}
28
29export default function Verify({ loaderData }: Route.ComponentProps) {
30 return (
31 <main className="mx-auto max-w-md px-4 py-32 text-center">
32 {loaderData.ok ? (
33 <>
34 <CircleCheck size={40} className="mx-auto text-accent" />
35 <h1 className="mt-6 text-2xl font-semibold tracking-tight">
36 Email confirmed
37 </h1>
38 <p className="mt-2 text-muted">
39 Your account {loaderData.username} is ready to use.
40 </p>
41 <div className="mt-8">
42 <ButtonLink to="/">Go to g1t</ButtonLink>
43 </div>
44 </>
45 ) : (
46 <>
47 <MailWarning size={40} className="mx-auto text-warn" />
48 <h1 className="mt-6 text-2xl font-semibold tracking-tight">
49 That link did not work
50 </h1>
51 <p className="mt-2 text-muted">{loaderData.message}</p>
52 <p className="mt-2 text-sm text-muted">
53 Sign in and use the banner at the top to send a new one.
54 </p>
55 <div className="mt-8">
56 <ButtonLink to="/login" variant="quiet">
57 Sign in
58 </ButtonLink>
59 </div>
60 </>
61 )}
62 </main>
63 );
64}