1(function(){try{var e=typeof window<`u`?window:typeof global<`u`?global:typeof globalThis<`u`?globalThis:typeof self<`u`?self:{},t=new e.Error().stack;t&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[t]=`fda4fda1-9b70-425e-b0d3-36420bdf565f`,e._sentryDebugIdIdentifier=`sentry-dbid-fda4fda1-9b70-425e-b0d3-36420bdf565f`)}catch{}})();import{a as e}from"./rolldown-runtime-eil0g4P7.js";import{Af as t,Ct as n,Es as r,Gl as i,Hn as a,Ii as o,Jn as s,L as c,Ld as l,N as u,On as d,Or as f,Pp as p,Sp as m,Ss as h,Tu as g,Ud as _,Ul as v,Vd as y,Xo as b,Y as ee,Yp as te,Z as x,fc as S,go as ne,gr as re,ia as ie,jt as ae,l as oe,mi as C,ml as se,or as w,vc as ce,zd as le}from"./icons-DpkGVEtF.js";import{At as T,Et as E,I as ue,Nt as D,Pt as de,Y as fe,a as O,at as k,it as A,mt as pe,n as j,nt as M,o as N,p as P,q as me,s as F,ut as he}from"./login-shell-shared-B1ZmoKZI.js";import{t as ge}from"./checkbox-B5UdlHdH.js";import{t as I}from"./scroll-area-CS2twjO7.js";import{t as _e}from"./switch-Du5Oz5KG.js";import{a as ve,o as ye,r as be}from"./tabs-B5qdTWIh.js";import{t as L}from"./button-BoQCzBK8.js";import{t as R}from"./badge-BpDlzPjV.js";import{n as xe,r as Se,t as Ce}from"./collapsible-J1L0PHNq.js";import{n as z}from"./use-toast-CN4ANMjg.js";import{h as we,o as Te,s as Ee,y as B}from"./schemas-CLG243Dt.js";import{t as De}from"./coerce-By0wHkon.js";import{Ai as Oe,Bn as ke,Ci as Ae,Cn as je,Di as V,Dn as Me,Ei as H,En as Ne,Hn as Pe,In as Fe,Kn as Ie,Ln as Le,Mn as Re,Ni as ze,Rn as Be,Si as U,Sn as Ve,Ti as W,Tn as He,Un as Ue,ai as We,bn as Ge,ci as G,di as Ke,ft as K,gi as qe,hi as Je,ht as Ye,ki as Xe,li as Ze,mi as Qe,mt as $e,ni as et,oi as tt,pi as nt,qn as rt,ui as it,wi as q,wn as at,xi as ot,xn as st,yi as ct,yn as lt,zr as ut}from"./full-app-shell-X40U7syq.js";import{a as dt,d as ft,g as pt,h as mt,i as ht,l as gt,m as _t,o as vt,p as yt,s as bt,t as xt}from"./sortable.esm-BYoXKwe9.js";import{t as St}from"./full-height-page-css-IFuI.js";var J=e(te(),1),Y=`/admin/rbac`,Ct=[`roles`,`users`,`catalog`],wt=[`permissions`,`scope`,`navigation`,`members`],Tt=[`pages`,`permissions`],Et=`roles`,Dt=`permissions`,Ot=`pages`;function kt(e){let t=(e.split(`?`)[0]||``).replace(/\/+$/,``);return t===`/admin/rbac`?[]:t.startsWith(`/admin/rbac/`)?t.slice(12).split(`/`).filter(Boolean):[]}function At(e,t,n){return t.includes(e)?e:n}function jt(e){if(e===void 0)return null;let t=Number(e);return Number.isInteger(t)?t:null}function X(){let[e,t]=pe(),n=(0,J.useMemo)(()=>kt(e),[e]),r=n.length===0,i=At(n[0],Ct,Et),a=jt(i===`roles`?n[1]:void 0);return{mode:i,roleId:a,userId:jt(i===`users`?n[1]:void 0),section:At(i===`roles`?n[2]:void 0,wt,Dt),entity:At(i===`catalog`?n[1]:void 0,Tt,Ot),needsRedirect:r,setMode:(0,J.useCallback)(e=>t(`${Y}/${e}`),[t]),selectRole:(0,J.useCallback)((e,n=Dt)=>{if(e===null){t(`${Y}/roles`);return}t(`${Y}/roles/${e}/${n}`)},[t]),selectUser:(0,J.useCallback)(e=>t(e===null?`${Y}/users`:`${Y}/users/${e}`),[t]),setSection:(0,J.useCallback)(e=>{a!==null&&t(`${Y}/roles/${a}/${e}`)},[t,a]),setEntity:(0,J.useCallback)(e=>t(`${Y}/catalog/${e}`),[t])}}var Z=de(),Mt={roles:{label:`Roles`,description:`Configure a role`,Icon:u},users:{label:`Users`,description:`Configure a user`,Icon:x},catalog:{label:`Catalog`,description:`Building blocks`,Icon:t}};function Nt({mode:e,onModeChange:t}){return(0,Z.jsx)(Fe,{type:`single`,value:e,onValueChange:e=>{e&&t(e)},variant:`outline`,className:`rounded-lg bg-muted/50 p-1`,"aria-label":`RBAC workspace mode`,children:Ct.map(e=>{let{label:t,Icon:n}=Mt[e];return(0,Z.jsxs)(Le,{value:e,"aria-label":t,className:`h-11 gap-2 border-0 px-4 font-sans data-[state=on]:bg-background data-[state=on]:text-primary data-[state=on]:shadow-xs`,"data-testid":`rbac-mode-${e}`,children:[(0,Z.jsx)(n,{className:`size-4`,"aria-hidden":`true`}),(0,Z.jsx)(`span`,{children:t})]},e)})})}function Pt(e={}){return T({queryKey:e.includeArchived?[`/api/rbac/roles`,{includeArchived:!0}]:[`/api/rbac/roles`],staleTime:6e4})}function Ft(){return T({queryKey:[`/api/rbac/pages`,{view:`workspace`}],staleTime:6e4})}function Q(){return T({queryKey:[`/api/rbac/permissions/with-roles`],staleTime:6e4})}function It(){return T({queryKey:[`/api/rbac/role-account-scopes`],staleTime:6e4})}function Lt(){return T({queryKey:[`/api/rbac/user-role-matrix`],staleTime:6e4})}function Rt(){return T({queryKey:[`/api/accounts`,{view:`options`}],staleTime:6e4})}function zt(e){return T({queryKey:[`/api/rbac/roles/${e??0}/permissions`,{view:`builder`}],enabled:e!==null,staleTime:3e4})}function Bt(){return T({queryKey:[`/api/rbac/navigation-layouts`],staleTime:3e4})}function Vt(e={}){let t=Pt(e);return{roles:t.data??[],isLoading:t.isLoading,isError:t.isError}}function Ht({roles:e,isLoading:t,selectedRoleId:n,showArchived:r,onShowArchivedChange:i,onSelectRole:a,onNewRole:o}){let[s,c]=(0,J.useState)(``),u=Q(),d=(0,J.useMemo)(()=>{let e=new Map;for(let t of u.data??[])for(let n of t.roleIds)e.set(n,(e.get(n)??
10)+1);return e},[u.data]),f=(0,J.useMemo)(()=>{let t=s.trim().toLowerCase(),n=[...r?e:e.filter(e=>e.archived_at==null)].sort((e,t)=>e.name.localeCompare(t.name));return t?n.filter(e=>e.name.toLowerCase().includes(t)||(e.description??``).toLowerCase().includes(t)):n},[e,s,r]);return(0,Z.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col gap-3`,children:[(0,Z.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,Z.jsxs)(`div`,{className:`relative flex-1`,children:[(0,Z.jsx)(w,{className:`pointer-events-none absolute left-2.5 top-1/2 size-4 -translate-y-1/2 text-muted-foreground`}),(0,Z.jsx)(j,{value:s,onChange:e=>c(e.target.value),placeholder:`Search roles`,className:`h-10 pl-8`,"aria-label":`Search roles`,"data-testid":`rbac-role-search`})]})}),(0,Z.jsxs)(`div`,{className:`flex items-center gap-2 px-1 text-sm text-muted-foreground`,children:[(0,Z.jsx)(ge,{id:`rbac-show-archived`,checked:r,onCheckedChange:e=>i(e===!0),"aria-label":`Show archived roles`,"data-testid":`rbac-show-archived`}),(0,Z.jsx)(`label`,{htmlFor:`rbac-show-archived`,children:`Show archived`})]}),(0,Z.jsx)(I,{className:`min-h-0 flex-1`,children:(0,Z.jsx)(`ul`,{className:`divide-y divide-border`,children:t?Array.from({length:6}).map((e,t)=>(0,Z.jsx)(`li`,{className:`px-1 py-3`,children:(0,Z.jsx)(A,{className:`h-5 w-full`})},t)):f.length===0?(0,Z.jsxs)(`li`,{className:`px-2 py-6 text-center text-sm text-muted-foreground`,children:[`No roles match â`,s,`â.`]}):f.map(e=>{let t=e.id===n,r=d.get(e.id)??0;return(0,Z.jsx)(`li`,{children:(0,Z.jsxs)(`button`,{type:`button`,onClick:()=>a(e.id),"aria-current":t?`true`:void 0,"data-testid":`rbac-role-item-${e.id}`,className:k(`flex min-h-11 w-full items-center gap-2 rounded-md p-2 text-left transition-colors`,t?`bg-brand-selected text-primary`:`hover:bg-muted/60`),children:[(0,Z.jsx)(`span`,{className:`min-w-0 flex-1`,children:(0,Z.jsxs)(`span`,{className:`flex items-center gap-1.5`,children:[(0,Z.jsx)(`span`,{className:`truncate font-sans text-sm font-medium`,children:e.name}),e.is_system?(0,Z.jsx)(R,{variant:`outline`,className:`h-4 px-1 text-xs font-normal`,children:`system`}):null,e.archived_at?(0,Z.jsx)(R,{variant:`secondary`,className:`h-4 px-1 text-xs font-normal`,children:`archived`}):null]})}),(0,Z.jsx)(`span`,{className:`font-mono text-xs tabular-nums text-muted-foreground`,children:r}),(0,Z.jsx)(l,{className:`size-4 shrink-0 text-muted-foreground`,"aria-hidden":`true`})]})},e.id)})})}),(0,Z.jsxs)(L,{variant:`outline`,className:`w-full gap-2`,onClick:o,"data-testid":`rbac-new-role`,children:[(0,Z.jsx)(C,{className:`size-4`,"aria-hidden":`true`}),`New role`]})]})}function Ut(e){return e.access_status==null||e.access_status===`active`}function Wt(e,t,n){return t.role===n||(e.additionalRoles[t.id]?.includes(n)??!1)}function Gt(e,t){let n=[];for(let r of e.users)r.role===t?n.push({user:r,membership:`primary`}):e.additionalRoles[r.id]?.includes(t)&&n.push({user:r,membership:`additional`});return n.sort((e,t)=>$(e.user).localeCompare($(t.user)))}function Kt(e,t){return e.users.reduce((n,r)=>Ut(r)&&Wt(e,r,t)?n+1:n,0)}function qt(e,t){return e.users.filter(n=>n.role!==t&&!(e.additionalRoles[n.id]?.includes(t)??!1)).sort((e,t)=>$(e).localeCompare($(t)))}function $(e){if(e.linked_contact){let t=[e.linked_contact.first,e.linked_contact.last].filter(Boolean).join(` `).trim();if(t)return t}return[e.first_name,e.last_name].filter(Boolean).join(` `).trim()||(e.email?e.email.split(`@`)[0]:e.yield_center_phone?e.yield_center_phone:`Unknown user`)}function Jt(e,t,n,r,i){let a=n.reduce((t,n)=>n.roleIds.includes(e)?t+1:t,0),o=r.find(t=>t.role_id===e)?.scope_strategy??null,s=0;return t&&i&&(s=Kt(i,t)),{permissionCount:a,scopeStrategy:o,memberCount:s}}function Yt(e,t){let n=Q(),r=It(),i=Lt(),a=zt(e),o=(0,J.useMemo)(()=>e===null?{permissionCount:0,scopeStrategy:null,memberCount:0}:Jt(e,t,n.data??[],r.data??[],i.data),[e,t,n.data,r.data,i.data]),s=(0,J.useMemo)(()=>e===null||!a.data?null:a.data.reduce((e,t)=>t.show_in_nav?e+1:e,0),[e,a.data]);return{...o,navPageCount:s,isLoading:n.isLoading||r.isLoading||i.isLoading||a.isLoading}}
1var Xt=[{value:`self`,label:`Self`,blurb:`Only the user's own account`,explanation:`Shows account records directly tied to the signed-in user.`,Icon:c},{value:`self_and_linked`,label:`Self + Linked`,blurb:`Own account plus linked accounts`,explanation:`Shows the user's account and accounts connected through their linked contact.`,Icon:b},{value:`region`,label:`Region`,blurb:`Accounts in assigned regions`,explanation:`Shows accounts mapped to the user's assigned region or territory.`,Icon:ne},{value:`all`,label:`All`,blurb:`Every account, across regions`,explanation:`Shows all accounts in the system with no account-scope filter.`,Icon:ce}];function Zt(e){return e?Xt.find(t=>t.value===e)??null:null}function Qt({summary:e}){let t=Zt(e.scopeStrategy),n=[{key:`perms`,Icon:a,label:`Permissions`,value:`${e.permissionCount}`},{key:`scope`,Icon:v,label:`Scope`,value:t?.label??`Not set`},{key:`nav`,Icon:ie,label:`Nav pages`,value:e.navPageCount===null?`â`:`${e.navPageCount}`},{key:`members`,Icon:u,label:`Active members`,value:`${e.memberCount}`}];return(0,Z.jsx)(`dl`,{className:`grid grid-cols-2 gap-3 sm:grid-cols-4`,children:n.map(({key:t,Icon:n,label:r,value:i})=>(0,Z.jsxs)(`div`,{className:`flex items-center gap-2 rounded-lg border border-border bg-muted/30 px-3 py-2`,"data-testid":`role-summary-${t}`,children:[(0,Z.jsx)(n,{className:`size-4 shrink-0 text-muted-foreground`,"aria-hidden":`true`}),(0,Z.jsxs)(`div`,{className:`min-w-0`,children:[(0,Z.jsx)(`dt`,{className:`truncate text-xs text-muted-foreground`,children:r}),(0,Z.jsx)(`dd`,{className:`truncate font-mono text-sm font-medium tabular-nums text-foreground`,children:e.isLoading?(0,Z.jsx)(A,{className:`h-4 w-8`}):i})]})]},t))})}function $t({group:e,granted:t,open:n,onOpenChange:r,onToggle:i,onSetAll:a}){let o=(0,J.useMemo)(()=>e.permissions.map(e=>e.id),[e.permissions]),s=o.reduce((e,n)=>t.has(n)?e+1:e,0),c=o.length,l=s===c&&c>0;return(0,Z.jsx)(fe,{className:`overflow-hidden`,children:(0,Z.jsxs)(Ce,{open:n,onOpenChange:r,children:[(0,Z.jsx)(Se,{asChild:!0,children:(0,Z.jsxs)(`button`,{type:`button`,className:`flex w-full items-center gap-3 px-4 py-3 text-left hover:bg-muted/40`,"data-testid":`perm-category-${e.category}`,children:[(0,Z.jsx)(y,{className:k(`size-4 shrink-0 text-muted-foreground transition-transform`,n&&`rotate-180`),"aria-hidden":`true`}),(0,Z.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Z.jsx)(`p`,{className:`truncate font-sans text-sm font-medium text-foreground`,children:e.category}),(0,Z.jsx)(Re,{value:c===0?0:s/c*100,className:`mt-1.5 h-1.5`})]}),(0,Z.jsxs)(`span`,{className:`font-mono text-xs tabular-nums text-muted-foreground`,children:[s,`/`,c]})]})}),(0,Z.jsx)(xe,{children:(0,Z.jsxs)(`div`,{className:`border-t border-border px-4 py-2`,children:[(0,Z.jsx)(`div`,{className:`flex justify-end py-1`,children:(0,Z.jsx)(L,{type:`button`,variant:`ghost`,size:`sm`,className:`h-8 text-xs`,onClick:()=>a(o,!l),children:l?`Revoke all`:`Grant all`})}),(0,Z.jsx)(`ul`,{className:`divide-y divide-border`,children:e.permissions.map(e=>(0,Z.jsxs)(`li`,{className:`flex items-center gap-3 py-2`,children:[(0,Z.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Z.jsx)(`p`,{className:`truncate font-mono text-sm text-foreground`,children:e.key}),e.description?(0,Z.jsx)(`p`,{className:`truncate text-xs text-muted-foreground`,children:e.description}):null]}),(0,Z.jsx)(_e,{checked:t.has(e.id),onCheckedChange:()=>i(e.id),"aria-label":`Toggle ${e.key}`,"data-testid":`perm-toggle-${e.id}`})]},e.id))})]})})]})})}function en(e,t){let n=new Set;for(let r of e)r.roleIds.includes(t)&&n.add(r.permission.id);return n}function tn(e,t){let n=new Set(e);return n.has(t)?n.delete(t):n.add(t),n}function nn(e,t,n){let r=new Set(e);for(let e of t)n?r.add(e):r.delete(e);return r}function rn(e,t){if(e.size!==t.size)return!0;for(let n of e)if(!t.has(n))return!0;return!1}function an(e){let t=new Map;for(let n of e){let e=n.permission.category??`Uncategorized`,r=t.get(e)??[];r.push(n.permission),t.set(e,r)}return Array.from(t.entries()).map(([e,t])=>({category:e,permissions:[...t].sort((e,t)=>
1e.key.localeCompare(t.key))})).sort((e,t)=>e.category.localeCompare(t.category))}function on({roleId:e}){let{toast:t}=z(),n=D(),r=Q(),i=(0,J.useMemo)(()=>en(r.data??[],e),[r.data,e]),a=(0,J.useMemo)(()=>an(r.data??[]),[r.data]),[o,s]=(0,J.useState)(i),[c,l]=(0,J.useState)(null),u=(0,J.useRef)(!1);(0,J.useEffect)(()=>{!u.current&&!r.isLoading&&(s(i),u.current=!0)},[i,r.isLoading]);let d=rn(o,i),p=E({mutationFn:async t=>P(`POST`,`/api/rbac/roles/${e}/action-permissions`,{permissionIds:t}),onSuccess:async()=>{await n.invalidateQueries({queryKey:[`/api/rbac/permissions/with-roles`]}),t({title:`Permissions saved`,description:`The role's permissions have been updated.`})},onError:e=>{t({title:`Save failed`,description:e.message,variant:`destructive`})}});return r.isLoading?(0,Z.jsx)(`div`,{className:`space-y-3`,children:Array.from({length:4}).map((e,t)=>(0,Z.jsx)(A,{className:`h-14 w-full`},t))}):(0,Z.jsxs)(`div`,{className:`space-y-4`,children:[(0,Z.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,Z.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[(0,Z.jsx)(`span`,{className:`font-mono text-foreground tabular-nums`,children:o.size}),` permissions granted`]}),(0,Z.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Z.jsxs)(L,{variant:`ghost`,size:`sm`,onClick:()=>s(i),disabled:!d||p.isPending,className:`gap-1.5`,children:[(0,Z.jsx)(f,{className:`size-4`,"aria-hidden":`true`}),`Reset`]}),(0,Z.jsxs)(L,{size:`sm`,onClick:()=>p.mutate([...o]),disabled:!d||p.isPending,className:`gap-1.5`,"data-testid":`perm-save`,children:[p.isPending?(0,Z.jsx)(M,{"aria-hidden":`true`}):(0,Z.jsx)(re,{className:`size-4`,"aria-hidden":`true`}),`Save`]})]})]}),(0,Z.jsx)(`div`,{className:`space-y-2`,children:a.map(e=>(0,Z.jsx)($t,{group:e,granted:o,open:c===e.category,onOpenChange:t=>l(t?e.category:null),onToggle:e=>s(t=>tn(t,e)),onSetAll:(e,t)=>
1s(n=>nn(n,e,t))},e.category))})]})}function sn({roleId:e}){let{toast:t}=z(),n=D(),r=It(),i=r.data?.find(t=>t.role_id===e)?.scope_strategy,a=E({mutationFn:async t=>P(`PUT`,`/api/rbac/role-account-scopes/${e}`,{scope_strategy:t}),onSuccess:async()=>{await n.invalidateQueries({queryKey:[`/api/rbac/role-account-scopes`]}),t({title:`Scope updated`,description:`The role's data visibility has been updated.`})},onError:e=>{t({title:`Update failed`,description:e.message,variant:`destructive`})}});if(r.isLoading)return(0,Z.jsx)(`div`,{className:`grid grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-4`,children:Array.from({length:4}).map((e,t)=>(0,Z.jsx)(A,{className:`h-28 w-full`},t))});let o=a.isPending?a.variables:null;return(0,Z.jsxs)(`div`,{className:`space-y-4`,children:[(0,Z.jsxs)(`div`,{className:`space-y-1`,children:[(0,Z.jsx)(`p`,{className:`text-sm font-medium text-foreground`,children:`What accounts can this role see?`}),(0,Z.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Scope applies after page and permission access. It limits which account records the role can view or act on.`})]}),(0,Z.jsx)(`div`,{className:`grid grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-4`,children:Xt.map(e=>(0,Z.jsx)(cn,{strategy:e,isSelected:i===e.value,isPending:o===e.value,disabled:a.isPending,onSelect:()=>a.mutate(e.value)},e.value))}),i===`region`?(0,Z.jsx)(`p`,{className:`rounded-md border border-border bg-muted/30 px-3 py-2 text-xs text-muted-foreground`,children:`Region scope limits accounts to the role's assigned region(s). Region configuration is managed with the regional-manager region mapping.`}):null]})}function cn({strategy:e,isSelected:t,isPending:n,disabled:r,onSelect:i}){let{value:a,label:o,blurb:s,explanation:c,Icon:l}=e,u=()=>{!t&&!r&&i()};return(0,Z.jsxs)(fe,{role:`button`,tabIndex:0,"aria-pressed":t,"aria-disabled":r,onClick:u,onKeyDown:e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),u())},"data-testid":`scope-strategy-${a}`,className:k(`relative flex min-h-40 cursor-pointer flex-col gap-3 p-4 transition-colors focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-hidden`,t?`border-primary bg-brand-selected`:`hover:border-primary/40 hover:bg-muted/40`),children:[(0,Z.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,Z.jsx)(l,{className:k(`size-5`,t?`text-primary`:`text-muted-foreground`),"aria-hidden":`true`}),(0,Z.jsx)(ln,{isPending:n,isSelected:t})]}),(0,Z.jsxs)(`div`,{className:`space-y-1`,children:[(0,Z.jsx)(`p`,{className:`font-sans text-sm font-medium text-foreground`,children:o}),(0,Z.jsx)(`p`,{className:`text-xs font-medium text-muted-foreground`,children:s})]}),(0,Z.jsx)(`p`,{className:`text-xs leading-5 text-muted-foreground`,children:c})]})}function ln({isPending:e,isSelected:t}){return e?(0,Z.jsx)(M,{className:`text-muted-foreground`,"aria-hidden":`true`}):t?(0,Z.jsx)(`span`,{className:`flex size-5 items-center justify-center rounded-full bg-primary text-primary-foreground`,children:(0,Z.jsx)(_,{className:`size-3`,"aria-hidden":`true`})}):null}var un=`page-`;function dn({page:e,isHidden:t,onToggleVisibility:n,overlay:r=!1}){let a=ht({id:`${un}${e.id}`,disabled:r}),o=r?void 0:{transform:pt.Transform.toString(a.transform),transition:a.transition};return(0,Z.jsxs)(`div`,{ref:r?void 0:a.setNodeRef,style:o,className:k(`flex min-h-11 items-center gap-1.5 rounded-md border border-border bg-card px-2 py-1.5`,r&&`shadow-lg`,!r&&a.isDragging&&`opacity-50`),"data-testid":`nav-page-card-${e.id}`,children:[(0,Z.jsx)(`button`,{type:`button`,className:`flex size-6 shrink-0 cursor-grab touch-none items-center justify-center rounded text-muted-foreground hover:bg-muted active:cursor-grabbing`,"aria-label":`Drag ${e.name}`,...r?{}:a.attributes,...r?{}:a.listeners,children:(0,Z.jsx)(S,{className:`size-4`,"aria-hidden":`true`})}),(0,Z.jsx)(`span`,{className:`shrink-0 text-muted-foreground`,children:K(e.icon,14)}),(0,Z.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-sans text-sm text-foreground`,children:e.name}),e.is_in_development?(0,Z.jsx)(R,{variant:`outline`,className:`shrink-0 font-sans text-xs`,children:`dev`}):null,(0,Z.jsx)(`button`,{type:`button`,onPointerDown:e=>e.stopPropagation(),onClick:t=>{t.stopPropagation(),n(e.id)},className:`flex size-8 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-muted`,"aria-pressed":!t,"aria-label":t?`Show ${e.name} in sidebar`:`Hide ${e.name} from sidebar`,"data-testid":`nav-page-toggle-${e.id}`,children:t?(0,Z.jsx)(i,{className:`size-4`,"aria-hidden":`true`}):(0,Z.jsx)(v,{className:`size-4`,"aria-hidden":`true`})})]})}var fn=`group-`;function pn({title:e,count:t,onRemove:n}){return(0,Z.jsxs)(lt,{children:[(0,Z.jsx)(Me,{asChild:!0,children:(0,Z.jsx)(L,{variant:`ghost`,size:`icon`,className:`size-8 shrink-0`,"aria-label":`Remove ${e}`,children:(0,Z.jsx)(ae,{className:`size-4`,"aria-hidden":`true`})})}),(0,Z.jsxs)(Ve,{children:[(0,Z.jsxs)(He,{children:[(0,Z.jsxs)(Ne,{children:[`Remove â`,e,`â?`]}),(0,Z.jsxs)(je,{children:[`Its `,t,` page`,t===1?``:`s`,` will move to Ungrouped. This takes effect when you save.`]})]}),(0,Z.jsxs)(at,{children:[(0,Z.jsx)(st,{children:`Cancel`}),(0,Z.jsx)(Ge,{onClick:n,children:`Remove group`})]})]})]})}function mn({title:e,count:t,editable:n,onRename:r,onRemove:i}){let[a,s]=(0,J.useState)(!1),[c,l]=(0,J.useState)(e),u=(0,J.useRef)(null);(0,J.useEffect)(()=>{a&&u.current?.focus()},[a]);let d=()=>{c.trim()&&r&&r(c.trim()),s(!1)},f=()=>{l(e),s(!1)};return a?(0,Z.jsxs)(`div`,{className:`flex min-h-11 items-center gap-1.5`,children:[(0,Z.jsx)(j,{ref:u,value:c,onChange:e=>l(e.target.value),onKeyDown:e=>{e.key===`Enter`&&d(),e.key===`Escape`&&f()},className:`h-8 font-sans text-sm`,"aria-label":`Group name`}),(0,Z.jsx)(L,{variant:`ghost`,size:`icon`,className:`size-8 shrink-0`,onClick:d,"aria-label":`Save group name`,children:(0,Z.jsx)(_,{className:`size-4`,"aria-hidden":`true`})}),(0,Z.jsx)(L,{variant:`ghost`,size:`icon`,className:`size-8 shrink-0`,onClick:f,"aria-label":`Cancel rename`,children:(0,Z.jsx)(oe,{className:`size-4`,"aria-hidden":`true`})})]}):(0,Z.jsxs)(`div`,{className:`flex min-h-11 items-center gap-1.5`,children:[(0,Z.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-sans text-sm font-medium text-foreground`,children:e}),(0,Z.jsx)(`span`,{className:`shrink-0 font-mono text-xs tabular-nums text-muted-foreground`,children:t}),n?(0,Z.jsx)(L,{variant:`ghost`,size:`icon`,className:`size-8 shrink-0`,onClick:()=>{l(e),s(!0)},"aria-label":`Rename ${e}`,children:(0,Z.jsx)(o,{className:`size-4`,"aria-hidden":`true`})}):null,n&&i?(0,Z.jsx)(pn,{title:e,count:t,onRemove:i}):null]})}function hn({columnKey:e,droppableId:t,title:n,pageIds:r,pagesById:i,hidden:a=!1,editable:o=!1,onToggleVisibility:s,onRename:c,onRemove:l}){let{setNodeRef:u,isOver:d}=yt({id:t,data:{columnKey:e}});return(0,Z.jsxs)(`div`,{className:k(`flex w-64 shrink-0 flex-col gap-2 rounded-lg border border-border p-2`,a?`bg-muted/40`:`bg-muted/20`),"data-testid":`nav-group-${e}`,children:[(0,Z.jsx)(mn,{title:n,count:r.length,editable:o,onRename:c,onRemove:l}),(0,Z.jsxs)(`div`,{ref:u,className:k(`flex min-h-24 flex-col gap-1.5 rounded-md p-1 transition-colors`,d&&`bg-brand-selected`),children:[(0,Z.jsx)(xt,{items:r.map(e=>`${un}${e}`),strategy:dt,children:r.map(e=>{let t=i.get(e);return t?(0,Z.jsx)(dn,{page:t,isHidden:a,onToggleVisibility:s},e):null})}),r.length===0?(0,Z.jsx)(`div`,{className:`flex flex-1 items-center justify-center rounded-md border border-dashed border-border px-2 py-6 text-center text-xs text-muted-foreground`,children:a?`Drag pages here to hide`:`Drop pages here`}):null]})]})}function gn(e,t,n){let r=new Map(t.map(e=>[e.page_id,e]));return e.map(e=>{let t=r.get(e.id);return{permission:{role_id:t?.role_id??n,page_id:e.id,show_in_nav:t?.show_in_nav??!1},page:e}})}var _n=`ungrouped`,vn=`hidden`,yn={roleId:null,functionGroupId:null},bn=0;function xn(){return bn+=1,`new-${bn}`}function Sn(e,t){let n=new Set(e.map(e=>e.page.id)),r=new Map(e.map(e=>[e.page.id,e.permission.show_in_nav])),i=[],a=new Set,o={},s=[],c=(e,t)=>{o[e]=t,s.push(e),a.add(e)};if(t)for(let e of[...t.groups].sort((e,t)=>
1e.order_index-t.order_index)){let t=`g${e.id}`,o=[];for(let i of e.pageIds)!n.has(i)||a.has(i)||(r.get(i)===!1?c(i,t):(o.push(i),a.add(i)));i.push({key:t,dbId:e.id,name:e.name,icon:e.icon,default_expanded:e.default_expanded,pageIds:o})}let l=[],u=t?[...t.ungroupedPages].sort((e,t)=>e.order_index-t.order_index).map(e=>e.pageId):[],d=e=>{!n.has(e)||a.has(e)||(r.get(e)===!1?c(e,null):(l.push(e),a.add(e)))};for(let e of u)d(e);for(let t of e)d(t.page.id);return{groups:i,ungroupedPageIds:l,hiddenPageIds:s,hiddenHomeGroupKey:o}}function Cn(e){return[...e.groups.flatMap(e=>e.pageIds),...e.ungroupedPageIds,...e.hiddenPageIds]}function wn(e,t){let n=new Set(e.hiddenPageIds),r={groups:e.groups.map((e,t)=>({id:e.dbId??void 0,name:e.name,description:null,icon:e.icon,default_expanded:e.default_expanded,order_index:t,is_active:!0,pageIds:e.pageIds})),ungroupedPageIds:e.ungroupedPageIds,ungroupedPages:e.ungroupedPageIds.map((e,t)=>({pageId:e,order_index:t}))},i=Cn(e).map(e=>({pageId:e,show_in_nav:!n.has(e)}));return t===void 0?{structure:r,navVisibility:i}:{structure:r,navVisibility:i,shareLayoutId:t}}function Tn(e){return{id:e.id,path:e.path,name:e.name,icon:e.icon,category:e.category}}function En(e,t){let n=e.groups.map((e,t)=>({id:e.dbId??-(t+1),name:e.name,description:null,icon:e.icon,default_expanded:e.default_expanded,order_index:t,is_active:!0})),r=[],i=[];return e.groups.forEach((e,n)=>{let a=e.dbId??-(n+1);e.pageIds.forEach((e,n)=>{let o=t.get(e);o&&(r.push(Tn(o)),i.push({pageId:e,functionGroupIds:[],sidebarAssignments:[{sidebarGroupId:a,...yn}],orderIndex:n}))})}),e.ungroupedPageIds.forEach((e,n)=>{let a=t.get(e);a&&(r.push(Tn(a)),i.push({pageId:e,functionGroupIds:[],sidebarAssignments:[],orderIndex:n}))}),{sidebarGroups:n,pages:r,pageAssignments:i}}function Dn(e,t){let n=e.groups.find(e=>e.pageIds.includes(t));return n?n.key:e.ungroupedPageIds.includes(t)?_n:e.hiddenPageIds.includes(t)?vn:null}var On=`${fn}${_n}`,kn=`${fn}${vn}`;function An(e){if(!e.startsWith(`page-`))return null;let t=Number(e.slice(un.length));return Number.isNaN(t)?null:t}function jn(e,t){return t===`ungrouped`?e.ungroupedPageIds:t===`hidden`?e.hiddenPageIds:e.groups.find(e=>e.key===t)?.pageIds??[]}function Mn(e,t,n){if(n.startsWith(`group-`))return{columnKey:n.slice(fn.length),index:null};let r=An(n);if(r===null||r===t)return null;let i=Dn(e,r);return i===null?null:{columnKey:i,index:jn(e,i).indexOf(r)}}function Nn({draft:e,pagesById:t,onMovePage:n,onToggleVisibility:r,onAddGroup:i,onRenameGroup:a,onRemoveGroup:o}){let s=mt(_t(gt,{activationConstraint:{distance:6}})),[c,l]=(0,J.useState)(null),[u,d]=(0,J.useState)(!1),[f,p]=(0,J.useState)(``),m=(0,J.useRef)(null);(0,J.useEffect)(()=>{u&&m.current?.focus()},[u]);let h=c===null?void 0:t.get(c),g=(0,J.useMemo)(()=>new Set(e.hiddenPageIds),[e.hiddenPageIds]),_=e=>{l(An(String(e.active.id)))},v=t=>{l(null);let{active:r,over:i}=t;if(!i)return;let a=An(String(r.id));if(a===null)return;let o=Mn(e,a,String(i.id));o&&n(a,o.columnKey,o.index)},y=()=>{f.trim()&&i(f.trim()),p(``),d(!1)};return(0,Z.jsxs)(vt,{sensors:s,collisionDetection:ft,onDragStart:_,onDragEnd:v,onDragCancel:()=>l(null),children:[(0,Z.jsxs)(`div`,{className:`flex gap-3 overflow-x-auto pb-2`,children:[e.groups.map(e=>(0,Z.jsx)(hn,{columnKey:e.key,droppableId:`${fn}${e.key}`,title:e.name,pageIds:e.pageIds,pagesById:t,editable:!0,onToggleVisibility:r,onRename:t=>a(e.key,t),onRemove:()=>o(e.key)},e.key)),(0,Z.jsx)(hn,{columnKey:_n,droppableId:On,title:`Ungrouped`,pageIds:e.ungroupedPageIds,pagesById:t,onToggleVisibility:r}),(0,Z.jsx)(hn,{columnKey:vn,droppableId:kn,title:`Hidden`,pageIds:e.hiddenPageIds,pagesById:t,hidden:!0,onToggleVisibility:r}),(0,Z.jsx)(`div`,{className:`w-64 shrink-0`,children:u?(0,Z.jsx)(`div`,{className:`flex flex-col gap-1.5 rounded-lg border border-dashed border-border p-2`,children:(0,Z.jsx)(j,{ref:m,value:f,placeholder:`Group name`,onChange:e=>p(e.target.value),onKeyDown:e=>{e.key===`Enter`&&y(),e.key===`Escape`&&(p(``),d(!1))},onBlur:y,className:`h-9 font-sans text-sm`,"aria-label":`New group name`})}):(0,Z.jsxs)(L,{variant:`outline`,className:`min-h-11 w-full justify-start gap-1.5 border-dashed font-sans`,onClick:()=>d(!0),"data-testid":`nav-add-group`,children:[(0,Z.jsx)(C,{className:`size-4`,"aria-hidden":`true`}),`New group`]})})]}),(0,Z.jsx)(bt,{children:h?(0,Z.jsx)(dn,{page:h,isHidden:c!==null&&g.has(c),onToggleVisibility:()=>void 0,overlay:!0}):null})]})}function Pn(e,t,n){return e.find(e=>e.roleId===t&&e.functionGroupId===n)}function Fn({assignments:e,roleId:t=null,functionGroupId:n=null}
1){let r=Pn(e,t,n);if(r)return r.sidebarGroupId;let i=Pn(e,t,null);if(i)return i.sidebarGroupId;let a=Pn(e,null,n);if(a)return a.sidebarGroupId;let o=Pn(e,null,null);return o?o.sidebarGroupId:null}function In({group:e,pages:t}){let[n,r]=(0,J.useState)(e.default_expanded),i=e.icon?K(e.icon,14):null;return(0,Z.jsxs)(`div`,{className:k(`border-b border-gray-100 last:border-b-0`,!e.is_active&&`opacity-70 border-l-2 border-l-amber-400`),children:[(0,Z.jsxs)(`button`,{type:`button`,onClick:()=>r(!n),className:`w-full flex items-center gap-1.5 px-2 py-1.5 text-left text-xs font-medium text-gray-700 hover:bg-gray-50 transition-colors`,children:[i&&(0,Z.jsx)(`span`,{className:`shrink-0 text-gray-500`,children:i}),(0,Z.jsx)(`span`,{className:`flex-1 truncate`,children:e.name}),!e.is_active&&(0,Z.jsx)(R,{variant:`outline`,className:`text-[10px] py-0 px-1 text-amber-600 border-amber-400 mr-1`,children:`Draft`}),n?(0,Z.jsx)(y,{className:`h-3 w-3 text-gray-400`}):(0,Z.jsx)(l,{className:`h-3 w-3 text-gray-400`})]}),n&&(0,Z.jsx)(`div`,{className:`pl-4 pb-1`,children:t.length===0?(0,Z.jsx)(`div`,{className:`flex items-center px-2 py-1.5 text-xs text-gray-400 italic`,children:`No pages assigned`}):t.map(e=>{let t=e.icon?K(e.icon,12):null;return(0,Z.jsxs)(`div`,{className:`flex items-center gap-1.5 px-2 py-1 text-xs text-gray-600 rounded hover:bg-gray-50`,children:[t&&(0,Z.jsx)(`span`,{className:`text-gray-400`,children:t}),(0,Z.jsx)(`span`,{className:`truncate`,children:e.name})]},e.id)})})]})}function Ln({functionGroups:e,sidebarGroups:t,pages:n,pageAssignments:r,selectedFunctionGroupId:i=null,selectedRoleId:a=null,onFunctionGroupSelect:o,className:s}){let c=(e,t)=>{let n=l.get(e.id)?.orderIndex??2**53-1,r=l.get(t.id)?.orderIndex??2**53-1;return n===r?e.name.localeCompare(t.name):n-r},l=(0,J.useMemo)(()=>{let e=new Map;return r.forEach(t=>{e.set(t.pageId,t)}),e},[r]),u=(0,J.useMemo)(()=>i===null?n:n.filter(e=>{let t=l.get(e.id);return!t||t.functionGroupIds.length===0||t.functionGroupIds.includes(i)}),[n,i,l]),d=(0,J.useMemo)(()=>{let e=new Map;return u.forEach(t=>{let n=Fn({assignments:l.get(t.id)?.sidebarAssignments??[],roleId:a,functionGroupId:i}),r=e.get(n)||[];r.push(t),e.set(n,r)}),e.forEach((t,n)=>{e.set(n,[...t].sort(c))}),e},[u,l,a,i]),f=(0,J.useMemo)(()=>[...t].sort((e,t)=>e.order_index-t.order_index),[t]),p=(0,J.useMemo)(()=>[...(d.get(null)||[]).map(e=>({type:`page`,key:`page-${e.id}`,orderIndex:l.get(e.id)?.orderIndex??2**53-1,page:e})),...f.map(e=>({type:`group`,key:`group-${e.id}`,orderIndex:e.order_index,group:e}))].sort((e,t)=>e.orderIndex-t.orderIndex),[l,d,f]),m=(0,J.useMemo)(()=>[...e].filter(e=>e.is_active).sort((e,t)=>e.order_index-t.order_index),[e]),h=e=>{o?.(e)};return(0,Z.jsxs)(`div`,{className:k(`flex flex-col h-full`,s),children:[m.length>0&&(0,Z.jsx)(`div`,{className:`shrink-0 border-b border-gray-200 bg-gray-50 p-1.5`,children:(0,Z.jsxs)(`div`,{className:`flex flex-wrap gap-1`,children:[(0,Z.jsx)(`button`,{type:`button`,onClick:()=>h(null),className:k(`px-2 py-1 text-xs rounded font-medium transition-colors`,i===null?`bg-brand-primary text-white`:`bg-white text-gray-600 hover:bg-gray-100 border border-gray-200`),children:`All`}),m.map(e=>{let t=e.icon?K(e.icon,12):null,n=i===e.id;return(0,Z.jsxs)(`button`,{type:`button`,onClick:()=>h(e.id),className:k(`flex items-center gap-1 px-2 py-1 text-xs rounded font-medium transition-colors`,n?`text-white`:`bg-white text-gray-600 hover:bg-gray-100 border border-gray-200`),style:n&&e.color?{backgroundColor:e.color}:n?{backgroundColor:me.primary}:void 0,children:[t&&(0,Z.jsx)(`span`,{children:t}),(0,Z.jsx)(`span`,{children:e.name})]},e.id)})]})}),(0,Z.jsx)(`div`,{className:`flex-1 overflow-y-auto bg-white`,children:u.length===0&&f.length===0?(0,Z.jsx)(`div`,{className:`flex items-center justify-center h-full p-4 text-xs text-gray-400`,children:`No pages or groups to display`}):(0,Z.jsx)(`div`,{className:`py-1`,children:p.map(e=>{if(e.type===`page`){let t=e.page,n=t.icon?K(t.icon,14):null;return(0,Z.jsxs)(`div`,{className:`flex items-center gap-1.5 px-3 py-1.5 text-xs text-gray-700 hover:bg-gray-50`,children:[n&&(0,Z.jsx)(`span`,{className:`text-gray-500`,children:n}),(0,Z.jsx)(`span`,{className:`truncate`,children:t.name})]},e.key)}let t=e.group;return(0,Z.jsx)(In,{group:t,pages:d.get(t.id)||[]},e.key)})})}),(0,Z.jsx)(`div`,{className:`shrink-0 border-t border-gray-200 bg-gray-50 px-2 py-1.5`,children:(0,Z.jsxs)(`div`,{className:`flex flex-wrap gap-1 text-xs text-gray-500`,children:[(0,Z.jsxs)(R,{variant:`outline`,className:`text-xs py-0`,children:[u.length,` pages`]}),f.length>0&&(0,Z.jsxs)(Z.Fragment,{children:[(0,Z.jsxs)(R,{variant:`outline`,className:`text-xs py-0`,children:[f.filter(e=>e.is_active).length,` groups`]}),f.some(e=>!e.is_active)&&(0,Z.jsxs)(R,{variant:`outline`,className:`text-xs py-0 text-amber-600 border-amber-400`,children:[f.filter(e=>!e.is_active).length,` draft`]})]})]})})]})}function Rn({preview:e}){return(0,Z.jsxs)(`div`,{className:`flex flex-col overflow-hidden rounded-lg border border-border bg-card`,children:[(0,Z.jsxs)(`div`,{className:`border-b border-border px-3 py-2`,children:[(0,Z.jsx)(`p`,{className:`font-sans text-sm font-medium text-foreground`,children:`Live preview`}),(0,Z.jsx)(`p`,{className:`font-sans text-xs text-muted-foreground`,children:`How the sidebar renders for this role`})]}),(0,Z.jsx)(Ln,{functionGroups:[],sidebarGroups:e.sidebarGroups,pages:e.pages,pageAssignments:e.pageAssignments,selectedRoleId:null,selectedFunctionGroupId:null,className:`min-h-80`})]})}function zn({roleId:e,layoutMode:t,shareTargetLayoutId:n,allLayouts:r,roleNamesById:i,onOwn:a,onCopyFrom:o,onShare:s}){let c=r.filter(t=>!t.roleIds.includes(e)),l=r.find(e=>e.id===n),u=t===`share`&&l?`Sharing: ${l.name}`:`Own layout`;return(0,Z.jsxs)(Be,{children:[(0,Z.jsx)(rt,{asChild:!0,children:(0,Z.jsxs)(L,{variant:`outline`,size:`sm`,className:`gap-1.5 font-sans`,"data-testid":`nav-layout-control`,children:[(0,Z.jsx)(`span`,{className:`max-w-40 truncate`,children:u}),(0,Z.jsx)(y,{className:`size-4`,"aria-hidden":`true`})]})}),(0,Z.jsx)(Bn,{layoutMode:t,shareTargetLayoutId:n,otherLayouts:c,roleNamesById:i,onOwn:a,onCopyFrom:o,onShare:s})]})}function Bn({layoutMode:e,shareTargetLayoutId:t,otherLayouts:n,roleNamesById:r,onOwn:i,onCopyFrom:a,onShare:o}){return(0,Z.jsxs)(ke,{align:`start`,className:`w-screen max-w-2xl p-2`,children:[(0,Z.jsxs)(Ue,{className:`px-1 pb-2 pt-1 font-sans`,children:[(0,Z.jsx)(`span`,{className:`text-sm font-medium text-foreground`,children:`Layout source`}),(0,Z.jsx)(`span`,{className:`block text-xs font-normal text-muted-foreground`,children:`Choose whether this role edits its own sidebar, copies another layout, or shares one.`})]}),(0,Z.jsx)(Vn,{isSelected:e===`own`,onOwn:i}),n.length>0?(0,Z.jsx)(Hn,{layoutMode:e,shareTargetLayoutId:t,layouts:n,roleNamesById:r,onCopyFrom:a,onShare:o}):(0,Z.jsx)(`p`,{className:`px-1 py-3 text-xs text-muted-foreground`,children:`No other role layouts are available to copy or share yet.`})]})}function Vn({isSelected:e,onOwn:t}){return(0,Z.jsx)(Pe,{onSelect:t,className:k(`items-start rounded-md border border-border/60 bg-background p-3 font-sans focus:bg-accent`,e&&`border-primary bg-brand-selected`),"aria-label":`Use own layout`,children:(0,Z.jsxs)(`div`,{className:`flex w-full gap-3`,children:[(0,Z.jsx)(ie,{className:`mt-0.5 size-4 text-muted-foreground`,"aria-hidden":`true`}),(0,Z.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Z.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,Z.jsx)(`span`,{className:`text-sm font-medium text-foreground`,children:`Own layout`}),e?(0,Z.jsx)(_,{className:`size-4 text-primary`,"aria-hidden":`true`}):null]}),(0,Z.jsx)(`p`,{className:`mt-1 text-xs leading-5 text-muted-foreground`,children:`Edit this roleâs sidebar directly. Saving only changes roles already bound to this layout.`})]})]})})}function Hn({layoutMode:e,shareTargetLayoutId:t,layouts:n,roleNamesById:r,onCopyFrom:i,onShare:a}){return(0,Z.jsxs)(Z.Fragment,{children:[(0,Z.jsx)(Ie,{}),(0,Z.jsxs)(`div`,{className:`grid gap-2 md:grid-cols-2`,children:[(0,Z.jsx)(Un,{title:`Copy structure from`,hint:`Start with another layout, then keep this role private.`,Icon:g,layouts:n,roleNamesById:r,actionLabel:`Copy`,onSelect:i}),(0,Z.jsx)(Un,{title:`Share existing layout`,hint:`Bind this role to a layout shared with other roles.`,Icon:s,layouts:n,roleNamesById:r,actionLabel:`Share`,selectedLayoutId:e===`share`?t:null,onSelect:a})]})]})}function Un({title:e,hint:t,Icon:n,layouts:r,roleNamesById:i,actionLabel:a,selectedLayoutId:o,onSelect:s}){return(0,Z.jsxs)(`section`,{className:`min-w-0 space-y-2`,"aria-label":e,children:[(0,Z.jsxs)(`div`,{className:`px-1`,children:[(0,Z.jsxs)(`h3`,{className:`flex items-center gap-1.5 font-sans text-xs font-medium text-foreground`,children:[(0,Z.jsx)(n,{className:`size-3.5`,"aria-hidden":`true`}),e]}),(0,Z.jsx)(`p`,{className:`mt-0.5 text-xs leading-5 text-muted-foreground`,children:t})]}),(0,Z.jsx)(`div`,{className:`space-y-1`,children:r.map(e=>(0,Z.jsx)(Wn,{layout:e,roleNamesById:i,actionLabel:a,isSelected:o===e.id,onSelect:()=>s(e)},`${a}-${e.id}`))})]})}function Wn({layout:e,roleNamesById:t,actionLabel:n,isSelected:r,onSelect:i}){let a=e.roleIds.map(e=>t.get(e)??`Role #${e}`);return(0,Z.jsx)(Pe,{onSelect:i,"aria-label":`${n} ${e.name}`,className:k(`items-start rounded-md border border-border/60 bg-background p-3 font-sans focus:bg-accent`,r&&`border-primary bg-brand-selected`),children:(0,Z.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Z.jsxs)(`div`,{className:`flex items-start justify-between gap-2`,children:[(0,Z.jsx)(`span`,{className:`min-w-0 truncate text-sm font-medium text-foreground`,children:e.name}),r?(0,Z.jsx)(_,{className:`size-4 shrink-0 text-primary`,"aria-hidden":`true`}):null]}),(0,Z.jsx)(`p`,{className:`mt-1 truncate text-xs text-muted-foreground`,children:a.length>0?a.join(`, `):`No roles currently bound`}),(0,Z.jsxs)(`div`,{className:`mt-2 flex flex-wrap gap-1`,children:[(0,Z.jsx)(R,{variant:`outline`,className:`text-xs`,children:Kn(e.groups.length,`group`)}),(0,Z.jsx)(R,{variant:`outline`,className:`text-xs`,children:Kn(Gn(e),`page`)})]})]})})}function Gn(e){return e.groups.reduce((e,t)=>
1e+t.pageIds.length,0)+e.ungroupedPageIds.length}function Kn(e,t){return`${e} ${e===1?t:`${t}s`}`}function qn(e,t){return{...e,groups:e.groups.map(e=>({...e,pageIds:e.pageIds.filter(e=>e!==t)})),ungroupedPageIds:e.ungroupedPageIds.filter(e=>e!==t),hiddenPageIds:e.hiddenPageIds.filter(e=>e!==t)}}function Jn(e,t,n){let r=[...e];return n===null||n<0||n>=r.length?r.push(t):r.splice(n,0,t),r}function Yn(e,t,n,r){let i=Dn(e,t);if(i===null)return e;if(n===`hidden`){let n=i===`ungrouped`||i===`hidden`?null:i,r=qn(e,t);return{...r,hiddenPageIds:[...r.hiddenPageIds,t],hiddenHomeGroupKey:{...r.hiddenHomeGroupKey,[t]:n}}}let a=qn(e,t),o={...a.hiddenHomeGroupKey};return delete o[t],n===`ungrouped`?{...a,ungroupedPageIds:Jn(a.ungroupedPageIds,t,r),hiddenHomeGroupKey:o}:{...a,groups:a.groups.map(e=>e.key===n?{...e,pageIds:Jn(e.pageIds,t,r)}:e),hiddenHomeGroupKey:o}}function Xn(e,t){let n=Dn(e,t);if(n===null)return e;if(n===`hidden`){let n=e.hiddenHomeGroupKey[t]??null;return Yn(e,t,n&&e.groups.some(e=>e.key===n)?n:_n,null)}return Yn(e,t,vn,null)}function Zn(e,t){let n=t.trim();if(!n)return e;let r={key:xn(),dbId:null,name:n,icon:null,default_expanded:!0,pageIds:[]};return{...e,groups:[...e.groups,r]}}function Qn(e,t,n){let r=n.trim();return r?{...e,groups:e.groups.map(e=>e.key===t?{...e,name:r}:e)}:e}function $n(e,t){let n=e.groups.find(e=>e.key===t);return n?{...e,groups:e.groups.filter(e=>e.key!==t),ungroupedPageIds:[...e.ungroupedPageIds,...n.pageIds]}:e}function er({roleId:e,roleName:t,onSaved:n}){let r=D(),{toast:i}=z();return E({mutationFn:({draft:t,shareLayoutId:n})=>P.put(`/api/rbac/roles/${e}/navigation`,wn(t,n)),onSuccess:async()=>{await Promise.all([r.invalidateQueries({queryKey:[`/api/rbac/roles/${e}/permissions`]}),r.invalidateQueries({queryKey:[`/api/rbac/navigation-layouts`]}),r.invalidateQueries({queryKey:ue})]),n(),i({title:`Navigation saved`,description:`Updated the sidebar for ${t}.`})},onError:e=>{i({title:`Failed to save navigation`,description:e.message||`Something went wrong. Please try again.`,variant:`destructive`})}})}var tr={groups:[],ungroupedPageIds:[],hiddenPageIds:[],hiddenHomeGroupKey:{}};function nr(e){if(e)return{id:e.id,name:e.name,roleIds:e.roleIds,groups:e.groups.map(e=>({id:e.id,name:e.name,icon:e.icon,default_expanded:e.default_expanded,order_index:e.order_index,pageIds:e.pageIds})),ungroupedPages:e.ungroupedPages}}function rr(e,t){let n=zt(e),r=Ft(),i=Bt(),a=Pt(),[o,s]=(0,J.useState)(null),[c,l]=(0,J.useState)(!1),[u,d]=(0,J.useState)(`own`),[f,p]=(0,J.useState)(null),m=(0,J.useRef)(null),h=(0,J.useMemo)(()=>gn(r.data??[],n.data??[],e),[r.data,n.data,e]),g=(0,J.useMemo)(()=>{let e=new Map;for(let t of h)e.set(t.page.id,t.page);return e},[h]),_=(0,J.useMemo)(()=>i.data??[],[i.data]),v=(0,J.useMemo)(()=>nr(_.find(t=>t.roleIds.includes(e))),[_,e]);n.isSuccess&&r.isSuccess&&i.isSuccess&&m.current!==e&&(m.current=e,s(Sn(h,v)),l(!1),d(`own`),p(null));let y=(0,J.useCallback)(e=>{s(e),l(!0)},[]),b=(0,J.useCallback)((e,t)=>{s(Sn(h,e)),l(t)},[h]),ee=(v?.roleIds.length??0)>1,te=(0,J.useMemo)(()=>{if(!v)return[];let t=new Map((a.data??[]).map(e=>[e.id,e.name]));return v.roleIds.filter(t=>t!==e).map(e=>t.get(e)??`Role #${e}`)},[v,a.data,e]),x=er({roleId:e,roleName:t,onSaved:()=>{l(!1),d(`own`),p(null)}}),S=o??tr,ne=(0,J.useMemo)(()=>En(S,g),[S,g]),re=(0,J.useMemo)(()=>({isPending:x.isPending,mutate:()=>x.mutate({draft:S,shareLayoutId:u===`share`&&f!==null?f:void 0})}),[x,S,u,f]),ie=(0,J.useMemo)(()=>({movePage:(e,t,n)=>y(Yn(S,e,t,n)),toggleShowInNav:e=>y(Xn(S,e)),addGroup:e=>y(Zn(S,e)),renameGroup:(e,t)=>y(Qn(S,e,t)),removeGroup:e=>y($n(S,e)),resetToBound:()=>{b(v,!1),d(`own`),p(null)},seedFromLayout:e=>{b(nr(e),!0),d(`own`),p(null)},selectShareLayout:e=>{p(e?.id??null),e&&(d(`share`),b(nr(e),!0))},setLayoutMode:e=>{d(e),e===`own`&&p(null)}}),[S,y,v,b]);return{isLoading:n.isLoading||r.isLoading||i.isLoading,isError:n.isError||r.isError||i.isError,hasNavigationPages:h.length>0,draft:S,isDirty:c,pagesById:g,boundLayout:v,isSharedLayout:ee,sharedWithRoleNames:te,allLayouts:_,layoutMode:u,shareTargetLayoutId:f,preview:ne,s
1ave:re,actions:ie}}function ir({role:e}){let t=rr(e.id,e.name),n=Pt(),r=(0,J.useMemo)(()=>new Map((n.data??[]).map(e=>[e.id,e.name])),[n.data]);return t.isLoading?(0,Z.jsx)(`div`,{className:`flex items-center justify-center gap-2 rounded-lg border border-border bg-muted/20 px-6 py-12 text-sm text-muted-foreground`,children:(0,Z.jsx)(M,{label:`Loading navigationâ¦`})}):t.isError?(0,Z.jsxs)(O,{variant:`destructive`,children:[(0,Z.jsx)(F,{children:`Couldnât load navigation`}),(0,Z.jsx)(N,{children:`Reload the page to try again.`})]}):t.hasNavigationPages?(0,Z.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,Z.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,Z.jsx)(zn,{roleId:e.id,layoutMode:t.layoutMode,shareTargetLayoutId:t.shareTargetLayoutId,allLayouts:t.allLayouts,roleNamesById:r,onOwn:()=>t.actions.setLayoutMode(`own`),onCopyFrom:e=>t.actions.seedFromLayout(e),onShare:e=>t.actions.selectShareLayout(e)}),(0,Z.jsxs)(`div`,{className:`flex items-center gap-2`,children:[t.isDirty?(0,Z.jsx)(L,{variant:`ghost`,size:`sm`,className:`font-sans`,onClick:t.actions.resetToBound,children:`Reset`}):null,(0,Z.jsxs)(L,{size:`sm`,className:`gap-1.5 font-sans`,disabled:!t.isDirty||t.save.isPending,onClick:()=>t.save.mutate(),"data-testid":`nav-save`,children:[t.save.isPending?(0,Z.jsx)(M,{"aria-hidden":`true`}):(0,Z.jsx)(re,{className:`size-4`,"aria-hidden":`true`}),`Save`]})]})]}),t.isSharedLayout?(0,Z.jsxs)(O,{children:[(0,Z.jsx)(u,{className:`size-4`,"aria-hidden":`true`}),(0,Z.jsx)(F,{className:`font-sans`,children:`Shared layout`}),(0,Z.jsxs)(N,{className:`font-sans`,children:[`This layout is shared with `,t.sharedWithRoleNames.join(`, `),`. Saving in Own mode changes the sidebar for`,` `,t.sharedWithRoleNames.length===1?`that role`:`those roles`,` too. Use âCopy structure fromâ to start a private copy instead.`]})]}):null,(0,Z.jsxs)(`div`,{className:`flex flex-col gap-3 lg:flex-row`,children:[(0,Z.jsx)(`div`,{className:`min-w-0 flex-1`,children:(0,Z.jsx)(Nn,{draft:t.draft,pagesById:t.pagesById,onMovePage:t.actions.movePage,onToggleVisibility:t.actions.toggleShowInNav,onAddGroup:t.actions.addGroup,onRenameGroup:t.actions.renameGroup,onRemoveGroup:t.actions.removeGroup})}),(0,Z.jsx)(`div`,{className:`w-full shrink-0 lg:w-80`,children:(0,Z.jsx)(Rn,{preview:t.preview})})]})]}):(0,Z.jsxs)(`div`,{className:`flex flex-col items-center gap-3 rounded-lg border border-dashed border-border bg-muted/30 px-6 py-10 text-center`,children:[(0,Z.jsx)(ie,{className:`size-6 text-muted-foreground`,"aria-hidden":`true`}),(0,Z.jsxs)(`div`,{children:[(0,Z.jsx)(`p`,{className:`font-sans text-sm font-medium text-foreground`,children:`No catalog pages yet`}),(0,Z.jsx)(`p`,{className:`mx-auto max-w-md font-sans text-sm text-muted-foreground`,children:`Create a page in Catalog before arranging role navigation.`})]})]})}function ar({open:e,onOpenChange:t,roleName:n,candidates:r,pendingUserId:i,onAdd:a}){let[o,s]=(0,J.useState)(``),c=(0,J.useMemo)(()=>{let e=o.trim().toLowerCase();return e?r.filter(t=>$(t).toLowerCase().includes(e)||(t.email??``).toLowerCase().includes(e)):r},[r,o]),l=c.slice(0,100),u=c.length>100;return(0,Z.jsx)(Ke,{open:e,onOpenChange:t,children:(0,Z.jsxs)(nt,{className:`max-w-lg`,children:[(0,Z.jsxs)(qe,{children:[(0,Z.jsxs)(ct,{className:`font-sans`,children:[`Add member to `,n]}),(0,Z.jsx)(Qe,{children:`Grant this role to a user as an additional role.`})]}),(0,Z.jsxs)(`div`,{className:`relative`,children:[(0,Z.jsx)(w,{className:`pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground`}),(0,Z.jsx)(j,{value:o,onChange:e=>s(e.target.value),placeholder:`Search users by name or email`,className:`h-10 pl-8`,"aria-label":`Search users`})]}),(0,Z.jsx)(I,{className:`h-72`,children:(0,Z.jsx)(`ul`,{className:`divide-y divide-border`,children:l.length===0?(0,Z.jsx)(`li`,{className:`px-2 py-6 text-center text-sm text-muted-foreground`,children:`No matching users.`}):l.map(e=>(0,Z.jsxs)(`li`,{className:`flex items-center gap-3 py-2 pr-1`,children:[(0,Z.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Z.jsx)(`p`,{className:`truncate font-sans text-sm text-foreground`,children:$(e)}),e.email?(0,Z.jsx)(`p`,{className:`truncate text-xs text-muted-foreground`,children:e.email}):null]}),(0,Z.jsxs)(L,{size:`sm`,variant:`outline`,className:`h-8 gap-1`,disabled:i!==null,onClick:()=>a(e.id),"data-testid":`member-add-${e.id}`,children:[i===e.id?(0,Z.jsx)(M,{className:`size-3.5`,"aria-hidden":`true`}):(0,Z.jsx)(C,{className:`size-3.5`,"aria-hidden":`true`}),`Add`]})]},e.id))})}),u?(0,Z.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Showing the first `,100,` of `,c.length,` users. Refine your search to narrow the list.`]}):null]})})}function or({member:e,roleName:t,removing:n,onRemove:r,onOpenUser:i}){let{user:a,membership:o}=e,s=$(a);return(0,Z.jsxs)(`li`,{className:`flex min-h-11 items-center gap-3 px-3 py-2`,children:[(0,Z.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Z.jsx)(`p`,{className:`truncate font-sans text-sm font-medium text-foreground`,children:s}),a.email?(0,Z.jsx)(`p`,{className:`truncate text-xs text-muted-foreground`,children:a.email}):null]}),(0,Z.jsx)(R,{variant:o===`primary`?`secondary`:`outline`,className:`text-xs`,children:o===`primary`?`primary`:`permissions only`}),a.access_status!=null&&a.access_status!==`active`?(0,Z.jsx)(R,{variant:`outline`,className:`text-xs`,children:`inactive`}):null,o===`additional`?(0,Z.jsx)(L,{size:`icon`,variant:`ghost`,className:`size-8 text-muted-foreground hover:text-destructive`,disabled:n,onClick:()=>r(a.id),"aria-label":`Remove ${s} from ${t}`,"data-testid":`member-remove-${a.id}`,children:n?(0,Z.jsx)(M,{"aria-hidden":`true`}):(0,Z.jsx)(oe,{className:`size-4`,"aria-hidden":`true`})}):(0,Z.jsx)(L,{size:`icon`,variant:`ghost`,className:`size-8 text-muted-foreground`,onClick:()=>i(a.id),"aria-label":`Manage ${s}'s primary role`,"data-testid":`member-manage-${a.id}`,children:(0,Z.jsx)(d,{className:`size-4`,"aria-hidden":`true`})})]})}function sr({roleName:e}){let t=X(),n=Lt(),[r,i]=(0,J.useState)(``),[a,o]=(0,J.useState)(!1),[s,c]=(0,J.useState)(null),l=(0,J.useMemo)(()=>n.data?Gt(n.data,e):[],[n.data,e]),u=(0,J.useMemo)(()=>n.data?qt(n.data,e):[],[n.data,e]),d=(0,J.useMemo)(()=>n.data?Kt(n.data,e):0,[n.data,e]),f=(0,J.useMemo)(()=>{let e=r.trim().toLowerCase();return e?l.filter(({user:t})=>$(t).toLowerCase().includes(e)||(t.email??``).toLowerCase().includes(e)):l},[l,r]),{addMutation:p,removeMutation:m}=cr({roleName:e,onPendingUserChange:c,onAdded:()=>o(!1)});return n.isLoading?(0,Z.jsx)(`div`,{className:`space-y-2`,children:Array.from({length:5}).map((e,t)=>(0,Z.jsx)(A,{className:`h-12 w-full`},t))}):(0,Z.jsxs)(`div`,{className:`space-y-4`,children:[(0,Z.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Z.jsxs)(`div`,{className:`relative flex-1`,children:[(0,Z.jsx)(w,{className:`pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground`}),(0,Z.jsx)(j,{value:r,onChange:e=>i(e.target.value),placeholder:`Search members`,className:`h-10 pl-8`,"aria-label":`Search members`})]}),(0,Z.jsxs)(L,{className:`gap-1.5`,onClick:()=>o(!0),"data-testid":`member-add-open`,children:[(0,Z.jsx)(ee,{className:`size-4`,"aria-hidden":`true`}),`Add`]})]}),(0,Z.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[(0,Z.jsx)(`span`,{className:`font-mono text-foreground tabular-nums`,children:d}),` active of `,(0,Z.jsx)(`span`,{className:`font-mono text-foreground tabular-nums`,children:l.length}),` total member`,l.length===1?``:`s`]}
1),(0,Z.jsx)(`ul`,{className:`divide-y divide-border rounded-lg border border-border`,children:f.length===0?(0,Z.jsx)(`li`,{className:`px-3 py-8 text-center text-sm text-muted-foreground`,children:l.length===0?`No users hold this role yet.`:`No members match â${r}â.`}):f.map(n=>(0,Z.jsx)(or,{member:n,roleName:e,removing:s===n.user.id&&m.isPending,onRemove:e=>m.mutate(e),onOpenUser:e=>t.selectUser(e)},n.user.id))}),(0,Z.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`A `,(0,Z.jsx)(`span`,{className:`font-medium`,children:`primary`}),` member holds this as their main role â it drives their navigation and account scope, and is replaced rather than removed. Open them in Users to change it. `,(0,Z.jsx)(`span`,{className:`font-medium`,children:`Permissions-only`}),` members hold it as an additional grant: it widens what they can do but adds no sidebar entries. Those can be removed here.`]}),(0,Z.jsx)(ar,{open:a,onOpenChange:o,roleName:e,candidates:u,pendingUserId:p.isPending?s:null,onAdd:e=>p.mutate(e)})]})}function cr({roleName:e,onPendingUserChange:t,onAdded:n}){let{toast:r}=z(),i=D(),a=()=>i.invalidateQueries({queryKey:[`/api/rbac/user-role-matrix`]});return{addMutation:E({mutationFn:async n=>(t(n),P(`POST`,`/api/rbac/users/${n}/roles`,{roleName:e})),onSuccess:async()=>{await a(),r({title:`Member added`,description:`Granted ${e} to the user.`}),n()},onError:e=>r({title:`Add failed`,description:e.message,variant:`destructive`}),onSettled:()=>t(null)}),removeMutation:E({mutationFn:async n=>(t(n),P(`DELETE`,`/api/rbac/users/${n}/roles/${encodeURIComponent(e)}`)),onSuccess:async()=>{await a(),r({title:`Member removed`,description:`Removed ${e} from the user.`})},onError:e=>r({title:`Remove failed`,description:e.message,variant:`destructive`}),onSettled:()=>t(null)})}}var lr={permissions:`Permissions`,scope:`Scope`,navigation:`Navigation`,members:`Members`};function ur({role:e,section:t,onSectionChange:n,onEditRole:r,onBack:i,onArchiveStateChange:a}){let{toast:o}=z(),s=D(),c=Yt(e.id,e.name),l=dr({role:e,queryClient:s,toast:o,onArchiveStateChange:a}),[u,d]=(0,J.useState)(null),f=c.memberCount,p=e.archived_at!=null,m=l.archive.isPending||l.restore.isPending;return(0,Z.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,Z.jsx)(fr,{role:e,summaryLoading:c.isLoading,activeMemberCount:f,archivePending:l.archive.isPending,restorePending:l.restore.isPending,mutationPending:m,onBack:i,onEditRole:r,onConfirmAction:d}),(0,Z.jsx)(Qt,{summary:c}),!p&&f>0?(0,Z.jsx)(`p`,{className:`text-xs text-muted-foreground`,"data-testid":`role-archive-blocked`,children:`Archive is available once this role has no active members.`}):null,(0,Z.jsx)(hr,{role:e,section:t,onSectionChange:n}),(0,Z.jsx)(gr,{action:u,roleName:e.name,mutationPending:m,onOpenChange:e=>!e&&d(null),onConfirm:()=>_r(u,l)})]})}function dr({role:e,queryClient:t,toast:n,onArchiveStateChange:r}){let i=async()=>{await Promise.all([t.invalidateQueries({queryKey:[`/api/rbac/roles`]}),t.invalidateQueries({queryKey:[`/api/rbac/user-role-matrix`]}),t.invalidateQueries({queryKey:[`/api/rbac/permissions/with-roles`]}),t.invalidateQueries({queryKey:[`/api/rbac/permission-matrix`]}),t.invalidateQueries({queryKey:[`/api/rbac/roles/${e.id}/permissions`]})])};return{archive:E({mutationFn:()=>P.post(`/api/rbac/roles/${e.id}/archive`),onSuccess:async()=>{await i(),n({title:`Role archived`,description:`â${e.name}â is hidden from active role lists.`}),r?.(!0)},onError:e=>{n({title:`Archive failed`,description:e.message,variant:`destructive`})}}),restore:E({mutationFn:()=>P.post(`/api/rbac/roles/${e.id}/unarchive`),onSuccess:async()=>{await i(),n({title:`Role restored`,description:`â${e.name}â is available again.`}),r?.(!1)},onError:e=>{n({title:`Restore failed`,description:e.message,variant:`destructive`})}})}}function fr({role:e,summaryLoading:t,activeMemberCount:n,archivePending:r,restorePending:i,mutationPending:a,onBack:o,onEditRole:s,onConfirmAction:c}){return(0,Z.jsxs)(`div`,{className:`flex items-start justify-between gap-2`,children:[(0,Z.jsx)(pr,{role:e,onBack:o}),(0,Z.jsx)(mr,{isArchived:e.archived_at!=null,archiveBlocked:t||n>0,archivePending:r,restorePending:i,mutationPending:a,onEditRole:s,onConfirmAction:c})]})}function pr({role:e,onBack:t}){return(0,Z.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2`,children:[(0,Z.jsx)(L,{variant:`ghost`,size:`icon`,className:`size-9 shrink-0 lg:hidden`,onClick:t,"aria-label":`Back to roles`,"data-testid":`role-back`,children:(0,Z.jsx)(m,{className:`size-4`,"aria-hidden":`true`})}),(0,Z.jsxs)(`div`,{className:`min-w-0`,children:[(0,Z.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Z.jsx)(`h2`,{className:`truncate font-sans text-xl font-semibold text-foreground`,children:e.name}),e.is_system?(0,Z.jsx)(R,{variant:`outline`,className:`shrink-0 font-sans`,children:`System role`}):null,e.archived_at?(0,Z.jsx)(R,{variant:`secondary`,className:`shrink-0 font-sans`,children:`Archived`}):null]}),e.description?(0,Z.jsx)(`p`,{className:`truncate text-sm text-muted-foreground`,children:e.description}):null]})]})}function mr({isArchived:e,archiveBlocked:t,archivePending:n,restorePending:r,mutationPending:i,onEditRole:a,onConfirmAction:s}){return e?(0,Z.jsx)(`div`,{className:`flex shrink-0 items-center gap-2`,children:(0,Z.jsxs)(L,{variant:`outline`,size:`sm`,className:`gap-1.5`,onClick:()=>s(`restore`),disabled:i,"data-testid":`role-restore`,children:[r?(0,Z.jsx)(M,{"aria-hidden":`true`}):(0,Z.jsx)(f,{className:`size-4`,"aria-hidden":`true`}),(0,Z.jsx)(`span`,{className:`hidden sm:inline`,children:`Restore`})]})}):(0,Z.jsxs)(`div`,{className:`flex shrink-0 items-center gap-2`,children:[(0,Z.jsxs)(L,{variant:`outline`,size:`sm`,className:`gap-1.5`,onClick:a,"data-testid":`role-edit`,children:[(0,Z.jsx)(o,{className:`size-4`,"aria-hidden":`true`}),(0,Z.jsx)(`span`,{className:`hidden sm:inline`,children:`Edit`})]}),(0,Z.jsxs)(L,{variant:`outline`,size:`sm`,className:`gap-1.5`,onClick:()=>s(`archive`),disabled:t||i,"data-testid":`role-archive`,children:[n?(0,Z.jsx)(M,{"aria-hidden":`true`}):(0,Z.jsx)(p,{className:`size-4`,"aria-hidden":`true`}),(0,Z.jsx)(`span`,{className:`hidden sm:inline`,children:`Archive`})]})]})}function hr({role:e,section:t,onSectionChange:n}){return e.archived_at==null?(0,Z.jsxs)(be,{value:t,onValueChange:e=>n(e),children:[(0,Z.jsx)(ve,{className:`w-full justify-start overflow-x-auto`,children:wt.map(e=>(0,Z.jsx)(ye,{value:e,className:`font-sans`,"data-testid":`role-section-${e}`,children:lr[e]},e))}),(0,Z.jsxs)(`div`,{className:`pt-4`,children:[t===`permissions`?(0,Z.jsx)(on,{roleId:e.id},e.id):null,t===`scope`?(0,Z.jsx)(sn,{roleId:e.id}):null,t===`navigation`?(0,Z.jsx)(ir,{role:e},e.id):null,t===`members`?(0,Z.jsx)(sr,{roleName:e.name}):null]})]}):(0,Z.jsxs)(O,{children:[(0,Z.jsx)(p,{className:`size-4`,"aria-hidden":`true`}),(0,Z.jsx)(F,{children:`Archived role`}),(0,Z.jsx)(N,{children:`This role is read-only and does not grant access while archived.`})]})}function gr({action:e,roleName:t,mutationPending:n,onOpenChange:r,onConfirm:i}){return(0,Z.jsx)(lt,{open:e!==null,onOpenChange:r,children:(0,Z.jsxs)(Ve,{children:[(0,Z.jsxs)(He,{children:[(0,Z.jsx)(Ne,{children:e===`restore`?`Restore â${t}â?`:`Archive â${t}â?`}),(0,Z.jsx)(je,{children:e===`restore`?`Restoring makes the role available for access checks and assignments again.`:`Archiv
1ing hides the role from active lists and stops it from granting access.`})]}),(0,Z.jsxs)(at,{children:[(0,Z.jsx)(st,{disabled:n,children:`Cancel`}),(0,Z.jsx)(Ge,{className:e===`archive`?`bg-destructive text-destructive-foreground hover:bg-destructive/90`:void 0,disabled:n,onClick:i,children:e===`restore`?`Restore role`:`Archive role`})]})]})})}function _r(e,t){e===`restore`?t.restore.mutate():e===`archive`&&t.archive.mutate()}var vr=we({name:B().trim().min(1,`Name is required`).max(80,`Name is too long`),description:B().trim().max(280,`Description is too long`).optional()});function yr({open:e,onOpenChange:t,role:n,onSaved:r}){let{toast:i}=z(),a=D(),o=n!==null,s=ze({resolver:Oe(vr),defaultValues:{name:``,description:``}});(0,J.useEffect)(()=>{e&&s.reset({name:n?.name??``,description:n?.description??``})},[e,n,s]);let c=E({mutationFn:async e=>{let t={name:e.name,description:e.description||null};return o&&n?P.patch(`/api/rbac/roles/${n.id}`,t):P.post(`/api/rbac/roles`,t)},onSuccess:async e=>{await a.invalidateQueries({queryKey:[`/api/rbac/roles`]}),i({title:o?`Role updated`:`Role created`,description:`â${e.name}â saved.`}),r(e),t(!1)},onError:e=>{i({title:`Save failed`,description:e.message,variant:`destructive`})}}),l=o&&n?.is_system===!0;return(0,Z.jsx)(Ke,{open:e,onOpenChange:t,children:(0,Z.jsxs)(nt,{className:`max-w-md`,children:[(0,Z.jsxs)(qe,{children:[(0,Z.jsx)(ct,{className:`font-sans`,children:o?`Edit role`:`New role`}),(0,Z.jsx)(Qe,{children:o?`Update this role's name and description.`:`Create a role, then configure its access.`})]}),(0,Z.jsx)(ot,{...s,children:(0,Z.jsxs)(`form`,{onSubmit:s.handleSubmit(e=>c.mutate(e)),className:`space-y-4`,children:[(0,Z.jsx)(q,{control:s.control,name:`name`,render:({field:e})=>
1(0,Z.jsxs)(W,{children:[(0,Z.jsx)(H,{children:`Name`}),(0,Z.jsx)(U,{children:(0,Z.jsx)(j,{...e,disabled:l,placeholder:`e.g. Access Administrator`})}),l?(0,Z.jsx)(Ae,{children:`System role names cannot be changed.`}):null,(0,Z.jsx)(V,{})]})}),(0,Z.jsx)(q,{control:s.control,name:`description`,render:({field:e})=>(0,Z.jsxs)(W,{children:[(0,Z.jsx)(H,{children:`Description`}),(0,Z.jsx)(U,{children:(0,Z.jsx)(ut,{...e,rows:3,placeholder:`What is this role for?`})}),(0,Z.jsx)(V,{})]})}),(0,Z.jsxs)(Je,{children:[(0,Z.jsx)(L,{type:`button`,variant:`ghost`,onClick:()=>t(!1),children:`Cancel`}),(0,Z.jsxs)(L,{type:`submit`,disabled:c.isPending,className:`gap-1.5`,children:[c.isPending?(0,Z.jsx)(M,{"aria-hidden":`true`}):null,o?`Save`:`Create`]})]})]})})]})})}function br(){let e=X(),{roles:t,isLoading:n}=Vt({includeArchived:!0}),{isDesktop:r}=et(),[i,a]=(0,J.useState)(!1),[o,s]=(0,J.useState)(null),[c,l]=(0,J.useState)(!1),u=e.roleId===null?null:t.find(t=>t.id===e.roleId)??null;(0,J.useEffect)(()=>{u?.archived_at&&l(!0)},[u?.archived_at]);let d=()=>{s(null),a(!0)},f=()=>{u&&(s(u),a(!0))},p=(0,Z.jsx)(Ht,{roles:t,isLoading:n,selectedRoleId:e.roleId,showArchived:c,onShowArchivedChange:l,onSelectRole:t=>e.selectRole(t,e.section),onNewRole:d}),m=u?(0,Z.jsx)(ur,{role:u,section:e.section,onSectionChange:e.setSection,onEditRole:f,onBack:()=>e.selectRole(null),onArchiveStateChange:e=>l(e)}):(0,Z.jsx)(xr,{}),h=(0,Z.jsx)(yr,{open:i,onOpenChange:a,role:o,onSaved:t=>e.selectRole(t.id,e.section)});return r?(0,Z.jsxs)(Z.Fragment,{children:[(0,Z.jsxs)(`div`,{className:`flex min-h-0 flex-1 gap-4`,children:[(0,Z.jsx)(`aside`,{className:`flex w-72 shrink-0 flex-col rounded-lg border border-border p-3 xl:w-80`,children:p}),(0,Z.jsx)(`section`,{className:`min-w-0 flex-1 overflow-y-auto rounded-lg border border-border p-4`,children:m})]}),h]}):(0,Z.jsxs)(Z.Fragment,{children:[(0,Z.jsx)(`div`,{className:`flex min-h-0 flex-1 flex-col`,children:u?m:p}),h]})}function xr(){return(0,Z.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col items-center justify-center gap-2 text-center text-muted-foreground`,children:[(0,Z.jsx)(u,{className:`size-8`,"aria-hidden":`true`}),(0,Z.jsx)(`p`,{className:`font-sans text-sm font-medium text-foreground`,children:`Select a role`}),(0,Z.jsx)(`p`,{className:`max-w-xs text-sm`,children:`Pick a role from the list to configure its permissions, scope, navigation, and members.`})]})}function Sr(e,t){let n=Cr(e,t);return{primary:t.role,additional:n,all:[t.role,...n]}}function Cr(e,t){return(e.additionalRoles[t.id]??[]).filter(e=>e!==t.role)}function wr(e,t){return e.find(e=>e.name===t)??null}function Tr(e,t,n){let r=new Map;for(let e of n.all){let n=wr(t,e);n&&r.set(n.id,n.name)}if(r.size===0)return[];let i=[];for(let t of e){let e=n.all.filter(e=>t.roleIds.some(t=>r.get(t)===e));e.length>0&&i.push({key:t.permission.key,description:t.permission.description,category:t.permission.category,viaRoles:e})}return i.sort((e,t)=>e.key.localeCompare(t.key))}function Er(e,t){return e.filter(e=>!e.viaRoles.includes(t.primary))}var Dr={self:`Own account only`,self_and_linked:`Own account and linked accounts`,all:`All accounts`,region:`Accounts in the assigned region`};function Or(e,t,n){let r=wr(t,n);return r?e.find(e=>e.role_id===r.id)??null:null}function kr(e,t){let n=new Set(t.all);return e.filter(e=>!e.archived_at&&!n.has(e.name)).sort((e,t)=>e.name.localeCompare(t.name))}var Ar=`__all__`,jr=200;function Mr({matrix:e,isLoading:t,selectedUserId:n,onSelectUser:r}){let[i,a]=(0,J.useState)(``),[o,s]=(0,J.useState)(Ar),[c,l]=(0,J.useState)(!1),u=(0,J.useMemo)(()=>Pr(e?.users??[],{search:i,roleFilter:o,includeInactive:c}),[e?.users,i,o,c]),d=u.slice(0,jr);return(0,Z.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col gap-3`,children:[(0,Z.jsxs)(`div`,{className:`relative`,children:[(0,Z.jsx)(w,{className:`pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground`}),(0,Z.jsx)(j,{value:i,onChange:e=>a(e.target.value),placeholder:`Search users`,className:`h-10 pl-8`,"aria-label":`Search users`,"data-testid":`rbac-user-search`})]}),(0,Z.jsxs)(We,{value:o,onValueChange:s,children:[(0,Z.jsx)(Ze,{className:`h-10`,"aria-label":`Filter by primary role`,"data-testid":`rbac-user-role-filter`,children:(0,Z.jsx)(it,{})}),(0,Z.jsxs)(tt,{children:[(0,Z.jsx)(G,{value:Ar,children:`All primary roles`}),(e?.roles??[]).map(e=>(0,Z.jsx)(G,{value:e.name,children:e.name},e.id))]})]}),(0,Z.jsxs)(`div`,{className:`flex items-center gap-2 px-1 text-sm text-muted-foreground`,children:[(0,Z.jsx)(ge,{id:`rbac-include-inactive`,checked:c,onCheckedChange:e=>l(e===!0),"aria-label":`Include inactive users`,"data-testid":`rbac-include-inactive`}),(0,Z.jsx)(`label`,{htmlFor:`rbac-include-inactive`,children:`Include inactive`})]}),(0,Z.jsx)(I,{className:`min-h-0 flex-1`,children:(0,Z.jsx)(`ul`,{className:`divi
1de-y divide-border`,children:t?Array.from({length:8}).map((e,t)=>(0,Z.jsx)(`li`,{className:`px-1 py-3`,children:(0,Z.jsx)(A,{className:`h-5 w-full`})},t)):d.length===0?(0,Z.jsx)(`li`,{className:`px-2 py-6 text-center text-sm text-muted-foreground`,children:`No users match these filters.`}):d.map(t=>(0,Z.jsx)(Nr,{user:t,additionalCount:e?Cr(e,t).length:0,isSelected:t.id===n,onSelect:r},t.id))})}),u.length>jr?(0,Z.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Showing the first `,jr,` of `,u.length,`. Refine your search to narrow the list.`]}):null]})}function Nr({user:e,additionalCount:t,isSelected:n,onSelect:r}){return(0,Z.jsx)(`li`,{children:(0,Z.jsxs)(`button`,{type:`button`,onClick:()=>r(e.id),"aria-current":n?`true`:void 0,"data-testid":`rbac-user-item-${e.id}`,className:k(`flex min-h-11 w-full items-center gap-2 rounded-md p-2 text-left transition-colors`,n?`bg-brand-selected text-primary`:`hover:bg-muted/60`),children:[(0,Z.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,Z.jsxs)(`span`,{className:`flex items-center gap-1.5`,children:[(0,Z.jsx)(`span`,{className:`truncate font-sans text-sm font-medium`,children:$(e)}),Ut(e)?null:(0,Z.jsx)(R,{variant:`outline`,className:`h-4 shrink-0 px-1 text-xs font-normal`,children:`inactive`})]}),(0,Z.jsxs)(`span`,{className:`block truncate text-xs text-muted-foreground`,children:[e.role,t>0?` +${t}`:``]})]}),(0,Z.jsx)(l,{className:`size-4 shrink-0 text-muted-foreground`,"aria-hidden":`true`})]})})}function Pr(e,t){let n=t.search.trim().toLowerCase();return e.filter(e=>t.includeInactive||Ut(e)).filter(e=>t.roleFilter===Ar||e.role===t.roleFilter).filter(e=>!n||$(e).toLowerCase().includes(n)||(e.email??``).toLowerCase().includes(n)).sort((e,t)=>$(e).localeCompare($(t)))}var Fr=[{title:`Sidebar and accessible pages`,detail:`Navigation is built from this one role. Additional roles add no menu items.`},{title:`Account scope`,detail:`Which accounts the user can see is resolved from this role alone, by design.`},{title:`Dealer account binding`,detail:`Dealer-scoped requests only resolve an account when this role is dealer.`},{title:`In-app role checks`,detail:`The browser only ever receives this role, so every client-side check reads it.`},{title:`Notifications and rosters`,detail:`Role-targeted notices, the RM roster, quote routing, and impersonation lists key off it.`},{title:`RAIN sync`,detail:`Editing it here pins the role locally; RAIN will report the user but stop overwriting it.`}];function Ir(){let[e,t]=(0,J.useState)(!1);return(0,Z.jsxs)(`div`,{className:`rounded-lg border border-border bg-muted/40 p-3`,children:[(0,Z.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,Z.jsx)(r,{className:`mt-0.5 size-4 shrink-0 text-muted-foreground`,"aria-hidden":`true`}),(0,Z.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Z.jsx)(`p`,{className:`font-sans text-sm font-medium text-foreground`,children:`The primary role decides who this user is in the app`}),(0,Z.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Additional roles only widen permissions. This one drives navigation, account scope, and every role check.`})]}),(0,Z.jsxs)(L,{variant:`ghost`,size:`sm`,className:`h-8 shrink-0 gap-1 text-muted-foreground`,onClick:()=>t(e=>!e),"aria-expanded":e,"data-testid":`primary-role-explainer-toggle`,children:[e?`Less`:`What changes?`,(0,Z.jsx)(y,{className:k(`size-4 transition-transform`,e&&`rotate-180`),"aria-hidden":`true`})]})]}),e?(0,Z.jsx)(`dl`,{className:`mt-3 grid gap-2 border-t border-border pt-3 sm:grid-cols-2`,children:Fr.map(e=>(0,Z.jsxs)(`div`,{children:[(0,Z.jsx)(`dt`,{className:`font-sans text-sm font-medium text-foreground`,children:e.title}),(0,Z.jsx)(`dd`,{className:`text-sm text-muted-foreground`,children:e.detail})]},e.title))}):null]})}var Lr=`__none__`;function Rr({role:e,onRoleChange:t,accountId:n,onAccountChange:r,assignableRoles:i,accounts:a,accountsLoading:o,roleUnavailable:s,savedRole:c}){return(0,Z.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-2`,children:[(0,Z.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Z.jsx)(Xe,{htmlFor:`primary-role-select`,children:`Primary role`}),(0,Z.jsxs)(We,{value:e,onValueChange:t,children:[(0,Z.jsx)(Ze,{id:`primary-role-select`,className:`h-10`,"data-testid":`primary-role-select`,children:(0,Z.jsx)(it,{placeholder:`Select a role`})}),(0,Z.jsxs)(tt,{children:[s?(0,Z.jsxs)(G,{value:c,children:[c,` (unavailable)`]}):null,i.map(e=>(0,Z.jsx)(G,{value:e.name,children:e.name},e.id))]})]})]}),(0,Z.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Z.jsx)(Xe,{htmlFor:`primary-account-select`,children:`Account`}),(0,Z.jsxs)(We,{value:n===null?Lr:String(n),onValueChange:e=>r(e===Lr?null:Number(e)),disabled:o,children:[(0,Z.jsx)(Ze,{id:`primary-account-select`,className:`h-10`,"data-testid":`primary-account-select`,children:(0,Z.jsx)(it,{placeholder:`Select an account`})}),(0,Z.jsxs)(tt,{children:[(0,Z.jsx)(G,{value:Lr,children:`No account`}),a.map(e=>(0,Z.jsxs)(G,{value:String(e.id),children:[e.name,` (`,e.type,`)`]},e.id))]})]})]})]})}function zr({open:e,onOpenChange:t,userLabel:n,previousRole:r,nextRole:i,roleChanged:a,pinsRoleSource:o,pe
1nding:s,onConfirm:c}){return(0,Z.jsx)(lt,{open:e,onOpenChange:t,children:(0,Z.jsxs)(Ve,{children:[(0,Z.jsxs)(He,{children:[(0,Z.jsx)(Ne,{children:a?`Change ${n} from ${r} to ${i}?`:`Update ${n}?`}),(0,Z.jsx)(je,{asChild:!0,children:(0,Z.jsxs)(`div`,{className:`space-y-2 text-sm`,children:[a?(0,Z.jsx)(`p`,{children:`Their sidebar, accessible pages, and account scope all change immediately â they will see a different app on their next page load.`}):(0,Z.jsx)(`p`,{children:`Their account binding changes, which changes the accounts they can see.`}),a&&o?(0,Z.jsx)(`p`,{children:`This also pins the role locally. RAIN reconciliation will report this user but never overwrite the role again.`}):null]})})]}),(0,Z.jsxs)(at,{children:[(0,Z.jsx)(st,{disabled:s,children:`Cancel`}),(0,Z.jsx)(Ge,{disabled:s,onClick:e=>{e.preventDefault(),c()},"data-testid":`primary-role-confirm`,children:s?`Savingâ¦`:`Save changes`})]})]})})}var Br=new Set([`dealer`,`customer`]);function Vr({user:e,roles:t}){let r=Rt(),[i,a]=(0,J.useState)(e.role),[o,s]=(0,J.useState)(e.account_id),[c,l]=(0,J.useState)(!1),u=(0,J.useMemo)(()=>t.filter(e=>!e.archived_at).sort((e,t)=>e.name.localeCompare(t.name)),[t]),d=(0,J.useMemo)(()=>[...r.data??[]].sort((e,t)=>e.name.localeCompare(t.name)),[r.data]),f=i!==e.role,p=o!==e.account_id,m=f||p,h=Br.has(i)&&o===null,g=!u.some(e=>e.name===i),_=Hr({user:e,role:i,accountId:o,roleChanged:f,accountChanged:p,onSettledOpenState:l});return(0,Z.jsxs)(`div`,{className:`space-y-4`,children:[(0,Z.jsx)(Ir,{}),g?(0,Z.jsxs)(O,{variant:`destructive`,children:[(0,Z.jsx)(n,{className:`size-4`,"aria-hidden":`true`}),(0,Z.jsxs)(F,{children:[`Primary role â`,e.role,`â is not an active role`]}),(0,Z.jsx)(N,{children:`It has been archived or removed, so it grants no permissions and no navigation. Pick a live role below.`})]}):null,(0,Z.jsx)(Rr,{role:i,onRoleChange:a,accountId:o,onAccountChange:s,assignableRoles:u,accounts:d,accountsLoading:r.isLoading,roleUnavailable:g,savedRole:e.role}),h?(0,Z.jsxs)(O,{children:[(0,Z.jsx)(n,{className:`size-4`,"aria-hidden":`true`}),(0,Z.jsxs)(F,{children:[`â`,i,`â usually needs an account`]}),(0,Z.jsx)(N,{children:`Without one, this user's account scope resolves to nothing and dealer-scoped screens will come back empty.`})]}):null,(0,Z.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,Z.jsxs)(L,{className:`gap-1.5`,disabled:!m||_.isPending,onClick:()=>l(!0),"data-testid":`primary-role-save`,children:[_.isPending?(0,Z.jsx)(M,{"aria-hidden":`true`}):(0,Z.jsx)(re,{className:`size-4`,"aria-hidden":`true`}),`Save changes`]}),m?(0,Z.jsx)(L,{variant:`ghost`,disabled:_.isPending,onClick:()=>{a(e.role),s(e.account_id)},children:`Reset`}):null]}),(0,Z.jsx)(zr,{open:c,onOpenChange:e=>!e&&l(!1),userLabel:$(e),previousRole:e.role,nextRole:i,roleChanged:f,pinsRoleSource:e.role_source!==`local`,pending:_.isPending,onConfirm:()=>_.mutate()})]})}function Hr({user:e,role:t,accountId:n,roleChanged:r,accountChanged:i,onSettledOpenState:a}){let{toast:o}=z(),s=D();return E({mutationFn:()=>P(`PATCH`,`/api/users/${e.id}`,{...r?{role:t}:{},...i?{accountId:n}:{}}),onSuccess:async()=>{await Promise.all([s.invalidateQueries({queryKey:[`/api/rbac/user-role-matrix`]}),s.invalidateQueries({queryKey:[`/api/users`]})]),a(!1),o({title:r?`Primary role updated`:`Account updated`,description:r?`${$(e)} is now ${t}.`:`Updated the account bound to ${$(e)}.`})},onError:e=>{a(!1),o({title:`Update failed`,description:e.message,variant:`destructive`})}})}function Ur({user:e,roles:t,roleSet:n}){let{toast:r}=z(),i=D(),[a,o]=(0,J.useState)(``),[s,c]=(0,J.useState)(null),l=(0,J.useMemo)(()=>kr(t,n),[t,n]),u=()=>i.invalidateQueries({queryKey:[`/api/rbac/user-role-matrix`]}),d=E({mutationFn:async t=>(c(t),P(`POST`,`/api/rbac/users/${e.id}/roles`,{roleName:t})),onSuccess:async(e,t)=>{await u(),o(``),r({title:`Role granted`,description:`Added ${t} as an additional role.`})},onError:e=>r({title:`Grant failed`,description:e.message,variant:`destructive`}),onSettled:()=>c(null)}),f=E({mutationFn:async t=>(c(t),P(`DELETE`,`/api/rbac/users/${e.id}/roles/${encodeURIComponent(t)}`)),onSuccess:async(e,t)=>
1{await u(),r({title:`Role removed`,description:`Removed ${t}.`})},onError:e=>r({title:`Remove failed`,description:e.message,variant:`destructive`}),onSettled:()=>c(null)}),p=d.isPending||f.isPending;return(0,Z.jsxs)(`div`,{className:`space-y-4`,children:[(0,Z.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[`Additional roles grant `,(0,Z.jsx)(`span`,{className:`font-medium text-foreground`,children:`permissions only`}),`. They do not add sidebar entries and do not widen account scope â both come from the primary role.`]}),(0,Z.jsx)(`ul`,{className:`divide-y divide-border rounded-lg border border-border`,children:n.additional.length===0?(0,Z.jsxs)(`li`,{className:`px-3 py-8 text-center text-sm text-muted-foreground`,children:[`No additional roles. This user's access comes entirely from â`,n.primary,`â.`]}):n.additional.map(e=>(0,Z.jsxs)(`li`,{className:`flex min-h-11 items-center gap-3 px-3 py-2`,children:[(0,Z.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-sans text-sm font-medium text-foreground`,children:e}),(0,Z.jsx)(R,{variant:`outline`,className:`text-xs`,children:`permissions only`}),(0,Z.jsx)(L,{size:`icon`,variant:`ghost`,className:`size-8 text-muted-foreground hover:text-destructive`,disabled:p,onClick:()=>f.mutate(e),"aria-label":`Remove ${e}`,"data-testid":`additional-role-remove-${e}`,children:s===e&&f.isPending?(0,Z.jsx)(M,{"aria-hidden":`true`}):(0,Z.jsx)(oe,{className:`size-4`,"aria-hidden":`true`})})]},e))}),(0,Z.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Z.jsxs)(We,{value:a,onValueChange:o,disabled:l.length===0,children:[(0,Z.jsx)(Ze,{className:`h-10 flex-1`,"aria-label":`Role to grant`,"data-testid":`additional-role-select`,children:(0,Z.jsx)(it,{placeholder:l.length===0?`No roles left to grant`:`Grant another role`})}),(0,Z.jsx)(tt,{children:l.map(e=>(0,Z.jsx)(G,{value:e.name,children:e.name},e.id))})]}),(0,Z.jsxs)(L,{className:`gap-1.5`,disabled:!a||p,onClick:()=>d.mutate(a),"data-testid":`additional-role-add`,children:[s===a&&d.isPending?(0,Z.jsx)(M,{"aria-hidden":`true`}):(0,Z.jsx)(C,{className:`size-4`,"aria-hidden":`true`}),`Grant`]})]})]})}function Wr({roles:e,roleSet:t}){let n=Q(),r=It(),[i,a]=(0,J.useState)(``),o=(0,J.useMemo)(()=>Tr(n.data??[],e,t),[n.data,e,t]),s=(0,J.useMemo)(()=>Er(o,t),[o,t]),c=(0,J.useMemo)(()=>Or(r.data??[],e,t.primary),[r.data,e,t.primary]),l=(0,J.useMemo)(()=>{let e=i.trim().toLowerCase();return e?o.filter(t=>t.key.toLowerCase().includes(e)||(t.category??``).toLowerCase().includes(e)):o},[o,i]);return(0,Z.jsxs)(`div`,{className:`space-y-5`,children:[(0,Z.jsxs)(`section`,{className:`space-y-2`,children:[(0,Z.jsx)(`h3`,{className:`font-sans text-sm font-medium text-foreground`,children:`Account scope`}),r.isLoading?(0,Z.jsx)(A,{className:`h-5 w-56`}):(0,Z.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[c?Dr[c.scope_strategy]:`No scope configured for â${t.primary}â.`,` `,(0,Z.jsx)(`span`,{className:`text-xs`,children:`Resolved from the primary role only â additional roles never widen scope.`})]})]}),(0,Z.jsxs)(`section`,{className:`space-y-3`,children:[(0,Z.jsxs)(`div`,{className:`flex flex-wrap items-baseline justify-between gap-2`,children:[(0,Z.jsx)(`h3`,{className:`font-sans text-sm font-medium text-foreground`,children:`Granted permissions`}),(0,Z.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[(0,Z.jsx)(`span`,{className:`font-mono text-foreground tabular-nums`,children:o.length}),` key`,o.length===1?``:`s`,` across `,t.all.length,` role`,t.all.length===1?``:`s`,s.length>0?`, ${s.length} from additional roles only`:``]})]}),(0,Z.jsxs)(`div`,{className:`relative`,children:[(0,Z.jsx)(w,{className:`pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground`}),(0,Z.jsx)(j,{value:i,onChange:e=>a(e.target.value),placeholder:`Search permissions`,className:`h-10 pl-8`,"aria-label":`Search permissions`,"data-testid":`user-permission-search`})]}),n.isLoading?(0,Z.jsx)(`div`,{className:`space-y-2`,children:Array.from({length:5}).map((e,t)=>(0,Z.jsx)(A,{className:`h-11 w-full`},t))}
1):(0,Z.jsx)(`ul`,{className:`divide-y divide-border rounded-lg border border-border`,children:l.length===0?(0,Z.jsx)(`li`,{className:`px-3 py-8 text-center text-sm text-muted-foreground`,children:o.length===0?`These roles grant no permissions.`:`No permissions match â${i}â.`}):l.map(e=>(0,Z.jsxs)(`li`,{className:`flex min-h-11 items-center gap-3 px-3 py-2`,children:[(0,Z.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,Z.jsx)(`p`,{className:`truncate font-mono text-sm text-foreground`,children:e.key}),e.description?(0,Z.jsx)(`p`,{className:`truncate text-xs text-muted-foreground`,children:e.description}):null]}),(0,Z.jsx)(`div`,{className:`flex shrink-0 flex-wrap justify-end gap-1`,children:e.viaRoles.map(e=>(0,Z.jsx)(R,{variant:e===t.primary?`secondary`:`outline`,className:`text-xs`,children:e},e))})]},e.key))}),(0,Z.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`These are the keys the user's roles grant. Wildcard grants (`,(0,Z.jsx)(`code`,{children:`resource.*`}),`,`,` `,(0,Z.jsx)(`code`,{children:`*.*`}),`) are expanded when a permission is checked, so a role holding one passes checks that are not listed individually here.`]})]})]})}var Gr=[`primary`,`additional`,`access`],Kr={primary:`Primary role`,additional:`Additional roles`,access:`Resulting access`};function qr({user:e,matrix:t,onBack:n}){let[r,i]=(0,J.useState)(`primary`),a=(0,J.useMemo)(()=>Sr(t,e),[t,e]);return(0,Z.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,Z.jsx)(Jr,{user:e,additionalCount:a.additional.length,onBack:n}),(0,Z.jsxs)(be,{value:r,onValueChange:e=>i(e),children:[(0,Z.jsx)(ve,{className:`w-full justify-start overflow-x-auto`,children:Gr.map(e=>(0,Z.jsx)(ye,{value:e,className:`font-sans`,"data-testid":`user-section-${e}`,children:Kr[e]},e))}),(0,Z.jsxs)(`div`,{className:`pt-4`,children:[r===`primary`?(0,Z.jsx)(Vr,{user:e,roles:t.roles}):null,r===`additional`?(0,Z.jsx)(Ur,{user:e,roles:t.roles,roleSet:a}):null,r===`access`?(0,Z.jsx)(Wr,{roles:t.roles,roleSet:a}):null]})]})]})}function Jr({user:e,additionalCount:t,onBack:n}){return(0,Z.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2`,children:[(0,Z.jsx)(L,{variant:`ghost`,size:`icon`,className:`size-9 shrink-0 lg:hidden`,onClick:n,"aria-label":`Back to users`,"data-testid":`user-back`,children:(0,Z.jsx)(m,{className:`size-4`,"aria-hidden":`true`})}),(0,Z.jsxs)(`div`,{className:`min-w-0`,children:[(0,Z.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,Z.jsx)(`h2`,{className:`truncate font-sans text-xl font-semibold text-foreground`,children:$(e)}),(0,Z.jsx)(R,{variant:`secondary`,className:`shrink-0 font-sans`,children:e.role}),t>0?(0,Z.jsxs)(R,{variant:`outline`,className:`shrink-0 font-sans`,children:[`+`,t,` additional`]}):null,Ut(e)?null:(0,Z.jsx)(R,{variant:`outline`,className:`shrink-0 font-sans`,children:`inactive`}),(0,Z.jsx)(R,{variant:`outline`,className:`shrink-0 font-sans`,title:e.role_source===`local`?`Pinned by an operator â RAIN reconciliation will not overwrite this role.`:`Follows RAIN reconciliation. Editing the role here pins it locally.`,children:e.role_source===`local`?`role pinned locally`:`role synced from RAIN`})]}),e.email?(0,Z.jsx)(`p`,{className:`truncate text-sm text-muted-foreground`,children:e.email}):null]})]})}function Yr(){let e=X(),t=Lt(),{isDesktop:n}=et(),r=t.data??null,i=(0,J.useMemo)(()=>r&&e.userId!==null?r.users.find(t=>t.id===e.userId)??null:null,[r,e.userId]),a=(0,Z.jsx)(Mr,{matrix:r,isLoading:t.isLoading,selectedUserId:e.userId,onSelectUser:t=>e.selectUser(t)}),o=r&&i?(0,Z.jsx)(qr,{user:i,matrix:r,onBack:()=>e.selectUser(null)},i.id):(0,Z.jsx)(Xr,{notFound:e.userId!==null&&r!==null});return n?(0,Z.jsxs)(`div`,{className:`flex min-h-0 flex-1 gap-4`,children:[(0,Z.jsx)(`aside`,{className:`flex w-72 shrink-0 flex-col rounded-lg border border-border p-3 xl:w-80`,children:a}),(0,Z.jsx)(`section`,{className:`min-w-0 flex-1 overflow-y-auto rounded-lg border border-border p-4`,children:o})]}):(0,Z.jsx)(`div`,{className:`flex min-h-0 flex-1 flex-col`,children:i?o:a})}function Xr({notFound:e}){return(0,Z.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col items-center justify-center gap-2 text-center text-muted-foreground`,children:[(0,Z.jsx)(x,{className:`size-8`,"aria-hidden":`true`}),(0,Z.jsx)(`p`,{className:`font-sans text-sm font-medium text-foreground`,children:e?`User not found`:`Select a user`}),(0,Z.jsx)(`p`,{className:`max-w-xs text-sm`,children:e?`That user no longer exists. Pick another from the list.`:`Pick a user to review and change their primary role, additional roles, and the access those grant.`})]})}var Zr={pages:{label:`Pages`,Icon:se},permissions:{label:`Permissions`,Icon:h}};function Qr({entity:e,onEntityChange:t,counts:n}){return(0,Z.jsx)(Fe,{type:`single`,value:e,onValueChange:e=>{e&&t(e)},variant:`outline`,className:`w-full justify-start rounded-lg bg-muted/50 p-1 sm:w-auto`,"aria-label":`Catalog entity`,children:Tt.map(e=>{let{label:t,Icon:r}=Zr[e],i=n?.[e];return(0,Z.jsxs)(Le,{value:e,"aria-label":t,className:`h-11 gap-2 border-0 px-4 font-sans data-[state=on]:bg-background data-[state=on]:text-primary data-[state=on]:shadow-xs`,"data-testid":`catalog-entity-${e}`,children:[(0,Z.jsx)(r,{className:`size-4`,"aria-hidden":`true`}),(0,Z.jsx)(`span`,{children:t}),typeof i==`number`?(0,Z.jsx)(`span`,{className:`font-mono text-xs tabular-nums text-muted-foreground`,children:i}):null]},e)})})}function $r({pages:e,isLoading:t,isReferenceLoading:n,isReferenceError:r,navigationReferenceCounts:i,selectedId:a,onSelect:o,onAdd:s}){let[c,l]=(0,J.useState)(``),[u,d]=(0,J.useState)(!1),f=(0,J.useMemo)(()=>e.filter(e=>(i.get(e.id)??0)===0).length,[i,e]),p=(0,J.useMemo)(()=>{let t=c.trim().toLowerCase(),a=u&&!n&&!r;return[...e].sort((e,t)=>
1e.order_index-t.order_index||e.name.localeCompare(t.name)).filter(e=>{let n=!t||e.name.toLowerCase().includes(t)||e.path.toLowerCase().includes(t)||(e.category??``).toLowerCase().includes(t),r=!a||(i.get(e.id)??0)===0;return n&&r})},[r,n,i,u,e,c]);return(0,Z.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col gap-3`,children:[(0,Z.jsx)(ei,{value:c,onChange:l}),(0,Z.jsx)(ti,{count:f,enabled:!n&&!r,pressed:u,onToggle:()=>d(e=>!e)}),(0,Z.jsx)(I,{className:`min-h-0 flex-1`,children:(0,Z.jsx)(ni,{pages:p,isLoading:t,canShowReferences:!n&&!r,navigationReferenceCounts:i,selectedId:a,onSelect:o})}),(0,Z.jsxs)(L,{variant:`outline`,className:`w-full gap-2`,onClick:s,"data-testid":`catalog-page-add`,children:[(0,Z.jsx)(C,{className:`size-4`,"aria-hidden":`true`}),`Add page`]})]})}function ei({value:e,onChange:t}){return(0,Z.jsxs)(`div`,{className:`relative`,children:[(0,Z.jsx)(w,{className:`pointer-events-none absolute left-2.5 top-1/2 size-4 -translate-y-1/2 text-muted-foreground`}),(0,Z.jsx)(j,{value:e,onChange:e=>t(e.target.value),placeholder:`Search pages`,className:`h-10 pl-8`,"aria-label":`Search pages`,"data-testid":`catalog-page-search`})]})}function ti({count:e,enabled:t,pressed:n,onToggle:r}){return(0,Z.jsxs)(L,{type:`button`,variant:n?`secondary`:`outline`,size:`sm`,className:`w-full justify-between gap-2`,disabled:!t,"aria-pressed":n,onClick:r,"data-testid":`catalog-page-unreferenced-filter`,children:[(0,Z.jsx)(`span`,{children:`Only unreferenced`}),t?(0,Z.jsx)(R,{variant:`outline`,className:`font-mono tabular-nums`,children:e}):null]})}function ni({pages:e,isLoading:t,canShowReferences:n,navigationReferenceCounts:r,selectedId:i,onSelect:a}){return t?(0,Z.jsx)(ri,{}):e.length===0?(0,Z.jsx)(`ul`,{className:`divide-y divide-border`,children:(0,Z.jsx)(`li`,{className:`px-2 py-6 text-center text-sm text-muted-foreground`,children:`No pages match your filters.`})}):(0,Z.jsx)(`ul`,{className:`divide-y divide-border`,children:e.map(e=>(0,Z.jsx)(ii,{page:e,isSelected:e.id===i,isUnreferenced:n&&(r.get(e.id)??0)===0,onSelect:a},e.id))})}function ri(){return(0,Z.jsx)(`ul`,{className:`divide-y divide-border`,children:Array.from({length:6}).map((e,t)=>(0,Z.jsx)(`li`,{className:`px-1 py-3`,children:(0,Z.jsx)(A,{className:`h-6 w-full`})},t))})}function ii({page:e,isSelected:t,isUnreferenced:n,onSelect:r}){return(0,Z.jsx)(`li`,{children:(0,Z.jsxs)(`button`,{type:`button`,onClick:()=>r(e.id),"aria-current":t?`true`:void 0,"data-testid":`catalog-page-item-${e.id}`,className:k(`flex min-h-11 w-full items-center gap-2 rounded-md p-2 text-left transition-colors`,t?`bg-brand-selected text-primary`:`hover:bg-muted/60`),children:[(0,Z.jsx)(`span`,{className:`shrink-0 text-muted-foreground`,children:K(e.icon,16)}),(0,Z.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,Z.jsx)(`span`,{className:`truncate font-sans text-sm font-medium`,children:e.name}),(0,Z.jsx)(`span`,{className:`block truncate font-mono text-xs text-muted-foreground`,children:e.path})]}),(0,Z.jsx)(ai,{page:e,isUnreferenced:n})]})})}function ai({page:e,isUnreferenced:t}){return(0,Z.jsxs)(`span`,{className:`flex shrink-0 items-center gap-1`,children:[t?(0,Z.jsx)(R,{variant:`secondary`,className:`text-xs`,children:`unreferenced`}):null,e.is_in_development?(0,Z.jsxs)(R,{variant:`outline`,className:`gap-1 border-destructive/40 text-xs text-destructive`,children:[(0,Z.jsx)(i,{className:`size-3`,"aria-hidden":`true`}),`dev`]}):null]})}var oi=B().trim().email();function si(e){return oi.safeParse(e).success}function ci(e){return e.is_in_development&&(e.dev_user_emails?.length??0)===0?`In development but no dev emails set â no one can preview this page.`:null}function li(e,t){let n=new Map(t.map(e=>[e.id,e.name]));return e.map(e=>n.get(e)).filter(e=>!!e).sort((e,t)=>e.localeCompare(t))}function ui(e){let t=new Map;for(let n of e){let e=n.permission.category??`Uncategorized`,r=t.get(e)??[];r.push(n),t.set(e,r)}return Array.from(t.entries()).map(([e,t])=>({category:e,entries:[...t].sort((e,t)=>e.permission.key.localeCompare(t.permission.key))})).sort((e,t)=>e.category.localeCompare(t.category))}var di=B().trim().transform(e=>e===``?null:e).nullable(),fi=we({path:B().trim().min(1,`Path is required`).regex(/^\//,`Path must start with /`),name:B().trim().min(1,`Name is required`),description:di,icon:B().trim().nullable(),category:di,order_index:De().int(`Order must be a whole number`).min(0,`Order must be ⥠0`),is_in_development:Ee(),dev_user_emails:Te(oi)}),pi={path:`/`,name:``,description:null,icon:null,category:null,order_index:0,is_in_development:!1,dev_user_emails:[]};function mi(e){return e?{path:e.path,name:e.name,description:e.description,icon:e.icon,category:e.category,order_index:e.order_index,is_in_development:e.is_in_development,dev_user_emails:e.dev_user_emails??[]}:{...pi}}function hi(e,t){let n=new Map(t.map(e=>[e.id,e.name])),r=new Map;for(let t of e){let e=yi(t.roleIds,n);for(let n of[...t.groups].sort((e,t)=>
1e.order_index-t.order_index))n.pageIds.forEach((i,a)=>{xi(r,i,t,e,{type:`group`,groupId:n.id,groupName:n.name,orderIndex:a})});bi(t).forEach(n=>{xi(r,n.pageId,t,e,{type:`ungrouped`,orderIndex:n.orderIndex})})}for(let e of r.values())e.sort((e,t)=>e.layoutName.localeCompare(t.layoutName));return r}function gi(e,t){let n=new Map;if(!t)return n;for(let r of t.roles){let i=t.permissions[Ci(e,r.id)];n.set(r.id,{showInNav:!!i?.show_in_nav})}return n}function _i(e){let t=new Set;for(let n of e)n.roleNames.forEach(e=>t.add(e));return Array.from(t).sort((e,t)=>e.localeCompare(t))}function vi(e){return e.type===`group`?`Group: ${e.groupName}`:`Ungrouped`}function yi(e,t){return e.map(e=>({id:e,name:t.get(e)??`Role #${e}`})).sort((e,t)=>e.name.localeCompare(t.name))}function bi(e){return e.ungroupedPages.length>0?[...e.ungroupedPages].sort((e,t)=>e.order_index-t.order_index).map(e=>({pageId:e.pageId,orderIndex:e.order_index})):e.ungroupedPageIds.map((e,t)=>({pageId:e,orderIndex:t}))}function xi(e,t,n,r,i){let a=e.get(t)??[],o=a.find(e=>e.layoutId===n.id);o||(o={layoutId:n.id,layoutName:n.name,roles:r,roleNames:r.map(e=>e.name),placements:[]},a.push(o),e.set(t,a)),o.placements.some(e=>Si(e)===Si(i))||o.placements.push(i)}function Si(e){return e.type===`group`?`group:${e.groupId}:${e.orderIndex}`:`ungrouped:${e.orderIndex}`}function Ci(e,t){return`${e}-${t}`}function wi({page:e,isDeleting:t,navigationReferences:n,isNavigationLoading:r,isNavigationError:i,navigationStateByRoleId:a,isVisibilityLoading:o,isVisibilityError:s,onEdit:c,onDelete:l,onSelectRoleNavigation:u,onBack:d}){let f=!r&&!i&&n.length===0;return(0,Z.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col gap-4`,children:[d?(0,Z.jsxs)(L,{variant:`ghost`,size:`sm`,className:`w-fit gap-1 px-2`,onClick:d,"data-testid":`catalog-page-back`,children:[(0,Z.jsx)(le,{className:`size-4`,"aria-hidden":`true`}),`Back`]}):null,(0,Z.jsx)(Ti,{page:e,isDeleting:t,onEdit:c,onDelete:l}),(0,Z.jsx)(Ei,{page:e}),(0,Z.jsx)(Oi,{description:e.description}),f?(0,Z.jsx)(ki,{}):null,(0,Z.jsx)(Ni,{references:n,isLoading:r,isError:i,navigationStateByRoleId:a,showRoleVisibility:!o&&!s,onSelectRoleNavigation:u}),e.is_in_development?(0,Z.jsx)(Ai,{page:e}):null]})}function Ti({page:e,isDeleting:t,onEdit:n,onDelete:r}){return(0,Z.jsxs)(`div`,{className:`flex items-start justify-between gap-3`,children:[(0,Z.jsxs)(`div`,{className:`flex min-w-0 items-start gap-3`,children:[(0,Z.jsx)(`span`,{className:`mt-0.5 text-muted-foreground`,children:K(e.icon,24)}),(0,Z.jsxs)(`div`,{className:`min-w-0`,children:[(0,Z.jsx)(`h2`,{className:`truncate font-sans text-lg font-semibold text-foreground`,children:e.name}),(0,Z.jsx)(`p`,{className:`truncate font-mono text-sm text-muted-foreground`,children:e.path})]})]}),(0,Z.jsxs)(`div`,{className:`flex shrink-0 items-center gap-2`,children:[(0,Z.jsxs)(L,{variant:`outline`,size:`sm`,className:`gap-1`,onClick:n,"data-testid":`catalog-page-edit`,children:[(0,Z.jsx)(o,{className:`size-4`,"aria-hidden":`true`}),`Edit`]}),(0,Z.jsxs)(L,{variant:`outline`,size:`sm`,className:`gap-1 text-destructive`,onClick:r,disabled:t,"data-testid":`catalog-page-delete`,children:[(0,Z.jsx)(ae,{className:`size-4`,"aria-hidden":`true`}),`Delete`]})]})]})}function Ei({page:e}){return(0,Z.jsxs)(`dl`,{className:`grid grid-cols-2 gap-3 text-sm sm:grid-cols-3`,children:[(0,Z.jsx)(Fi,{label:`Category`,value:e.category??`â`}),(0,Z.jsx)(Fi,{label:`Order`,value:(0,Z.jsx)(`span`,{className:`font-mono tabular-nums`,children:e.order_index})}),(0,Z.jsx)(Fi,{label:`Status`,value:(0,Z.jsx)(Di,{isInDevelopment:e.is_in_development})})]})}function Di({isInDevelopment:e}){return e?(0,Z.jsxs)(R,{variant:`outline`,className:`gap-1 border-destructive/40 text-destructive`,children:[(0,Z.jsx)(i,{className:`size-3`,"aria-hidden":`true`}),`In development`]}):(0,Z.jsxs)(R,{variant:`outline`,className:`gap-1 text-muted-foreground`,children:[(0,Z.jsx)(v,{className:`size-3`,"aria-hidden":`true`}),`Live`]})}function Oi({description:e}){return e?(0,Z.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:e}):(0,Z.jsx)(`p`,{className:`text-sm text-muted-foreground italic`,children:`No description.`})}function ki(){return(0,Z.jsxs)(O,{"data-testid":`catalog-page-unreferenced-warning`,children:[(0,Z.jsx)(n,{className:`size-4`,"aria-hidden":`true`}),(0,Z.jsx)(F,{children:`Not in navigation`}),(0,Z.jsx)(N,{children:`No navigation layout explicitly places this page. Roles may
1still see it as an ungrouped item when they have navigation visibility on. Add it to a role navigation to choose its placement.`})]})}function Ai({page:e}){let t=ci(e),n=e.dev_user_emails??[];return(0,Z.jsxs)(`section`,{className:`rounded-lg border border-destructive/40 bg-destructive/5 p-3`,children:[(0,Z.jsxs)(`h3`,{className:`flex items-center gap-1.5 font-sans text-sm font-medium text-foreground`,children:[(0,Z.jsx)(i,{className:`size-4 text-destructive`,"aria-hidden":`true`}),`Dev preview`]}),t?(0,Z.jsx)(ji,{warning:t}):(0,Z.jsx)(Mi,{emails:n})]})}function ji({warning:e}){return(0,Z.jsxs)(`p`,{className:`mt-2 flex items-start gap-1.5 text-sm text-destructive`,children:[(0,Z.jsx)(n,{className:`mt-0.5 size-4 shrink-0`,"aria-hidden":`true`}),e]})}function Mi({emails:e}){return(0,Z.jsxs)(Z.Fragment,{children:[(0,Z.jsx)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:`Only these emails can see this page:`}),(0,Z.jsx)(`ul`,{className:`mt-2 flex flex-wrap gap-1.5`,children:e.map(e=>(0,Z.jsx)(`li`,{children:(0,Z.jsx)(R,{variant:`secondary`,className:`font-mono text-xs`,children:e})},e))})]})}function Ni({references:e,isLoading:t,isError:n,navigationStateByRoleId:r,showRoleVisibility:i,onSelectRoleNavigation:a}){return(0,Z.jsxs)(`section`,{className:`rounded-lg border border-border p-3`,children:[(0,Z.jsxs)(`h3`,{className:`flex items-center gap-1.5 font-sans text-sm font-medium text-foreground`,children:[(0,Z.jsx)(ie,{className:`size-4 text-muted-foreground`,"aria-hidden":`true`}),`Navigation references`]}),t?(0,Z.jsx)(`p`,{className:`mt-2 text-sm text-muted-foreground`,children:(0,Z.jsx)(M,{label:`Loading navigation references...`})}):null,n?(0,Z.jsx)(`p`,{className:`mt-2 text-sm text-destructive`,children:`Couldn't load navigation references.`}):null,!t&&!n&&e.length===0?(0,Z.jsx)(`p`,{className:`mt-2 text-sm text-muted-foreground`,children:`No grouped or ungrouped navigation placement.`}):null,!t&&!n&&e.length>0?(0,Z.jsx)(`ul`,{className:`mt-3 flex flex-col gap-3`,children:e.map(e=>(0,Z.jsxs)(`li`,{className:`rounded-md bg-muted/40 p-3`,children:[(0,Z.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,Z.jsx)(`p`,{className:`font-sans text-sm font-medium text-foreground`,children:e.layoutName}),(0,Z.jsxs)(R,{variant:`outline`,className:`font-mono text-xs tabular-nums`,children:[e.roles.length,` `,e.roles.length===1?`role`:`roles`]})]}),(0,Z.jsx)(Pi,{roles:e.roles,navigationStateByRoleId:r,showRoleVisibility:i,onSelectRoleNavigation:a}),(0,Z.jsx)(`div`,{className:`mt-2 flex flex-wrap gap-1.5`,children:e.placements.map((t,n)=>(0,Z.jsx)(R,{variant:`secondary`,className:`text-xs`,children:vi(t)},`${e.layoutId}-${n}`))})]},e.layoutId))}):null]})}function Pi({roles:e,navigationStateByRoleId:t,showRoleVisibility:n,onSelectRoleNavigation:r}){return e.length===0?(0,Z.jsx)(`p`,{className:`mt-2 text-sm text-muted-foreground`,children:`No roles assigned.`}):(0,Z.jsx)(`ul`,{className:`mt-2 flex flex-wrap gap-1.5`,children:e.map(e=>{let i=t.get(e.id),a=n&&i!==void 0&&!i.showInNav;return(0,Z.jsx)(`li`,{children:(0,Z.jsxs)(L,{type:`button`,variant:`outline`,size:`sm`,className:`h-7 gap-1.5 px-2 text-xs`,onClick:()=>r(e.id),"data-testid":`catalog-page-nav-role-${e.id}`,children:[e.name,a?(0,Z.jsx)(`span`,{className:`rounded-sm bg-muted px-1 label-mono font-mono text-xs text-muted-foreground`,children:`hidden`}):null]})},e.id)})})}function Fi({label:e,value:t}){return(0,Z.jsxs)(`div`,{children:[(0,Z.jsx)(`dt`,{className:`label-mono text-xs text-muted-foreground`,children:e}),(0,Z.jsx)(`dd`,{className:`mt-0.5 text-foreground`,children:t})]})}var Ii=120;function Li({value:e,onChange:t,onClear:n,maxIcons:r=Ii}){let[i,a]=(0,J.useState)(``),[o,s]=(0,J.useState)(null);(0,J.useEffect)(()=>{let e=!0;return Ye().then(t=>{e&&s(t)},()=>{}),()=>{e=!1}},[]);let c=(0,J.useMemo)(()=>o?.names??Object.keys($e),[o]),l=(0,J.useMemo)(()=>{let t=i.trim().toLowerCase(),n=t?c.filter(e=>e.toLowerCase().includes(t)):c,a=n.slice(0,r);return e&&!a.includes(e)&&n.includes(e)&&a.unshift(e),a},[c,i,r,e]);return(0,Z.jsxs)(`div`,{className:`space-y-2`,children:[(0,Z.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Z.jsxs)(`div`,{className:`relative flex-1`,children:[(0,Z.jsx)(w,{className:`pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground`}),(0,Z.jsx)(j,{value:i,onChange:e=>a(e.target.value),placeholder:`Search icons`,className:`h-10 pl-8`,"aria-label":`Search icons`,"data-testid":`inline-icon-search`})]}),e&&n?(0,Z.jsxs)(L,{type:`button`,variant:`outline`,size:`sm`,className:`h-10 gap-1`,onClick:n,"data-testid":`inline-icon-clear`,children:[(0,Z.jsx)(oe,{className:`size-4`,"aria-hidden":`true`}),`Clear`]}):null]}),(0,Z.jsx)(I,{className:`h-40 rounded-md border border-border`,children:(0,Z.jsxs)(`div`,{className:`grid grid-cols-8 gap-1 p-2`,children:[l.map(n=>{let r=n===e;return(0,Z.jsx)(`button`,{type:`button`,title:n,"aria-label":n,"aria-pressed":r,onClick:()=>t(n),"data-testid":`inline-icon-${n}`,className:k(`flex size-9 items-center justify-center rounded-md text-foreground transition-colors`,r?`bg-brand-selected text-primary`:`hover:bg-muted/60`),children:K(n,18)},n)}),l.length===0?(0,Z.jsxs)(`p`,{className:`col-span-8 py-6 text-center text-sm text-muted-foreground`,children:[`No icons match â`,i,`â.`]}):null]})})]})}
1function Ri({value:e,onChange:t}){let[n,r]=(0,J.useState)(``),[i,a]=(0,J.useState)(null),o=()=>{let i=n.trim();if(i){if(!si(i)){a(`â${i}â is not a valid email.`);return}if(e.some(e=>e.toLowerCase()===i.toLowerCase())){r(``),a(null);return}t([...e,i]),r(``),a(null)}},s=n=>{t(e.filter(e=>e!==n))};return(0,Z.jsxs)(`div`,{className:`space-y-2`,children:[(0,Z.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Z.jsx)(j,{value:n,onChange:e=>{r(e.target.value),a(null)},onKeyDown:e=>{(e.key===`Enter`||e.key===`,`)&&(e.preventDefault(),o())},type:`email`,inputMode:`email`,placeholder:`[email protected]`,"aria-label":`Add dev-preview email`,"data-testid":`dev-email-input`}),(0,Z.jsxs)(L,{type:`button`,variant:`outline`,size:`sm`,className:`h-10 shrink-0 gap-1`,onClick:o,"data-testid":`dev-email-add`,children:[(0,Z.jsx)(C,{className:`size-4`,"aria-hidden":`true`}),`Add`]})]}),i?(0,Z.jsx)(`p`,{className:`text-xs text-destructive`,children:i}):null,e.length>0?(0,Z.jsx)(`ul`,{className:`flex flex-wrap gap-1.5`,children:e.map(e=>(0,Z.jsx)(`li`,{children:(0,Z.jsxs)(R,{variant:`secondary`,className:`gap-1 font-mono text-xs`,children:[e,(0,Z.jsx)(`button`,{type:`button`,onClick:()=>s(e),"aria-label":`Remove ${e}`,"data-testid":`dev-email-remove-${e}`,className:`rounded-sm hover:text-destructive`,children:(0,Z.jsx)(oe,{className:`size-3`,"aria-hidden":`true`})})]})},e))}):(0,Z.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`No dev emails â only these addresses can preview an in-development page.`})]})}function zi({open:e,onOpenChange:t,page:n,isSaving:r,onSubmit:i}){let a=n!==null,o=ze({resolver:Oe(fi),defaultValues:mi(n)});return(0,J.useEffect)(()=>{e&&o.reset(mi(n))},[e,n,o]),(0,Z.jsx)(Ke,{open:e,onOpenChange:t,children:(0,Z.jsxs)(nt,{className:`sm:max-w-lg`,children:[(0,Z.jsxs)(qe,{children:[(0,Z.jsx)(ct,{className:`font-sans`,children:a?`Edit page`:`Add page`}),(0,Z.jsx)(Qe,{children:a?`Update this page's registry metadata and dev-preview access.`:`Register a page so roles can grant navigation access to it.`})]}),(0,Z.jsx)(ot,{...o,children:(0,Z.jsxs)(`form`,{onSubmit:o.handleSubmit(i),className:`space-y-4`,children:[(0,Z.jsx)(Bi,{form:o}),(0,Z.jsxs)(Je,{children:[(0,Z.jsx)(L,{type:`button`,variant:`outline`,onClick:()=>t(!1),children:`Cancel`}),(0,Z.jsxs)(L,{type:`submit`,disabled:r,"data-testid":`page-editor-save`,children:[r?(0,Z.jsx)(M,{className:`mr-2`,"aria-hidden":`true`}):null,a?`Save`:`Create`]})]})]})})]})})}function Bi({form:e}){return(0,Z.jsxs)(Z.Fragment,{children:[(0,Z.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-2`,children:[(0,Z.jsx)(q,{control:e.control,name:`path`,render:({field:e})=>(0,Z.jsxs)(W,{children:[(0,Z.jsx)(H,{children:`Path`}),(0,Z.jsx)(U,{children:(0,Z.jsx)(j,{placeholder:`/admin/example`,...e,"data-testid":`page-field-path`})}),(0,Z.jsx)(V,{})]})}),(0,Z.jsx)(q,{control:e.control,name:`name`,render:({field:e})=>
1(0,Z.jsxs)(W,{children:[(0,Z.jsx)(H,{children:`Name`}),(0,Z.jsx)(U,{children:(0,Z.jsx)(j,{placeholder:`Example page`,...e,"data-testid":`page-field-name`})}),(0,Z.jsx)(V,{})]})}),(0,Z.jsx)(q,{control:e.control,name:`category`,render:({field:e})=>(0,Z.jsxs)(W,{children:[(0,Z.jsx)(H,{children:`Category`}),(0,Z.jsx)(U,{children:(0,Z.jsx)(j,{placeholder:`e.g. CRM`,...e,value:e.value??``,"data-testid":`page-field-category`})}),(0,Z.jsx)(V,{})]})}),(0,Z.jsx)(q,{control:e.control,name:`order_index`,render:({field:e})=>(0,Z.jsxs)(W,{children:[(0,Z.jsx)(H,{children:`Order`}),(0,Z.jsx)(U,{children:(0,Z.jsx)(j,{type:`number`,min:0,...e,"data-testid":`page-field-order`})}),(0,Z.jsx)(V,{})]})})]}),(0,Z.jsx)(q,{control:e.control,name:`description`,render:({field:e})=>(0,Z.jsxs)(W,{children:[(0,Z.jsx)(H,{children:`Description`}),(0,Z.jsx)(U,{children:(0,Z.jsx)(ut,{placeholder:`What is this page for?`,...e,value:e.value??``,"data-testid":`page-field-description`})}),(0,Z.jsx)(V,{})]})}),(0,Z.jsx)(q,{control:e.control,name:`icon`,render:({field:e})=>(0,Z.jsxs)(W,{children:[(0,Z.jsx)(H,{children:`Icon`}),(0,Z.jsx)(U,{children:(0,Z.jsx)(Li,{value:e.value,onChange:e.onChange,onClear:()=>e.onChange(null)})}),(0,Z.jsx)(V,{})]})}),(0,Z.jsx)(q,{control:e.control,name:`is_in_development`,render:({field:e})=>(0,Z.jsxs)(W,{className:`flex items-center justify-between rounded-lg border border-border p-3`,children:[(0,Z.jsxs)(`div`,{className:`space-y-0.5`,children:[(0,Z.jsx)(H,{children:`In development`}),(0,Z.jsx)(Ae,{children:`Hidden from everyone except the dev-preview emails below.`})]}),(0,Z.jsx)(U,{children:(0,Z.jsx)(_e,{checked:e.value,onCheckedChange:e.onChange,"data-testid":`page-field-dev`})})]})}),(0,Z.jsx)(q,{control:e.control,name:`dev_user_emails`,render:({field:e})=>(0,Z.jsxs)(W,{children:[(0,Z.jsx)(H,{children:`Dev-preview emails`}),(0,Z.jsx)(U,{children:(0,Z.jsx)(Ri,{value:e.value,onChange:e.onChange})}),(0,Z.jsx)(V,{})]})})]})}var Vi=[`/api/rbac/pages`],Hi=[`/api/rbac/permission-matrix`,{view:`visibility`}];function Ui(){let{toast:e}=z(),t=D(),{isDesktop:n}=et(),r=X(),i=Ft(),a=i.data??[],[o,s]=(0,J.useState)(null),[c,l]=(0,J.useState)(!1),[u,d]=(0,J.useState)(null),[f,p]=(0,J.useState)(null),m=o===null?null:a.find(e=>e.id===o)??null,h=Wi(a,m);(0,J.useEffect)(()=>{!n||a.length===0||(o===null||!a.some(e=>e.id===o))&&s(a[0].id)},[n,a,o]);let{saveMutation:g,deleteMutation:_}=Gi({editingPage:u,selectedId:o,setEditorOpen:l,setEditingPage:d,setPendingDelete:p,setSelectedId:s,toast:e,queryClient:t}),v=()=>{d(null),l(!0)},y=()=>{m&&(d(m),l(!0))},b=(0,Z.jsx)($r,{pages:a,isLoading:i.isLoading,isReferenceLoading:h.isNavigationReferenceLoading,isReferenceError:h.isNavigationReferenceError,navigationReferenceCounts:h.navigationReferenceCounts,selectedId:o,onSelect:s,onAdd:v}),ee=m?(0,Z.jsx)(wi,{page:m,isDeleting:_.isPending,navigationReferences:h.selectedNavigationReferences,isNavigationLoading:h.isNavigationReferenceLoading,isNavigationError:h.isNavigationReferenceError,navigationStateByRoleId:h.selectedNavigationStateByRoleId,isVisibilityLoading:h.isVisibilityLoading,isVisibilityError:h.isVisibilityError,onEdit:y,onDelete:()=>p(m),onSelectRoleNavigation:e=>r.selectRole(e,`navigation`),onBack:n?void 0:()=>s(null)}):(0,Z.jsx)(Ji,{}),te=(0,Z.jsx)(zi,{open:c,onOpenChange:l,page:u,isSaving:g.isPending,onSubmit:e=>g.mutate(e)}),x=(0,Z.jsx)(Ki,{page:f,navigationReferences:f?h.navigationReferencesByPageId.get(f.id)??[]:[],isNavigationLoading:h.isNavigationReferenceLoading,isNavigationError:h.isNavigationReferenceError,onOpenChange:e=>!e&&p(null),onConfirm:e=>_.mutate(e)});return n?(0,Z.jsxs)(Z.Fragment,{children:[(0,Z.jsxs)(`div`,{className:`flex min-h-0 flex-1 gap-4`,children:[(0,Z.jsx)(`aside`,{className:`flex w-72 shrink-0 flex-col rounded-lg border border-border p-3 xl:w-80`,children:b}),(0,Z.jsx)(`section`,{className:`min-w-0 flex-1 overflow-y-auto rounded-lg border border-border p-4`,children:ee})]}),te,x]}):(0,Z.jsxs)(Z.Fragment,{children:[(0,Z.jsx)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-y-auto rounded-lg border border-border p-3`,children:m?ee:b}),te,x]})}function Wi(e,t){let n=Bt(),r=Pt(),i=T({queryKey:Hi,staleTime:3e4}),a=(0,J.useMemo)(()=>hi(n.data??[],r.data??[]),[n.data,r.data]);return{navigationReferenceCounts:(0,J.useMemo)(()=>{let t=new Map;for(let n of e)t.set(n.id,a.get(n.id)?.length??0);return t},[a,e]),selectedNavigationReferences:t?a.get(t.id)??[]:[],selectedNavigationStateByRoleId:(0,J.useMemo)(()=>t?gi(t.id,i.data):new Map,[t,i.data]),isNavigationReferenceLoading:n.isLoading||r.isLoading,isNavigationReferenceError:n.isError||r.isError,isVisibilityLoading:i.isLoading,isVisibilityError:i.isError,navigationReferencesByPageId:a}}function Gi({editingPage:e,selectedId:t,setEditorOpen:n,setEditingPage:r,setPendingDelete:i,setSelectedId:a,toast:o,queryClient:s}){let c=()=>{s.invalidateQueries({queryKey:Vi}),s.invalidateQueries({queryKey:ue})};return{saveMutation:E({mutationFn:async t=>e?P.patch(`/api/rbac/pages/${e.id}`,t):P.post(`/api/rbac/pages`,t),onSuccess:()=>{c(),o({title:e?`Page updated`:`Page created`}),n(!1),r(null)},onError:e=>{o({title:`Error`,description:e.message,variant:`destructive`})}}),deleteMutation:E({mutationFn:async e=>P.delete(`/api/rbac/pages/${e}`),onSuccess:(e,n)=>{c(),o({title:`Page deleted`}),t===n&&a(null),i(null)},onError:e=>{o({title:`Error`,description:e.message,variant:`destructive`})}})}}function Ki({page:e,navigationReferences:t,isNavigationLoading:n,isNavigationError:r,onOpenChange:i,onConfirm:a}){return(0,Z.jsx)(lt,{open:e!==null,onOpenChange:i,children:(0,Z.jsxs)(Ve,{children:[(0,Z.jsxs)(He,{children:[(0,Z.jsxs)(Ne,{children:[`Delete â`,e?.name,`â?`]}),(0,Z.jsx)(je,{children:`This removes the page from the registry and any role navigation that references it. This cannot be undone.`}),(0,Z.jsx)(qi,{references:t,isLoading:n,isError:r})]}),(0,Z.jsxs)(at,{children:[(0,Z.jsx)(st,{children:`Cancel`}),(0,Z.jsx)(Ge,{className:`bg-destructive text-destructive-foreground hover:bg-destructive/90`,onClick:()=>e&&a(e.id),children:`Delete`})]})]})})}function qi({references:e,isLoading:t,isError:n}){if(t)return(0,Z.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Checking affected role navigations...`});if(n)return(0,Z.jsx)(`p`,{className:`text-sm text-destructive`,children:`N
1avigation reference data could not be loaded. Deleting may still affect role navigations.`});if(e.length===0)return(0,Z.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`No role navigations currently reference this page.`});let r=_i(e),i=r.length>0?r.join(`, `):`layouts not assigned to roles`;return(0,Z.jsxs)(`div`,{className:`rounded-md border border-destructive/30 bg-destructive/5 p-3 text-sm`,children:[(0,Z.jsx)(`p`,{className:`font-medium text-foreground`,children:`Affected role navigations`}),(0,Z.jsxs)(`p`,{className:`mt-1 text-muted-foreground`,children:[e.length,` navigation `,e.length===1?`layout`:`layouts`,` reference this page: `,i,`.`]})]})}function Ji(){return(0,Z.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col items-center justify-center gap-2 text-center text-muted-foreground`,children:[(0,Z.jsx)(se,{className:`size-8`,"aria-hidden":`true`}),(0,Z.jsx)(`p`,{className:`font-sans text-sm font-medium text-foreground`,children:`Select a page`}),(0,Z.jsx)(`p`,{className:`max-w-xs text-sm`,children:`Pick a page to view its registry metadata and dev-preview settings.`})]})}function Yi({entry:e,roles:t,onJumpToRole:n}){let{permission:r,roleIds:i}=e,a=new Map(t.map(e=>[e.name,e.id])),o=li(i,t);return(0,Z.jsxs)(`li`,{className:`py-3`,children:[(0,Z.jsxs)(`div`,{className:`flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1`,children:[(0,Z.jsx)(`p`,{className:`font-mono text-sm text-foreground`,children:r.key}),(0,Z.jsxs)(`span`,{className:`font-mono text-xs tabular-nums text-muted-foreground`,children:[o.length,` `,o.length===1?`role`:`roles`]})]}),r.description?(0,Z.jsx)(`p`,{className:`mt-0.5 text-xs text-muted-foreground`,children:r.description}):null,o.length>0?(0,Z.jsx)(`ul`,{className:`mt-2 flex flex-wrap gap-1.5`,children:o.map(e=>{let t=a.get(e);return(0,Z.jsx)(`li`,{children:(0,Z.jsx)(L,{type:`button`,variant:`outline`,size:`sm`,className:`h-7 gap-1 px-2 text-xs`,onClick:()=>t!==void 0&&n(t),"data-testid":`catalog-perm-role-${r.id}-${t}`,children:e})},e)})}):(0,Z.jsx)(R,{variant:`outline`,className:`mt-2 text-xs text-muted-foreground`,children:`Held by no roles`})]})}function Xi(){let e=X(),t=Q(),n=Pt().data??[],[r,i]=(0,J.useState)(``),[a,o]=(0,J.useState)(null),s=(0,J.useMemo)(()=>{let e=r.trim().toLowerCase();return ui(e?(t.data??[]).filter(t=>t.permission.key.toLowerCase().includes(e)||(t.permission.description??``).toLowerCase().includes(e)||(t.permission.category??``).toLowerCase().includes(e)):t.data??[])},[t.data,r]),c=t=>{e.selectRole(t,`permissions`)};return t.isLoading?(0,Z.jsx)(`div`,{className:`flex min-h-0 flex-1 flex-col gap-2 overflow-y-auto rounded-lg border border-border p-3`,children:Array.from({length:5}).map((e,t)=>(0,Z.jsx)(A,{className:`h-14 w-full`},t))}):(0,Z.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col gap-3 rounded-lg border border-border p-3`,children:[(0,Z.jsxs)(`div`,{className:`relative`,children:[(0,Z.jsx)(w,{className:`pointer-events-none absolute left-2.5 top-1/2 size-4 -translate-y-1/2 text-muted-foreground`}),(0,Z.jsx)(j,{value:r,onChange:e=>i(e.target.value),placeholder:`Search permissions`,className:`h-10 pl-8`,"aria-label":`Search permissions`,"data-testid":`catalog-perm-search`})]}),(0,Z.jsx)(`div`,{className:`flex min-h-0 flex-1 flex-col gap-2 overflow-y-auto`,children:s.length===0?(0,Z.jsxs)(`div`,{className:`flex flex-1 flex-col items-center justify-center gap-2 py-10 text-center text-muted-foreground`,children:[(0,Z.jsx)(h,{className:`size-8`,"aria-hidden":`true`}),(0,Z.jsx)(`p`,{className:`text-sm`,children:r?`No permissions match your search.`:`No action permissions defined yet.`})]}):s.map(e=>{let t=a===e.category;return(0,Z.jsx)(fe,{className:`shrink-0 overflow-hidden`,children:(0,Z.jsxs)(Ce,{open:t,onOpenChange:t=>o(t?e.category:null),children:[(0,Z.jsx)(Se,{asChild:!0,children:(0,Z.jsxs)(`button`,{type:`button`,className:`flex w-full items-center gap-3 px-4 py-3 text-left hover:bg-muted/40`,"data-testid":`catalog-perm-category-${e.category}`,children:[(0,Z.jsx)(y,{className:k(`size-4 shrink-0 text-muted-foreground transition-transform`,t&&`rotate-180`),"aria-hidden":`true`}),(0,Z.jsx)(`p`,{className:`min-w-0 flex-1 truncate font-sans text-sm font-medium text-foreground`,children:e.category}),(0,Z.jsx)(`span`,{className:`font-mono text-xs tabular-nums text-muted-foreground`,children:e.entries.length})]})}
1),(0,Z.jsx)(xe,{children:(0,Z.jsx)(`ul`,{className:`divide-y divide-border border-t border-border px-4`,children:e.entries.map(e=>(0,Z.jsx)(Yi,{entry:e,roles:n,onJumpToRole:c},e.permission.id))})})]})},e.category)})})]})}function Zi(){let e=X(),t=Ft(),n=Q();return(0,Z.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col gap-3`,children:[(0,Z.jsx)(Qr,{entity:e.entity,onEntityChange:e.setEntity,counts:{pages:t.data?.length,permissions:n.data?.length}}),(0,Z.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col`,children:[e.entity===`pages`?(0,Z.jsx)(Ui,{}):null,e.entity===`permissions`?(0,Z.jsx)(Xi,{}):null]})]})}function Qi(){let e=X();return e.needsRedirect?(0,Z.jsx)(he,{to:`${Y}/roles`,replace:!0}):(0,Z.jsxs)(St,{children:[(0,Z.jsxs)(St.Header,{className:`flex flex-col gap-3 p-3 sm:flex-row sm:items-center sm:justify-between`,children:[(0,Z.jsxs)(`div`,{className:`min-w-0`,children:[(0,Z.jsx)(`h1`,{className:`font-sans text-2xl font-semibold text-foreground`,children:`Access Control`}),(0,Z.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Configure what each role can do, see, and reach â and who holds it.`})]}),(0,Z.jsx)(Nt,{mode:e.mode,onModeChange:e.setMode})]}),(0,Z.jsxs)(St.Body,{className:`p-3 pt-0`,children:[e.mode===`roles`?(0,Z.jsx)(br,{}):null,e.mode===`users`?(0,Z.jsx)(Yr,{}):null,e.mode===`catalog`?(0,Z.jsx)(Zi,{}):null]})]})}export{Qi as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.