1import{l as t,e as $e,aL as qe,J as Qe,y as r,k as He,s as p,K as _,H as i,at as ye,ax as Z,ab as Ve,ac as Xe,a0 as be,Q as D,R as B,T as F,V as I,W as O,aw as Ce,O as Ne,aM as Se,B as Ge,aN as We,aO as Pe,$ as Ye,X as z,N as Je,G as d,aP as ke,aQ as Ze,aR as _e,aS as et,aT as M}from"./index-BlWJXOKl.js";import{E as tt}from"./empty-state-Djotqn7k.js";import{S as st,a as at,b as rt,c as ot,d as nt}from"./select-Cb6WUDzo.js";import{A as it}from"./add-site-dialog-DSt2nqIU.js";import{C as $,u as lt,r as ct,g as dt,S as mt,v as ut,s as ht}from"./portal-sites-CJbJJeKs.js";import{A as w,S as pt,a as xt,b as gt}from"./site-picker-DBl4r578.js";import{L as Ee}from"./lcr-table-ND-eaTiA.js";import{u as ft,a as wt,C as jt}from"./crat-data-JvYID9bF.js";import{f as Re}from"./dates-B3fEvU1D.js";import{I as vt}from"./image-plus-C_SwiKIi.js";import{I as yt}from"./image-off-Ce7PmBJK.js";import{T as K}from"./trash-2-DrMLs71x.js";import{D as Ae}from"./download-0bQLzQuX.js";import{E as bt}from"./eye-CdYv1Z_w.js";import"./inbox-Cx7SLX5C.js";import"./chevron-up-C67YE0Jl.js";import"./badge-Dp9vI53R.js";import"./arrow-left-BYvWXTz9.js";import"./table-DyXVsDX_.js";import"./arrow-up-down-DyDcQs7x.js";function Ct(x){return t.jsx(it,{registry:$,readyFor:"contracts",...x})}$.photoBucket;function Nt(x,u){return lt($,x,u)}function St(x){return ct($,x)}function Vt(){var je;const{user:x}=$e(),{canManage:u,isSuperUser:Le,loading:ee}=qe(),te=Qe(),[h,j]=r.useState(w),[b,se]=r.useState(""),[Te,q]=r.useState(!1),[Q,ae]=r.useState(""),[re,H]=r.useState(""),[o,E]=r.useState(null),[Ue,V]=r.useState(!1),[n,oe]=r.useState(null),[v,R]=r.useState(null),[De,X]=r.useState(!1),[g,A]=r.useState(null),ne=r.useRef(null),ie=r.useRef(null),{data:f=[],isLoading:L,error:Be}=ft(),{data:le=[]}=wt(),{data:C=[],isLoading:ce,error:Fe}=He({queryKey:["crat-contracts"],enabled:!!x,queryFn:async()=>{const{data:e,error:s}=await p.from("crat_contracts").select("id, site_id, title, filename, storage_path, mime_type, size_bytes, uploaded_by, created_at, profiles:uploaded_by(display_name)").order("created_at",{ascending:!1}).limit(1e3);if(s)throw s;return e??[]}}),y=r.useMemo(()=>new Map(f.map(e=>[e.id,e])),[f]),l=h===w?null:y.get(h)??null;r.useEffect(()=>{h!==w&&!L&&!y.has(h)&&j(w)},[h,L,y]),r.useEffect(()=>()=>{n&&URL.revokeObjectURL(n.url)},[n]);const N=r.useMemo(()=>dt(C),[C]),de=r.useMemo(()=>{const e=new Map;for(const s of le)e.set(s.site_id,(e.get(s.site_id)??0)+1);return e},[le]),T=r.useMemo(()=>{const e=b.trim().toLowerCase();return C.filter(s=>(h===w||s.site_id===h)&&(!e||s.title.toLowerCase().includes(e)||s.filename.toLowerCase().includes(e)))},[C,h,b]),me=()=>te.invalidateQueries({queryKey:["crat-contracts"]}),G=()=>te.invalidateQueries({queryKey:jt});function S(e){if(!u)throw new Error(`Only Contract & Risk managers can ${e}.`)}const m=_({mutationFn:async()=>{if(!x)throw new Error("Sign in first.");S("upload contracts");const e=y.get(Q);if(!e)throw new Error("Choose a site.");if(!o)throw new Error("Choose a contract file to upload.");if(o.size>_e)throw new Error(`${o.name} exceeds the 50 MB upload limit.`);const s=crypto.randomUUID(),a=et(e.id,s,o.name),{error:c}=await p.storage.from(M).upload(a,o,{cacheControl:"3600",upsert:!1});if(c)throw new Error(c.message);const{error:ve}=await p.from("crat_contracts").insert({id:s,site_id:e.id,title:re.trim()||Se(o.name),filename:o.name,storage_path:a,mime_type:o.type||null,size_bytes:o.size,uploaded_by:x.id});if(ve)throw await p.storage.from(M).remove([a]),new Error(ve.message);return e},onSuccess:e=>{d.success("Contract uploaded",{description:`Filed under ${e.name}.`}),q(!1),E(null),H(""),j(e.id),me()},onError:e=>d.error("Upload failed",{description:e.message})});function Ie(e){var a;const s=e&&y.has(e)?e:((a=f[0])==null?void 0:a.id)??"";ae(s),H(""),E(null),q(!0)}function ue(){m.isPending||q(!1)}function he(e){const s=e==null?void 0:e[0];if(s){if(s.size>_e){d.error("File too large",{description:`${s.name} exceeds the 50 MB upload limit.`});return}E(s)}}const P=_({mutationFn:async e=>{S("remove contracts");const{error:s}=await p.storage.from(M).remove([e.storage_path]);if(s)throw new Error(s.message);const{error:a}=await p.from("crat_contracts").delete().eq("id",e.id);if(a)throw new Error(a.message)},onSuccess:()=>{d.success("Contract removed"),R(null),me()},onError:e=>d.error("Could not remove contract",{description:e.message})}),k=_({mutationFn:async e=>{var a;if(S("remove sites"),(((a=N.get(e.id))==null?void 0:a.length)??0)>0)throw new Error("Remove this siteâs contracts first.");if((de.get(e.id)??0)>0)throw new Error("Remove this siteâs KPIs first.");const{error:s}=await p.from("crat_sites").delete().eq("id",e.id);if(s)throw s.code==="23503"?new Error("This site still has contracts or KPIs."):new Error(s.message)},onSuccess:()=>{d.success("Site removed"),A(null),j(w),G()},onError:e=>d.error("Could not remove site",{description:e.message})}),U=_({mutationFn:async({site:e,file:s})=>{S("change a site's display picture");const a=await Nt(e.id,s),{error:c}=await p.from("crat_sites").update({photo_url:a}).eq("id",e.id);if(c)throw new Error(c.message)},onSuccess:()=>{d.success("Display picture updated"),G()},onError:e=>d.error("Could not update picture",{description:e.message})}),W=_({mutationFn:async e=>{S("remove a site's display picture"),await St(e.id);const{error:s}=await p.from("crat_sites").update({photo_url:null}).eq("id",e.id);if(s)throw new Error(s.message)},onSuccess:()=>{d.success("Display picture removed"),G()},onError:e=>d.error("Could not remove picture",{description:e.message})});function Oe(e){const s=e==null?void 0:e[0];if(!s||!l)return;const a=ut(s);if(a){d.error("Photo not accepted",{description:a});return}U.mutate({site:l,file:s})}async function pe(e){const{data:s,error:a}=await p.storage.from(M).download(e.storage_path);return a||!s?(d.error("Could not load file",{description:a==null?void 0:a.message}),null):s}async function Y(e){const s=await pe(e);if(!s)return;const a=URL.createObjectURL(s),c=document.createElement("a");c.href=a,c.download=e.filename,document.body.appendChild(c),c.click(),c.remove(),URL.revokeObjectURL(a)}async function ze(e){const s=ke(e.mime_type,e.filename);if(!s){Y(e);return}const a=await pe(e);if(!a)return;const c=new Blob([a],{type:s==="pdf"?"application/pdf":a.type});oe({contract:e,url:URL.createObjectURL(c),kind:s})}const xe=h===w,ge=[{key:"contract",header:"Contract",width:xe?"32%":"44%",align:"left",render:e=>t.jsxs("div",{className:"min-w-0",children:[t.jsx("p",{className:"truncate font-medium",title:e.title,children:e.title}),t.jsx("p",{className:"truncate text-xs text-muted-foreground",title:e.filename,children:e.filename})]})},...xe?[{key:"site",header:"Site",width:"16%",align:"left",hideBelow:"md",render:e=>{const s=y.get(e.site_id);return s?t.jsxs("span",{className:"inline-flex min-w-0 items-center gap-2",children:[t.jsx(Ze,{name:s.name,slug:ht(s),src:s.photo_url,className:"h-6 w-6 rounded",fallbackClassName:"rounded bg-brand/10 text-[10px] font-bold text-brand"}),t.jsx("span",{className:"truncate font-mono text-xs uppercase text-muted-foreground",title:s.name,children:s.code})]}):t.jsx("span",{className:"text-xs text-muted-foreground",children:"â"})}}]:[],{key:"by",header:"Uploaded by",width:"16%",hideBelow:"lg",cellClassName:"text-sm text-muted-foreground",render:e=>{var s;return((s=e.profiles)==null?void 0:s.display_name)??"â"}},{key:"on",header:"Uploaded",width:"12%",hideBelow:"sm",cellClassName:"text-sm text-muted-foreground",render:e=>Re(e.created_at)},{key:"size",header:"Size",width:"9%",hideBelow:"lg",cellClassName:"font-mono text-xs text-muted-foreground",render:e=>Pe(e.size_bytes)},{key:"actions",header:"",width:"15%",align:"right",render:e=>{const s=ke(e.mime_type,e.filename)!==null;return t.jsxs("div",{className:"flex items-center justify-end gap-0.5",children:[s&&t.jsx(i,{size:"icon",variant:"ghost",className:"h-8 w-8","aria-label":`Preview ${e.title}`,title:"Preview",onClick:()=>void ze(e),children:t.jsx(bt,{className:"h-4 w-4"})}),t.jsx(i,{size:"icon",variant:"ghost",className:"h-8 w-8","aria-label":`Download ${e.title}`,title:"Download",onClick:()=>void Y(e),children:t.jsx(Ae,{className:"h-4 w-4"})}),u&&t.jsx(i,{size:"icon",variant:"ghost",className:"h-8 w-8 text-muted-foreground hover:text-destructive","aria-label":`Remove ${e.title}`,title:"Remove",onClick:()=>R(e),children:t.jsx(K,{className:"h-4 w-4"})})]})}}
1],fe=Be??Fe,Me=l?((je=N.get(l.id))==null?void 0:je.length)??0:0,Ke=l?de.get(l.id)??0:0,J=Me>0?"contracts":Ke>0?"KPIs":null,we=e=>t.jsxs("div",{className:"relative min-w-[220px]",children:[t.jsx(Je,{className:"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground"}),t.jsx(Ne,{value:b,onChange:s=>se(s.target.value),placeholder:e,className:"pl-9"})]});return t.jsxs("div",{className:"space-y-6",children:[t.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[t.jsxs("div",{className:"space-y-1",children:[t.jsx("p",{className:"text-xs font-semibold uppercase tracking-[0.2em] text-brand",children:"Contract & Risk Assessment"}),t.jsx("h2",{className:"font-display text-2xl font-semibold tracking-tight",children:"Site Contracts"}),t.jsx("p",{className:"max-w-2xl text-sm text-muted-foreground",children:"Upload contracts and browse them by site. Sites here are tracked by this portal on their own â they don't need to exist in the Life Cycle Portal. Everyone with access can view and download; managers can add sites and upload or remove contracts."})]}),u&&t.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[t.jsxs(i,{variant:"outline",className:"gap-1.5",onClick:()=>X(!0),children:[t.jsx(ye,{className:"h-4 w-4"}),"Add site"]}),f.length>0&&t.jsxs(i,{className:"gap-1.5",onClick:()=>Ie(l==null?void 0:l.id),children:[t.jsx(Z,{className:"h-4 w-4"}),"Upload contract"]})]})]}),t.jsx(pt,{sites:f,selectedId:h,totalCount:C.length,countFor:e=>{var s;return((s=N.get(e.id))==null?void 0:s.length)??0},onSelect:j}),fe&&t.jsxs("div",{className:"rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm",children:["Couldn't load the contract library: ",fe.message]}),!L&&!ee&&f.length===0?t.jsx(Ve,{children:t.jsx(tt,{icon:Xe,title:"No sites yet",description:u?"Add the first site and its contract library will appear here.":"No sites have been added to Contract & Risk Assessment yet. A portal manager can add them.",children:u&&t.jsxs(i,{size:"sm",variant:"outline",className:"mt-2 gap-1.5",onClick:()=>X(!0),children:[t.jsx(ye,{className:"h-4 w-4"}),"Add a site"]})})}):l?t.jsxs("div",{className:"space-y-4",children:[t.jsx(xt,{site:l,subtitle:`${T.length} contract${T.length===1?"":"s"}`,onBack:()=>j(w),actions:t.jsxs(t.Fragment,{children:[we("Search this site's contractsâ¦"),u&&t.jsxs(t.Fragment,{children:[t.jsxs(i,{variant:"ghost",size:"sm",className:"gap-1.5 text-muted-foreground hover:text-foreground",disabled:U.isPending||W.isPending,title:l.photo_url?"Replace the display picture":"Add a display picture",onClick:()=>{var e;return(e=ie.current)==null?void 0:e.click()},children:[t.jsx(vt,{className:"h-4 w-4"}),U.isPending?"Uploadingâ¦":l.photo_url?"Change photo":"Add photo"]}),l.photo_url&&t.jsxs(i,{variant:"ghost",size:"sm",className:"gap-1.5 text-muted-foreground hover:text-foreground",disabled:U.isPending||W.isPending,title:"Remove the display picture",onClick:()=>W.mutate(l),children:[t.jsx(yt,{className:"h-4 w-4"}),"Remove photo"]}),t.jsx("input",{ref:ie,type:"file",accept:mt,className:"hidden",onChange:e=>{Oe(e.target.files),e.target.value=""}}),t.jsxs(i,{variant:"ghost",size:"sm",className:"gap-1.5 text-muted-foreground hover:text-destructive",disabled:J!==null,title:J?`Remove its ${J} before removing the site`:"Remove this site",onClick:()=>A(l),children:[t.jsx(K,{className:"h-4 w-4"}),"Remove site"]})]})]})}),t.jsx(Ee,{columns:ge,rows:T,isLoading:ce,getRowKey:e=>e.id,empty:{icon:t.jsx(be,{className:"h-8 w-8 text-muted-foreground/50"}),text:b?"No contracts match your search.":u?"No contracts for this site yet â upload the first one.":"No contracts have been uploaded for this site yet."}})]}):t.jsxs("div",{className:"space-y-6",children:[t.jsx(gt,{sites:f,loading:L,countFor:e=>{var s;return((s=N.get(e.id))==null?void 0:s.length)??0},subtitleFor:e=>{var a;const s=(a=N.get(e.id))==null?void 0:a[0];return s?`Latest upload ${Re(s.created_at)}`:"No contracts yet"},onSelect:j}),t.jsxs("div",{className:"space-y-3",children:[t.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[t.jsx("h3",{className:"font-display text-base font-semibold",children:"All contracts"}),we("Search all contractsâ¦")]}
1),t.jsx(Ee,{columns:ge,rows:T,isLoading:ce,getRowKey:e=>e.id,empty:{icon:t.jsx(be,{className:"h-8 w-8 text-muted-foreground/50"}),text:b?"No contracts match your search.":u?"No contracts uploaded yet â pick a site and upload the first one.":"No contracts have been uploaded yet."}})]})]}),t.jsx(D,{open:Te,onOpenChange:e=>!e&&ue(),children:t.jsxs(B,{className:"sm:max-w-lg",children:[t.jsxs(F,{children:[t.jsx(I,{children:"Upload contract"}),t.jsx(O,{children:"Add a contract file to a site's library. Everyone with access to this portal will be able to view and download it."})]}),t.jsxs("div",{className:"space-y-4",children:[t.jsxs("div",{className:"space-y-1.5",children:[t.jsx(Ce,{children:"Site"}),t.jsxs(st,{value:Q,onValueChange:ae,disabled:m.isPending,children:[t.jsx(at,{children:t.jsx(rt,{placeholder:"Choose a siteâ¦"})}),t.jsx(ot,{children:f.map(e=>t.jsxs(nt,{value:e.id,children:[t.jsx("span",{className:"font-mono text-xs text-muted-foreground",children:e.code})," · ",e.name]},e.id))})]})]}),t.jsxs("div",{className:"space-y-1.5",children:[t.jsxs(Ce,{htmlFor:"crat-title",children:["Title ",t.jsx("span",{className:"font-normal text-muted-foreground",children:"(optional)"})]}),t.jsx(Ne,{id:"crat-title",value:re,onChange:e=>H(e.target.value),placeholder:o?Se(o.name):"e.g. Master Services Agreement",disabled:m.isPending})]}),t.jsxs("div",{onDragOver:e=>{e.preventDefault(),m.isPending||V(!0)},onDragLeave:()=>V(!1),onDrop:e=>{e.preventDefault(),V(!1),m.isPending||he(e.dataTransfer.files)},onClick:()=>{var e;m.isPending||(e=ne.current)==null||e.click()},className:Ge("cursor-pointer rounded-xl border border-dashed px-5 py-7 text-center transition-all duration-200",Ue?"border-brand bg-brand/10":"border-glass-border/70 bg-glass/50 hover:border-brand/40 hover:bg-brand/5",m.isPending&&"cursor-not-allowed opacity-60"),children:[t.jsx(Z,{className:"mx-auto h-6 w-6 text-muted-foreground/45"}),t.jsx("p",{className:"mt-2 text-sm font-medium",children:o?"Drop a different file to replace it":"Drop a contract here or click to browse"}),t.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:"PDF, Word, Excel, images, or text â up to 50 MB."})]}),t.jsx("input",{ref:ne,type:"file",accept:We,className:"hidden",onChange:e=>{he(e.target.files),e.target.value=""}}),o&&t.jsxs("div",{className:"flex items-center justify-between gap-3 rounded-xl border border-glass-border/70 bg-background/70 px-3 py-2.5 shadow-sm",children:[t.jsxs("div",{className:"min-w-0 flex-1",children:[t.jsx("p",{className:"truncate text-sm font-medium",title:o.name,children:o.name}),t.jsx("p",{className:"text-xs text-muted-foreground",children:Pe(o.size)})]}),t.jsx(i,{size:"icon",variant:"ghost",className:"h-7 w-7",disabled:m.isPending,onClick:()=>E(null),"aria-label":`Remove ${o.name}`,children:t.jsx(Ye,{className:"h-4 w-4"})})]})]}),t.jsxs(z,{children:[t.jsx(i,{variant:"ghost",onClick:ue,disabled:m.isPending,children:"Cancel"}),t.jsxs(i,{className:"gap-1.5",disabled:!Q||!o||m.isPending,onClick:()=>m.mutate(),children:[t.jsx(Z,{className:"h-4 w-4"}),m.isPending?"Uploadingâ¦":"Upload"]})]})]})}),t.jsx(D,{open:!!n,onOpenChange:e=>!e&&oe(null),children:t.jsxs(B,{className:"max-w-5xl",children:[t.jsxs(F,{className:"pr-8",children:[t.jsx(I,{className:"truncate",children:(n==null?void 0:n.contract.title)??"Preview"}),t.jsx(O,{className:"truncate",children:n==null?void 0:n.contract.filename})]}),n&&t.jsx("div",{className:"h-[70vh] min-h-[320px] shrink-0 overflow-hidden rounded-lg border border-glass-border/60 bg-muted/30",children:n.kind==="pdf"?t.jsx("iframe",{src:`${n.url}#toolbar=0&navpanes=0`,title:n.contract.title,className:"h-full w-full border-0"}):t.jsx("img",{src:n.url,alt:n.contract.title,className:"h-full w-full object-contain"})}),t.jsx(z,{children:t.jsxs(i,{variant:"outline",className:"gap-1.5",onClick:()=>n&&void Y(n.contract),children:[t.jsx(Ae,{className:"h-4 w-4"}),"Download"]})})]})}),t.jsx(D,{open:!!v,onOpenChange:e=>!e&&!P.isPending&&R(null),children:t.jsxs(B,{className:"sm:max-w-md",children:[t.jsxs(F,{children:[t.jsx(I,{children:"Remove contract?"}),t.jsxs(O,{children:[t.jsx("span",{className:"font-medium text-foreground",children:v==null?void 0:v.title})," and its file will be permanently removed from this site's library."]})]}),t.jsxs(z,{children:[t.jsx(i,{variant:"ghost",onClick:()=>R(null),disabled:P.isPending,children:"Cancel"}),t.jsxs(i,{variant:"destructive",className:"gap-1.5",disabled:P.isPending,onClick:()=>v&&P.mutate(v),children:[t.jsx(K,{className:"h-4 w-4"}),P.isPending?"Removingâ¦":"Remove"]})]})]})}),t.jsx(D,{open:!!g,onOpenChange:e=>!e&&!k.isPending&&A(null),children:t.jsxs(B,{className:"sm:max-w-md",children:[t.jsxs(F,{children:[t.jsx(I,{children:"Remove site?"}),t.jsxs(O,{children:[t.jsx("span",{className:"font-medium text-foreground",children:g==null?void 0:g.name})," (",g==null?void 0:g.code,") will be removed from Contract & Risk Assessment. This doesn't affect the Life Cycle Portal."]})]}),t.jsxs(z,{children:[t.jsx(i,{variant:"ghost",onClick:()=>A(null),disabled:k.isPending,children:"Cancel"}),t.jsxs(i,{variant:"destructive",className:"gap-1.5",disabled:k.isPending,onClick:()=>g&&k.mutate(g),children:[t.jsx(K,{className:"h-4 w-4"}),k.isPending?"Removingâ¦":"Remove site"]})]})]})}),t.jsx(Ct,{open:De,onOpenChange:X,onCreated:e=>{se(""),j(e.id)}}),Le&&!ee&&t.jsx("p",{className:"text-center font-mono text-[10px] uppercase tracking-widest text-muted-foreground
1/50",children:"Super user · full access to this portal"})]})}export{Vt as SiteContracts};
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.