import { useState } from 'react'; import { Button } from '#/components/atoms/button.jsx'; import { Notice } from '#/components/atoms/notice.jsx'; import { Panel } from '#/components/atoms/panel.jsx'; import { ErrorNotice } from '#/components/molecules/error-notice.jsx'; import { Section } from '#/components/molecules/section.jsx'; import { TextField } from '#/components/molecules/text-field.jsx'; import { post } from '#/lib/api.js'; /** * Change the account password. The current password is required even inside * a signed-in session, so a stolen cookie alone cannot rotate the * credential. Open sessions and app passwords stay valid. */ export function PasswordCard() { const [current, setCurrent] = useState(''); const [next, setNext] = useState(''); const [confirm, setConfirm] = useState(''); const [busy, setBusy] = useState(false); const [error, setError] = useState(''); const [done, setDone] = useState(false); const submit = async (/** @type {import('react').FormEvent} */ event) => { event.preventDefault(); setError(''); setDone(false); if (next !== confirm) { setError('The new passwords do not match.'); return; } setBusy(true); try { await post('/password', { currentPassword: current, newPassword: next }); setDone(true); setCurrent(''); setNext(''); setConfirm(''); } catch (caught) { setError(String(caught?.message || caught)); } finally { setBusy(false); } }; return (
{done && ( Password changed. Open sessions stay signed in. )} setCurrent(e.target.value)} required /> setNext(e.target.value)} minLength={8} hint="At least 8 characters." required /> setConfirm(e.target.value)} required />
); }