// Account Settings modal — self-service for the currently-signed-in user. // Change display name + password. Username and role are admin-only. function AccountSettingsModal({ onClose }) { const me = window.ZAMPP_DATA?.ME || {}; const [tab, setTab] = React.useState('profile'); const [displayName, setDisplayName] = React.useState(me.display_name || me.name || ''); const [savingName, setSavingName] = React.useState(false); const [nameMsg, setNameMsg] = React.useState(null); const [curPw, setCurPw] = React.useState(''); const [newPw, setNewPw] = React.useState(''); const [newPw2, setNewPw2] = React.useState(''); const [savingPw, setSavingPw] = React.useState(false); const [pwMsg, setPwMsg] = React.useState(null); const [showNew, setShowNew] = React.useState(false); const saveName = async (e) => { e.preventDefault(); setNameMsg(null); if (!displayName.trim()) { setNameMsg({ ok: false, text: 'Display name cannot be empty' }); return; } setSavingName(true); try { const r = await window.ZAMPP_API.fetch('/auth/me', { method: 'PATCH', body: JSON.stringify({ display_name: displayName.trim() }), }); // refresh ME cache if (window.ZAMPP_DATA) { window.ZAMPP_DATA.ME = { ...(window.ZAMPP_DATA.ME || {}), display_name: r.display_name, name: r.display_name }; } setNameMsg({ ok: true, text: 'Display name updated' }); } catch (err) { setNameMsg({ ok: false, text: err.message || 'Update failed' }); } finally { setSavingName(false); } }; const savePw = async (e) => { e.preventDefault(); setPwMsg(null); if (newPw !== newPw2) { setPwMsg({ ok: false, text: 'New passwords do not match' }); return; } if (newPw.length < 8) { setPwMsg({ ok: false, text: 'Password must be at least 8 characters' }); return; } setSavingPw(true); try { await window.ZAMPP_API.fetch('/auth/password', { method: 'POST', body: JSON.stringify({ current_password: curPw, new_password: newPw }), }); setPwMsg({ ok: true, text: 'Password updated — all other sessions signed out' }); setCurPw(''); setNewPw(''); setNewPw2(''); } catch (err) { setPwMsg({ ok: false, text: err.message || 'Update failed' }); } finally { setSavingPw(false); } }; return (
e.stopPropagation()}>
Account settings
{me.username || '—'} · {me.role || '—'}{me.is_client ? ' · client' : ''}
{[ { id: 'profile', label: 'Profile' }, { id: 'password', label: 'Password' }, ].map(t => ( ))}
{tab === 'profile' && (
setDisplayName(e.target.value)} maxLength={120} />
{nameMsg && (
{nameMsg.text}
)}
)} {tab === 'password' && (
setCurPw(e.target.value)} autoComplete="current-password" required />
setNewPw(e.target.value)} autoComplete="new-password" required minLength={8} style={{ paddingRight: 36 }} />
8+ chars, mixed case, digit, symbol
setNewPw2(e.target.value)} autoComplete="new-password" required minLength={8} />
{pwMsg && (
{pwMsg.text}
)}
)}
); } window.AccountSettingsModal = AccountSettingsModal;