nxtgauge-frontend-solid/src/routes/reset-password.tsx

106 lines
3.4 KiB
TypeScript

import { createSignal, Show } from 'solid-js';
import { useNavigate, useSearchParams } from '@solidjs/router';
const API = import.meta.env.VITE_API_URL ?? 'http://localhost:8000';
export default function ResetPassword() {
const [params] = useSearchParams();
const navigate = useNavigate();
const [password, setPassword] = createSignal('');
const [confirm, setConfirm] = createSignal('');
const [error, setError] = createSignal('');
const [loading, setLoading] = createSignal(false);
const [success, setSuccess] = createSignal(false);
async function handleReset(e: Event) {
e.preventDefault();
if (password() !== confirm()) {
setError('Passwords do not match');
return;
}
setLoading(true);
setError('');
try {
const res = await fetch(`${API}/api/auth/reset-password`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
token: params.token,
new_password: password()
}),
});
if (res.ok) {
setSuccess(true);
setTimeout(() => navigate('/login'), 2000);
} else {
const data = await res.json();
setError(data.error ?? 'Invalid or expired reset link');
}
} catch (e) {
setError('Network error. Please try again.');
} finally {
setLoading(false);
}
}
return (
<div style={{
height: '100vh', display: 'flex', 'align-items': 'center', 'justify-content': 'center',
background: 'linear-gradient(135deg, #f0fdf4 0%, #fff 100%)'
}}>
<div class="form-card" style={{ 'max-width': '400px', width: '100%', padding: '40px' }}>
<div style={{ 'text-align': 'center', 'margin-bottom': '24px' }}>
<h1 style={{ 'font-size': '24px', 'font-weight': '800', margin: 0 }}>Reset Password</h1>
<p style={{ color: '#64748b', 'font-size': '14px', 'margin-top': '8px' }}>
Choose a new secure password.
</p>
</div>
<Show when={success()}>
<div class="status-banner status-banner--success" style={{ 'margin-bottom': '20px' }}>
Password reset! Redirecting to login...
</div>
</Show>
<Show when={error()}>
<div class="error-banner" style={{ 'margin-bottom': '20px' }}>{error()}</div>
</Show>
<form onSubmit={handleReset} style={{ display: 'flex', 'flex-direction': 'column', gap: '20px' }}>
<div class="field">
<label class="label">New Password</label>
<input
class="input"
type="password"
placeholder="••••••••"
minLength={8}
value={password()}
onInput={(e) => setPassword(e.currentTarget.value)}
required
/>
</div>
<div class="field">
<label class="label">Confirm New Password</label>
<input
class="input"
type="password"
placeholder="••••••••"
minLength={8}
value={confirm()}
onInput={(e) => setConfirm(e.currentTarget.value)}
required
/>
</div>
<button class="btn btn-primary" type="submit" disabled={loading() || success()} style={{ width: '100%' }}>
{loading() ? 'Updating...' : 'Reset Password'}
</button>
</form>
</div>
</div>
);
}