// ===================================================================== // Viewer context — drives the "View as..." access-control demo. // The App provides a viewer (one of VIEWERS) and every screen uses // useViewer() to filter what they show. // ===================================================================== const ViewerContext = React.createContext(null); function ViewerProvider({ viewer, children }) { return {children}; } function useViewer() { return React.useContext(ViewerContext) || VIEWERS[0]; // default to admin } // Filter a candidate list down to what the current viewer can see. function useVisibleCandidates(list = CANDIDATES) { const viewer = useViewer(); return React.useMemo(() => visibleCandidates(viewer, list), [viewer, list]); } // ===================================================================== // "Viewing as..." top banner — slim strip above the topnav, color-coded // to the viewer's role. Only shows when role !== 'admin' so the default // experience has no chrome cost. // ===================================================================== function RoleBanner() { const viewer = useViewer(); if (!viewer || viewer.role === "admin") return null; const role = ROLES[viewer.role]; if (!role) return null; const visibleCount = visibleCandidates(viewer).length; const authUser = window.__atsAuthUser; const isSimulated = authUser && authUser.role === "admin" && viewer.role !== "admin"; const exitSimulation = () => { if (typeof window.__atsSetViewer === "function" && authUser) { const nameParts = (authUser.full_name || "").split(" "); const initials = nameParts.map(p => p[0] || "").join("").slice(0, 2).toUpperCase(); window.__atsSetViewer({ id: authUser.id, name: authUser.full_name, initials, color: "#7595D5", role: "admin", title: authUser.email, avatar_url: authUser.avatar_url, }); } }; return (
{isSimulated ? "Viewing as" : ""} {role.label} · {viewer.name} Showing {visibleCount} candidates · {role.desc} {isSimulated && ( )}
); } // ===================================================================== // "Hidden by access" placeholder — replaces a row/card when a feature // would have been visible to admins but the current viewer is locked // out. (Used in the Permissions screen demos.) // ===================================================================== function AccessLock({ reason }) { return ( Hidden ); } Object.assign(window, { ViewerContext, ViewerProvider, useViewer, useVisibleCandidates, RoleBanner, AccessLock, });