"use client"; /** * The signed-in staff member's role and permissions, for the whole panel. * * Used to HIDE what someone can't do — nav entries, buttons, whole pages. * Hiding is a courtesy, not the boundary: every /admin/* route on the BFF * checks its own permission, so a hidden button that somehow fired would * still be refused. */ import { createContext, useContext } from "react"; import type { StaffMe } from "@/lib/api"; const StaffContext = createContext(null); export const StaffProvider = StaffContext.Provider; export function useStaff() { const me = useContext(StaffContext); const perms = new Set(me?.permissions ?? []); return { me, can: (perm: string) => perms.has(perm), }; } /** * Renders children only for staff holding `perm`; otherwise a short notice. * Wraps whole pages, so landing on one by URL explains itself rather than * showing a screen of 403 errors. */ export function RequirePermission({ perm, children, }: { perm: string; children: React.ReactNode; }) { const { can } = useStaff(); if (!can(perm)) { return (
Your role doesn't include access to this section. A superadmin can change that from the Staff page.
); } return <>{children}; } /** Renders children only when the signed-in role holds `perm`. */ export function Can({ perm, children }: { perm: string; children: React.ReactNode }) { const { can } = useStaff(); return can(perm) ? <>{children} : null; }