| 1 | import { useState } from 'react'
|
|---|
| 2 | import { api, auth } from '../lib/api.js'
|
|---|
| 3 |
|
|---|
| 4 | export default function Login({ onSignedIn }) {
|
|---|
| 5 | const [mode, setMode] = useState('login')
|
|---|
| 6 | const [form, setForm] = useState({ email: '', username: '', password: '' })
|
|---|
| 7 | const [error, setError] = useState(null)
|
|---|
| 8 | const [busy, setBusy] = useState(false)
|
|---|
| 9 |
|
|---|
| 10 | const set = (k) => (e) => setForm({ ...form, [k]: e.target.value })
|
|---|
| 11 |
|
|---|
| 12 | const submit = async () => {
|
|---|
| 13 | setBusy(true)
|
|---|
| 14 | setError(null)
|
|---|
| 15 | try {
|
|---|
| 16 | const body = mode === 'login'
|
|---|
| 17 | ? { email: form.email, password: form.password }
|
|---|
| 18 | : form
|
|---|
| 19 | const res = await api.post(`/auth/${mode}`, body)
|
|---|
| 20 | auth.save(res)
|
|---|
| 21 | onSignedIn(auth.user())
|
|---|
| 22 | } catch (e) {
|
|---|
| 23 | setError(e.message)
|
|---|
| 24 | } finally {
|
|---|
| 25 | setBusy(false)
|
|---|
| 26 | }
|
|---|
| 27 | }
|
|---|
| 28 |
|
|---|
| 29 | return (
|
|---|
| 30 | <div className="app">
|
|---|
| 31 | <header className="top"><h1>Nutritioneer</h1><span className="muted">prototype</span></header>
|
|---|
| 32 |
|
|---|
| 33 | <div className="card" style={{ maxWidth: 440 }}>
|
|---|
| 34 | <h3>{mode === 'login' ? 'Sign in' : 'Create an account'}</h3>
|
|---|
| 35 | {error && <div className="error">{error}</div>}
|
|---|
| 36 |
|
|---|
| 37 | <div className="stack">
|
|---|
| 38 | <input placeholder="email" value={form.email} onChange={set('email')} />
|
|---|
| 39 | {mode === 'register' &&
|
|---|
| 40 | <input placeholder="username" value={form.username} onChange={set('username')} />}
|
|---|
| 41 | <input placeholder="password" type="password"
|
|---|
| 42 | value={form.password} onChange={set('password')} />
|
|---|
| 43 |
|
|---|
| 44 | <div className="row">
|
|---|
| 45 | <button className="primary" onClick={submit} disabled={busy}>
|
|---|
| 46 | {busy ? 'working...' : mode === 'login' ? 'Sign in' : 'Register'}
|
|---|
| 47 | </button>
|
|---|
| 48 | <button className="small"
|
|---|
| 49 | onClick={() => { setMode(mode === 'login' ? 'register' : 'login'); setError(null) }}>
|
|---|
| 50 | {mode === 'login' ? 'need an account?' : 'have an account?'}
|
|---|
| 51 | </button>
|
|---|
| 52 | </div>
|
|---|
| 53 | </div>
|
|---|
| 54 |
|
|---|
| 55 | <p className="muted" style={{ marginTop: 14 }}>
|
|---|
| 56 | Seed accounts use the password <code>testPass@1</code>, for example{' '}
|
|---|
| 57 | <code>marija.trajkovska@gmail.com</code> or <code>admin@nutritioneer.mk</code>.
|
|---|
| 58 | </p>
|
|---|
| 59 | </div>
|
|---|
| 60 | </div>
|
|---|
| 61 | )
|
|---|
| 62 | }
|
|---|