64 lines · 2.1 KB
1 ---
2 import Base from '../layouts/Base.astro';
3 import { apiPost } from '../lib/api';
4
5 let error = '';
6
7 if (Astro.request.method === 'POST') {
8 try {
9 const formData = await Astro.request.formData();
10 const username = formData.get('username') as string;
11 const email = formData.get('email') as string;
12 const password = formData.get('password') as string;
13
14 await apiPost('/api/register', { username, email, password });
15
16 // Auto-login after registration
17 const { data, headers } = await apiPost('/api/login', { username, password });
18 const setCookie = headers.get('set-cookie');
19 if (setCookie) {
20 Astro.cookies.set('session', setCookie.match(/session=([^;]+)/)?.[1] || '', {
21 path: '/',
22 httpOnly: true,
23 secure: true,
24 sameSite: 'strict',
25 maxAge: 7 * 24 * 60 * 60,
26 });
27 }
28
29 return Astro.redirect('/');
30 } catch (e: any) {
31 error = e.message;
32 }
33 }
34 ---
35
36 <Base title="Sign up">
37 <div class="container" style="max-width: 400px; padding-top: 48px;">
38 <div class="card">
39 <h1 style="font-size: 1.25rem; margin-bottom: 20px; text-align: center;">Create your account</h1>
40
41 {error && <div class="flash-error">{error}</div>}
42
43 <form method="POST">
44 <div class="form-group">
45 <label for="username">Username</label>
46 <input type="text" id="username" name="username" required pattern="[a-zA-Z0-9_-]{2,32}" />
47 </div>
48 <div class="form-group">
49 <label for="email">Email</label>
50 <input type="email" id="email" name="email" required />
51 </div>
52 <div class="form-group">
53 <label for="password">Password</label>
54 <input type="password" id="password" name="password" required minlength="8" autocomplete="new-password" />
55 </div>
56 <button type="submit" class="btn btn-primary" style="width: 100%;">Create account</button>
57 </form>
58 </div>
59 <p style="text-align: center; margin-top: 16px; font-size: 0.875rem; color: var(--text-muted);">
60 Already have an account? <a href="/login">Sign in</a>
61 </p>
62 </div>
63 </Base>
64