web/src/routes/login/+page.svelte (view raw)
1<script lang="ts">
2 import { login, register } from '$lib/api';
3
4 let username = $state('');
5 let password = $state('');
6 let error = $state('');
7 let loading = $state(false);
8 let isRegister = $state(false);
9
10 async function handleSubmit(e: Event) {
11 e.preventDefault();
12 error = '';
13 loading = true;
14 try {
15 if (isRegister) {
16 await register(username, password);
17 }
18 await login(username, password);
19 window.location.href = '/browse';
20 } catch (err) {
21 error = err instanceof Error ? err.message : 'Login failed';
22 } finally {
23 loading = false;
24 }
25 }
26</script>
27
28<h1>{isRegister ? 'Register' : 'Login'}</h1>
29
30<form onsubmit={handleSubmit}>
31 {#if error}
32 <p class="error">{error}</p>
33 {/if}
34 <label>
35 Username
36 <input type="text" bind:value={username} required minlength={3} disabled={loading} />
37 </label>
38 <label>
39 Password
40 <input type="password" bind:value={password} required minlength={8} disabled={loading} />
41 </label>
42 <button type="submit" disabled={loading}>
43 {isRegister ? 'Register' : 'Login'}
44 </button>
45</form>
46
47<p class="toggle">
48 <button class="link" onclick={() => { isRegister = !isRegister; error = ''; }}>
49 {isRegister ? 'Already have an account? Log in' : 'No account? Register'}
50 </button>
51</p>
52
53<style>
54 h1 {
55 margin-bottom: 1rem;
56 }
57 form {
58 display: flex;
59 flex-direction: column;
60 gap: 0.75rem;
61 max-width: 320px;
62 }
63 label {
64 display: flex;
65 flex-direction: column;
66 gap: 0.25rem;
67 }
68 input {
69 padding: 0.5rem;
70 border: 1px solid #ccc;
71 border-radius: 4px;
72 }
73 button[type="submit"] {
74 padding: 0.5rem;
75 background: #1a1a2e;
76 color: #eee;
77 border: none;
78 border-radius: 4px;
79 cursor: pointer;
80 }
81 button[type="submit"]:disabled {
82 opacity: 0.6;
83 }
84 .error {
85 color: #c0392b;
86 font-size: 0.9rem;
87 }
88 .toggle {
89 margin-top: 1rem;
90 }
91 button.link {
92 background: none;
93 border: none;
94 color: #1a1a2e;
95 text-decoration: underline;
96 cursor: pointer;
97 padding: 0;
98 font-size: inherit;
99 }
100</style>