secutorpro commited on
Commit
0e5d563
·
verified ·
1 Parent(s): 025301c

login screen

Browse files
Files changed (1) hide show
  1. web/src/components/Login.jsx +35 -0
web/src/components/Login.jsx ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useState } from 'react';
2
+ import { api } from '../api.js';
3
+
4
+ export default function Login({ onLogin }) {
5
+ const [username, setUsername] = useState('');
6
+ const [password, setPassword] = useState('');
7
+ const [error, setError] = useState('');
8
+ const [busy, setBusy] = useState(false);
9
+
10
+ const submit = async (e) => {
11
+ e.preventDefault();
12
+ setBusy(true);
13
+ setError('');
14
+ try {
15
+ await onLogin(username, password);
16
+ } catch (err) {
17
+ setError(err.message || 'Login failed');
18
+ } finally {
19
+ setBusy(false);
20
+ }
21
+ };
22
+
23
+ return (
24
+ <div className="login-wrap">
25
+ <form className="login" onSubmit={submit}>
26
+ <h1>Dispatch Console</h1>
27
+ <input placeholder="Username" value={username} onChange={(e) => setUsername(e.target.value)} autoFocus />
28
+ <input type="password" placeholder="Password" value={password} onChange={(e) => setPassword(e.target.value)} />
29
+ {error && <p className="error">{error}</p>}
30
+ <button disabled={busy}>{busy ? 'Signing in…' : 'Sign in'}</button>
31
+ <p className="muted small">First run creates admin / admin — change it.</p>
32
+ </form>
33
+ </div>
34
+ );
35
+ }