import { useState } from 'react' import { useAuth } from '../contexts/AuthContext.jsx' import { api } from '../api/client.js' // Compact in-game moderation controls (kick / ban / unban) scoped to a single // game account. Reused wherever a linked account or character is shown to staff: // the admin user-detail account list and the character sheet. Self-gates on role // (admin/moderator) so it is safe to render inside components that players also // see — a player never gets the controls, and the API enforces the same gate. // // `actor` is stamped server-side from the session; nothing here sends it. Kick is // reversible (they reconnect) so it acts immediately; Ban reveals an inline // confirm with an optional duration + reason before it fires. export default function ShardAccountActions({ account, style }) { const { user } = useAuth() const [busy, setBusy] = useState('') const [ok, setOk] = useState('') const [err, setErr] = useState('') const [banOpen, setBanOpen] = useState(false) const [durationSec, setDurationSec] = useState('') const [reason, setReason] = useState('') // Only staff who can actually use the write plane see the controls. if (!user || !['admin', 'moderator'].includes(user.role) || !account) return null async function run(label, fn, done) { setBusy(label); setOk(''); setErr('') try { const r = await fn() setOk(done(r)) } catch (e) { setErr(e.message || 'Action failed.') } finally { setBusy('') } } const kick = () => run('kick', () => api.admin.shardOps.kick({ account }), (r) => { const n = r && r.sessions != null ? r.sessions : null const plural = n === 1 ? '' : 's' const sessions = n != null ? ` (${n} session${plural})` : '' return `Kicked${sessions}.` }) const unban = () => run('unban', () => api.admin.shardOps.unban(account), () => 'Unbanned.') const ban = () => run('ban', () => api.admin.shardOps.ban({ account, durationSec: durationSec === '' ? undefined : Number(durationSec), reason: reason.trim() || undefined, }), () => { setBanOpen(false) const when = durationSec ? ` for ${durationSec}s` : ' indefinitely' return `Banned${when}.` }) const btn = { fontSize: '0.72rem', padding: '4px 10px' } return (
{ok && {ok}} {err && {err}}
{banOpen && (
)}
) }