55 lines
2.8 KiB
TypeScript
55 lines
2.8 KiB
TypeScript
import { useState } from 'react';
|
|
import type { FormEvent } from 'react';
|
|
import { useNavigate } from 'react-router';
|
|
import { useAuth } from '../auth/AuthContext';
|
|
import { Alert, errorMessage } from '../components/Feedback';
|
|
import { Icon } from '../components/Icon';
|
|
|
|
export function ChangePasswordPage() {
|
|
const { user, changePassword, logout } = useAuth();
|
|
const navigate = useNavigate();
|
|
const [currentPassword, setCurrentPassword] = useState('');
|
|
const [newPassword, setNewPassword] = useState('');
|
|
const [confirmation, setConfirmation] = useState('');
|
|
const [error, setError] = useState('');
|
|
const [submitting, setSubmitting] = useState(false);
|
|
|
|
const submit = async (event: FormEvent) => {
|
|
event.preventDefault();
|
|
setError('');
|
|
if (newPassword !== confirmation) return setError('Las contraseñas nuevas no coinciden');
|
|
if (newPassword.length < 12) return setError('La nueva contraseña debe tener al menos 12 caracteres');
|
|
setSubmitting(true);
|
|
try {
|
|
await changePassword(currentPassword, newPassword);
|
|
navigate('/', { replace: true });
|
|
} catch (requestError) {
|
|
setError(errorMessage(requestError));
|
|
} finally {
|
|
setSubmitting(false);
|
|
}
|
|
};
|
|
|
|
const leave = async () => {
|
|
await logout().catch(() => undefined);
|
|
navigate('/login', { replace: true });
|
|
};
|
|
|
|
return (
|
|
<main className="centered-page">
|
|
<form className="login-card password-card" onSubmit={submit}>
|
|
<div className="round-icon"><Icon name="key" size={24} /></div>
|
|
<span className="eyebrow">SEGURIDAD DE CUENTA</span>
|
|
<h2>{user?.mustChangePassword ? 'Cambiá tu contraseña temporal' : 'Cambiar contraseña'}</h2>
|
|
<p className="muted">Usá al menos 12 caracteres. Las demás sesiones abiertas se cerrarán automáticamente.</p>
|
|
{error && <Alert>{error}</Alert>}
|
|
<label className="field"><span>Contraseña actual</span><input type="password" autoComplete="current-password" value={currentPassword} onChange={(event) => setCurrentPassword(event.target.value)} required /></label>
|
|
<label className="field"><span>Nueva contraseña</span><input type="password" autoComplete="new-password" minLength={12} value={newPassword} onChange={(event) => setNewPassword(event.target.value)} required /></label>
|
|
<label className="field"><span>Repetir nueva contraseña</span><input type="password" autoComplete="new-password" minLength={12} value={confirmation} onChange={(event) => setConfirmation(event.target.value)} required /></label>
|
|
<button className="button primary wide" disabled={submitting}>{submitting ? 'Guardando…' : 'Guardar nueva contraseña'}</button>
|
|
<button className="button text wide" type="button" onClick={leave}>Cerrar sesión</button>
|
|
</form>
|
|
</main>
|
|
);
|
|
}
|