id-document.tsx (4861B)
1 import { IDDocumentListResponse } from "#core/application/id_document/list.ts"; 2 import { AppState } from "#http/routes/_middleware.ts"; 3 import { PageProps } from "$fresh/server.ts"; 4 import { Handlers } from "$fresh/src/server/types.ts"; 5 import * as V from "$valita"; 6 7 type Props = { 8 items: IDDocumentListResponse["items"]; 9 next: URL; 10 }; 11 12 export const handler: Handlers<Props, AppState<"/verify/id-document">> = { 13 async GET(_req, ctx) { 14 const { app, forms, formContext } = ctx.state; 15 const { idDocumentList, isIdDocumentAdmin } = app; 16 if (formContext === null) { 17 return forms.redirect({ 18 form: "/verify/id-document", 19 context: { cursor: 0 }, 20 }); 21 } 22 const { cursor } = formContext; 23 if (forms.session === null) { 24 return forms.redirect({ 25 form: "/connect", 26 context: { 27 back: { form: "/verify/id-document", context: formContext }, 28 }, 29 }); 30 } 31 if (!(await isIdDocumentAdmin.execute({ uuid: forms.session.uuid }))) { 32 return forms.redirect("/"); 33 } 34 const { items, next: nextCursor } = await idDocumentList.execute({ 35 cursor, 36 }); 37 const next = forms.link({ 38 form: "/verify/id-document", 39 context: { cursor: nextCursor }, 40 }); 41 return ctx.render({ items, next }); 42 }, 43 44 async POST(req, ctx) { 45 const { app, forms, formContext } = ctx.state; 46 const { idDocumentApprove, idDocumentDecline, isIdDocumentAdmin } = app; 47 if (formContext === null) { 48 return forms.redirect("/"); 49 } 50 51 if (forms.session === null) { 52 return forms.redirect({ 53 form: "/connect", 54 context: { 55 back: { form: "/verify/id-document", context: formContext }, 56 }, 57 }); 58 } 59 if (!(await isIdDocumentAdmin.execute({ uuid: forms.session.uuid }))) { 60 return forms.redirect("/"); 61 } 62 63 const { uuid, approved } = await forms.inputs( 64 req, 65 V.object({ 66 uuid: V.string(), 67 approved: V.string().map(() => true).default(false), 68 }), 69 ); 70 71 if (approved) { 72 await idDocumentApprove.execute({ 73 admin: forms.session.uuid, 74 uuid, 75 }); 76 } else { 77 await idDocumentDecline.execute({ 78 admin: forms.session.uuid, 79 uuid, 80 }); 81 } 82 83 return forms.redirect(req.url); 84 }, 85 }; 86 87 export default function IDDocumentPage( 88 { data }: PageProps<Props, AppState<"/verify/id-document">>, 89 ) { 90 return ( 91 <> 92 <div class="grid"> 93 {data.items.map((i) => ( 94 <article style="max-width: 32em;"> 95 <header style="text-align: center;"> 96 <b>ID Information</b> 97 </header> 98 <div> 99 <table> 100 <tr> 101 <th> 102 <b>First name</b> 103 </th> 104 <td>{i.firstName ? i.firstName : "—"}</td> 105 </tr> 106 <tr> 107 <th> 108 <b>Last name</b> 109 </th> 110 <td>{i.lastName ? i.lastName : "—"}</td> 111 </tr> 112 <tr> 113 <th> 114 <b>Sex</b> 115 </th> 116 <td>{i.sex ? i.sex : "—"}</td> 117 </tr> 118 <tr> 119 <th> 120 <b>Birth date</b> 121 </th> 122 <td> 123 {i.birthDate 124 ? i.birthDate.toLocaleDateString("en", { 125 year: "numeric", 126 month: "long", 127 day: "numeric", 128 }) 129 : "—"} 130 </td> 131 </tr> 132 <tr> 133 <th> 134 <b>Nationality</b> 135 </th> 136 <td>{i.nationality ? i.nationality : "—"}</td> 137 </tr> 138 <tr> 139 <th> 140 <b>Country</b> 141 </th> 142 <td>{i.country ? i.country : "—"}</td> 143 </tr> 144 </table> 145 <section className="grid"> 146 {i.docFront && <img src={i.docFront} />} 147 {i.docBack && <img src={i.docBack} />} 148 {i.faceLeft && <img src={i.faceLeft} />} 149 {i.faceFront && <img src={i.faceFront} />} 150 {i.faceRight && <img src={i.faceRight} />} 151 </section> 152 <form method="POST"> 153 <input type="hidden" name="uuid" value={i.uuid} /> 154 <div role="group"> 155 <button type="submit" class="secondary">Decline</button> 156 <button type="submit" name="approved" value="on"> 157 Approve 158 </button> 159 </div> 160 </form> 161 </div> 162 </article> 163 ))} 164 165 </div> 166 <nav role="group"> 167 <a role="button" href={data.next.href}>Next</a> 168 </nav> 169 </> 170 ); 171 }