MotorSignal-App/website/components/auth-form.tsx

44 lines
1.8 KiB
TypeScript

'use client';
import { FormEvent, useState } from 'react';
type AuthMode = 'login' | 'register';
export function AuthForm({ mode }: { mode: AuthMode }) {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [deviceName, setDeviceName] = useState('Web browser');
const [message, setMessage] = useState('');
const [busy, setBusy] = useState(false);
async function submit(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
setBusy(true);
setMessage('');
try {
const response = await fetch(`/api/auth/${mode}`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ email, password, device_name: deviceName }),
});
const body = await response.json().catch(() => ({}));
if (!response.ok) throw new Error(body.detail ?? 'Authentication failed.');
window.location.assign('/account');
} catch (error) {
setMessage(error instanceof Error ? error.message : 'Authentication failed.');
} finally {
setBusy(false);
}
}
return (
<form className="auth-form" onSubmit={submit}>
<label>Email<input required type="email" autoComplete="email" value={email} onChange={(e) => setEmail(e.target.value)} /></label>
<label>Password<input required minLength={12} type="password" autoComplete={mode === 'login' ? 'current-password' : 'new-password'} value={password} onChange={(e) => setPassword(e.target.value)} /></label>
<label>Device name<input maxLength={255} value={deviceName} onChange={(e) => setDeviceName(e.target.value)} /></label>
{message && <p className="form-error" role="alert">{message}</p>}
<button className="button" disabled={busy} type="submit">{busy ? 'Working...' : mode === 'login' ? 'Sign in' : 'Create account'}</button>
</form>
);
}