54 lines
1.7 KiB
TypeScript
54 lines
1.7 KiB
TypeScript
"use client";
|
|
|
|
/**
|
|
* /staff — who can use the admin panel, and with what powers. Superadmins only.
|
|
*
|
|
* Two tabs: the people (grant, change role, block, revoke) and the roles
|
|
* (the three system roles, plus custom ones built from the permission
|
|
* catalog). Every rule that matters — you can't act on yourself, the last
|
|
* active superadmin can't be removed, custom roles can't hold staff
|
|
* management — is enforced by the BFF; this page just explains the refusal.
|
|
*/
|
|
|
|
import { useState } from "react";
|
|
import { cn } from "@/lib/utils";
|
|
import { StaffTab } from "./staff-tab";
|
|
import { RolesTab } from "./roles-tab";
|
|
|
|
export default function StaffPage() {
|
|
const [tab, setTab] = useState<"staff" | "roles">("staff");
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<header>
|
|
<h1 className="text-xl font-semibold text-foreground">
|
|
Staff & roles
|
|
</h1>
|
|
<p className="mt-1 text-sm text-muted-foreground">
|
|
Decide who can use this panel and what each role may do.
|
|
</p>
|
|
</header>
|
|
|
|
<div className="flex gap-1 border-b border-border">
|
|
{(["staff", "roles"] as const).map((t) => (
|
|
<button
|
|
key={t}
|
|
type="button"
|
|
onClick={() => setTab(t)}
|
|
className={cn(
|
|
"-mb-px border-b-2 px-3 py-2 text-sm capitalize transition-colors",
|
|
tab === t
|
|
? "border-primary font-medium text-foreground"
|
|
: "border-transparent text-muted-foreground hover:text-foreground",
|
|
)}
|
|
>
|
|
{t}
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
{tab === "staff" ? <StaffTab /> : <RolesTab />}
|
|
</div>
|
|
);
|
|
}
|