email.tsx (2330B)
1 import CodeInput from "#http/islands/code_input.tsx"; 2 import DelayedButton from "#http/islands/delayed_button.tsx"; 3 import { AppState } from "#http/routes/_middleware.ts"; 4 import { Handlers, PageProps } from "$fresh/src/server/types.ts"; 5 import * as V from "$valita"; 6 7 type Props = { invalid: boolean; delay: number }; 8 9 export const handler: Handlers<Props, AppState<"/verify/email">> = { 10 async GET(_req, ctx) { 11 const { app, forms, formContext } = ctx.state; 12 if (formContext === null) { 13 return forms.redirect({ form: "/connect", context: { back: "/" } }); 14 } 15 const { back } = formContext; 16 if (forms.session !== null) { 17 return forms.redirect(back); 18 } 19 const { uuid } = formContext; 20 const { authEmailChallenge } = app; 21 const result = await authEmailChallenge.execute({ uuid }); 22 if (result.status === "verified") { 23 return forms.redirect({ 24 form: "/login", 25 context: { uuid, back }, 26 }); 27 } 28 return ctx.render({ 29 invalid: result.status === "invalid", 30 delay: result.delay, 31 }); 32 }, 33 34 async POST(req, ctx) { 35 const { forms, formContext } = ctx.state; 36 if (formContext === null) { 37 return forms.redirect({ 38 form: "/connect", 39 context: { back: "/" }, 40 }); 41 } 42 const { uuid, back } = formContext; 43 const { authVerifyEmail } = ctx.state.app; 44 const { code } = await forms.inputs(req, V.object({ code: V.string() })); 45 const result = await authVerifyEmail.execute({ uuid, code }); 46 if (result.status === "blocked") { 47 return ctx.render({ invalid: false, delay: result.delay }); 48 } 49 if (result.status === "invalid") { 50 return ctx.render({ invalid: true, delay: result.delay }); 51 } 52 return forms.redirect({ 53 form: "/login", 54 context: { uuid, back }, 55 }); 56 }, 57 }; 58 59 export default function VerifyEmailPages({ url, data }: PageProps<Props>) { 60 return ( 61 <article> 62 <header style="text-align: center;"> 63 <b>Email verification</b> 64 </header> 65 <form method="POST"> 66 <CodeInput error={data.invalid} /> 67 <div role="group"> 68 <DelayedButton delay={data.delay} href={url.href}> 69 Resend 70 </DelayedButton> 71 <button type="submit">Verify</button> 72 </div> 73 </form> 74 </article> 75 ); 76 }