import { useCallback, useEffect, useState } from 'react' import { Link } from 'react-router-dom' import { Loading, ErrorState } from './PageState.jsx' // Shared game-account linking + character roster, used by both the player portal // (/player) and the staff account page (/admin/account). `scope` is the api // object with { link, accounts, roster } (player or admin self-service); `charTo` // maps a serial to the route for that character's sheet. function LinkForm({ scope, onLinked, compact }) { const [code, setCode] = useState('') const [busy, setBusy] = useState(false) const [msg, setMsg] = useState('') const [error, setError] = useState('') async function submit(e) { e.preventDefault() setMsg(''); setError('') if (!code.trim()) return setBusy(true) try { const { account } = await scope.link(code.trim()) setMsg(`Linked ${account}.`) setCode('') await onLinked() } catch (err) { setError(err.message || 'Could not link that code.') } finally { setBusy(false) } } return (
) } function AccountRoster({ scope, account, charTo }) { const [roster, setRoster] = useState(null) const [error, setError] = useState('') const [unavailable, setUnavailable] = useState(false) const load = useCallback(async () => { setError(''); setUnavailable(false) try { setRoster(await scope.roster(account)) } catch (err) { if (err.status === 503) setUnavailable(true) else setError(err.message || 'Could not load this account.') } }, [scope, account]) useEffect(() => { load() }, [load]) if (unavailable) { return (The game server is restarting — try again shortly.
{error}
if (!roster) returnLoading…
const chars = roster.chars || [] if (chars.length === 0) returnNo characters on this account.
return (
You haven’t linked a game account yet. In game, type [link to get a
one-time code, then enter it below to see your characters, stats, skills and vendors here.