Add admin foundation + Users resource (Filament replacement, slice 1)
Plain App Router admin (aligned to habbo-next, no Refine): - rank surfaced on the NextAuth session; staff guard isStaff() [pure, unit-tested] + requireStaff() reading min_staff_rank, gating /admin. - /admin dashboard (counts), /admin/users (paginated + search), /admin/users/[id] detail. - src/actions/admin-users.ts: staff-gated server actions wiring the user editor to the existing services — giveCurrency (RCON or DB fallback), setMotto/setRank (DB + RCON), alertUser, disconnectUser. Verified: tsc exit 0, vitest 45/45, next build exit 0 (/admin routes).
This commit is contained in:
1 parent
d9a8ce532f
commit
9f81096f05
10 files changed
+334
-3
No files matched your search
@@ -0,0 +1,24 @@
|
||||
import Link from "next/link";
|
||||
import type { ReactNode } from "react";
|
||||
import { requireStaff } from "@/lib/admin/guard";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function AdminLayout({ children }: { children: ReactNode }) {
|
||||
const staff = await requireStaff();
|
||||
|
||||
return (
|
||||
<div style={{ display: "grid", gridTemplateColumns: "190px 1fr", gap: "1.5rem" }}>
|
||||
<aside className="card" style={{ height: "fit-content" }}>
|
||||
<p className="muted" style={{ marginTop: 0 }}>
|
||||
Staff · {staff.username} (rank {staff.rank})
|
||||
</p>
|
||||
<nav style={{ display: "grid", gap: "0.45rem" }}>
|
||||
<Link href="/admin">Dashboard</Link>
|
||||
<Link href="/admin/users">Users</Link>
|
||||
</nav>
|
||||
</aside>
|
||||
<section>{children}</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user