flagon-io/g1t

public

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t/apps/web/app/routes/register.tsx

85 lines2,530 bytesCodeBlame
1import { Form, Link, redirect } from "react-router";
2
3import type { Route } from "./+types/register";
4import { page } from "../lib/meta";
5import { AuthCard } from "../components/auth-card";
6import { Button, ErrorText, Field, Input } from "../components/ui";
7import { identity } from "../lib/services.server";
8import {
9 assertSameOrigin,
10 getViewer,
11 nextPath,
12 startSession,
13} from "../lib/session.server";
14
15export function meta(args: Route.MetaArgs) {
16 return page(args, { title: "Create an account · g1t" });
17}
18
19export function loader({ request, context }: Route.LoaderArgs) {
20 if (getViewer(context)) throw redirect(nextPath(request));
21 return null;
22}
23
24export async function action({ request }: Route.ActionArgs) {
25 assertSameOrigin(request);
26 const form = await request.formData();
27 const result = await identity.register(
28 String(form.get("username") ?? ""),
29 String(form.get("email") ?? ""),
30 String(form.get("password") ?? ""),
31 );
32 if (!result.ok) return { error: result.error.message };
33 throw redirect(nextPath(request), {
34 headers: { "set-cookie": startSession(result.value.sessionToken) },
35 });
36}
37
38export default function Register({ actionData }: Route.ComponentProps) {
39 return (
40 <AuthCard
41 title="Create your account"
42 subtitle="Git for AI scale"
43 footer={
44 <>
45 Already have an account?{" "}
46 <Link to="/login" className="text-fg underline underline-offset-4">
47 Sign in
48 </Link>
49 </>
50 }
51 >
52 <Form method="post" className="space-y-4">
53 <Field
54 label="Username"
55 hint="Lowercase letters, digits and hyphens. It is how you sign in and how others see you."
56 >
57 <Input
58 name="username"
59 autoComplete="username"
60 required
61 autoFocus
62 maxLength={39}
63 pattern="[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9]))*"
64 />
65 </Field>
66 <Field label="Email">
67 <Input name="email" type="email" autoComplete="email" required />
68 </Field>
69 <Field label="Password" hint="At least 10 characters.">
70 <Input
71 name="password"
72 type="password"
73 autoComplete="new-password"
74 required
75 minLength={10}
76 />
77 </Field>
78 <ErrorText>{actionData?.error}</ErrorText>
79 <div className="pt-2 *:w-full">
80 <Button type="submit">Create account</Button>
81 </div>
82 </Form>
83 </AuthCard>
84 );
85}