1import{o as le,aa as q,ax as R,ay as f,a8 as je,l as ve,r as i,j as e,B as h,C as F,d as ae,e as te,b as P,aE as o,ac as u,X as ge,aJ as ye,F as be}from"./index-Db4qfLtJ.js";import{u as Ne}from"./use-admin-companies-BVcqu1QY.js";import{U as we}from"./user-plus-CtCDdSRw.js";import{P as Se}from"./pencil-CotvlqjN.js";import{T as Ce}from"./trash-2-B7PJlOg5.js";const j=je;async function Fe(){const a=await f(),r=await fetch(`${j}/api/admin/users`,{headers:a}),t=await r.json();if(!r.ok)throw new Error(t.error||"Failed to fetch users");return t.users}async function Pe(a){const r=await f(),t=new URLSearchParams({company_id:a}),n=await fetch(`${j}/api/admin/users/teams?${t.toString()}`,{headers:r}),c=await n.json();if(!n.ok)throw new Error(c.error||"Failed to fetch teams");return c.teams}async function Ee(a){const r=await f(),t=await fetch(`${j}/api/admin/users`,{method:"POST",headers:{...r,"Content-Type":"application/json"},body:JSON.stringify(a)}),n=await t.json();if(!t.ok)throw new Error(n.error||"Failed to provision user");return n.user}async function _e(a,r){const t=await f(),n=await fetch(`${j}/api/admin/users/${a}`,{method:"PATCH",headers:{...t,"Content-Type":"application/json"},body:JSON.stringify(r)}),c=await n.json();if(!n.ok)throw new Error(c.error||"Failed to update user");return c.user}async function Ue(a){const r=await f(),t=await fetch(`${j}/api/admin/users/${a}`,{method:"DELETE",headers:r}),n=await t.json();if(!t.ok)throw new Error(n.error||"Failed to delete user")}function Te(){return le({queryKey:["admin","users"],queryFn:Fe})}function ne(a){return le({queryKey:["admin","users","teams",a],queryFn:()=>a?Pe(a):Promise.resolve([]),enabled:!!a})}function ke(){const a=q();return R({mutationFn:Ee,onSuccess:()=>a.invalidateQueries({queryKey:["admin","users"]})})}function Ae(){const a=q();return R({mutationFn:({id:r,...t})=>_e(r,t),onSuccess:()=>a.invalidateQueries({queryKey:["admin","users"]})})}function $e(){const a=q();return R({mutationFn:Ue,onSuccess:()=>a.invalidateQueries({queryKey:["admin","users"]})})}const qe={admin:"DSP Admin",dispatcher:"Dispatcher",hr:"HR",read_only:"Read Only",super_admin:"Super Admin"},ie=[{value:"admin",label:"DSP Admin"},{value:"dispatcher",label:"Dispatcher"},{value:"hr",label:"HR"},{value:"read_only",label:"Read Only"}];function re({idPrefix:a,teams:r,selectedIds:t,onChange:n,disabled:c=!1}){const p=new Set(t);function v(d,m){n(m?[...new Set([...t,d])]:t.filter(x=>x!==d))}return c?e.jsx("p",{className:"text-sm text-muted-foreground",children:"Select a company to assign teams."}):r.length===0?e.jsx("p",{className:"text-sm text-muted-foreground",children:"No active teams found for this company."}):e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-2 rounded-md border bg-slate-50 p-3",children:r.map(d=>e.jsxs("label",{htmlFor:`${a}-${d.id}`,className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{id:`${a}-${d.id}`,type:"checkbox",className:"h-4 w-4 rounded border-slate-300",checked:p.has(d.id),onChange:m=>v(d.id,m.target.checked)}),e.jsx("span",{children:d.label})]},d.id))})}function Oe(){const{toast:a}=ve(),{data:r,isLoading:t}=Te(),{data:n}=Ne(),c=ke(),p=Ae(),v=$e(),[d,m]=i.useState(!1),[x,oe]=i.useState(""),[g,L]=i.useState(""),[D,M]=i.useState(""),[I,O]=i.useState("admin"),[y,B]=i.useState(""),[b,H]=i.useState("email"),[E,J]=i.useState(""),[K,Q]=i.useState(""),[z,_]=i.useState([]),[U,G]=i.useState(null),[V,X]=i.useState(""),[W,T]=i.useState(""),[Y,k]=i.useState("dispatcher"),[N,A]=i.useState(""),[Z,$]=i.useState(""),[ee,w]=i.useState([]),{data:de=[]}=ne(y||void 0),{data:ce=[]}=ne(N||void 0),se=(r||[]).filter(s=>{if(!x)return!0;const l=x.toLowerCase();return s.email.toLowerCase().includes(l)||(s.full_name||"").toLowerCase().includes(l)||(s.phone||"").toLowerCase().includes(l)}),me=i.useMemo(()=>new Map((n||[]).map(s=>[s.id,s.name])),[n]);function he(){L(""),M(""),O("admin"),B(""),J(""),Q(""),_([]),H("email")}function S(){G(null),X(""),T(""),k("dispatcher"),A(""),$(""),w([])}function ue(s){s.company_id&&(m(!1),G(s.id),X(s.email),T(s.full_name||""),k(s.role),A(s.company_id),$(s.phone||""),w(s.team_ids||[]))}const pe=async s=>{s.preventDefault();try{const l={email:g,full_name:D||void 0,role:I,company_id:y,phone:K||void 0,team_ids:z};b==="email"&&E&&(l.password=E),await c.mutateAsync(l);const C=b==="email"?`${g} can now sign in with email, password, or verified phone.`:`${g} has been set up for Google or verified phone sign-in.`;a({title:"User provisioned",description:C}
1),he(),m(!1)}catch(l){a({title:"Provisioning failed",description:l instanceof Error?l.message:"Unknown error",variant:"destructive"})}},xe=async s=>{if(s.preventDefault(),!!U)try{await p.mutateAsync({id:U,full_name:W,role:Y,company_id:N,phone:Z,team_ids:ee}),a({title:"User updated",description:`${V} has been updated.`}),S()}catch(l){a({title:"Update failed",description:l instanceof Error?l.message:"Unknown error",variant:"destructive"})}},fe=async(s,l)=>{if(window.confirm(`Remove ${l}? They will no longer be able to sign in.`))try{await v.mutateAsync(s),a({title:"User removed",description:`${l} has been removed.`})}catch(C){a({title:"Delete failed",description:C instanceof Error?C.message:"Unknown error",variant:"destructive"})}};return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h1",{className:"text-2xl font-bold",children:"User Management"}),e.jsxs(h,{onClick:()=>{S(),m(!d)},children:[e.jsx(we,{className:"h-4 w-4 mr-2"}),"Add User"]})]}),d&&e.jsxs(F,{children:[e.jsx(ae,{children:e.jsx(te,{className:"text-lg",children:"Provision New User"})}),e.jsx(P,{children:e.jsxs("form",{onSubmit:pe,className:"grid grid-cols-1 sm:grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"prov-email",children:"Email"}),e.jsx(u,{id:"prov-email",type:"email",value:g,onChange:s=>L(s.target.value),placeholder:"[email protected]",required:!0})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"prov-name",children:"Full Name"}),e.jsx(u,{id:"prov-name",value:D,onChange:s=>M(s.target.value),placeholder:"Jane Smith"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"prov-auth",children:"Sign-in Method"}),e.jsxs("select",{id:"prov-auth",value:b,onChange:s=>H(s.target.value),className:"h-10 w-full rounded-md border border-input bg-background px-3 text-sm",children:[e.jsx("option",{value:"email",children:"Email + Password"}),e.jsx("option",{value:"google",children:"Google OAuth"})]})]}),b==="email"&&e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"prov-password",children:"Password"}),e.jsx(u,{id:"prov-password",type:"password",value:E,onChange:s=>J(s.target.value),placeholder:"Min 6 characters",minLength:6,required:!0})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"prov-role",children:"Role"}),e.jsx("select",{id:"prov-role",value:I,onChange:s=>O(s.target.value),className:"h-10 w-full rounded-md border border-input bg-background px-3 text-sm",required:!0,children:ie.map(s=>e.jsx("option",{value:s.value,children:s.label},s.value))})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"prov-company",children:"Company"}),e.jsxs("select",{id:"prov-company",value:y,onChange:s=>{B(s.target.value),_([])},className:"h-10 w-full rounded-md border border-input bg-background px-3 text-sm",required:!0,children:[e.jsx("option",{value:"",children:"Select company..."}),(n||[]).map(s=>e.jsx("option",{value:s.id,children:s.name},s.id))]})]}),e.jsxs("div",{className:"space-y-2 sm:col-span-2",children:[e.jsx(o,{htmlFor:"prov-phone",children:"Phone"}),e.jsx(u,{id:"prov-phone",type:"tel",value:K,onChange:s=>Q(s.target.value),placeholder:"(555) 123-4567"})]}),e.jsxs("div",{className:"space-y-2 sm:col-span-2",children:[e.jsx(o,{children:"Teams"}),e.jsx(re,{idPrefix:"prov-team",teams:de,selectedIds:z,onChange:_,disabled:!y})]}),e.jsxs("div",{className:"sm:col-span-2 flex gap-2",children:[e.jsx(h,{type:"submit",disabled:c.isPending,children:c.isPending?"Provisioning...":"Provision User"}),e.jsx(h,{type:"button",variant:"ghost",onClick:()=>m(!1),children:"Cancel"})]})]})})]}),U&&e.jsxs(F,{children:[e.jsxs(ae,{className:"flex flex-row items-center justify-between",children:[e.jsx(te,{className:"text-lg",children:"Edit User"}),e.jsx(h,{type:"button",variant:"ghost",size:"sm",onClick:S,children:e.jsx(ge,{className:"h-4 w-4"})})]}),e.jsx(P,{children:e.jsxs("form",{onSubmit:xe,className:"grid grid-cols-1 sm:grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"edit-email",children:"Email"}),e.jsx(u,{id:"edit-email",value:V,disabled:!0})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"edit-name",children:"Full Name"}),e.jsx(u,{id:"edit-name",value:W,onChange:s=>T(s.target.value),placeholder:"Jane Smith"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"edit-role",children:"Role"}),e.jsx("select",{id:"edit-role",value:Y,onChange:s=>k(s.target.value),className:"h-10 w-full rounded-md border border-input bg-background px-3 text-sm",required:!0,children:ie.map(s=>e.jsx("option",{value:s.value,children:s.label},s.value))})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(o,{htmlFor:"edit-company",children:"Company"}),e.jsx("select",{id:"edit-company",value:N,onChange:s=>{A(s.target.value),w([])},className:"h-10 w-full rounded-md border border-input bg-background px-3 text-sm",required:!0,children:(n||[]).map(s=>e.jsx("option",{value:s.id,children:s.name},s.id))})]}),e.jsxs("div",{className:"space-y-2 sm:col-span-2",children:[e.jsx(o,{htmlFor:"edit-phone",children:"Phone"}),e.jsx(u,{id:"edit-phone",type:"tel",value:Z,onChange:s=>$(s.target.value),placeholder:"(555) 123-4567"})]}),e.jsxs("div",{className:"space-y-2 sm:col-span-2",children:[e.jsx(o,{children:"Teams"}),e.jsx(re,{idPrefix:"edit-team",teams:ce,selectedIds:ee,onChange:w,disabled:!N})]}),e.jsxs("div",{className:"sm:col-span-2 flex gap-2",children:[e.jsx(h,{type:"submit",disabled:p.isPending,children:p.isPending?"Saving...":"Save Changes"}),e.jsx(h,{type:"button",variant:"ghost",onClick:S,children:"Cancel"})]})]})})]}),e.jsx(F,{children:e.jsx(P,{className:"pt-4",children:e.jsxs("div",{className:"relative",children:[e.jsx(ye,{className:"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground"}),e.jsx(u,{placeholder:"Search by email, name, or phone...",value:x,onChange:s=>oe(s.target.value),className:"pl-9"})]})})}),e.jsx(F,{children:e.jsx(P,{className:"p-0",children:t?e.jsx("div",{className:"flex items-center justify-center h-32",children:e.jsx("div",{className:"animate-pulse text-muted-foreground",children:"Loading..."})}):se.length===0?e.jsx("div",{className:"flex flex-col items-center justify-center h-32 text-muted-foreground",children:e.jsx("p",{children:"No users found"})}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b bg-slate-50",children:[e.jsx("th",{className:"text-left p-3 font-medium",children:"Email"}),e.jsx("th",{className:"text-left p-3 font-medium hidden sm:table-cell",children:"Name"}),e.jsx("th",{className:"text-left p-3 font-medium",children:"Role"}),e.jsx("th",{className:"text-left p-3 font-medium hidden md:table-cell",children:"Phone"}),e.jsx("th",{className:"text-left p-3 font-medium hidden lg:table-cell",children:"Teams"}),e.jsx("th",{className:"text-left p-3 font-medium hidden xl:table-cell",children:"Created"}),e.jsx("th",{className:"text-right p-3 font-medium",children:"Actions"})]})}),e.jsx("tbody",{children:se.map(s=>e.jsxs("tr",{className:"border-b hover:bg-slate-50 transition-colors",children:[e.jsxs("td",{className:"p-3 font-medium",children:[e.jsx("div",{children:s.email}),s.company_id&&e.jsx("div",{className:"text-xs font-normal text-muted-foreground",children:me.get(s.company_id)||s.company_id})]}),e.jsx("td",{className:"p-3 text-muted-foreground hidden sm:table-cell",children:s.full_name||"-"}),e.jsx("td",{className:"p-3",children:e.jsx("span",{className:`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${s.role==="super_admin"?"bg-indigo-100 text-indigo-700":s.role==="admin"?"bg-blue-100 text-blue-700":s.role==="hr"?"bg-amber-100 text-amber-700":"bg-slate-100 text-slate-700"}`,children:qe[s.role]||s.role})}),e.jsx("td",{className:"p-3 hidden md:table-cell",children:s.phone?e.jsxs("div",{className:"space-y-1",children:[e.jsx("div",{children:s.phone}),e.jsx("span",{className:`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${s.phone_verified?"bg-emerald-100 text-emerald-700":"bg-slate-100 text-slate-700"}`,children:s.phone_verified?"Verified":"Unverified"})]}):e.jsx("span",{className:"text-muted-foreground",children:"-"})}),e.jsx("td",{className:"p-3 text-muted-foreground hidden lg:table-cell",children:s.team_ids?.length?`${s.team_ids.length} team${s.team_ids.length===1?"":"s"}`:"-"}),e.jsx("td",{className:"p-3 text-muted-foreground hidden xl:table-cell",children:be(new Date(s.created_at),{addSuffix:!0})}),e.jsx("td",{className:"p-3 text-right",children:s.role!=="super_admin"&&e.jsxs("div",{className:"flex items-center justify-end gap-1",children:[e.jsx(h,{variant:"ghost",size:"sm",onClick:()=>ue(s),disabled:p.isPending,children:e.jsx(Se,{className:"h-4 w-4"})}),e.jsx(h,{variant:"ghost",size:"sm",onClick:()=>fe(s.id,s.email),disabled:v.isPending,children:e.jsx(Ce,{className:"h-4 w-4 text-rose-500"})})]})})]},s.id))})]})})})})]})}export{Oe 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.