PageSourceSearch

https://www.coastalreconstruction.com/assets/_authenticated.vendors.admin-Csuxo1vV.js

js coastalreconstruction.com collected 2026-10-04 21:14:56 UTC 13,154 bytes, 1 lines download raw bytes

1import{k as G,h as F,r as i,s as b,j as e,L as P,F as M,B as x,m as Q,x as p,E as $}from"./index-BCGrvFuq.js";import{I as U}from"./input-DgtOFYLN.js";import{T as I}from"./textarea-9fgiouS3.js";import{L as E}from"./label-opIYTMqD.js";import{B as W}from"./badge-BduXL2S1.js";import{S as R,D as J,C as z}from"./DocumentCard-DHrIOJo4.js";import{a as H}from"./gohighlevel.functions-D-_0pUKN.js";import{S as X}from"./search-Ce1Vfr-0.js";import{R as T}from"./refresh-cw-D7ioWiwr.js";import{C as V}from"./circle-alert-BOTIKWoH.js";import{A as K}from"./arrow-left-BIer0Zp2.js";import{E as Y}from"./external-link-YqreJiaH.js";import"./index-DhMUBjnI.js";import"./upload-DNZ1HFX2.js";import"./auth-middleware-ret5nsuJ.js";import"./types-e6apbZGd.js";const Z="iJzCISjcQOF42WeMyOVp",B=a=>`https://app.gohighlevel.com/v2/location/${Z}/contacts/detail/${a}`;function ee({vendor:a}){return a.ghl_sync_error?e.jsxs("span",{title:a.ghl_sync_error,className:"inline-flex items-center gap-1 text-emergency",children:[e.jsx(V,{className:"h-4 w-4"}),e.jsx("span",{className:"text-xs font-bold",children:"Failed"})]}):a.ghl_contact_id?e.jsxs("a",{href:B(a.ghl_contact_id),target:"_blank",rel:"noopener noreferrer",title:"Open contact in GoHighLevel",className:"inline-flex items-center gap-1 text-green-700 hover:underline",onClick:m=>m.stopPropagation(),children:[e.jsx($,{className:"h-4 w-4"}),e.jsx("span",{className:"text-xs font-bold",children:"Synced"})]}):e.jsx("span",{className:"text-ink/60",children:"—"})}function ve(){const{isAdmin:a,loading:m,signOut:n}=G(),j=F(),[o,O]=i.useState([]),[_,k]=i.useState(null),[f,D]=i.useState(""),[c,h]=i.useState("pending_review"),[g,v]=i.useState(new Set),[N,A]=i.useState({}),[t,l]=i.useState(!1);i.useEffect(()=>{!m&&!a&&j({to:"/vendors/portal"})},[m,a,j]);const u=async()=>{const{data:s}=await b.from("vendors").select("id, company_name, contact_name, contact_email, trade, status, submitted_at, created_at, ghl_contact_id, ghl_sync_error").order("submitted_at",{ascending:!1,nullsFirst:!1});s&&O(s);const{data:r}=await b.from("vendor_documents").select("vendor_id, file_path").not("file_path","is",null);if(r){const d={};for(const C of r)d[C.vendor_id]=(d[C.vendor_id]??0)+1;A(d)}};i.useEffect(()=>{a&&u()},[a]),i.useEffect(()=>{if(!a)return;const s=new Date;s.setDate(s.getDate()+30),b.from("vendor_documents").select("vendor_id, expiry_date").eq("kind","coi").not("expiry_date","is",null).lte("expiry_date",s.toISOString().slice(0,10)).then(({data:r})=>{r&&v(new Set(r.map(d=>d.vendor_id)))})},[a,o]);const S=i.useMemo(()=>{const s=f.trim().toLowerCase();return o.filter(r=>!s||r.company_name?.toLowerCase().includes(s)||r.contact_name?.toLowerCase().includes(s)||r.contact_email.toLowerCase().includes(s)||r.trade?.toLowerCase().includes(s)?c==="all"?!0:c==="expiring"?g.has(r.id):r.status===c:!1)},[o,f,c,g]),y=i.useMemo(()=>({pending_review:o.filter(s=>s.status==="pending_review").length,approved:o.filter(s=>s.status==="approved").length,rejected:o.filter(s=>s.status==="rejected").length,incomplete:o.filter(s=>s.status==="incomplete").length,expiring:g.size,all:o.length}),[o,g]);return m?e.jsx("div",{className:"bg-cream min-h-screen p-10 text-sm text-ink/75",children:"Loading…"}):a?_?e.jsx(se,{vendorId:_,onBack:()=>{k(null),u()}}):e.jsx("div",{className:"bg-cream min-h-screen",children:e.jsxs("div",{className:"mx-auto max-w-7xl px-4 py-10 sm:px-6",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3 mb-8",children:[e.jsxs(P,{to:"/vendors/portal",className:"text-xs uppercase tracking-[0.22em] font-bold text-ink/75 hover:text-gold",children:[e.jsx(M,{className:"inline h-4 w-4 mr-1"})," My packet"]}),e.jsxs(x,{variant:"outline",size:"sm",onClick:async()=>{await n(),j({to:"/vendors"})},children:[e.jsx(Q,{className:"h-4 w-4 mr-1"})," Sign out"]})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-gold font-bold text-xs uppercase tracking-[0.3em] mb-2",children:"Admin"}),e.jsx("h1",{className:"display text-4xl font-bold tracking-tight text-navy",children:"Vendor administration"}),e.jsx("p",{className:"mt-2 text-sm text-ink/65",children:"Review submissions, approve packets, and track expirations."})]}),e.jsxs("div",{className:"mt-6 grid grid-cols-2 gap-3 sm:grid-cols-5",children:[e.jsx(L,{label:"Pending review",value:y.pending_review,active:c==="pending_review",onClick:()=>h("pending_review")}),e.jsx(L,{label:"Approved",value:y.approved,active:c==="approved",onClick:()=>h("approved")}),e.jsx(L,{label:"Rejected",value:y.rejected,active:c==="rejected",onClick:()=>h("rejected")}),e.jsx(L,{label:"Incomplete",value:y.incomplete,active:c==="incomplete",onClick:()=>h("incomplete")}
1),e.jsx(L,{label:"COI ≤30d",value:y.expiring,active:c==="expiring",onClick:()=>h("expiring")})]}),e.jsxs("div",{className:"mt-6 flex flex-wrap items-center gap-3",children:[e.jsxs("div",{className:"relative max-w-md flex-1",children:[e.jsx(X,{className:"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-ink/70"}),e.jsx(U,{value:f,onChange:s=>D(s.target.value),placeholder:"Search company, contact, email, trade…",className:"pl-9"})]}),e.jsxs(x,{variant:"outline",size:"sm",onClick:()=>h("all"),children:["All (",y.all,")"]}),e.jsxs(x,{variant:"outline",size:"sm",disabled:t,onClick:async()=>{l(!0);const s=[...o];let r=0,d=0;const C=p.loading(`Syncing to GoHighLevel 0/${s.length}…`);for(const q of s){try{(await H({data:{vendorId:q.id}}))?.ok||(d+=1)}catch{d+=1}r+=1,p.loading(`Syncing to GoHighLevel ${r}/${s.length}…`,{id:C})}l(!1),p.success(`Synced ${r-d} of ${s.length} vendors${d?`, ${d} failed`:""}`,{id:C}),u()},children:[e.jsx(T,{className:`h-4 w-4 mr-1 ${t?"animate-spin":""}`})," Sync all to GoHighLevel"]})]}),e.jsx("div",{className:"mt-4 overflow-hidden rounded-sm border border-ink/10 bg-white",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{className:"bg-ink/5 text-left text-xs uppercase tracking-wider text-ink/75",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-4 py-3 font-bold",children:"Company"}),e.jsx("th",{className:"px-4 py-3 font-bold",children:"Contact"}),e.jsx("th",{className:"px-4 py-3 font-bold",children:"Trade"}),e.jsx("th",{className:"px-4 py-3 font-bold",children:"Docs"}),e.jsx("th",{className:"px-4 py-3 font-bold",children:"GHL"}),e.jsx("th",{className:"px-4 py-3 font-bold",children:"Status"}),e.jsx("th",{className:"px-4 py-3 font-bold",children:"Submitted"}),e.jsx("th",{className:"px-4 py-3"})]})}),e.jsxs("tbody",{children:[S.length===0&&e.jsx("tr",{children:e.jsx("td",{colSpan:8,className:"px-4 py-10 text-center text-ink/75",children:"No vendors match."})}),S.map(s=>e.jsxs("tr",{className:"border-t border-ink/10 hover:bg-cream/60",children:[e.jsxs("td",{className:"px-4 py-3 font-semibold text-navy",children:[s.company_name||e.jsx("span",{className:"text-ink/70",children:"—"}),g.has(s.id)&&e.jsxs(W,{variant:"outline",className:"ml-2 border-emergency/40 bg-emergency/10 text-emergency",children:[e.jsx(V,{className:"h-3 w-3 mr-1"})," COI expiring"]})]}),e.jsxs("td",{className:"px-4 py-3",children:[e.jsx("div",{children:s.contact_name||"—"}),e.jsx("div",{className:"text-xs text-ink/75",children:s.contact_email})]}),e.jsx("td",{className:"px-4 py-3",children:s.trade||"—"}),e.jsx("td",{className:"px-4 py-3",children:e.jsxs("span",{className:`text-xs font-bold ${(N[s.id]??0)===3?"text-navy":(N[s.id]??0)>0?"text-gold":"text-ink/60"}`,children:[N[s.id]??0,"/3 uploaded"]})}),e.jsx("td",{className:"px-4 py-3",children:e.jsx(ee,{vendor:s})}),e.jsx("td",{className:"px-4 py-3",children:e.jsx(R,{status:s.status==="incomplete"?"missing":s.status})}),e.jsx("td",{className:"px-4 py-3 text-ink/75",children:s.submitted_at?new Date(s.submitted_at).toLocaleDateString():"—"}),e.jsx("td",{className:"px-4 py-3 text-right",children:e.jsx(x,{size:"sm",variant:"outline",onClick:()=>k(s.id),children:"Review"})})]},s.id))]})]})})]})}):null}function L({label:a,value:m,active:n,onClick:j}){return e.jsxs("button",{onClick:j,className:`rounded-sm border p-4 text-left transition-all ${n?"border-gold bg-gold/10":"border-ink/10 bg-white hover:border-gold/40"}`,children:[e.jsx("div",{className:"text-2xl font-bold text-navy",children:m}),e.jsx("div",{className:"mt-1 text-[11px] font-bold uppercase tracking-wider text-ink/75",children:a})]})}function se({vendorId:a,onBack:m}){const[n,j]=i.useState(null),[o,O]=i.useState([]),[_,k]=i.useState(""),[f,D]=i.useState({}),[c,h]=i.useState(!1),{user:g}=G(),v=async()=>{const[t,l]=await Promise.all([b.from("vendors").select("*").eq("id",a).maybeSingle(),b.from("vendor_documents").select("*").eq("vendor_id",a).order("kind")]);if(t.data&&(j(t.data),k(t.data.admin_notes??"")),l.data){O(l.data);const u={};l.data.forEach(S=>{u[S.id]=S.reviewer_notes??""}),D(u)}};i.useEffect(()=>
1{v()},[a]);const N=async(t,l)=>{const{error:u}=await b.from("vendor_documents").update({status:l,reviewer_notes:f[t]||null,reviewed_at:new Date().toISOString(),reviewed_by:g?.id}).eq("id",t);u?p.error(u.message):(p.success(`Document ${l}`),v())},A=async t=>{const{error:l}=await b.from("vendors").update({status:t,admin_notes:_||null,reviewed_at:new Date().toISOString(),reviewed_by:g?.id}).eq("id",a);l?p.error(l.message):(p.success(`Vendor ${t}`),v())};return n?e.jsx("div",{className:"bg-cream min-h-screen",children:e.jsxs("div",{className:"mx-auto max-w-5xl px-4 py-10 sm:px-6",children:[e.jsxs(x,{variant:"ghost",size:"sm",onClick:m,children:[e.jsx(K,{className:"h-4 w-4 mr-1"})," Back to list"]}),e.jsxs("div",{className:"mt-4 flex flex-wrap items-start justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"display text-3xl font-bold tracking-tight text-navy",children:n.company_name||"Unnamed vendor"}),e.jsxs("p",{className:"mt-1 text-sm text-ink/65",children:[n.contact_name," · ",n.contact_email]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[n.ghl_contact_id&&e.jsx(x,{asChild:!0,variant:"outline",size:"sm",children:e.jsxs("a",{href:B(n.ghl_contact_id),target:"_blank",rel:"noopener noreferrer",children:[e.jsx(Y,{className:"h-4 w-4 mr-1"})," Open in GoHighLevel"]})}),e.jsxs(x,{variant:"outline",size:"sm",disabled:c,onClick:async()=>{h(!0);try{const t=await H({data:{vendorId:a}});t?.ok?p.success("Synced to GoHighLevel"):p.error(t?.error||"Sync failed")}catch(t){p.error(t?.message??"Sync failed")}h(!1),v()},children:[e.jsx(T,{className:`h-4 w-4 mr-1 ${c?"animate-spin":""}`})," ",c?"Syncing…":"Sync to GoHighLevel"]}),e.jsx(R,{status:n.status==="incomplete"?"missing":n.status})]})]}),e.jsxs("div",{className:"mt-8 grid gap-3 rounded-sm border border-ink/10 bg-white p-6 sm:grid-cols-2 text-sm",children:[e.jsx(w,{label:"Phone",value:n.phone}),e.jsx(w,{label:"EIN",value:n.ein}),e.jsx(w,{label:"Trade",value:n.trade}),e.jsx(w,{label:"Service areas",value:n.service_areas}),e.jsx(w,{label:"Address",value:n.address,wide:!0}),e.jsx(w,{label:"Submitted",value:n.submitted_at?new Date(n.submitted_at).toLocaleString():"—"})]}),e.jsx("h2",{className:"mt-10 display text-xl font-bold text-navy",children:"Documents"}),e.jsx("div",{className:"mt-4 space-y-6",children:o.map(t=>e.jsxs("div",{className:"space-y-3",children:[e.jsx(J,{doc:t,vendorId:a,onChange:v,readOnly:!0}),e.jsxs("div",{className:"rounded-sm border border-ink/10 bg-white p-4",children:[e.jsx(E,{className:"text-xs",children:"Reviewer note (optional)"}),e.jsx(I,{className:"mt-1",rows:2,value:f[t.id]??"",onChange:l=>D({...f,[t.id]:l.target.value}),placeholder:"What needs to change?"}),e.jsxs("div",{className:"mt-3 flex gap-2",children:[e.jsxs(x,{size:"sm",onClick:()=>N(t.id,"approved"),disabled:!t.file_path,className:"bg-green-700 text-white hover:bg-green-800",children:[e.jsx($,{className:"h-4 w-4 mr-1"})," Approve"]}),e.jsxs(x,{size:"sm",variant:"outline",onClick:()=>N(t.id,"rejected"),disabled:!t.file_path,className:"border-emergency/40 text-emergency hover:bg-emergency/10",children:[e.jsx(z,{className:"h-4 w-4 mr-1"})," Reject"]})]})]})]},t.id))}),e.jsx("h2",{className:"mt-10 display text-xl font-bold text-navy",children:"Overall decision"}),e.jsxs("div",{className:"mt-4 rounded-sm border border-ink/10 bg-white p-6",children:[e.jsx(E,{className:"text-xs",children:"Notes to vendor (optional)"}),e.jsx(I,{rows:3,className:"mt-1",value:_,onChange:t=>k(t.target.value)}),e.jsxs("div",{className:"mt-4 flex gap-2",children:[e.jsxs(x,{onClick:()=>A("approved"),className:"bg-green-700 text-white hover:bg-green-800",children:[e.jsx($,{className:"h-4 w-4 mr-1"})," Approve vendor"]}),e.jsxs(x,{variant:"outline",onClick:()=>A("rejected"),className:"border-emergency/40 text-emergency hover:bg-emergency/10",children:[e.jsx(z,{className:"h-4 w-4 mr-1"})," Reject vendor"]})]})]})]})}):e.jsx("div",{className:"bg-cream min-h-screen p-10 text-sm text-ink/75",children:"Loading…"})}function w({label:a,value:m,wide:n}){return e.jsxs("div",{className:n?"sm:col-span-2":"",children:[e.jsx("div",{className:"text-[10px] uppercase tracking-wider font-bold text-ink/75",children:a}),e.jsx("div",{className:"mt-1 whitespace-pre-line text-ink",children:m||"—"})]})}
1export{ve 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.