PageSourceSearch

https://skuuz.com/assets/AdminAccess-BqQJ8hxJ.js

js skuuz.com collected 2026-10-02 06:28:26 UTC 33,327 bytes, 1 lines download raw bytes

1import{r as o,j as e,R as Ge,k as Xe}from"./react-vendor-DTEXiHme.js";import{T as Ye,a as Ze,b as ue,c as he}from"./tabs-C_TdZTlp.js";import{b as We,u as Re,B as g,l as es,i as ss,N as Q,t as Ne,y as we,Z as Ce,_ as be,k as le,a1 as Se,z as ze,s as u,ab as f,J as Fe,F as as,X as rs,v as Te}from"./index-Cas2BA8G.js";import{u as ge}from"./useMutation-C1UN62nU.js";import{f as Oe}from"./index-DYj0fNDf.js";import{I as G}from"./input-COMpcq49.js";import{L as I}from"./label-CPIAGVc8.js";import{T as Ae,a as Me,b as ae,c as W,d as Ue,e as J}from"./table-CTm7mt6O.js";import{o as X,u as Pe,a as ts,D as is}from"./operatorFilter-DBWwNsLg.js";import{S as re,a as te,b as ie,c as ne,d as Y}from"./select-Dd8j6Fts.js";import{D as ns}from"./DataTableColumnVisibility-C6PWZiOz.js";import{D as fe,f as ls,a as pe,b as je,c as _e,d as ye,e as Ee}from"./dialog-DMFGNqoH.js";import{P as ke}from"./pencil-DRRIH9sd.js";import{T as ce}from"./trash-2-Cha7UE-i.js";import{P as de}from"./plus-BnJ7jTMP.js";import{M as $e}from"./mail-i_SPxsIs.js";import{S as oe}from"./star-Bh_9zoqF.js";import{f as ve}from"./format-CpEgwowc.js";import{f as os}from"./formatDistanceToNow-CmN47SIe.js";import"./popover-CQgjLlkx.js";import{C as cs}from"./checkbox-D0k8Hnb-.js";import{A as Ke,a as Le,b as Ve,c as qe,d as He,e as Be,f as Ie,g as Je}from"./alert-dialog-Cc121-Mn.js";import{A as ds}from"./AddUserModal-BDQNaxkZ.js";import{S as ms}from"./settings-2-ifeXNVik.js";import{K as us}from"./key-round-D7K7cFOR.js";import{U as hs}from"./user-x-DMCuaTHB.js";import{U as gs}from"./user-check-5azMKnxb.js";import{S as xs,a as fs,b as ps,c as js,d as _s,e as ys}from"./sheet-DgWE-ybh.js";import"./excel-CPlAJqTR.js";import"./radix-C8G44Doi.js";import"./arrow-up-CIk-09Z9.js";import"./arrow-down-XUl8eEu7.js";import"./filter-JbNBtMLY.js";import"./chevron-left-C6mkHNrW.js";import"./en-US-Ca8fhmg7.js";import"./switch-CuPZPfg3.js";const vs=async()=>{const[m,D,E,_,R,T]=await Promise.all([u.from("organizations").select("*").order("name",{ascending:!0}),u.rpc("get_org_user_counts"),u.from("plan_tiers").select("id, name"),u.from("custom_plan_tiers").select("id, name"),u.from("user_organizations").select("user_id, org_id, is_primary"),u.from("profiles").select("user_id, full_name, email, role")]);if(m.error)throw m.error;const{data:b}=await u.rpc("get_org_last_logins"),p={};(D.data||[]).forEach(c=>{p[c.org_id]=Number(c.user_count)});const z={};(E.data||[]).forEach(c=>{z[c.id]=c.name});const y={};(_.data||[]).forEach(c=>{y[c.id]=c.name});const F={};(b||[]).forEach(c=>{F[c.org_id]=c.last_login_at});const P=new Map((T.data||[]).map(c=>[c.user_id,c])),S={};for(const c of R.data||[]){const N=P.get(c.user_id);N&&(S[c.org_id]||(S[c.org_id]=[]),S[c.org_id].push({user_id:c.user_id,full_name:N.full_name||"Unnamed",email:N.email||"",role:N.role||"user",is_primary:c.is_primary}))}return(m.data||[]).map(c=>({...c,user_count:p[c.id]||0,plan_name:c.plan_tier_id?z[c.plan_tier_id]:void 0,custom_tier_name:c.custom_plan_tier_id?y[c.custom_plan_tier_id]:void 0,last_login_at:F[c.id]||null,users:S[c.id]||[]}))},Ns=async()=>{const{data:m,error:D}=await u.from("plan_tiers").select("id, name, slug").order("name");if(D)throw D;return m||[]},xe={name:"",slug:"",plan_tier_id:"",custom_plan_tier_id:""},ws=()=>{const m=We(),[D,E]=o.useState(!1),[_,R]=o.useState(!1),[T,b]=o.useState(null),[p,z]=o.useState(xe),{data:y=[],isLoading:F}=Re({queryKey:["admin-organizations"],queryFn:vs}),{data:P=[]}=Re({queryKey:["plan-tiers-list"],queryFn:Ns}),S=()=>m.invalidateQueries({queryKey:["admin-organizations"]}),c=ge({mutationFn:async s=>{const{error:i}=await u.from("organizations").insert({name:s.name.trim(),slug:s.slug.trim()||s.name.toLowerCase().replace(/\s+/g,"-"),plan_tier_id:s.plan_tier_id});if(i)throw i},onSuccess:()=>{f.success("Organization created"),E(!1),z(xe),S()},onError:s=>f.error("Failed to create organization: "+s.message)}),N=ge({mutationFn:async({id:s,data:i})=>{const{error:j}=await u.from("organizations").update({name:i.name.trim(),slug:i.slug.trim()||null,plan_tier_id:i.plan_tier_id}).eq("id",s);if(j)throw j},onSuccess:()=>{f.success("Organization updated"),R(!1),b(null),z(xe),S()},onError:s=>f.error("Failed to update organization: "+s.message)}),k=ge({mutationFn:async s=>{const{error:i}=await u.rpc("delete_organization",{target_org_id:s});if(i)throw i},onSuccess:()=>{f.success("Organization deleted"),S()},onError:s=>f.error("Failed to delete organization: "+s.message)}),A=s=>{confirm(`Are you sure you want to delete "${s.name}
1"? This will permanently remove the organization and ALL its data. This action cannot be undone.`)&&k.mutate(s.id)},w=s=>{b(s),z({name:s.name,slug:s.slug||"",plan_tier_id:s.plan_tier_id||"",custom_plan_tier_id:s.custom_plan_tier_id||""}),R(!0)},v=p.name.trim()&&p.plan_tier_id,V=p.name.trim()&&p.plan_tier_id,[M,K]=o.useState(new Set),L=s=>{K(i=>{const j=new Set(i);return j.has(s)?j.delete(s):j.add(s),j})},r=o.useMemo(()=>[{id:"_expand",header:"",size:36,enableSorting:!1,enableColumnFilter:!1,cell:({row:s})=>{var x;if((((x=s.original.users)==null?void 0:x.length)??0)===0)return null;const j=M.has(s.original.id);return e.jsx(g,{variant:"ghost",size:"sm",className:"h-6 w-6 p-0",onClick:H=>{H.stopPropagation(),L(s.original.id)},children:j?e.jsx(es,{className:"h-4 w-4"}):e.jsx(ss,{className:"h-4 w-4"})})}},{id:"name",header:"Name",accessorKey:"name",filterFn:X,cell:({getValue:s})=>e.jsx("span",{className:"font-medium",children:s()})},{id:"slug",header:"Slug",accessorKey:"slug",filterFn:X,cell:({getValue:s})=>{const i=s();return i?e.jsx(Q,{variant:"outline",children:i}):e.jsx("span",{className:"text-muted-foreground",children:"—"})}},{id:"plan_name",header:"Plan Tier",accessorKey:"plan_name",filterFn:X,cell:({getValue:s})=>{const i=s();return i?e.jsx(Q,{variant:"secondary",children:i}):e.jsx("span",{className:"text-muted-foreground text-sm",children:"No plan"})}},{id:"custom_tier_name",header:"Custom Tier",accessorKey:"custom_tier_name",filterFn:X,cell:({getValue:s})=>{const i=s();return i?e.jsx(Q,{className:"bg-amber-500/10 text-amber-600 border-amber-500/20",children:i}):e.jsx("span",{className:"text-muted-foreground text-sm",children:"—"})}},{id:"user_count",header:"Users",accessorKey:"user_count",meta:{filterType:"number"},cell:({getValue:s})=>e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(Ne,{className:"h-4 w-4 text-muted-foreground"}),s()]})},{id:"last_login_at",header:"Last Login",accessorKey:"last_login_at",cell:({getValue:s})=>{const i=s();return i?e.jsx("span",{className:"text-sm",title:ve(new Date(i),"PPpp"),children:os(new Date(i),{addSuffix:!0})}):e.jsx("span",{className:"text-muted-foreground text-sm",children:"Never"})}},{id:"created_at",header:"Created",accessorKey:"created_at",cell:({getValue:s})=>ve(new Date(s()),"MMM d, yyyy")},{id:"actions",header:"",enableSorting:!1,enableColumnFilter:!1,cell:({row:s})=>e.jsxs("div",{className:"flex items-center justify-end gap-2",children:[e.jsx(g,{variant:"ghost",size:"icon",onClick:()=>w(s.original),children:e.jsx(ke,{className:"h-4 w-4"})}),e.jsx(g,{variant:"ghost",size:"icon",onClick:()=>A(s.original),children:e.jsx(ce,{className:"h-4 w-4 text-destructive"})})]})}],[w,A]),{table:C}=Pe({data:y,columns:r,enablePagination:!0,pageSize:25}),q=({id:s,value:i,onChange:j})=>e.jsxs("div",{className:"space-y-2",children:[e.jsx(I,{htmlFor:s,children:"Plan Tier *"}),e.jsxs(re,{value:i,onValueChange:j,children:[e.jsx(te,{id:s,children:e.jsx(ie,{placeholder:"Select a plan tier"})}),e.jsx(ne,{children:P.map(x=>e.jsx(Y,{value:x.id,children:x.name},x.id))})]})]});return e.jsx("div",{className:"h-full overflow-y-auto p-6",children:e.jsxs("div",{className:"max-w-7xl mx-auto space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold",children:"Organizations"}),e.jsx("p",{className:"text-muted-foreground",children:"Manage all organizations in the system"})]}),e.jsxs(fe,{open:D,onOpenChange:E,children:[e.jsx(ls,{asChild:!0,children:e.jsxs(g,{children:[e.jsx(de,{className:"h-4 w-4 mr-2"}),"Create Organization"]})}),e.jsxs(pe,{children:[e.jsxs(je,{children:[e.jsx(_e,{children:"Create Organization"}),e.jsx(ye,{children:"Add a new organization to the system"})]}),e.jsxs("div",{className:"space-y-4 py-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(I,{htmlFor:"name",children:"Name *"}),e.jsx(G,{id:"name",value:p.name,onChange:s=>z(i=>({...i,name:s.target.value})),placeholder:"Acme Corporation"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(I,{htmlFor:"slug",children:"Slug (optional)"}),e.jsx(G,{id:"slug",value:p.slug,onChange:s=>
1z(i=>({...i,slug:s.target.value})),placeholder:"acme-corp"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"URL-friendly identifier. Auto-generated from name if left empty."})]}),e.jsx(q,{id:"plan-tier",value:p.plan_tier_id,onChange:s=>z(i=>({...i,plan_tier_id:s}))})]}),e.jsxs(Ee,{children:[e.jsx(g,{variant:"outline",onClick:()=>E(!1),children:"Cancel"}),e.jsx(g,{onClick:()=>c.mutate(p),disabled:c.isPending||!v,children:"Create"})]})]})]})]}),e.jsxs(we,{children:[e.jsx(Ce,{children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsxs(be,{className:"flex items-center gap-2",children:[e.jsx(le,{className:"h-5 w-5"}),"All Organizations"]}),e.jsxs(Se,{children:[y.length," organization",y.length!==1?"s":""," registered"]})]}),e.jsx(ns,{table:C})]})}),e.jsx(ze,{children:F?e.jsx("p",{className:"text-muted-foreground text-center py-8",children:"Loading..."}):y.length===0?e.jsx("p",{className:"text-muted-foreground text-center py-8",children:"No organizations found"}):e.jsx("div",{className:"rounded-md border",children:e.jsxs(Ae,{children:[e.jsx(Me,{children:C.getHeaderGroups().map(s=>e.jsx(ae,{children:s.headers.map(i=>e.jsx(W,{children:i.isPlaceholder?null:typeof i.column.columnDef.header=="string"?e.jsx(ts,{header:i}):Oe(i.column.columnDef.header,i.getContext())},i.id))},s.id))}),e.jsx(Ue,{children:C.getRowModel().rows.map(s=>{const i=M.has(s.original.id),j=s.original.users??[];return e.jsxs(Ge.Fragment,{children:[e.jsx(ae,{children:s.getVisibleCells().map(x=>e.jsx(J,{className:"px-2 py-1",children:Oe(x.column.columnDef.cell,x.getContext())},x.id))}),i&&j.length>0&&e.jsx(ae,{className:"bg-muted/20 hover:bg-muted/30",children:e.jsxs(J,{colSpan:C.getVisibleFlatColumns().length,className:"px-6 py-2",children:[e.jsxs("div",{className:"text-xs font-medium text-muted-foreground mb-1",children:[j.length," User",j.length!==1?"s":""]}),e.jsxs("table",{className:"w-full text-xs",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b",children:[e.jsx("th",{className:"text-left py-1 pr-3 font-medium text-muted-foreground",children:"Name"}),e.jsx("th",{className:"text-left py-1 pr-3 font-medium text-muted-foreground",children:"Email"}),e.jsx("th",{className:"text-left py-1 pr-3 font-medium text-muted-foreground",children:"Role"}),e.jsx("th",{className:"text-left py-1 pr-3 font-medium text-muted-foreground",children:"Primary"})]})}),e.jsx("tbody",{children:j.map(x=>e.jsxs("tr",{className:"border-b border-muted/50",children:[e.jsx("td",{className:"py-1 pr-3 font-medium",children:x.full_name}),e.jsxs("td",{className:"py-1 pr-3 flex items-center gap-1",children:[e.jsx($e,{className:"h-3 w-3 text-muted-foreground"}),x.email]}),e.jsx("td",{className:"py-1 pr-3",children:e.jsx(Q,{variant:"outline",className:"text-[10px]",children:x.role})}),e.jsx("td",{className:"py-1 pr-3",children:x.is_primary?e.jsx(oe,{className:"h-3 w-3 text-amber-500"}):"—"})]},x.user_id))})]})]})})]},s.id)})})]})})})]}),e.jsx(fe,{open:_,onOpenChange:R,children:e.jsxs(pe,{children:[e.jsxs(je,{children:[e.jsx(_e,{children:"Edit Organization"}),e.jsx(ye,{children:"Update organization details"})]}),e.jsxs("div",{className:"space-y-4 py-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(I,{htmlFor:"edit-name",children:"Name *"}),e.jsx(G,{id:"edit-name",value:p.name,onChange:s=>z(i=>({...i,name:s.target.value}))})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(I,{htmlFor:"edit-slug",children:"Slug"}),e.jsx(G,{id:"edit-slug",value:p.slug,onChange:s=>z(i=>({...i,slug:s.target.value}))})]}),e.jsx(q,{id:"edit-plan-tier",value:p.plan_tier_id,onChange:s=>z(i=>({...i,plan_tier_id:s}))})]}),e.jsxs(Ee,{children:[e.jsx(g,{variant:"outline",onClick:()=>R(!1),children:"Cancel"}),e.jsx(g,{onClick:()=>T&&N.mutate({id:T.id,data:p}),disabled:N.isPending||!V,children:"Save Changes"})]})]})})]})})},Cs=()=>{const[m,D]=o.useState([]),[E,_]=o.useState([]),[R,T]=o.useState(!0),[b,p]=o.use
1State(null),[z,y]=o.useState(!1),[F,P]=o.useState(!1),[S,c]=o.useState(!1),[N,k]=o.useState([]),[A,w]=o.useState(!1),[v,V]=o.useState(null),[M,K]=o.useState(!1),[L,r]=o.useState(null),[C,q]=o.useState(""),s=async()=>{var n;try{const[t,d,$]=await Promise.all([u.from("profiles").select("*").order("created_at",{ascending:!1}),u.from("organizations").select("id, name").order("name"),u.from("user_organizations").select("user_id, org_id, is_primary")]);if(t.error)throw t.error;if(d.error)throw d.error;if($.error)throw $.error;const B=new Map(((n=d.data)==null?void 0:n.map(U=>[U.id,U.name]))||[]),me=new Map;($.data||[]).forEach(U=>{const De=me.get(U.user_id)||[];De.push({org_id:U.org_id,is_primary:U.is_primary,organization_name:B.get(U.org_id)||"Unknown"}),me.set(U.user_id,De)}),D((t.data||[]).map(U=>({...U,is_active:U.is_active??!0,organizations:U.user_id?me.get(U.user_id)||[]:[]}))),_(d.data||[])}catch(t){console.error("Error fetching data:",t),f.error("Failed to load users")}finally{T(!1)}};o.useEffect(()=>{s()},[]);const i=n=>{p(n),k(n.organizations.map(t=>({org_id:t.org_id,is_primary:t.is_primary}))),y(!0)},j=n=>{k(t=>{const d=t.find($=>$.org_id===n);if(d){const $=t.filter(B=>B.org_id!==n);return d.is_primary&&$.length>0&&($[0].is_primary=!0),$}else return[...t,{org_id:n,is_primary:t.length===0}]})},x=n=>{k(t=>t.map(d=>({...d,is_primary:d.org_id===n})))},H=async()=>{if(b!=null&&b.user_id){c(!0);try{const{data:n,error:t}=await u.rpc("set_user_org_memberships",{p_user_id:b.user_id,p_memberships:N.map(d=>({org_id:d.org_id,is_primary:d.is_primary}))});if(t)throw t;f.success("User organizations updated"),y(!1),s()}catch(n){console.error("Error updating user orgs:",n),f.error("Failed to update: "+n.message)}finally{c(!1)}}},Z=async n=>{try{const{error:t}=await u.from("profiles").update({is_active:!n.is_active}).eq("id",n.id);if(t)throw t;f.success(`User ${n.is_active?"deactivated":"activated"} successfully`),s()}catch(t){console.error("Error toggling user status:",t),f.error("Failed to update user status: "+t.message)}},ee=n=>{V(n),w(!0)},a=async n=>{const t=C.trim();if(!t){r(null);return}try{const{error:d}=await u.from("profiles").update({full_name:t}).eq("id",n);if(d)throw d;f.success("Name updated"),r(null),s()}catch(d){f.error("Failed to update name: "+d.message)}},h=async()=>{if(v!=null&&v.user_id){K(!0);try{const{data:n,error:t}=await u.functions.invoke("delete-user",{body:{user_id:v.user_id}});if(t)throw t;if(n!=null&&n.error)throw new Error(n.error);f.success("User deleted successfully"),w(!1),V(null),s()}catch(n){console.error("Error deleting user:",n),f.error("Failed to delete user: "+n.message)}finally{K(!1)}}},l=async(n,t)=>{try{const{error:d}=await u.auth.resetPasswordForEmail(n,{redirectTo:`${window.location.origin}/reset-password`});if(d)throw d;f.success(`Password reset email sent to ${t||n}`)}catch(d){console.error("Error sending password reset:",d),f.error("Failed to send password reset: "+d.message)}},O=o.useMemo(()=>[{id:"full_name",header:"Name",accessorKey:"full_name",filterFn:X,cell:({row:n})=>{const t=n.original;return L===t.id?e.jsx(G,{autoFocus:!0,value:C,onChange:d=>q(d.target.value),onKeyDown:d=>{d.key==="Enter"&&a(t.id),d.key==="Escape"&&r(null)},onBlur:()=>a(t.id),className:"h-8 w-48"}):e.jsxs("button",{className:"group flex items-center gap-1.5 hover:underline text-left font-medium",onClick:()=>{r(t.id),q(t.full_name||"")},children:[t.full_name||"Unnamed User",e.jsx(ke,{className:"h-3 w-3 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity"})]})}},{id:"email",header:"Email",accessorKey:"email",filterFn:X,cell:({getValue:n})=>e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx($e,{className:"h-4 w-4 text-muted-foreground"}),n()||"—"]})},{id:"is_active",header:"Status",accessorKey:"is_active",cell:({getValue:n})=>e.jsx(Q,{variant:n()?"default":"secondary",children:n()?"Active":"Inactive"})},{id:"organizations",header:"Organizations",accessorFn:n=>{var t;return((t=n.organizations)==null?void 0:t.map(d=>d.organization_name).join(", "))??""},filterFn:X,cell:({row:n})=>{const t=n.original.organizations||[];return t.length===0?e.jsx("span",{className:"text-muted-foreground text-sm",children:"No organizations"}):e.jsx("div",{className:"flex flex-wrap gap-1",children:t.map(d=>e.jsxs(Q,{variant:d.is_primary?"default":"secondary",className:"flex items-center gap-1",children:[d.is_primary&&e.jsx(oe,{className:"h-3 w-3"}),d.organization_name]},d.org_id))})}},{id:"created_at",header:"Joined",accessorKey:"created_at",cell:({getValue:n})=>ve(new Date(n()),"MMM d, yyyy")},{id:"actions",header:"",enableSorting:!1,enableColumnFilter:!1,cell:({row:n})=>{const t=n.original;return e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(g,{variant:"ghost",size:"sm",onClick:()=>i(t),title:"Edit organizations",children:e.jsx(ms,{className:"h-4 w-4"})}),e.jsx(g,{variant:"ghost",size:"sm",onClick:()=>l(t.email,t.full_name||""),disabled:!t.email,title:"Send password reset email",children:e.jsx(us,{className:"h-4 w-4"})}),e.jsx(g,{variant:"ghost",size:"sm",onClick:()=>Z(t),title:t.is_active?"Deactivate user":"Activate user",children:t.is_active?e.jsx(hs,{className:"h-4 w-4 text-muted-foreground"}):e.jsx(gs,{className:"h-4 w-4 text-green-600"})}),e.jsx(g,{variant:"ghost",size:"sm",onClick:()=>ee(t),disabled:M,title:"Delete user",children:e.jsx(ce,{className:"h-4 w-4 text-destructive"})})]})}}],[L,C]),{table:Qe}=Pe({data:m,columns:O,enablePagination:!0,pageSize:25});return e.jsx("div",{className:"h-full overflow-y-auto p-6",children:e.jsxs("div",{className:"max-w-7xl mx-auto 
1space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold",children:"Users"}),e.jsx("p",{className:"text-muted-foreground",children:"Manage users and their organization assignments"})]}),e.jsxs(g,{onClick:()=>P(!0),children:[e.jsx(de,{className:"h-4 w-4 mr-2"}),"Add User"]})]}),e.jsxs(we,{children:[e.jsxs(Ce,{children:[e.jsxs(be,{className:"flex items-center gap-2",children:[e.jsx(Ne,{className:"h-5 w-5"}),"All Users"]}),e.jsxs(Se,{children:[m.length," user",m.length!==1?"s":""," in the system"]})]}),e.jsx(ze,{children:R?e.jsx("p",{className:"text-muted-foreground text-center py-8",children:"Loading..."}):e.jsx(is,{table:Qe,showPagination:!0,emptyMessage:"No users found"})})]}),e.jsx(fe,{open:z,onOpenChange:y,children:e.jsxs(pe,{className:"max-w-md",children:[e.jsxs(je,{children:[e.jsx(_e,{children:"Edit Organizations"}),e.jsx(ye,{children:(b==null?void 0:b.full_name)||(b==null?void 0:b.email)||"User"})]}),e.jsxs("div",{className:"space-y-4 py-4",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Select organizations for this user. Click the star to set the primary organization."}),e.jsx("div",{className:"space-y-2 max-h-64 overflow-y-auto",children:E.map(n=>{var $;const t=N.some(B=>B.org_id===n.id),d=(($=N.find(B=>B.org_id===n.id))==null?void 0:$.is_primary)||!1;return e.jsxs("div",{className:"flex items-center justify-between p-3 rounded-lg border hover:bg-muted/50 transition-colors",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(cs,{checked:t,onCheckedChange:()=>j(n.id)}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(le,{className:"h-4 w-4 text-muted-foreground"}),e.jsx("span",{children:n.name})]})]}),t&&e.jsx(g,{variant:"ghost",size:"sm",onClick:()=>x(n.id),className:d?"text-yellow-500":"text-muted-foreground",children:e.jsx(oe,{className:`h-4 w-4 ${d?"fill-current":""}`})})]},n.id)})})]}),e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx(g,{variant:"outline",onClick:()=>y(!1),children:"Cancel"}),e.jsx(g,{onClick:H,disabled:S,children:S?"Saving...":"Save Changes"})]})]})}),e.jsx(Ke,{open:A,onOpenChange:w,children:e.jsxs(Le,{children:[e.jsxs(Ve,{children:[e.jsx(qe,{children:"Delete User"}),e.jsxs(He,{children:["Are you sure you want to delete ",(v==null?void 0:v.full_name)||(v==null?void 0:v.email)||"this user","? This action cannot be undone and will remove all their data."]})]}),e.jsxs(Be,{children:[e.jsx(Ie,{children:"Cancel"}),e.jsx(Je,{onClick:h,disabled:M,className:"bg-destructive text-destructive-foreground hover:bg-destructive/90",children:M?"Deleting...":"Delete"})]})]})}),e.jsx(ds,{open:F,onOpenChange:P,organizations:E,onUserCreated:s})]})})},se=()=>({key:Math.random().toString(36).slice(2),org_id:"",role_id:"",is_primary:!1});function bs({open:m,onOpenChange:D,onSaved:E,editUser:_,editAssignment:R}){const[T,b]=o.useState([]),[p,z]=o.useState([]),[y,F]=o.useState(""),[P,S]=o.useState(!1),[c,N]=o.useState(!1),[k,A]=o.useState(null),[w,v]=o.useState([se()]),[V,M]=o.useState(!1),[K,L]=o.useState(null);o.useEffect(()=>{m&&(async()=>{const[a,h]=await Promise.all([u.from("organizations").select("id, name").order("name"),u.from("roles").select("id, name, org_id")]);b(a.data??[]),z(h.data??[])})()},[m]),o.useEffect(()=>{m&&(A(_??null),F((_==null?void 0:_.email)??""),v(R?[{key:Math.random().toString(36).slice(2),org_id:R.org_id,role_id:R.role_id,is_primary:R.is_primary}]:[se()]))},[m,_,R]),o.useEffect(()=>{if(_)return;const a=y.trim();if(!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(a)){A(null),N(!1);return}if(k&&k.email===a)return;const h=setTimeout(()=>{i()},400);return()=>clearTimeout(h)},[y,m,_]);const r=o.useMemo(()=>w.find(a=>a.org_id&&!a.role_id)??null,[w]),C=a=>p.filter(h=>h.org_id===a||h.org_id===null),q=a=>{var h;return((h=T.find(l=>l.id===a))==null?void 0:h.name)??"org"},s=!!k&&w.length>0&&w.every(a=>a.org_id&&a.role_id)&&new Set(w.map(a=>a.org_id)).size===w.length,i=async()=>{if(y.trim()){S(!0),A(null),N(!1);try{const{data:a,error:h}=await u.from("profiles").select("user_id, email, full_name").eq("email",y.trim()).maybeSingle();if(h)throw h;a?A({id:a.user_id,email:a.email??"",name:a.full_name??"Unknown"}):N(!0)}catch(a){f.error("Couldn't search for that user: "+a.message)}finally{S(!1)}}},j=()=>
1{if(r){L(()=>()=>{v(a=>[...a.filter(h=>h.key!==r.key),se()])});return}v(a=>[...a,se()])},x=(a,h)=>v(l=>l.map(O=>O.key===a?{...O,...h}:O)),H=a=>v(h=>h.length===1?[se()]:h.filter(l=>l.key!==a)),Z=()=>{if(r){L(()=>()=>D(!1));return}D(!1)},ee=async()=>{if(!(!s||!k)){M(!0);try{for(const a of w){const{error:h}=await u.rpc("admin_set_user_org_role",{p_user_id:k.id,p_org_id:a.org_id,p_role_id:a.role_id,p_is_primary:a.is_primary});if(h)throw new Error(`${q(a.org_id)}: ${h.message}`)}f.success(`Saved ${w.length} assignment${w.length!==1?"s":""} for ${k.name}.`),E(),D(!1)}catch(a){f.error("Couldn't save: "+a.message)}finally{M(!1)}}};return e.jsxs(e.Fragment,{children:[e.jsx(xs,{open:m,onOpenChange:a=>a?D(!0):Z(),children:e.jsxs(fs,{side:"right",className:"w-1/2 max-w-none sm:max-w-none flex flex-col",children:[e.jsxs(ps,{children:[e.jsx(js,{children:R?"Edit assignment":_?"Edit access":"Assign a user"}),e.jsx(_s,{children:"Give this user a role in each organization. Every organization needs a role before you can save."})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto space-y-6 py-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(I,{children:"User email"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(G,{value:y,disabled:!!_,placeholder:"[email protected]",onChange:a=>F(a.target.value),onKeyDown:a=>a.key==="Enter"&&i()}),!_&&e.jsx(g,{variant:"secondary",onClick:i,disabled:P,children:e.jsx(Fe,{className:"h-4 w-4"})})]}),c&&!P&&e.jsx("p",{className:"text-sm text-destructive",children:"No user found with that email. Check the address, or invite them from Members & Roles."}),k&&e.jsxs("div",{className:"flex items-center gap-2 rounded-md border bg-muted/40 p-3",children:[e.jsx(as,{className:"h-4 w-4 text-muted-foreground"}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium leading-none",children:k.name}),e.jsx("p",{className:"text-xs text-muted-foreground",children:k.email})]})]})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsx(I,{children:"Organizations & roles"}),w.map(a=>{const h=a.org_id?C(a.org_id):[];return e.jsxs("div",{className:"rounded-lg border p-3 space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(le,{className:"h-4 w-4 text-muted-foreground shrink-0"}),e.jsxs(re,{value:a.org_id,onValueChange:l=>x(a.key,{org_id:l,role_id:""}),children:[e.jsx(te,{className:"flex-1",children:e.jsx(ie,{placeholder:"Choose organization"})}),e.jsx(ne,{children:T.filter(l=>l.id===a.org_id||!w.some(O=>O.org_id===l.id)).map(l=>e.jsx(Y,{value:l.id,children:l.name},l.id))})]}),e.jsx(g,{variant:"ghost",size:"icon",className:"h-8 w-8 shrink-0",onClick:()=>H(a.key),"aria-label":"Remove organization",children:e.jsx(ce,{className:"h-4 w-4 text-muted-foreground"})})]}),e.jsxs(re,{value:a.role_id,disabled:!a.org_id,onValueChange:l=>x(a.key,{role_id:l}),children:[e.jsx(te,{children:e.jsx(ie,{placeholder:a.org_id?"Select a role (required)":"Choose an organization first"})}),e.jsx(ne,{children:h.map(l=>e.jsx(Y,{value:l.id,children:l.name},l.id))})]}),a.org_id&&!a.role_id&&e.jsxs("p",{className:"text-xs text-destructive",children:["Pick a role for ",q(a.org_id)," to continue."]})]},a.key)}),e.jsxs(g,{variant:"outline",size:"sm",onClick:j,className:"w-full",children:[e.jsx(de,{className:"h-4 w-4 mr-2"}),"Add another organization"]})]})]}),e.jsxs(ys,{children:[e.jsx(g,{variant:"outline",onClick:Z,children:"Cancel"}),e.jsx(g,{onClick:ee,disabled:!s||V,children:V?"Saving…":"Save access"})]})]})}),e.jsx(Ke,{open:!!K,onOpenChange:a=>!a&&L(null),children:e.jsxs(Le,{children:[e.jsxs(Ve,{children:[e.jsx(qe,{children:"Unsaved changes"}),e.jsx(He,{children:"You picked an organization but haven't chosen a role for it yet. That assignment won't be saved. Discard it and continue?"})]}),e.jsxs(Be,{children:[e.jsx(Ie,{children:"Keep editing"}),e.jsx(Je,{onClick:()=>{K==null||K(),L(null)},children:"Discard and continue"})]})]})})]})}const Ss=m=>{switch(m){case"Owner":return"default";case"Admin":return"secondary";default:return"outline"}},zs=()=>{const[m,D]=o.useState([]),[E,_]=o.useState(!0),[R,T]=o.useState(!1),[b,p]=o.use
1State(null),[z,y]=o.useState(null),[F,P]=o.useState(""),[S,c]=o.useState("all"),[N,k]=o.useState("all"),A=async()=>{_(!0);try{const[r,C,q,s,i,j]=await Promise.all([u.from("user_org_roles").select("user_id, org_id, role_id"),u.from("profiles").select("user_id, email, full_name"),u.from("organizations").select("id, name"),u.from("roles").select("id, name"),u.from("user_organizations").select("user_id, org_id, is_primary"),u.from("user_roles").select("user_id, role")]),x=new Map((C.data??[]).map(l=>[l.user_id,l])),H=new Map((q.data??[]).map(l=>[l.id,l.name])),Z=new Map((s.data??[]).map(l=>[l.id,l.name])),ee=new Map((i.data??[]).map(l=>[`${l.user_id}:${l.org_id}`,l.is_primary??!1])),a=new Set((j.data??[]).filter(l=>l.role==="super_admin").map(l=>l.user_id)),h=(r.data??[]).filter(l=>!a.has(l.user_id)).map(l=>{const O=x.get(l.user_id);return{user_id:l.user_id,email:(O==null?void 0:O.email)??"Unknown",name:(O==null?void 0:O.full_name)??"Unknown",org_id:l.org_id,org_name:H.get(l.org_id)??"Unknown org",role_id:l.role_id,role_name:Z.get(l.role_id)??"Unknown role",is_primary:ee.get(`${l.user_id}:${l.org_id}`)??!1}});h.sort((l,O)=>l.name.localeCompare(O.name)||l.org_name.localeCompare(O.org_name)),D(h)}catch(r){console.error("Error loading assignments:",r),f.error("Couldn't load role assignments.")}finally{_(!1)}};o.useEffect(()=>{A()},[]);const w=o.useMemo(()=>[...new Set(m.map(r=>r.role_name))].sort(),[m]),v=o.useMemo(()=>[...new Set(m.map(r=>r.org_name))].sort(),[m]),V=F||S!=="all"||N!=="all",M=m.filter(r=>{if(F){const C=F.toLowerCase();if(!r.name.toLowerCase().includes(C)&&!r.email.toLowerCase().includes(C))return!1}return!(S!=="all"&&r.role_name!==S||N!=="all"&&r.org_name!==N)}),K=async r=>{if(confirm(`Remove ${r.name}'s ${r.role_name} access to ${r.org_name}?`))try{const{error:C}=await u.rpc("admin_remove_user_from_org",{p_user_id:r.user_id,p_org_id:r.org_id});if(C)throw C;f.success(`Removed ${r.name} from ${r.org_name}.`),A()}catch(C){f.error("Couldn't remove access: "+C.message)}},L=r=>{p({id:r.user_id,email:r.email,name:r.name}),y({org_id:r.org_id,role_id:r.role_id,is_primary:r.is_primary}),T(!0)};return e.jsx("div",{className:"h-full overflow-y-auto p-6",children:e.jsxs("div",{className:"max-w-7xl mx-auto space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold",children:"Roles"}),e.jsx("p",{className:"text-muted-foreground",children:"Each row is one user's role in one organization."})]}),e.jsxs(g,{onClick:()=>{p(null),y(null),T(!0)},children:[e.jsx(de,{className:"h-4 w-4 mr-2"}),"Assign Role"]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsxs("div",{className:"relative flex-1 min-w-[200px] max-w-sm",children:[e.jsx(Fe,{className:"absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground"}),e.jsx(G,{placeholder:"Search by name or email…",value:F,onChange:r=>P(r.target.value),className:"pl-9"})]}),e.jsxs(re,{value:S,onValueChange:c,children:[e.jsx(te,{className:"w-[160px]",children:e.jsx(ie,{placeholder:"All Roles"})}),e.jsxs(ne,{children:[e.jsx(Y,{value:"all",children:"All Roles"}),w.map(r=>e.jsx(Y,{value:r,children:r},r))]})]}),e.jsxs(re,{value:N,onValueChange:k,children:[e.jsx(te,{className:"w-[200px]",children:e.jsx(ie,{placeholder:"All Organizations"})}),e.jsxs(ne,{children:[e.jsx(Y,{value:"all",children:"All Organizations"}),v.map(r=>e.jsx(Y,{value:r,children:r},r))]})]}),V&&e.jsxs(g,{variant:"ghost",size:"sm",onClick:()=>{P(""),c("all"),k("all")},children:[e.jsx(rs,{className:"h-4 w-4 mr-1"}),"Clear"]})]}),e.jsxs(we,{children:[e.jsxs(Ce,{children:[e.jsxs(be,{className:"flex items-center gap-2",children:[e.jsx(Te,{className:"h-5 w-5"}),"User Roles & Organizations"]}),e.jsx(Se,{children:V?`${M.length} of ${m.length} assignment${m.length!==1?"s":""}`:`${m.length} assignment${m.length!==1?"s":""}`})]}),e.jsx(ze,{children:E?e.jsx("p",{className:"text-muted-foreground text-center py-8",children:"Loading…"}):m.length===0?e.jsx("p",{className:"text-muted-foreground text-center py-8",children:"No role assignments yet. Use Assign Role to give a user access to an organization."}):M.length===0?e.jsx("p",{className:"text-muted-foreground text-center py-8",children:"No assignments match the current filters."}):e.jsxs(Ae,{children:[e.jsx(Me,{children:e.jsxs(ae,{children:[e.jsx(W,{children:"User"}),e.jsx(W,{children:"Email"}),e.jsx(W,{children:"Organization"}),e.jsx(W,{children:"Role"}),e.jsx(W,{className:"text-right",children:"Actions"})]})}),e.jsx(Ue,{children:M.map(r=>e.jsxs(ae,{children:[e.jsx(J,{className:"font-medium",children:r.name}),e.jsx(J,{className:"text-muted-foreground",children:r.email}),e.jsx(J,{children:e.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.jsx(le,{className:"h-3 w-3 text-muted-foreground"}),r.org_name,r.is_primary&&e.jsx(oe,{className:"h-3 w-3 text-amber-500 fill-amber-500","aria-label":"Primary org"})]})}),e.jsx(J,{children:e.jsx(Q,{variant:Ss(r.role_name),children:r.role_name})}),e.jsxs(J,{className:"text-right",children:[e.jsx(g,{variant:"ghost",size:"icon",className:"h-7 w-7",onClick:()=>L(r),"aria-label":"Edit assignment",children:e.jsx(ke,{className:"h-4 w-4 text-muted-foreground"})}),e.jsx(g,{variant:"ghost",size:"icon",className:"h-7 w-7",onClick:()=>K(r),"aria-label":"Remove assignment",children:e.jsx(ce,{className:"h-4 w-4 text-destructive"})})]})]},`${r.user_id}:${r.org_id}`))})]})})]}),e.jsx(bs,{open:R,onOpenChange:T,editUser:b,editAssignment:z,onSaved:A})]})})};function da(){const[m,D]=Xe(),E=m.get("tab")||"organizations";return e.jsx("div",{className:"h-full overflow-auto",children:e.jsxs("div",{className:"p-6 pb-0",children:[e.jsx("h1",{className:"text-2xl font-bold text-foreground",children:"Access Management"}),e.jsx("p",{className:"text-muted-foreground text-sm mb-6",children:"Manage organizations, users, and role assignments."}),e.jsxs(Ye,{value:E,onValueChange:_=>D({tab:_}),children:[e.jsxs(Ze,{children:[e.jsxs(ue,{value:"organizations",className:"gap-1.5",children:[e.jsx(le,{className:"h-4 w-4"}),"Organizations"]}),e.jsxs(ue,{value:"users",className:"gap-1.5",children:[e.jsx(Ne,{className:"h-4 w-4"}),"Users"]}),e.jsxs(ue,{value:"roles",className:"gap-1.5",children:[e.jsx(Te,{className:"h-4 w-4"}),"Roles"]})]}),e.jsx(he,{value:"organizations",className:"mt-0",children:e.jsx(ws,{})}),e.jsx(he,{value:"users",className:"mt-0",children:e.jsx(Cs,{})}),e.jsx(he,{value:"roles",className:"mt-0",children:e.jsx(zs,{})})]})]})})}export{da 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.