-
Notifications
You must be signed in to change notification settings - Fork 166
Expand file tree
/
Copy pathsetup.tsx
More file actions
93 lines (85 loc) · 3.17 KB
/
Copy pathsetup.tsx
File metadata and controls
93 lines (85 loc) · 3.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import { useState, type FormEvent } from "react";
import { Button } from "@executor-js/react/components/button";
import { Input } from "@executor-js/react/components/input";
import { Label } from "@executor-js/react/components/label";
import { authClient } from "./auth-client";
import { AuthLayout } from "./auth-layout";
// First-run setup. A fresh instance has no users, so the first visitor creates
// the admin account here. The server admits the first signup into the empty org
// as its owner (no invite code needed); once anyone is a member, signup is
// invite-gated and this page is never shown again. The auth gate renders this
// when /api/setup-status reports the instance still needs setup.
export const SetupPage = () => {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState<string | null>(null);
const [busy, setBusy] = useState(false);
const submit = async (event: FormEvent) => {
event.preventDefault();
setBusy(true);
setError(null);
const result = await authClient.signUp.email({ name, email, password });
if (result.error) {
setBusy(false);
setError(result.error.message ?? "Could not create the admin account.");
return;
}
window.location.href = "/";
};
return (
<AuthLayout>
<form
onSubmit={submit}
className="w-full max-w-sm space-y-4 rounded-xl border border-border bg-card p-6 shadow-sm"
>
<div className="space-y-1">
<h1 className="text-xl font-semibold tracking-tight text-foreground">Set up Executor</h1>
<p className="text-sm text-muted-foreground">
Create the admin account for this instance. You can invite your team once you're in.
</p>
</div>
<div className="space-y-1.5">
<Label htmlFor="name">Name</Label>
<Input
id="name"
placeholder="Your name"
value={name}
onChange={(e) => setName((e.target as HTMLInputElement).value)}
autoComplete="name"
required
/>
</div>
<div className="space-y-1.5">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
placeholder="you@example.com"
value={email}
onChange={(e) => setEmail((e.target as HTMLInputElement).value)}
autoComplete="email"
required
/>
</div>
<div className="space-y-1.5">
<Label htmlFor="password">Password</Label>
<Input
id="password"
type="password"
placeholder="••••••••"
value={password}
onChange={(e) => setPassword((e.target as HTMLInputElement).value)}
autoComplete="new-password"
required
minLength={8}
/>
</div>
{error && <p className="text-sm text-destructive">{error}</p>}
<Button type="submit" disabled={busy} className="w-full">
{busy ? "Creating…" : "Create admin account"}
</Button>
</form>
</AuthLayout>
);
};