"use client"; import { useState } from "react"; import { createAdminAccount, deleteAdminAccount, updateAdminAccount, } from "@/app/actions/account-actions"; import { emptyPagePermissions, PAGE_KEYS, type PageKey, type PagePermissions, type SessionAccount, } from "@/lib/auth/permissions"; const PAGE_LABELS: Record = { players: "Players", matches: "Matches", analysis: "Analysis", matchmaker: "Matchmaker", ledger: "Ledger", logs: "System logs", "founders-card": "Founders card", }; type Props = { accounts: SessionAccount[]; accountError: string | null; accountOk: string | null; }; function errorMessage(code: string | null): string | null { if (!code) return null; switch (code) { case "missingUsername": return "Username is required."; case "missingPassword": return "Password is required."; case "duplicate": return "That username is already taken."; case "notFound": return "Account not found."; case "cannotDeleteAdmin": return "The admin account cannot be deleted."; default: return "Could not update accounts. Try again."; } } function okMessage(code: string | null): string | null { if (!code) return null; switch (code) { case "created": return "Account created."; case "updated": return "Account updated."; case "deleted": return "Account deleted."; default: return "Done."; } } function PermissionCheckboxes({ idPrefix, permissions, onChange, }: { idPrefix: string; permissions: PagePermissions; onChange: (next: PagePermissions) => void; }) { function setPerm(page: PageKey, field: "read" | "write", value: boolean) { const next = { ...permissions, [page]: { ...permissions[page] } }; if (page === "logs") { next[page] = { read: field === "read" ? value : next[page].read, write: false }; onChange(next); return; } if (field === "write") { next[page] = { write: value, read: value ? true : next[page].read }; } else { next[page] = { read: value, write: value ? next[page].write : false, }; } onChange(next); } return (
{PAGE_KEYS.map((page) => ( ))}
Page Read Write
Overview Always enabled
{PAGE_LABELS[page]} setPerm(page, "read", e.target.checked)} className="size-4 rounded border-zinc-300 text-zinc-900 focus:ring-zinc-400 dark:border-zinc-600" /> {page === "logs" ? ( ) : ( setPerm(page, "write", e.target.checked)} className="size-4 rounded border-zinc-300 text-zinc-900 focus:ring-zinc-400 dark:border-zinc-600" /> )}
); } function permissionSummary(account: SessionAccount): string { if (account.isAdmin) return "Full access"; const parts: string[] = ["Overview"]; for (const page of PAGE_KEYS) { const p = account.permissions[page]; if (p.write) parts.push(`${PAGE_LABELS[page]} (rw)`); else if (p.read) parts.push(`${PAGE_LABELS[page]} (r)`); } return parts.join(", "); } function AccountEditForm({ account, onClose, }: { account: SessionAccount; onClose: () => void; }) { const [username, setUsername] = useState(account.username); const [password, setPassword] = useState(""); const [permissions, setPermissions] = useState(account.permissions); return (
{account.isAdmin ? (

Admin account — username is fixed; only the password can be changed.

) : (
setUsername(e.target.value)} required className="mt-1 w-full rounded-lg border border-zinc-300 bg-white px-3 py-2 text-sm text-zinc-900 shadow-sm outline-none ring-zinc-400 focus:ring-2 dark:border-zinc-600 dark:bg-zinc-900 dark:text-zinc-50" />
)}
setPassword(e.target.value)} required={account.isAdmin} className="mt-1 w-full rounded-lg border border-zinc-300 bg-white px-3 py-2 text-sm text-zinc-900 shadow-sm outline-none ring-zinc-400 focus:ring-2 dark:border-zinc-600 dark:bg-zinc-900 dark:text-zinc-50" />
{!account.isAdmin ? ( ) : null}
); } function AddAccountForm() { const [permissions, setPermissions] = useState(() => emptyPagePermissions(), ); return (

Add account

); } export function AdminAccountsEditor({ accounts, accountError, accountOk, }: Props) { const [editingId, setEditingId] = useState(null); const err = errorMessage(accountError); const ok = okMessage(accountOk); return (

Accounts

Manage panel logins and per-page read/write access. Only the admin account can manage other accounts.

{err ? (
{err}
) : null} {ok ? (
{ok}
) : null}

Existing accounts

    {accounts.map((account) => (
  • {account.username} {account.isAdmin ? ( Admin ) : null}

    {permissionSummary(account)}

    {!account.isAdmin ? (
    ) : null}
    {editingId === account.id ? ( setEditingId(null)} /> ) : null}
  • ))}
); }