39 lines
2.5 KiB
TypeScript
39 lines
2.5 KiB
TypeScript
'use client';
|
|
|
|
import { FormEvent, useState } from 'react';
|
|
|
|
export function RecoveryForm() {
|
|
const [email, setEmail] = useState('');
|
|
const [token, setToken] = useState('');
|
|
const [password, setPassword] = useState('');
|
|
const [message, setMessage] = useState('');
|
|
const [busy, setBusy] = useState(false);
|
|
|
|
async function submitRequest(event: FormEvent) {
|
|
event.preventDefault();
|
|
setBusy(true); setMessage('');
|
|
try {
|
|
const response = await fetch('/api/auth/password-reset-request', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ email }) });
|
|
const body = await response.json().catch(() => ({}));
|
|
if (!response.ok) throw new Error(body.detail ?? 'Unable to request reset.');
|
|
setMessage('If the account exists, reset instructions have been sent.');
|
|
} catch (error) { setMessage(error instanceof Error ? error.message : 'Unable to request reset.'); }
|
|
finally { setBusy(false); }
|
|
}
|
|
|
|
async function submitReset(event: FormEvent) {
|
|
event.preventDefault();
|
|
setBusy(true); setMessage('');
|
|
try {
|
|
const response = await fetch('/api/auth/password-reset', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ token, password }) });
|
|
const body = await response.json().catch(() => ({}));
|
|
if (!response.ok) throw new Error(body.detail ?? 'Unable to reset password.');
|
|
setMessage('Password reset complete. You can sign in now.');
|
|
setToken(''); setPassword('');
|
|
} catch (error) { setMessage(error instanceof Error ? error.message : 'Unable to reset password.'); }
|
|
finally { setBusy(false); }
|
|
}
|
|
|
|
return <div className="recovery-stack"><form className="auth-form" onSubmit={submitRequest}><label>Email<input required type="email" autoComplete="email" value={email} onChange={(event) => setEmail(event.target.value)} /></label><button className="button" disabled={busy} type="submit">{busy ? 'Working...' : 'Email reset link'}</button></form><div className="form-divider">Already have a reset link?</div><form className="auth-form" onSubmit={submitReset}><label>Reset token<input required value={token} onChange={(event) => setToken(event.target.value)} /></label><label>New password<input required minLength={12} type="password" autoComplete="new-password" value={password} onChange={(event) => setPassword(event.target.value)} /></label><button className="button button-secondary" disabled={busy} type="submit">Set new password</button></form>{message && <p className="form-message" role="status">{message}</p>}</div>;
|
|
}
|