import { useState, useEffect, useContext, useCallback } from 'react' import { AuthContext } from '../App.jsx' import { listAdminUsers, createAdminUser, setUserStatus, assignRole, removeRole, listRoles, createRole } from '../api.js' const ROLE_ADMIN = 4 export default function AdminView({ archives }) { const { currentUser } = useContext(AuthContext) ?? {} const isAdmin = currentUser && (currentUser.role_bits & ROLE_ADMIN) !== 0 const [tab, setTab] = useState('users') const [users, setUsers] = useState([]) const [roles, setRoles] = useState([]) const [loading, setLoading] = useState(false) const [error, setError] = useState(null) // Create user form state const [newUsername, setNewUsername] = useState('') const [newPassword, setNewPassword] = useState('') const [newEmail, setNewEmail] = useState('') const [createError, setCreateError] = useState(null) const [creating, setCreating] = useState(false) // Create role form state const [newRoleSlug, setNewRoleSlug] = useState('') const [newRoleName, setNewRoleName] = useState('') const [roleCreateError, setRoleCreateError] = useState(null) const [creatingRole, setCreatingRole] = useState(false) const refresh = useCallback(async () => { if (!isAdmin) return setLoading(true) setError(null) try { const [u, r] = await Promise.all([listAdminUsers(), listRoles()]) setUsers(u) setRoles(r) } catch (e) { setError(e.message) } finally { setLoading(false) } }, [isAdmin]) useEffect(() => { refresh() }, [refresh]) async function handleToggleStatus(user) { const next = user.status === 'active' ? 'disabled' : 'active' try { await setUserStatus(user.user_uid, next) setUsers(us => us.map(u => u.user_uid === user.user_uid ? { ...u, status: next } : u)) } catch (e) { setError(e.message) } } async function handleCreateUser(e) { e.preventDefault() if (!newUsername.trim() || !newPassword) { setCreateError('Username and password required'); return } setCreating(true) setCreateError(null) try { await createAdminUser(newUsername.trim(), newPassword, newEmail.trim() || undefined) setNewUsername('') setNewPassword('') setNewEmail('') await refresh() } catch (e) { setCreateError(e.message) } finally { setCreating(false) } } async function handleCreateRole(e) { e.preventDefault() if (!newRoleSlug.trim() || !newRoleName.trim()) { setRoleCreateError('Slug and name required'); return } setCreatingRole(true) setRoleCreateError(null) try { await createRole(newRoleSlug.trim(), newRoleName.trim()) setNewRoleSlug('') setNewRoleName('') await refresh() } catch (e) { setRoleCreateError(e.message) } finally { setCreatingRole(false) } } if (!isAdmin) { return (

Admin

You need admin privileges to access this panel.

Mounted Archives

{archives.map(a => (
{a.label}
{a.archive_path}
))}
) } return (

Admin

{error &&
{error}
} {tab === 'users' && (

Users

{loading ?

Loading…

: ( {users.map(u => ( ))}
UsernameEmailRolesStatusActions
{u.username} {u.email || '—'} {u.role_slugs.join(', ') || '—'} {u.status}
)}

Create User

setNewUsername(e.target.value)} required /> setNewPassword(e.target.value)} required /> setNewEmail(e.target.value)} /> {createError &&
{createError}
}
)} {tab === 'roles' && (

Roles

{loading ?

Loading…

: ( {roles.map(r => ( ))}
SlugNameLevelBitBuilt-in
{r.slug} {r.name} {r.level} {r.bit_position} {r.is_builtin ? '✓' : ''}
)}

Create Custom Role

setNewRoleSlug(e.target.value)} required /> setNewRoleName(e.target.value)} required /> {roleCreateError &&
{roleCreateError}
}
)} {tab === 'archives' && (

Mounted Archives

{archives.map(a => (
{a.label}
{a.archive_path}
))}
)}
) }