import { useState } from 'react' import { useNavigate } from 'react-router-dom' import { useAuth } from '../../contexts/AuthContext.jsx' import { useSite } from '../../contexts/SiteContext.jsx' import { api } from '../../api/client.js' import { showNotice } from '../../lib/notice.js' import { WHAT_GOES, WHAT_STAYS, STAFF_NAME_NOTE, isStaffRole, usernameMatches, isSharedDemoLogin, refusalMessage, } from '../../lib/accountDeletion.js' // "Delete my account" (docs/website/ACCOUNT_DELETION.md §4.2). Last on the // Account page and set apart from the sections above it. // // The account goes at once — there is no grace period (AD4) — so the safeguard // is the confirm step: the typed username, the password, and a two-factor code // when two-factor is on. Delete stays off until the username matches. // // On success the server has already dropped every session. This screen sends // the browser home, re-reads the session (which is now gone) and says so. const DANGER = '#d98b84' export default function DeleteAccountPanel({ account }) { const { refresh } = useAuth() const { settings } = useSite() const navigate = useNavigate() const [open, setOpen] = useState(false) const [typed, setTyped] = useState('') const [password, setPassword] = useState('') const [code, setCode] = useState('') const [useRecovery, setUseRecovery] = useState(false) const [busy, setBusy] = useState(false) const [error, setError] = useState('') const demoLocked = isSharedDemoLogin(settings, account.username) const noPassword = account.has_password === false const needsCode = Boolean(account.totp_enabled) const ready = usernameMatches(typed, account.username) && password.length > 0 && (!needsCode || code.trim().length > 0) function close() { setOpen(false) setTyped('') setPassword('') setCode('') setUseRecovery(false) setError('') } async function confirm(e) { e.preventDefault() if (!ready || busy) return setBusy(true) setError('') try { await api.deleteMyAccount({ username: typed.trim(), password, ...(needsCode ? (useRecovery ? { recoveryCode: code.trim() } : { code: code.trim() }) : {}), }) navigate('/', { replace: true }) showNotice('Your account has been deleted.') await refresh() } catch (err) { setError(refusalMessage(err)) setBusy(false) } } return (

Delete my account

Your account is deleted straight away and cannot be restored. These go with it:

What stays:

{isStaffRole(account.role) &&

{STAFF_NAME_NOTE}

}
{noPassword && (

This account has no password yet. Set one in the Password section above first; the password is how you confirm a deletion.

)} {!open && (
{demoLocked && (

This is turned off on the demo site.

)}
)} {open && (
{needsCode && ( )}
{error &&

{error}

}
)}
) }