PageSourceSearch

https://www.coastalreconstruction.com/assets/_reports.reports.team-B9jgD07V.js

js coastalreconstruction.com collected 2026-10-04 21:15:01 UTC 7,325 bytes, 1 lines download raw bytes

1import{c as N,k as I,i as S,x as i,j as a,X as k,B as d,r as f,J as C}from"./index-BCGrvFuq.js";import{u as y,f as w}from"./queries-CWzLUq4Z.js";import{u as x}from"./useMutation-Dw0vjPeH.js";import{r as j,i as b,g as F,a as A}from"./reports-team.functions-DKnqBX6S.js";import{I as p}from"./input-DgtOFYLN.js";import{L as u}from"./label-opIYTMqD.js";import{B as D}from"./badge-BduXL2S1.js";import{S as R}from"./skeleton-qDqPJJin.js";import{I as T,S as E,r as L}from"./primitives-auO43y7A.js";import{S as _,a as q,b as P,c as $,d as B}from"./select-BtwWZyAb.js";import{d as z,g as M,e as O,h as K,f as Q,i as U,j as G}from"./dialog-BR-MpFEH.js";import"./auth-middleware-ret5nsuJ.js";import"./index-DhMUBjnI.js";import"./index-BBpOTIOW.js";import"./index-CrZSH2-t.js";import"./index-C6nczEkU.js";const H=[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}],["line",{x1:"19",x2:"19",y1:"8",y2:"14",key:"1bvyxn"}],["line",{x1:"22",x2:"16",y1:"11",y2:"11",key:"1shjgl"}]],J=N("user-plus",H),g={admin:"Admin",staff:"Staff",client:"Client"};function V(t){return t?L(t):"Never signed in"}function ue(){const{isAdmin:t}=I(),h=S(),c=y({queryKey:["reports","users"],queryFn:()=>A()}),o=()=>h.invalidateQueries({queryKey:["reports","users"]}),n=x({mutationFn:e=>j({data:e}),onSuccess:e=>{if(!e.ok)return i.error(e.error);i.success("Access removed."),o()},onError:e=>i.error(e.message)}),r=x({mutationFn:e=>b({data:{email:e.email,name:e.name??void 0,role:e.role}}),onSuccess:e=>{if(!e.ok)return i.error(e.error);i.success("Invite resent."),o()},onError:e=>i.error(e.message)}),m=x({mutationFn:async e=>{const s=await F({data:{email:e.email,role:e.to}});return s.ok?j({data:{userId:e.userId,role:e.from}}):s},onSuccess:e=>{if(!e.ok)return i.error(e.error);i.success("Role updated."),o()},onError:e=>i.error(e.message)});return a.jsxs("div",{children:[a.jsxs("div",{className:"mb-6 flex flex-wrap items-center justify-between gap-3",children:[a.jsx("h1",{className:"display text-2xl font-bold text-navy sm:text-3xl",children:"Team and client access"}),t&&a.jsxs("div",{className:"flex flex-wrap gap-2",children:[a.jsx(v,{kind:"staff",onDone:o}),a.jsx(v,{kind:"client",onDone:o})]})]}),!t&&a.jsx("p",{className:"mb-4 rounded-md border border-ink/10 bg-white px-4 py-3 text-sm text-ink/65",children:"You can view access here. An admin can invite people and change roles."}),c.isLoading?a.jsx("div",{className:"space-y-3",children:Array.from({length:5}).map((e,s)=>a.jsx(R,{className:"h-16 rounded-xl"},s))}):a.jsx("div",{className:"overflow-hidden rounded-xl border border-ink/10 bg-white",children:a.jsxs("ul",{className:"divide-y divide-ink/8",children:[(c.data??[]).map(e=>a.jsxs("li",{className:"grid grid-cols-[auto_minmax(0,1fr)] items-start gap-3 p-4 sm:grid-cols-[auto_minmax(0,1fr)_auto] sm:items-center",children:[a.jsx(T,{name:e.name??e.email,size:"md",tone:"ink"}),a.jsxs("div",{className:"min-w-0",children:[a.jsx("p",{className:"truncate text-sm font-bold text-navy",children:e.name??"Name not set"}),a.jsx("p",{className:"truncate text-xs text-ink/55",children:e.email}),a.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-1.5",children:[e.roles.map(s=>a.jsxs(D,{variant:"secondary",className:"gap-1",children:[g[s]??s,t&&a.jsx("button",{type:"button","aria-label":`Remove ${g[s]??s} access for ${e.email}`,onClick:()=>n.mutate({userId:e.id,role:s}),className:"ml-0.5 rounded-full transition-colors duration-150 hover:text-emergency focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gold",children:a.jsx(k,{className:"h-3 w-3","aria-hidden":"true"})})]},s)),e.roles.length===0&&a.jsx(E,{label:"No access",tone:"neutral"}),a.jsx("span",{className:"text-xs text-ink/45",children:V(e.lastSignInAt)})]})]}),(t||!e.lastSignInAt&&e.roles.length===1&&e.roles[0]==="client")&&a.jsxs("div",{className:"col-span-2 flex flex-wrap gap-2 sm:col-span-1",children:[!e.lastSignInAt&&e.roles.length>0&&a.jsx(d,{size:"sm",variant:"outline",disabled:r.isPending&&r.variables?.email===e.email,onClick:()=>r.mutate({email:e.email,name:e.name,role:e.roles.includes("admin")?"admin":e.roles.includes("staff")?"
1staff":"client"}),children:r.isPending&&r.variables?.email===e.email?"Sending...":"Resend invite"}),t&&e.roles.includes("staff")&&!e.roles.includes("admin")&&a.jsx(d,{size:"sm",variant:"outline",onClick:()=>m.mutate({userId:e.id,email:e.email,from:"staff",to:"admin"}),children:"Make admin"}),t&&e.roles.includes("admin")&&a.jsx(d,{size:"sm",variant:"outline",onClick:()=>m.mutate({userId:e.id,email:e.email,from:"admin",to:"staff"}),children:"Make staff"})]})]},e.id)),(c.data??[]).length===0&&a.jsx("li",{className:"px-4 py-10 text-center text-sm text-ink/55",children:"No accounts yet."})]})})]})}function v({kind:t,onDone:h}){const[c,o]=f.useState(!1),[n,r]=f.useState({email:"",name:"",company:"",jobId:""}),m=y({queryKey:["reports","jobs","picker"],queryFn:w,enabled:c&&t==="client"}),e=x({mutationFn:()=>b({data:{email:n.email.trim(),name:n.name.trim()||void 0,company:t==="client"&&n.company.trim()||void 0,role:t,jobId:t==="client"&&n.jobId?n.jobId:void 0}}),onSuccess:s=>{if(!s.ok)return i.error(s.error);i.success(s.invited?"Invitation sent.":"Access granted to the existing account."),r({email:"",name:"",company:"",jobId:""}),o(!1),h()},onError:s=>i.error(s.message)});return a.jsxs(z,{open:c,onOpenChange:o,children:[a.jsx(M,{asChild:!0,children:a.jsxs(d,{variant:t==="staff"?"default":"outline",children:[a.jsx(J,{className:"mr-2 h-4 w-4","aria-hidden":"true"}),"Invite ",t]})}),a.jsxs(O,{children:[a.jsxs(K,{children:[a.jsxs(Q,{children:["Invite ",t==="staff"?"a staff member":"a client"]}),a.jsx(U,{children:t==="staff"?"They get an email from Coastal Reconstruction Group with a link to create their password, then land on the reports dashboard.":"They get an email from Coastal Reconstruction Group with a link to create their password, then see only the jobs you attach them to."})]}),a.jsxs("form",{className:"space-y-4",onSubmit:s=>{s.preventDefault(),e.mutate()},children:[a.jsxs("div",{className:"space-y-2",children:[a.jsx(u,{htmlFor:`invite-email-${t}`,children:"Email"}),a.jsx(p,{id:`invite-email-${t}`,type:"email",required:!0,value:n.email,onChange:s=>r(l=>({...l,email:s.target.value}))})]}),a.jsxs("div",{className:"space-y-2",children:[a.jsx(u,{htmlFor:`invite-name-${t}`,children:"Full name"}),a.jsx(p,{id:`invite-name-${t}`,value:n.name,onChange:s=>r(l=>({...l,name:s.target.value}))})]}),t==="client"&&a.jsxs(a.Fragment,{children:[a.jsxs("div",{className:"space-y-2",children:[a.jsx(u,{htmlFor:"invite-company",children:"Company"}),a.jsx(p,{id:"invite-company",value:n.company,onChange:s=>r(l=>({...l,company:s.target.value}))})]}),a.jsxs("div",{className:"space-y-2",children:[a.jsx(u,{htmlFor:"invite-job",children:"Attach to a job"}),a.jsxs(_,{value:n.jobId,onValueChange:s=>r(l=>({...l,jobId:s})),children:[a.jsx(q,{id:"invite-job",children:a.jsx(P,{placeholder:"Optional"})}),a.jsx($,{children:(m.data??[]).map(s=>a.jsxs(B,{value:s.id,children:[s.job_number," ",s.property_name]},s.id))})]})]})]}),a.jsx(G,{children:a.jsxs(d,{type:"submit",disabled:e.isPending,children:[e.isPending&&a.jsx(C,{className:"mr-2 h-4 w-4 animate-spin","aria-hidden":"true"}),"Send invitation"]})})]})]})]})}export{ue as component};

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.