1import{a as p,j as e,d as Ke,u as $a,e as Ta}from"./vendor-query-Oehb3qcy.js";import{c as Vl,L as ni,N as ii}from"./vendor-react-D9OxxSlj.js";import{aO as oi,f_ as ss,f$ as rs,B as H,bQ as Va,bp as ha,g0 as ls,bt as Pe,bE as Ma,cQ as ca,C as ye,cM as Ks,bz as ke,cN as Ws,bd as fa,bS as ci,bg as ie,X as Et,cO as Gs,b8 as je,c1 as xe,dA as Be,dB as Ve,dC as ze,dD as Ue,dE as me,s as ge,bv as le,cH as Na,cI as ka,cc as Hs,cJ as Ca,aC as Ga,cG as mr,aQ as zl,fn as di,R as ur,dk as mi,bC as Fe,h2 as ys,cw as da,fN as Sa,cx as ma,aY as hr,aZ as Ul,bV as Xe,cR as Qs,cS as Js,bP as Ys,cU as Xs,iU as Zs,cV as Oa,dG as Wa,cW as ql,bb as Ha,bc as Qa,be as Ja,bf as Ya,da as it,db as Xa,b0 as Ba,fp as ot,fm as lt,bA as Ce,bR as Rr,gT as Ze,gU as ea,gV as Le,gW as Z,gX as aa,gY as Q,cq as ba,aR as _r,e9 as Kl,ea as Wl,eb as Gl,ec as Hl,ed as Ql,cs as ct,ee as Jl,ef as Yl,eg as Xl,de as ui,ba as Tr,g9 as ns,bh as is,W as Zl,dg as os,dh as cs,di as ia,dj as oa,bl as en,hE as an,k as pr,iL as hi,c7 as er,bm as Lr,gc as Mr,ga as et,eN as ds,bT as tn,bM as _i,h$ as pi,fr as ar,gS as Pr,aD as wt,i3 as xi,b2 as gi,bD as Ye,h_ as bi,gN as Ir,bH as fi,aT as wi,hC as yi,bO as ji,c0 as _t,jJ as It,jK as js,aV as Fr,jL as vi}from"./index-DWPX9Ugs.js";import{u as Ni}from"./useDebouncedValue-CGAmLjHF.js";import{u as ki}from"./vendor-virtual-Ch5EKWyr.js";import{f as Ci,W as Ua,v as qa}from"./WiringVerdictPanel-6UVKVhoU.js";import{S as Si}from"./shield-question-uNt9kvJa.js";import{S as $i}from"./shield-alert-jJxgTzKU.js";import{S as ms}from"./shield-check-BED3at5L.js";import{b as vt,s as sn,A as Ai,d as Ei,t as xr,P as rn,g as Ri,e as Ti,f as Li}from"./cardScopeClassifier-BnRVzJtE.js";import{u as ln}from"./useActualCompanyScope-CAXMwxlL.js";import{T as dt,a as ta}from"./toggle-group-B98pYqe2.js";import{F as Ht}from"./flask-conical-DGMK22ie.js";import{utils as sa,writeFile as Mi,read as Pi}from"./xlsx-VD8g3AFw.js";import{U as nn}from"./upload-CtJ_TCqH.js";import{C as Ii}from"./clipboard-copy-Cj2D_HQD.js";import{P as Or}from"./percent-iktQYppw.js";import{A as Fi}from"./arrow-down-to-line-QkxEapNg.js";import{P as tr}from"./power-off-NXBe1gt5.js";import{P as on}from"./power-DdDAHENz.js";import{G as us}from"./globe-CTofyzMl.js";import{S as Ct}from"./slider-iBQyJLzl.js";import{S as Dr}from"./square-check-big-BXTWoAtQ.js";import{S as Oi}from"./square-C5-LcVks.js";import{A as Di}from"./arrow-up-down-DNN3x6Tc.js";import{A as Bi}from"./arrow-down-C99l4_fe.js";import{R as pt,P as Br,c as Vr,C as zr,T as xt,e as Ur,B as vs,d as Ns,X as ks,Y as Cs,a as Ft}from"./vendor-charts-D1V0tSmm.js";import{a as Vi}from"./vendor-date-CM9FFnu7.js";import{P as zi}from"./play-CS_QgkpW.js";import"./vendor-radix-BXYZ6viG.js";import"./vendor-supabase-BNeImLMT.js";import"./vendor-utils-GtKaikA9.js";import"./vendor-pdf-BSfaJZ25.js";import"./vendor-editor-C83GjTkp.js";import"./circle-minus-BSILxssY.js";/** 2 * @license lucide-react v0.462.0 - ISC 3 * 4 * This source code is licensed under the ISC license. 5 * See the LICENSE file in the root directory of this source tree. 6 */const Ui=oi("ShieldX",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"m14.5 9.5-5 5",key:"17q4r4"}],["path",{d:"m9.5 9.5 5 5",key:"18nt4w"}]]);function xa({label:a,options:t,selected:s,onChange:r,width:l="w-[210px]",allLabel:o="All"}){var x;const[i,d]=p.useState(""),_=u=>r(s.includes(u)?s.filter(N=>N!==u):[...s,u]),n=p.useMemo(()=>{const u=i.trim().toLowerCase();return u?t.filter(N=>`${N.label} ${N.value}`.toLowerCase().includes(u)):t},[t,i]),c=s.length===0?o:s.length===1?((x=t.find(u=>u.value===s[0]))==null?void 0:x.label)??s[0]:`${s.length} selected`,m=n.map(u=>u.value),h=m.length>0&&m.every(u=>s.includes(u)),j=()=>r(Array.from(new Set([...s,...m]))),b=()=>r(s.filter(u=>!m.includes(u)));return e.jsxs(ss,{children:[e.jsx(rs,{asChild:!0,children:e.jsxs(H,{variant:"outline",className:`${l} justify-between font-normal whitespace-nowrap`,size:"sm",children:[e.jsxs("span",{className:"flex min-w-0 items-center gap-1.5",children:[e.jsx(Va,{className:"h-3.5 w-3.5 shrink-0 opacity-60"}),e.jsx("span",{className:"truncate",children:c})]}),e.jsx(ha,{className:"h-3.5 w-3.5 opacity-60 shrink-0"})]})}),e.jsxs(ls,{align:"start",className:"w-[360px] p-0",children:[e.jsxs("div",{className:"flex items-center justify-between px-3 py-2 border-b border-primary/20 bg-primary/[0.06]",children:[e.jsxs("span",{className:"text-xs font-semibold text-primary",children:[a," · ",t.length,s.length>0&&` · ${s.length} picked`]}),s.length>0&&e.jsx(H,{variant:"ghost",size:"sm",className:"h-6 text-xs",onClick:()=>r([]),children:"Clear"})]}),e.jsxs("div",{className:"border-b border-primary/10 p-2 space-y-2",children:[e.jsxs("div",{className:"relative",children:[e.jsx(Va,{className:"absolute left-2 top-2.5 h-3.5 w-3.5 text-primary/60"}),e.jsx(Pe,{autoFocus:!0,value:i,onChange:u=>d(u.target.value),placeholder:`Type to find ${a.toLowerCase()}â¦`,className:"h-8 pl-7 text-xs"})]}),e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("span",{className:"text-[11px] text-muted-foreground",children:[n.length," match",n.length===1?"":"es"]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsxs(H,{variant:"outline",size:"sm",className:"h-6 text-[11px]",disabled:m.length===0||h,onClick:j,children:["Select all ",i.trim()?"matching":""]}),e.jsx(H,{variant:"ghost",size:"sm",className:"h-6 text-[11px]",disabled:!m.some(u=>s.includes(u)),onClick:b,children:"Deselect"})]})]})]}),e.jsx(Ma,{className:"h-[min(420px,60vh)]",children:e.jsxs("div",{className:"p-1",children:[n.map(u=>e.jsxs("label",{className:"flex items-center gap-2 rounded px-2 py-1.5 text-sm hover:bg-primary/10 cursor-pointer",title:u.description,children:[e.jsx(ca,{checked:s.includes(u.value),onCheckedChange:()=>_(u.value)}),e.jsx("span",{className:"flex-1 truncate",children:u.label}),u.count!==void 0&&e.jsx("span",{className:"text-xs text-primary/70 tabular-nums",children:u.count})]},u.value)),!n.length&&e.jsx("p",{className:"px-2 py-3 text-xs text-muted-foreground",children:t.length?"No option matches that search":"Nothing to filter"})]})})]})]})}const We={primary:"bg-primary/10 text-primary border-primary/30",navy:"bg-indigo-500/10 text-indigo-700 dark:text-indigo-300 border-indigo-500/30",gold:"bg-[#C9A96E]/15 text-[#8a6f34] dar
6k:text-[#e2c894] border-[#C9A96E]/40",teal:"bg-teal-500/10 text-teal-700 dark:text-teal-300 border-teal-500/30",green:"bg-emerald-500/10 text-emerald-700 dark:text-emerald-400 border-emerald-500/30",amber:"bg-amber-500/10 text-amber-700 dark:text-amber-400 border-amber-500/30",rose:"bg-destructive/10 text-destructive border-destructive/30",violet:"bg-violet-500/10 text-violet-700 dark:text-violet-300 border-violet-500/30"},Da={ai_generated:{label:"AI generated",short:"AI",description:"The rate for this item code was produced by an AI pricing pass â verify before relying on it.",className:We.rose},bulk_updated:{label:"Bulk updated",short:"Bulk",description:"Last moved by a bulk percentage or absolute adjustment rather than an individual quote.",className:We.amber},system:{label:"System seeded",short:"System",description:"Seeded by the platform when the catalog was created.",className:We.navy},company:{label:"Company override",short:"Company",description:"This company has its own row overriding the global template.",className:We.primary},audited:{label:"Audited edit",short:"Audited",description:"Changed at least once through the audited pricing service, with a reason on record.",className:We.green},seeded:{label:"No provenance",short:"Unstamped",description:"No provenance stamp and no recorded audited edit â origin of these numbers is unknown.",className:We.gold}},qi=Object.keys(Da),ua={v2_backend:{label:"V2 backend",short:"V2",description:"Read by a live V2 card reader, so this row prices real estimates through calculate-all-card-totals.",className:"bg-emerald-500/10 text-emerald-700 dark:text-emerald-400 border-emerald-500/30"},legacy_retired:{label:"Retired / legacy",short:"Legacy",description:"The V2 backend never reads this source. Numbers here are historical and do not price new estimates.",className:"bg-amber-500/10 text-amber-700 dark:text-amber-400 border-amber-500/30"}},Ki=Object.keys(ua),cn={structural_line_items_global:"get-structural-line-items",interior_building_line_items_global:"get-interior-building-line-items",millwork_line_items_global:"get-millwork-line-items",kitchen_line_items_global:"get-kitchen-line-items",bar_line_items_global:"get-bar-line-items",full_bath_line_items_global:"get-full-bath-line-items",half_bath_line_items_global:"get-half-bath-line-items",primary_bath_line_items_global:"get-primary-bath-line-items",hardwood_line_items_global:"get-hardwood-line-items",basement_flooring_line_items_global:"get-basement-flooring-line-items",builtins_line_items_global:"get-builtins-line-items",mudroom_line_items_global:"get-mudroom-line-items",laundry_line_items_global:"get-laundry-line-items",fireplace_line_items_global:"get-fireplace-line-items",hvac_extension_line_items_global:"get-hvac-extension-line-items",roofing_line_items_global:"get-roofing-line-items",siding_line_items_global:"get-siding-line-items",windows_line_items_global:"get-windows-line-items",patio_doors_line_items_global:"get-patio-doors-line-items",skylights_line_items_global:"get-skylights-line-items",deck_line_items_global:"get-deck-line-items",deck_line_items_global_remodel:"get-deck-line-items-remodel",driveway_line_items_global:"get-driveway-line-items",driveway_line_items_global_remodel:"get-driveway-line-items-remodel",paver_patio_line_items_global:"get-paver-patio-line-items",paver_patio_line_items_global_remodel:"get-paver-patio-line-items-remodel",exterior_stairs_line_items_global:"get-exterior-stairs-line-items",exterior_stairs_line_items_global_remodel:"get-exterior-stairs-line-items-remodel",window_well_line_items_global:"get-window-well-line-items",window_well_line_items_global_remodel:"get-window-well-line-items-remodel",fence_line_items_global:"get-fence-line-items",seepage_pit_line_items_global:"get-seepage-pit-line-items",septic_line_items_global:"get-septic-line-items"};function qr(a){return cn[a]?"v2_backend":"legacy_retired"}function gr(a){return cn[a]||null}function Wi(a){const t=gr(a);return t?`${ua.v2_backend.description} 7Reader: ${t} 8Table: ${a}`:`${ua.legacy_retired.description} 9Table: ${a}`}const Gi={install:"install",teardown:"tear-out",new_opening:"new opening",accessory:"accessory",other:"scope"},Hi={install:"Installs the finished material or assembly.",teardown:"Pays for demolition / removal / tear-out of the existing material. On a remodel this is a separate row from the install â if it carries no money the remodel reads low.",new_opening:"Cuts a brand-new opening rather than reusing an existing one.",accessory:"Card-level accessory or trim work (gutters, fascia, wainscot, extra stone) that belongs to the card rather than to one material.",other:"Scope row on this card."},dn=["demolition","demolish","demo","removal","remove","removals","tear out","tearout","tear-out","teardown","tear down","strip out","gut","haul away","disposal","dumpster"],Kr=["gutter","gutters","leader","leaders","azek","trim","fascia","soffit","wainscot","stone","accessory","accessories","optional","included"],Qi=["addition","additions","add","remodel","remodels","rem","existing","new"],Ji=["install","installation","installed","replace","replacement","opening","openings","work","area","areas","additional",...dn.flatMap(a=>a.split(/[\s-]+/))],St=a=>(a||"").toLowerCase().replace(/[^a-z0-9]+/g," ").trim().split(" ").filter(
9Boolean),Yi=a=>` ${St(`${a.item_code??""} ${a.item_name??""} ${a.category_display??""}`).join(" ")} `,Ss=a=>a.length>3&&a.endsWith("s")&&!a.endsWith("ss")?a.slice(0,-1):a;function sr(a){return ja(a)==="teardown"}function ja(a){const t=St(a.category_display??""),s=` ${t.join(" ")} `,r=Yi(a),l=o=>dn.some(i=>o.includes(` ${i.replace(/[-]/g," ")} `));return l(s)?"teardown":t.some(o=>Kr.includes(o))?"accessory":s.includes(" installation ")||s.includes(" install ")?"install":l(r)?"teardown":r.includes(" new opening ")||r.includes(" new openings ")?"new_opening":St(`${a.item_code??""} ${a.item_name??""}`).some(o=>Kr.includes(o))?"accessory":r.includes(" install ")||r.includes(" installation ")||r.includes(" replacement ")||r.includes(" replace ")?"install":"other"}function mn(a){if(ja(a)==="accessory")return"__accessories";const t=a.item_code||a.item_name||"",s=new Set([...Qi,...Ji].map(Ss)),r=St(t).map(Ss).filter(o=>!s.has(o)).filter(o=>o.length>1);return r.length>0?r.join("_"):St(a.card_code||a.card_label||a.trade||t).map(Ss).filter(o=>!s.has(o)).join("_")||"other"}function Wr(a){return`${a.card_label||a.card_code||a.trade||"Other"} :: ${mn(a)}`}function Xi(a){if(a.length===0)return"Other";if(ja(a[0])==="accessory")return"Card accessories";const t=a.find(r=>ja(r)==="install")??a[0],s=(t.item_name??"").trim();return s?s.replace(/\s*[-â]\s*(addition|remodel)\s*$/i,"").replace(/\s*\((addition|remodel)\)\s*$/i,"").replace(/\s+(installation|install)\s*$/i,"").trim():mn(t).replace(/_/g," ")}function Zi(a,t=0){const s=[];if(a.length===0)return s;const r=ja(a[0])==="accessory",l=a.filter(c=>ja(c)==="install"||ja(c)==="new_opening"),o=a.filter(c=>ja(c)==="teardown"),i=new Set(l.map(c=>c.pair_side??"unknown")),d=l.some(c=>c.pair_side==="remodel"&&c.hasMoney),_=o.some(c=>c.hasMoney),n=a.some(c=>!c.hasMoney);return t>0&&s.push({id:"hidden_by_filter",label:`${t} related row${t===1?"":"s"} hidden by filters`,title:"This family has related rows your current filters are hiding. Clear the filters to judge whether the family is complete.",tone:"info"}),d&&!_&&s.push({id:"no_teardown_priced",label:"no tear-out priced",title:"The remodel install carries money but no removal / demolition row in this family does. That is the usual reason a remodel card reads low â the tear-out is being done for free.",tone:"warn"}),!r&&t===0&&l.length>0&&(i.has("addition")&&!i.has("remodel")&&s.push({id:"addition_only",label:"addition only",title:"Only the addition side of this item exists. A remodel card has nothing to read here.",tone:"warn"}),i.has("remodel")&&!i.has("addition")&&s.push({id:"remodel_only",label:"remodel only",title:"Only the remodel side of this item exists. An addition card has nothing to read here.",tone:"warn"})),n&&s.push({id:"zero_money",label:"row at $0",title:"At least one row in this family carries no money in the finish tier shown. Some items are legitimately material-only or allowance-only â check the row before changing it.",tone:"info"}),s.length===0&&s.push({id:"complete",label:"complete",title:"Every row in this family exists and carries money in the tier shown.",tone:"ok"}),s}const Nt={flat:"Flat list",card:"By card",trade:"By trade",card_side:"By card â side",family:"Item family (addition / remodel / demo)"},un=a=>a.engine;function eo(a){let t=0,s=0,r=0,l=0;return a.forEach(o=>{un(o)==="v2_backend"&&(t+=1),o.ai_generated&&(s+=1),o.usage_basis!=="none"&&(r+=1),o.is_active===!1&&(l+=1)}),{total:a.length,v2:t,legacy:a.length-t,ai:s,used:r,unused:a.length-r,inactive:l,fullyV2:a.length>0&&t===a.length}}function ao(a,t){return t==="trade"?a.trade||"Other":a.card_label||"Other"}const $s=a=>Object.values(a.values||{}).some(t=>Number(t??0)>0),st={addition:0,remodel:1,unknown:2},to=a=>a==="addition"?"Addition":a==="remodel"?"Remodel":"Unassigned side";function Ot(a,t,s,r){let l=0,o=0,i=0,d=0,_=0,n=0,c=0;const m=new Set;let h=!1,j=!1;s.forEach(N=>{un(N)==="v2_backend"&&(l+=1),N.ai_generated&&(o+=1),r.attention(N)&&(i+=1),r.selected.has(N.key)&&(d+=1),N.usage_basis!=="none"&&(_+=1),N.is_active===!1&&(n+=1);const y=sr(N);y&&(c+=1),m.add(N.pair_side||"unknown"),N.pair_side==="remodel"&&!y&&$s(N)&&(h=!0),y&&$s(N)&&(j=!0)});let b,x,u;
9if(r.familyRows){const N=new Set(s.map(y=>y.key));u=r.familyRows.filter(y=>!N.has(y.key)).length,b=Zi(r.familyRows.map(y=>({...y,hasMoney:$s(y)})),u),x=Array.from(new Set(r.familyRows.map(y=>ja(y))))}return{id:a,label:t,total:s.length,v2:l,legacy:s.length-l,ai:o,attention:i,selected:d,used:_,unused:s.length-_,inactive:n,fullyV2:s.length>0&&l===s.length,depth:r.depth??0,demo:c,sides:Array.from(m).sort((N,y)=>st[N]-st[y]),demoGap:h&&!j,roles:x,flags:b,hiddenByFilter:u,tintIndex:r.tintIndex}}function hn(a,t,s={}){const r=s.selectedKeys??new Set,l=s.collapsed??new Set,o=s.needsAttention??(()=>!1);if(t==="flat")return{entries:a.map(c=>({kind:"item",id:c.key,item:c,groupId:""})),groups:[]};const i=[],d=[],_=c=>{const m=new Map;return a.forEach(h=>{const j=c(h),b=m.get(j);b?b.push(h):m.set(j,[h])}),m};if(t==="card_side"){const c=_(m=>m.card_label||"Other");return Array.from(c.keys()).sort((m,h)=>m.localeCompare(h)).forEach(m=>{const h=c.get(m),j=Ot(m,m,h,{selected:r,attention:o,depth:0});i.push(j);const b=l.has(m);if(d.push({kind:"group",id:`g:${m}`,stats:j,collapsed:b}),b)return;const x=new Map;h.forEach(u=>{const N=u.pair_side||"unknown",y=x.get(N);y?y.push(u):x.set(N,[u])}),Array.from(x.keys()).sort((u,N)=>(st[u]??9)-(st[N]??9)).forEach(u=>{const N=x.get(u),y=`${m} :: ${u}`,L=Ot(y,`${to(u)} â ${m}`,N,{selected:r,attention:o,depth:1});i.push(L);const I=l.has(y);d.push({kind:"group",id:`g:${y}`,stats:L,collapsed:I}
9),!I&&N.forEach($=>d.push({kind:"item",id:$.key,item:$,groupId:y}))})}),{entries:d,groups:i}}if(t==="family"){const c=_(u=>Wr(u)),m=new Map;(s.unfilteredItems??a).forEach(u=>{const N=Wr(u),y=m.get(N);y?y.push(u):m.set(N,[u])});const h=Array.from(c.keys()).sort((u,N)=>u.localeCompare(N)),j=new Map;h.forEach((u,N)=>{var $;const y=c.get(u),L=m.get(u)??y,I=`${Xi(L)} · ${(($=y[0])==null?void 0:$.card_label)||"Other"}`;j.set(u,Ot(u,I,y,{selected:r,attention:o,depth:0,familyRows:L,tintIndex:N%2}))});const b=s.incompleteFirst?[...h].sort((u,N)=>{var I,$;const y=(((I=j.get(u))==null?void 0:I.flags)??[]).some(ee=>ee.tone==="warn")?0:1,L=((($=j.get(N))==null?void 0:$.flags)??[]).some(ee=>ee.tone==="warn")?0:1;return y!==L?y-L:u.localeCompare(N)}):h;let x=0;return b.forEach(u=>{const N=c.get(u),L=(m.get(u)??N).length<=1,I={...j.get(u),tintIndex:L?0:x%2};if(L){d.push({kind:"item",id:N[0].key,item:N[0],groupId:u});return}x+=1,i.push(I);const $=l.has(u);if(d.push({kind:"group",id:`g:${u}`,stats:I,collapsed:$}),$)return;[...N].sort((U,E)=>{const J=sr(U)?1:0,be=sr(E)?1:0;if(J!==be)return J-be;const F=st[U.pair_side||"unknown"]??9,se=st[E.pair_side||"unknown"]??9;return F!==se?F-se:U.item_name.localeCompare(E.item_name)}).forEach(U=>d.push({kind:"item",id:U.key,item:U,groupId:u}))}),{entries:d,groups:i}}const n=_(c=>ao(c,t));return Array.from(n.keys()).sort((c,m)=>c.localeCompare(m)).forEach(c=>{const m=n.get(c),h=Ot(c,c,m,{selected:r,attention:o,depth:0});i.push(h);const j=l.has(c);d.push({kind:"group",id:`g:${c}`,stats:h,collapsed:j}),j||m.forEach(b=>d.push({kind:"item",id:b.key,item:b,groupId:c}))}),{entries:d,groups:i}}function Gr(a,t){if(t==="flat")return[];const{groups:s}=hn(a,t,{});return s.map(r=>r.id)}const Hr={addition:"addition side",remodel:"remodel side",both:"both sides",none:""};function Qr(a){return(a.card_label||a.category_display||a.source_table).trim()}function _n(a){if(a.engine!=="v2_backend")return{coverage:"none",label:"No card yet",card:null,sides:"none",narration:"No calculator card prices with this row â its table has no live V2 reader, so the numbers never reach an estimate.",tint:"gold",className:We.gold};if(a.is_active===!1){const l=Qr(a);return{coverage:"none",label:"No card yet",card:l,sides:"none",narration:`Retired â the ${l} card skips this row today. Restore it to price with it again.`,tint:"gold",className:We.gold}}const t=Qr(a),s=a.side==="both"?"both":a.side,r=s==="both"?`Used by the ${t} cards on the addition and remodel sides.`:`Used by the ${t} card on the ${Hr[s]}.`;return{coverage:"card",label:`${t} · ${Hr[s]}`,card:t,sides:s,narration:a.card_code?`${r} Card code ${a.card_code}.`:r,tint:s==="both"?"teal":"primary",className:s==="both"?We.teal:We.primary}}function so(a,t){if(t==="all")return!0;const{coverage:s}=_n(a);return t==="used"?s==="card":s==="none"}const As={all:"Any card coverage",used:"Used by a card",none:"No card yet"},pn={bar_line_items_company:["best_allowance_labor","best_allowance_material","best_labor_rate","best_material_rate","better_allowance_labor","better_allowance_material","better_labor_rate","better_material_rate","company_id","entry_allowance_labor","entry_allowance_material","entry_labor_rate","entry_material_rate","good_allowance_labor","good_allowance_material","good_labor_rate","good_material_rate","is_active","item_code"],bar_line_items_global:["best_allowance_labor","best_allowance_material","best_labor_rate","best_material_rate","better_allowance_labor","better_allowance_material","better_labor_rate","better_material_rate","entry_allowance_labor","entry_allowance_material","entry_labor_rate","entry_material_rate","good_allowance_labor","good_allowance_material","good_labor_rate","good_material_rate","is_active","item_code"],basement_flooring_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],basement_flooring_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],builtins_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],builtins_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],deck_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],deck_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],deck_line_items_global_remodel:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],driveway_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],driveway_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],driveway_line_items_global_remodel:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],exterior_stairs_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],exterior_stairs_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],exterior_stairs_line_items_global_remodel:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],fence_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],fence_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],fireplace_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],fireplace_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],full_bath_line_items_company:["card_code","company_id","is_active","item_code","labor_allowance","labor_unit_price","material_allowance","material_unit_price"],full_bath_line_items_global:["best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","labor_unit_price","material_allowance","material_unit_price"],half_bath_line_items_company:["card_code","company_id","is_active","item_code","labor_allowance","labor_unit_price","material_allowance","material_unit_price"],half_bath_line_items_global:["best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","labor_unit_price","material_allowance","material_unit_price"],hardwood_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],hardwood_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],hvac_extension_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],hvac_extension_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],interior_building_line_items_company:["best_allowance_labor","best_allowance_material","best_labor_rate","best_material_rate","better_allowance_labor","better_allowance_material","better_labor_rate","better_material_rate","company_id","entry_allowance_labor","entry_allowance_material","entry_labor_rate","entry_material_rate","good_allowance_labor","good_allowance_material","good_labor_rate","good_material_rate","is_active","item_code"],interior_building_line_items_global:["best_allowance_labor","best_allowance_material","best_labor_rate","best_material_rate","better_allowance_labor","better_allowance_material","better_labor_rate","better_material_rate","entry_allowance_labor","entry_allowance_material","entry_labor_rate","entry_material_rate","good_allowance_labor","good_allowance_material","good_labor_rate","good_material_rate","is_active","item_code"],kitchen_line_items_company:["best_allowance_labor","best_allowance_material","best_labor_rate","best_material_rate","better_allowance_labor","better_allowance_material","better_labor_rate","better_material_rate","card_code","company_id","entry_allowance_labor","entry_allowance_material","entry_labor_rate","entry_material_rate","good_allowance_labor","good_allowance_material","good_labor_rate","good_material_rate","is_active","item_code","labor_allowance","material_allowance"],kitchen_line_items_global:["best_allowance_labor","best_allowance_material","best_labor_rate","best_material_rate","better_allowance_labor","better_allowance_material","better_labor_rate","better_material_rate","card_code","entry_allowance_labor","entry_allowance_material","entry_labor_rate","entry_material_rate","good_allowance_labor","good_allowance_material","good_labor_rate","good_material_rate","is_active","item_code","labor_allowance","material_allowance"],lau
9ndry_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],laundry_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],millwork_line_items_company:["best_allowance_labor","best_allowance_material","best_labor_rate","best_material_rate","better_allowance_labor","better_allowance_material","better_labor_rate","better_material_rate","company_id","entry_allowance_labor","entry_allowance_material","entry_labor_rate","entry_material_rate","good_allowance_labor","good_allowance_material","good_labor_rate","good_material_rate","is_active","item_code"],millwork_line_items_global:["best_allowance_labor","best_allowance_material","best_labor_rate","best_material_rate","better_allowance_labor","better_allowance_material","better_labor_rate","better_material_rate","entry_allowance_labor","entry_allowance_material","entry_labor_rate","entry_material_rate","good_allowance_labor","good_allowance_material","good_labor_rate","good_material_rate","is_active","item_code"],mudroom_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],mudroom_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],patio_doors_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],patio_doors_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],paver_patio_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],paver_patio_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],paver_patio_line_items_global_remodel:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],primary_bath_line_items_company:["card_code","company_id","is_active","item_code","labor_allowance","labor_unit_price","material_allowance","material_unit_price"],primary_bath_line_items_global:["best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","labor_unit_price","material_allowance","material_unit_price"],roofing_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],roofing_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],seepage_pit_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],seepage_pit_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],siding_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],siding_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],skylights_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],skylights_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],structural_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],structural_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],window_well_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],window_well_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],window_well_line_items_global_remodel:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code","labor_allowance","material_allowance"],windows_line_items_company:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","company_id","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"],windows_line_items_global:["base_labor_rate","base_material_rate","best_allowance_labor","best_allowance_material","better_allowance_labor","better_allowance_material","card_code","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","is_active","item_code"]},qe=["entry","good","better","best"],$t=["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance",...qe.flatMap(a=>[`${a}_labor_rate`,`${a}_material_rate`,`${a}_allowance_labor`,`${a}_allowance_material`])];function Za(a,t){return(pn[a]||[]).includes(t)}function Jr(a){const t=pn[a]||[];
9return $t.filter(s=>t.includes(s))}function xn(a){return Za(a,"good_labor_rate")}function ro(a){return Za(a,"good_allowance_labor")}function lo(a){return Za(a,"labor_allowance")}const ga={same_side_duplicate:{id:"same_side_duplicate",label:"Duplicate row",tone:"critical",weight:110,description:"Another live row on the same card and the same side prices this same item. Only one of them can be the row the reader consumes."},tier_reversal:{id:"tier_reversal",label:"Tier reversal",tone:"critical",weight:100,description:"A richer finish tier costs less than a cheaper one â usually a transposed number."},dead_tier:{id:"dead_tier",label:"Dead tier",tone:"critical",weight:90,description:"One tier prices at $0 while another tier in the same family carries money."},no_money:{id:"no_money",label:"No money at all",tone:"warning",weight:70,description:"Every rate and allowance on this row is zero or empty â it contributes nothing."},invalid_code:{id:"invalid_code",label:"Suspicious item code",tone:"critical",weight:95,description:"The item code is numeric or too short to be a real code â almost always a bad import. Nothing reads it reliably."},side_divergence:{id:"side_divergence",label:"Sides differ",tone:"warning",weight:65,description:"The same item exists on both the addition and remodel side with different money. Intentional or not, the two sides will price differently."},flat_allowance_not_tiered:{id:"flat_allowance_not_tiered",label:"Flat allowance, no tiers",tone:"warning",weight:60,description:"The legacy flat allowance carries money but the per-tier labor/material allowance columns are empty, so tier selection has no effect."},mixed_allowance_model:{id:"mixed_allowance_model",label:"Mixed allowance model",tone:"warning",weight:70,description:"The row carries BOTH a flat allowance labor/material pair and per-tier allowance money. Two competing allowance definitions on one item â clear one of them so it is unamb
9iguous which one prices."},nonfinish_allowance:{id:"nonfinish_allowance",label:"Allowance on non-finish work",tone:"warning",weight:80,description:"Demolition, removals, drywall, insulation, electrical, rough plumbing, protection, repair and paint work is not something a homeowner picks a finish level for. It must price from base labor + material only â allowance money here makes the price swing with an unrelated finish choice."},retired_but_consumed:{id:"retired_but_consumed",label:"Retired but still used",tone:"critical",weight:105,description:"This row is retired, yet a live project still prices with it. New projects will lose the money unless a replacement is mapped."},family_role_duplicate:{id:"family_role_duplicate",label:"Duplicate in family",tone:"warning",weight:75,description:"Another live row in the same related-pricing family covers the same side (addition / remodel / demo). Keep one and retire or replace the other."},copy_paste_tiers:{id:"copy_paste_tiers",label:"Copy-paste tiers",tone:"info",weight:40,description:"Entry, Better and Best are identical while Good differs â typically a backfilled row that never received real tier pricing."},stale:{id:"stale",label:"Stale",tone:"muted",weight:10,description:"Not touched in a long time. Not necessarily wrong â worth a market check."},healthy:{id:"healthy",label:"Healthy",tone:"ok",weight:0,description:"No anomalies detected."}},gn=["retired_but_consumed","family_role_duplicate","same_side_duplicate","tier_reversal","dead_tier","invali
9d_code","no_money","side_divergence","flat_allowance_not_tiered","mixed_allowance_model","nonfinish_allowance","copy_paste_tiers","stale"],bn={critical:We.rose,warning:We.amber,info:We.primary,muted:We.violet,ok:We.green},no={critical:"bg-destructive/5",warning:"bg-amber-500/5",info:"bg-primary/5",muted:"bg-violet-500/[0.04]",ok:""},gt=[{key:"labor_rate",label:"Labor rate"},{key:"material_rate",label:"Material rate"},{key:"allowance_labor",label:"Allowance labor"},{key:"allowance_material",label:"Allowance material"}],io=["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance"],Yr=/(demo|demolition|removal|protection|repair)|drywall|insulat|electrical|rough_plumb|dryer_vent|gas_line|_paint|paint_/i;function oo(a,t){return Yr.test(a??"")||Yr.test(t??"")}const Pa=(a,t)=>{if(!a.editable_columns.includes(t))return null;const s=a.values[t];return s==null?null:Number(s)},Aa=a=>`$${a.toLocaleString(void 0,{maximumFractionDigits:2})}`;function fn(a,t={}){var h;const s=t.staleMonths??12,r=[];let l=0,o=!1;const i=j=>{const b=Pa(a,j);b!==null&&(o=!0,l+=b)};io.forEach(i),gt.forEach(j=>qe.forEach(b=>i(`${b}_${j.key}`)));for(const j of gt){const b=qe.map(L=>`${L}_${j.key}`);if(!b.every(L=>a.editable_columns.includes(L)))continue;const x=b.map(L=>Pa(a,L)),u=x.filter(L=>L!==null);if(!u.length||!u.some(L=>L>0))continue;const y=qe.filter((L,I)=>!x[I]||x[I]===0);if(y.length&&r.push({flag:"dead_tier",detail:`${j.label}: ${y.join(", ")} priced at $0 while other tiers carry money (${qe.map((L,I)=>`${L} ${x[I]===null?"â":Aa(x[I])}`).join(" â ")}).`}),x.every(L=>L!==null&&L>0)){const L=x,I=[];for(let J=1;J<L.length;J++)L[J]<L[J-1]-.005&&I.push(`${qe[J-1]} ${Aa(L[J-1])} â ${qe[J]} ${Aa(L[J])}`);I.length&&r.push({flag:"tier_reversal",detail:`${j.label} goes backwards: ${I.join("; ")}.`});const[$,ee,U,E]=L;
9$===U&&U===E&&ee!==$&&r.push({flag:"copy_paste_tiers",detail:`${j.label}: entry, better and best are all ${Aa($)} while good is ${Aa(ee)} â tiers look backfilled.`})}}const d=(Pa(a,"labor_allowance")??0)+(Pa(a,"material_allowance")??0);if(d>0&&a.has_tier_allowance)if(gt.filter(b=>b.key.startsWith("allowance")).reduce((b,x)=>b+qe.reduce((u,N)=>u+(Pa(a,`${N}_${x.key}`)??0),0),0)===0)r.push({flag:"flat_allowance_not_tiered",detail:`Flat allowance of ${Aa(d)} is set but every per-tier allowance column is empty, so changing the finish tier will not change this allowance.`});else{const b=qe.map(x=>{const u=gt.filter(N=>N.key.startsWith("allowance")).reduce((N,y)=>N+(Pa(a,`${x}_${y.key}`)??0),0);return`${x} ${Aa(u)}`}).join(" · ");r.push({flag:"mixed_allowance_model",detail:`Two allowance definitions on one row: flat allowance ${Aa(d)} AND per-tier allowances (${b}). The backend resolves the per-tier value first, so the flat pair prices nothing but still shows on legacy reports â clear the one you do not want.`})}if(a.is_active!==!1&&oo(a.item_code,a.item_name)){const b=["labor_allowance","material_allowance",...gt.filter(x=>x.key.startsWith("allowance")).flatMap(x=>qe.map(u=>`${u}_${x.key}`))].filter(x=>(Pa(a,x)??0)!==0);b.length&&r.push({flag:"nonfinish_allowance",detail:`This is non-finish work (demo / removal / drywall / insulation / electrical / protection / paint), but ${b.map(x=>`${x} ${Aa(Pa(a,x)??0)}`).join(", ")} carry allowance money. Move it into base labor + material so the price does not move with the finish tier.`})}o&&l===0&&r.push({flag:"no_money",detail:"Every rate and allowance column on this row is zero â the item can never contribute money."});const _=String(a.item_code??"").trim();if((!_||/^\d+$/.test(_)||_.length<3)&&r.push({flag:"invalid_code",detail:`Item code "${_||"(empty)"}" is not a usable code â this row is almost certainly a bad import and no card reads it by name.`}),(h=a.same_side_duplicate_keys)!=null&&h.length&&r.push({flag:"same_side_duplicate",detail:`${a.same_side_duplicate_keys.length} other live row${a.same_side_duplicate_keys.length===1?"":"s"} on this card price the same item on the same side â only one can be the row the reader consumes.`}),a.side_divergent&&r.push({flag:"side_divergence",detail:"The matching item on the opposite side (addition vs remodel) carries different money, so the two sides price differently."}),a.is_active===!1&&(a.usage_projects??0)>0&&r.push({flag:"retired_but_consumed",detail:`Retired, but ${a.usage_projects} live project${a.usage_projects===1?"":"s"} still price with this row. Map a replacement so new projects keep the money, or restore it.`}),a.family_role_duplicate&&a.is_active!==!1&&r.push({flag:"family_role_duplicate",detail:"Another live row in this related-pricing family prices the same side, so which one a card reads depends on the reader. Keep one and retire or replace the other from the Related pricing panel."}),a.updated_at){const j=(Date.now()-new Date(a.updated_at).getTime())/2630016e3;j>=s&&r.push({flag:"stale",detail:`Last updated ${Math.floor(j)} months ago (${new Date(a.updated_at).toLocaleDateString()}).`})}const n=Array.from(new Set(r.map(j=>j.flag))),c=n.length?n.map(j=>ga[j]).sort((j,b)=>b.weight-j.weight)[0]:ga.healthy,m=n.reduce((j,b)=>j+ga[b].weight,0);return{flags:n.length?n:["healthy"],findings:r,topFlag:c,severity:m,totalMoney:l}}const bt={searchText:"",trades:[],cards:[],items:[],side:"all",flags:[],shapes:[],provenances:[],usage:"all",cardCoverage:"all",engines:[],includeLegacy:!1,includeInactive:!1,mergeSides:!0,breakdown:"family",divergedOnly:!1,finishOnly:!1,allowanceOnly:!1,areaBandOnly:!1,modifiedWithinDays:null,groupColumn:"Tier allowances (labor + material)",tier:"good"},Es={base_only:"Base labor/material only",tiered:"Tiered by finish level",allowance_only:"Allowance only",base_and_allowance:"Base + allowance",empty:"No money at all"},Rs={all:"Any usage",in_use:"Ever used (estimate history)",live:"Used by a live project",unused:"Never used anywhere"};function co({filters:a,setFilters:t,reset:s,universe:r,healthFor:l,columnGroups:o,scopeControl:i,summary:d}){const[_,n]=p.useState(!1),c=p.useMemo(()=>{const u=new Map,N=new Map,y=new Map,L=new Map,I=new Map;return r.forEach($=>{u.set($.trade,(u.get($.trade)||0)+1),N.set($.card_label,(N.get($.card_label)||0)+1),I.set($.engine,(I.get($.engine)||0)+1),$.provenance.forEach(U=>
9L.set(U,(L.get(U)||0)+1)),l($).flags.forEach(U=>y.set(U,(y.get(U)||0)+1))}),{trades:u,cards:N,flags:y,provenances:L,engines:I}},[r,l]),m=p.useMemo(()=>{const u=new Map;r.forEach(y=>{const L=u.get(y.item_code)||{label:y.item_name||y.item_code,cards:new Set,count:0};L.count+=1,y.card_label&&L.cards.add(y.card_label),u.set(y.item_code,L)});const N=new Map;return u.forEach(y=>N.set(y.label,(N.get(y.label)||0)+1)),Array.from(u.entries()).map(([y,L])=>({value:y,label:(N.get(L.label)||0)>1?`${L.label} · ${y}`:L.label,count:L.count,description:`${y}${L.cards.size?` · ${Array.from(L.cards).sort().join(", ")}`:""}`})).sort((y,L)=>y.label.localeCompare(L.label))},[r]),h=u=>{var N;return((N=m.find(y=>y.value===u))==null?void 0:N.label)??u},j=u=>Array.from(u.entries()).sort((N,y)=>N[0].localeCompare(y[0])).map(([N,y])=>({value:N,label:N,count:y})),b=u=>t({engines:u,includeLegacy:u.includes("legacy_retired")}),x=[];return a.searchText&&x.push({key:"q",label:`"${a.searchText}"`,clear:()=>t({searchText:""})}),a.trades.forEach(u=>x.push({key:`t-${u}`,label:u,clear:()=>t({trades:a.trades.filter(N=>N!==u)})})),a.cards.forEach(u=>x.push({key:`c-${u}`,label:u,clear:()=>t({cards:a.cards.filter(N=>N!==u)})})),a.items.forEach(u=>x.push({key:`i-${u}`,label:h(u),clear:()=>t({items:a.items.filter(N=>N!==u)})})),a.flags.forEach(u=>x.push({key:`f-${u}`,label:ga[u].label,clear:()=>t({flags:a.flags.filter(N=>N!==u)})})),a.shapes.forEach(u=>x.push({key:`s-${u}`,label:Es[u],clear:()=>t({shapes:a.shapes.filter(N=>N!==u)})})),a.provenances.forEach(u=>x.push({key:`p-${u}`,label:Da[u].label,clear:()=>t({provenances:a.provenances.filter(N=>N!==u)})})),a.engines.forEach(u=>x.push({key:`e-${u}`,label:ua[u].label,clear:()=>b(a.engines.filter(N=>N!==u))})),a.includeInactive&&x.push({key:"inactive",label:"Including retired rows",clear:()=>t({includeInactive:!1})}),a.mergeSides||x.push({key:"pair",label:"Addition & remodel shown separately",clear:()=>t({mergeSides:!0})}),a.usage!=="all"&&x.push({key:"usage",label:Rs[a.usage],clear:()=>t({usage:"all"})}),a.cardCoverage!=="all"&&x.push({key:"cardcov",label:As[a.cardCoverage],clear:()=>t({cardCoverage:"all"})}),a.side!=="all"&&x.push({key:"side",label:a.side,clear:()=>t({side:"all"})}),a.divergedOnly&&x.push({key:"div",label:"Differs from global",clear:()=>t({divergedOnly:!1})}),a.areaBandOnly&&x.push({key:"band",label:"Area-band (ladder) pricing only",clear:()=>t({areaBandOnly:!1})}),a.modifiedWithinDays&&x.push({key:"recent",label:`Changed ⤠${a.modifiedWithinDays}d`,clear:()=>t({modifiedWithinDays:null})}),a.breakdown!=="flat"&&x.push({key:"by",label:Nt[a.breakdown],clear:()=>t({breakdown:"flat"})}),e.jsx(ye,{className:"border-primary/20",children:e.jsxs(Ks,{open:_,onOpenChange:n,children:[e.jsxs(ke,{className:"py-2 px-3 space-y-2",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(Ws,{asChild:!0,children:e.jsxs(H,{variant:"ghost",size:"sm",className:"text-xs font-semibold text-primary",children:[_?e.jsx(ha,{className:"h-3.5 w-3.5 mr-1"}):e.jsx(fa,{className:"h-3.5 w-3.5 mr-1"}),e.jsx(ci,{className:"h-3.5 w-3.5 mr-1"}),"Filters",x.length?` (${x.length})`:""]})}),d&&e.jsx("span",{className:"text-xs text-muted-foreground",children:d}),e.jsxs("div",{className:"ml-auto flex w-full min-w-0 flex-wrap items-center gap-2 sm:w-auto",children:[i,e.jsxs("div",{className:"relative min-w-0 flex-1 sm:flex-none",children:[e.jsx(Va,{className:"absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground"}),e.jsx(Pe,{className:"pl-8 h-9 w-full sm:w-[260px]",value:a.searchText,onChange:u=>t({searchText:u.target.value}),placeholder:"Search item, code, trade or card"})]}),e.jsx(xa,{label:"Items",allLabel:"All items",width:"w-[190px]",options:m,selected:a.items,onChange:u=>t({items:u})})]})]}),x.length>0&&e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[x.map(u=>e.jsxs(ie,{variant:"secondary",className:"gap-1",children:[u.label,e.jsx("button",{onClick:u.clear,className:"opacity-60 hover:opacity-100","aria-label":`Remove ${u.label}`,children:e.jsx(Et,{className:"h-3 w-3"})})]},u.key)),e.jsx(H,{variant:"ghost",size:"sm",className:"h-6 text-xs",onClick:s,children:"Clear all"})]})]}),e.jsx(Gs,{children:e.jsxs(je,{className:"pt-0 pb-3 px-3 space-y-3",children:[e.jsxs("div",{className:"rounded-md border border-primary/15 bg-primary/[0.04] p-2",children:[e.jsx("p",{className:"text-[11px] font-semibold uppercase tracking-wide text-primary mb-2",children:"Find"}),e.jsxs("div",{className:"flex flex-wrap items-end gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Item (type to find)"}),e.jsx(xa,{label:"Items",allLabel:"All items",width:"w-[240px]",options:m,selected:a.items,onChange:u=>t({items:u})})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Trade"}),e.jsx(xa,{label:"Trades",allLabel:"All trades",options:j(c.trades),selected:a.trades,onChange:u=>t({trades:u})})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Card"}),e.jsx(xa,{label:"Cards",allLabel:"All cards",options:j(c.cards),selected:a.cards,onChange:u=>t({cards:u})})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Side"}),e.jsxs(Be,{value:a.side,onValueChange:u=>t({side:u}),children:[e.jsx(Ve,{className:"whitespace-nowrap [&>span]:truncate w-[130px]",children:e.jsx(ze,{})}),e.jsxs(Ue,{children:[e.jsx(me,{value:"all",children:"Both"}),e.jsx(me,{value:"addition",children:"Addition"}),e.jsx(me,{value:"remodel",children:"Remodel"})]})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Card coverage"}),e.jsxs(Be,{value:a.cardCoverage,onValueChange:u=>t({cardCoverage:u}),children:[e.jsx(Ve,{className:"whitespace-nowrap [&>span]:truncate w-[190px]",children:e.jsx(ze,{})}),e.jsx(Ue,{children:Object.keys(As).map(u=>e.jsx(me,{value:u,children:As[u]},u))})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Breakdown"}),e.jsxs(Be,{value:a.breakdown,onValueChange:u=>t({breakdown:u}),children:[e.jsx(Ve,{className:"whitespace-nowrap [&>span]:truncate w-[150px]",children:e.jsx(ze,{})}),e.jsx(Ue,{children:Object.keys(Nt).map(u=>e.jsx(me,{value:u,children:Nt[u]},u))})]})]}),e.jsxs("label",{className:`flex items-center gap-2 text-sm pb-2 font-medium ${a.breakdown==="family"?"opacity-50":""}`,title:a.breakdown==="family"?"Family view always shows both sides, so shared rows are never merged here.":"When the same item is priced i
9dentically on the addition and the remodel side, show it once. Editing that row writes both sides. Pairs whose money differs always stay split.",children:[e.jsx(ca,{checked:a.breakdown==="family"?!1:a.mergeSides,disabled:a.breakdown==="family",onCheckedChange:u=>t({mergeSides:!!u})}),"Shared addition/remodel items once"]})]})]}),e.jsxs("div",{className:"rounded-md border border-primary/15 bg-accent/[0.07] p-2",children:[e.jsx("p",{className:"text-[11px] font-semibold uppercase tracking-wide text-primary mb-2",children:"Money"}),e.jsxs("div",{className:"flex flex-wrap items-end gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Finish tier shown"}),e.jsxs(Be,{value:a.tier,onValueChange:u=>t({tier:u}),children:[e.jsx(Ve,{className:"whitespace-nowrap [&>span]:truncate w-[140px]",children:e.jsx(ze,{})}),e.jsx(Ue,{children:qe.map(u=>e.jsx(me,{value:u,className:"capitalize",children:u},u))})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Extra per-tier columns"}),e.jsxs(Be,{value:a.groupColumn,onValueChange:u=>t({groupColumn:u}),children:[e.jsx(Ve,{className:"whitespace-nowrap [&>span]:truncate w-[210px]",children:e.jsx(ze,{})}),e.jsxs(Ue,{children:[e.jsx(me,{value:"None",children:"None (4 money columns)"}),o.map(u=>e.jsx(me,{value:u.label,children:u.label},u.label))]})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Pricing shape"}),e.jsx(xa,{label:"Pricing shape",allLabel:"Any shape",width:"w-[210px]",options:Object.keys(Es).map(u=>({value:u,label:Es[u]})),selected:a.shapes,onChange:u=>t({shapes:u})})]}),e.jsxs("label",{className:"flex items-center gap-2 text-sm pb-2",children:[e.jsx(ca,{checked:a.divergedOnly,onCheckedChange:u=>t({divergedOnly:!!u})}),"Differs from global"]}),e.jsxs("label",{className:"flex items-center gap-2 text-sm pb-2",title:"Items whose rate steps by project area (a band ladder). Edit the bands themselves in the Area bands view.",children:[e.jsx(ca,{checked:a.areaBandOnly,onCheckedChange:u=>t({areaBandOnly:!!u})}),"Area-band pricing only"]})]})]}),e.jsxs("div",{className:"rounded-md border border-primary/15 bg-primary/[0.04] p-2",children:[e.jsx("p",{className:"text-[11px] font-semibold uppercase tracking-wide text-primary mb-2",children:"Status"}),e.jsxs("div",{className:"flex flex-wrap items-end gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Needs attention"}),e.jsx(xa,{label:"Health flags",allLabel:"Any health",width:"w-[190px]",options:[...gn,"healthy"].map(u=>({value:u,label:ga[u].label,count:c.flags.get(u)||0,description:ga[u].description})),selected:a.flags,onChange:u=>t({flags:u})})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Pricing engine"}),e.jsx(xa,{label:"Engine",allLabel:"Any engine",width:"w-[210px]",options:Ki.map(u=>({value:u,label:ua[u].label,count:c.engines.get(u)||0,description:ua[u].description})),selected:a.engines,onChange:b})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Source / provenance"}),e.jsx(xa,{label:"Provenance",allLabel:"Any source",width:"w-[200px]",options:qi.map(u=>({value:u,label:Da[u].label,count:c.provenances.get(u)||0})),selected:a.provenances,onChange:u=>t({provenances:u})})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Backend usage"}),e.jsxs(Be,{value:a.usage,onValueChange:u=>t({usage:u}),children:[e.jsx(Ve,{className:"whitespace-nowrap [&>span]:truncate w-[170px]",children:e.jsx(ze,{})}),e.jsx(Ue,{children:Object.keys(Rs).map(u=>e.jsx(me,{value:u,children:Rs[u]},u))})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Changed"}),e.jsxs(Be,{value:a.modifiedWithinDays?String(a.modifiedWithinDays):"any",onValueChange:u=>t({modifiedWithinDays:u==="any"?null:Number(u)}),children:[e.jsx(Ve,{className:"whitespace-nowrap [&>span]:truncate w-[150px]",children:e.jsx(ze,{})}),e.jsxs(Ue,{children:[e.jsx(me,{value:"any",children:"Any time"}),e.jsx(me,{value:"7",children:"Last 7 days"}),e.jsx(me,{value:"30",children:"Last 30 days"}),e.jsx(me,{value:"90",children:"Last 90 days"})]})]})]}),e.jsxs("label",{className:"flex items-center gap-2 text-sm pb-2",title:"Show rows that were retired. They price nothing today, but can be restored from the grid.",children:[e.jsx(ca,{checked:a.includeInactive,onCheckedChange:u=>t({includeInactive:!!u})}),"Include retired rows"]})]})]})]})})]})})}const mo=36;function uo(){return Ke({queryKey:["pricing-usage-freshness"],queryFn:async()=>{const{count:a,error:t}=await ge.from("pricing_item_usage").select("item_code",{count:"exact",head:!0});if(t)throw t;const{data:s}=await ge.from("pricing_item_usage").select("refreshed_at").order("refreshed_at",{ascending:!1}).limit(1).maybeSingle(),r=(s==null?void 0:s.refreshed_at)||null,l=r?(Date.now()-new Date(r).getTime())/36e5:null;return{itemCodes:a||0,refreshedAt:r,ageHours:l,stale:l===null||l>mo}},staleTime:6e4})}function ho(){const[a,t]=p.useState(!1),s=$a();return{refresh:p.useCallback(async()=>{t(!0);try{const{data:l,error:o}=await ge.functions.invoke("refresh-pricing-usage",{body:{}});if(o)throw o;if(!(l!=null&&l.success))throw new Error((l==null?void 0:l.error)||"Refresh failed");return le.success("Usage index rebuilt",{description:`${Number(l.itemCodes||0).toLocaleStr
9ing()} item codes indexed from real estimate history.`}),await Promise.all([s.invalidateQueries({queryKey:["pricing-catalog"]}),s.invalidateQueries({queryKey:["pricing-usage-freshness"]})]),!0}catch(l){return le.error("Could not rebuild the usage index",{description:(l==null?void 0:l.message)??String(l)}),!1}finally{t(!1)}},[s]),refreshing:a}}function _o({canRefresh:a}){var i;const{data:t,isLoading:s}=uo(),{refresh:r,refreshing:l}=ho(),o=(t==null?void 0:t.ageHours)===null||(t==null?void 0:t.ageHours)===void 0?"never built":t.ageHours<1?"just now":t.ageHours<48?`${Math.round(t.ageHours)}h ago`:`${Math.round(t.ageHours/24)}d ago`;return e.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[e.jsxs(Na,{children:[e.jsx(ka,{asChild:!0,children:e.jsxs("span",{className:`inline-flex items-center gap-1 px-1.5 py-0.5 rounded border text-[11px] ${t!=null&&t.stale?"bg-[#C9A96E]/10 text-[#8a6f36] dark:text-[#C9A96E] border-[#C9A96E]/40":"bg-primary/10 text-primary border-primary/30"}`,children:[e.jsx(Hs,{className:"h-3 w-3"}),s?"usage indexâ¦":`usage index ${o}`]})}),e.jsxs(Ca,{className:"max-w-xs text-xs",children:["Usage is measured from every generated estimate's saved line items, plus frozen project snapshots and allowance overrides â ",((i=t==null?void 0:t.itemCodes)==null?void 0:i.toLocaleString())??0," item codes indexed. It rebuilds nightly; rebuild it now if you just generated estimates."]})]}),a&&e.jsxs(H,{type:"button",variant:"ghost",size:"sm",className:"h-6 px-1.5 text-[11px]",disabled:l,onClick:()=>r(),children:[e.jsx(Ga,{className:`h-3 w-3 mr-1 ${l?"animate-spin":""}`}),l?"Rebuildingâ¦":"Rebuild"]})]})}const po={verified:{label:"Verified",hint:"Proven end-to-end by the final wiring check.",badgeVariant:"default",chipClass:"bg-primary/10 text-primary border-primary/30",textClass:"text-primary"},caution:{label:"Caution",hint:"Applied, but the checker flagged something worth a look.",badgeVariant:"secondary",chipClass:"bg-secondary text-secondary-foreground border-border",textClass:"text-secondary-foreground"},failed:{label:"Not wired",hint:"A check failed â the price does not reach every surface.",badgeVariant:"destructive",chipClass:"bg-destructive/10 text-destructive border-destructive/30",textClass:"text-destructive"},reverted:{label:"Rolled back",hint:"The write failed its checks and was reverted automatically.",badgeVariant:"destructive",chipClass:"bg-destructive/10 text-destructive border-destructive/40",textClass:"text-destructive"},unverified:{label:"Unverified",hint:"No final wiring check has run for this row yet.",badgeVariant:"outline",chipClass:"bg-muted text-muted-foreground border-border",textClass:"text-muted-foreground"}},wn=["reverted","failed","caution","unverified","verified"];function Yt(a){return!a||!a.state?"unverified":a.reverted?"reverted":a.state==="pass"?"verified":a.state==="warn"?"caution":"failed"}function hs(a){return po[a]}const xo={verified:e.jsx(ms,{className:"h-3 w-3"}),caution:e.jsx(zl,{className:"h-3 w-3"}),failed:e.jsx($i,{className:"h-3 w-3"}),reverted:e.jsx(Ui,{className:"h-3 w-3"}),unverified:e.jsx(Si,{className:"h-3 w-3"})};function _s({itemCode:a,enabled:t=!0,preloaded:s,preloadedReady:r}){const l=r!==void 0,[o,i]=p.useState(null),[d,_]=p.useState(!1);p.useEffect(()=>{if(l||!t||!a)return;let b=!0;return Ci(a).then(x=>{b&&(i(x),_(!0))}),()=>{b=!1}},[a,t,l]);const n=l?s??null:o;if(!(l?!!r:d))return null;const m=Yt(n),h=hs(m),j=n?`${n.summary??h.label} â checked ${new Date(n.created_at).toLocaleString()}${n.reverted?" (change was rolled back)":""}`:`${h.hint} Run one before trusting the price end-to-end.`;return e.jsx(mr,{children:e.jsxs(Na,{children:[e.jsx(ka,{asChild:!0,children:e.jsxs(ie,{variant:h.badgeVariant,className:"gap-1 whitespace-nowrap text-[10px] px-1.5 py-0",children:[xo[m],h.label]})}),e.jsx(Ca,{className:"max-w-xs text-xs",children:j})]})})}const Dt=1e3,go=40;async function bo(){const a=new Map;for(let t=0;t<go;t++){const{data:s,error:r}=await ge.from("pricing_wiring_verdicts").select("item_code, state, summary, created_at, reverted").order("created_at",{ascending:!1}).range(t*Dt,t*Dt+Dt-1);if(r||!s)return a;for(const l of s)!l.item_code||a.has(l.item_code)||a.set(l.item_code,{state:l.state,summary:l.summary??null,created_at:l.created_at,reverted:!!l.reverted});if(s.length<Dt)break}return a}function Rt(a=!0){return Ke({queryKey:["pricing-wiring-verdicts","latest"],enabled:a,staleTime:6e4,queryFn:bo})}const rt=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,Xr=/^[0-9a-f]{64}$/,fo=["actorId","allowedStateCodes","catalogKey","checkedAt","companyColumns","companyComplete","companyId","companyRows","defaultStateCode","globalColumns","globalComplete","globalRows","nextCompanyCursor","nextGlobalCursor","readOnly","rowDigest","scopeDigest","version"].sort().join(","),na=()=>new Error("Your current company catalog access could not be confirmed."),wo={septic_line_items_global:["card_code","is_active","base_labor_rate","base_material_rate","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"],septic_line_items_company:["card_code","is_active","base_labor_rate","base_material_rate","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"],full_bath_line_items_company:["entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"],half_bath_line_items_company:["entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"],primary_bath_line_items_company:["entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},Zr=a=>{if(!a||typeof a!="object"||Array.isArray(a))throw na();return a},yo=(a,t)=>Object.keys(a).sort().join(",")===[...t].sort().join(",");function rr(a,t){const s=vt.find(i=>i.table===a.table);if(!s)throw na();const r=t==="global"?s.table:sn(s.table,"company"),l=wo[r]||[],o=i=>Za(r,i)||l.includes(i);return Array.from(new Set(["id","item_code",...o("card_code")?["card_code"]:[],...t==="global"?[s.nameColumn,s.categoryColumn].filter(i=>!!i):[],...o("is_active")?["is_active"]:[],...$t.filter(o)]))}function jo(a,t,s,r,l,o=100){const i=Zr(a),d=typeof i.checkedAt=="string"?Date.parse(i.checkedAt):NaN;if(Object.keys(i).sort().join(",")!==fo||i.version!=="company-pricing-catalog-v1"||i.catalogKey!==t.table||i.actorId!==s.actorId||i.companyId!==s.companyId||!rt.test(s.actorId)||!rt.test(s.companyId)||i.readOnly!==!0||typeof i.scopeDigest!="string"||!Xr.test(i.scopeDigest)||typeof i.rowDigest!="string"||!Xr.test(i.rowDigest)||!Number.isFinite(d)||d<r-5e3||d>Date.now()+5e3||Date.now()-d>3e4||!Array.isArray(i.allowedStateCodes)||!i.allowedStateCodes.length||i.allowedStateCodes.length>51||!i.allowedStateCodes.every(m=>typeof m=="string"&&di(m)===m)||new Set(i.allowedStateCodes).size!==i.allowedStateCodes.length||[...i.allowedStateCodes].sort().join(",")!==[...s.allowedStateCodes].sort().join(",")||i.defaultStateCode!==s.defaultStateCode||typeof i.defaultStateCode!="string"||!i.allowedStateCodes.includes(i.defaultStateCode))throw na();const _=(m,h)=>{const j=rr(t,m),b=i[m+"Columns"],x=i[m+"Rows"],u=i[m+"Complete"],N=i[m==="global"?"nextGlobalCursor":"nextCompanyCursor"];if(!Array.isArray(b)||b.length!==j.length||b.some((I,$)=>I!==j[$])||!Array.isArray(x)||x.length>o||typeof u!="boolean"||!(N===null||typeof N=="string"&&rt.test(N))||u&&N!==null||!u&&(x.length!==o||!x.length))throw na();let y=h;const L=x.map(I=>{const $=Zr(I);if(!yo($,j)||typeof $.id!="string"||!rt.test($.id)||y!==null&&$.id<=y||typeof $.item_code!="string"||!$.item_code||$.item_code.length>200)throw na();
9y=$.id;for(const ee of j){const U=$[ee];if($t.includes(ee)){if(!(U===null||typeof U=="number"&&Number.isFinite(U)&&Math.abs(U)<=Number.MAX_SAFE_INTEGER))throw na()}else if(ee==="is_active"){if(!(U===null||typeof U=="boolean"))throw na()}else if(!(U===null||typeof U=="string"&&U.length<=2e3))throw na()}return $});if(!u&&N!==y)throw na();return{rows:L,complete:u,next:N}},n=_("global",l.global),c=_("company",l.company);return{identity:{...s,allowedStateCodes:[...i.allowedStateCodes]},scopeDigest:i.scopeDigest,globalRows:n.rows,companyRows:c.rows,nextGlobalCursor:n.next,nextCompanyCursor:c.next,globalComplete:n.complete,companyComplete:c.complete}}async function vo(a,t,s,r){var n,c;if(!vt.some(m=>m.table===t.table)||!rt.test(s.actorId)||!rt.test(s.companyId)||!s.allowedStateCodes.length||r.aborted)throw na();const l=[],o=[];let i=null,d=null,_=null;for(let m=0;m<250;m++){if(r.aborted)throw na();const h=Date.now(),{data:j,error:b}=await a.rpc("read_company_pricing_catalog",{p_catalog_key:t.table,p_global_after_id:i,p_company_after_id:d,p_limit:100}).abortSignal(r);if(b)throw b;if(r.aborted)throw na();const x=jo(j,t,s,h,{global:i,company:d});if(_!==null&&_!==x.scopeDigest)throw na();if(_=x.scopeDigest,l.push(...x.globalRows),o.push(...x.companyRows),i=((n=x.globalRows.at(-1))==null?void 0:n.id)??i,d=((c=x.companyRows.at(-1))==null?void 0:c.id)??d,x.globalComplete&&x.companyComplete)return{globalRows:l,companyRows:o}}throw new Error("The complete company catalog exceeds the safe paging bound.")}const De=(a,t="both")=>({trade:a,side:t}),br={structural_line_items_global:De("Structural / Framing"),interior_building_line_items_global:De("Interior Building"),millwork_line_items_global:De("Millwork & Trim"),kitchen_line_items_global:De("Kitchen"),bar_line_items_global:De("Bar"),full_bath_line_items_global:De("Bathrooms"),half_bath_line_items_global:De("Bathrooms"),primary_bath_line_items_global:De("Bathrooms"),hardwood_line_items_global:De("Flooring"),basement_flooring_line_items_global:De("Flooring"),builtins_line_items_global:De("Storage & Built-Ins"),mudroom_line_items_global:De("Living Features"),laundry_line_items_global:De("Living Features"),fireplace_line_items_global:De("Living Features"),hvac_extension_line_items_global:De("Mechanical / HVAC"),roofing_line_items_global:De("Exterior Building"),siding_line_items_global:De("Exterior Building"),windows_line_items_global:De("Exterior Building"),patio_doors_line_items_global:De("Exterior Building"),skylights_line_items_global:De("Exterior Building"),deck_line_items_global:De("Exterior Non-Building","addition"),deck_line_items_global_remodel:De("Exterior Non-Building","remodel"),driveway_line_items_global:De("Exterior Non-Building","addition"),driveway_line_items_global_remodel:De("Exterior Non-Building","remodel"),paver_patio_line_items_global:De("Exterior Non-Building","addition"),paver_patio_line_items_global_remodel:De("Exterior Non-Building","remodel"),exterior_stairs_line_items_global:De("Exterior Non-Building","addition"),exterior_stairs_line_items_global_remodel:De("Exterior Non-Building","remodel"),window_well_line_items_global:De("Exterior Non-Building","addition"),window_well_line_items_global_remodel:De("Exterior Non-Building","remodel"),fence_line_items_global:De("Exterior Non-Building"),seepage_pit_line_items_global:De("Site & Drainage")};function No(a){var t;return((t=br[a])==null?void 0:t.trade)||"Other"}function ko(a){var t;return((t=br[a])==null?void 0:t.side)||"both"}Array.from(new Set(Object.values(br).map(a=>a.trade))).sort();const Co=1e3;async function fr(a,t,s=Co){const r=[];for(let l=0;;l+=s){const{data:o,error:i}=await t(l,l+s-1);if(i)throw new Error(`Could not load the complete ${a} catalog: ${i.message}`);const d=o||[];if(r.push(...d),d.length<s)break}return r}const So=["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","allowance_good","entry_labor_rate","entry_material_rate","entry_allowance_labor","entry_allowance_material","entry_allowance_total","good_labor_rate","good_material_rate","good_allowance_labor","good_allowance_material","good_allowance_total","better_labor_rate","better_material_rate","better_allowance_labor","better_allowance_material","better_allowance_total","best_labor_rate","best_material_rate","best_allowance_labor","best_allowance_material","best_allowance_total"],yn={bar_line_items_global:{reader:"get-bar-line-items",consumed:["labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_labor_rate","entry_material_rate","entry_allowance_labor","entry_allowance_material","entry_allowance_total","good_labor_rate","good_material_rate","good_allowance_labor","good_allowance_material","good_allowance_total","better_labor_rate","better_material_rate","better_allowance_labor","better_allowance_material","better_allowance_total","best_labor_rate","best_material_rate","best_allowance_labor","best_allowance_material","best_allowance_total"]},basement_flooring_line_items_global:{reader:"get-basement-flooring-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},builtins_line_items_global:{reader:"get-builtins-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},deck_line_items_global:{reader:"get-deck-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},deck_line_items_global_remodel:{reader:"get-deck-line-items-remodel",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},driveway_line_items_global:{reader:"get-driveway-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},driveway_line_items_global_remodel:{reader:"get-driveway-line-items-remodel",consumed:["base_labor_rate","base_material_rate","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},exterior_stairs_line_items_global:{reader:"get-exterior-stairs-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},exterior_stairs_line_items_global_remodel:{reader:"get-exterior-stairs-line-items-remodel",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},fence_line_items_global:{reader:"get-fence-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},fireplace_line_items_global:{reader:"get-fireplace-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},full_bath_line_items_global:{reader:"get-full-bath-line-items",consumed:["labor_unit_price","material_unit_price","labor_allowance","material_allowance","allowance_good","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},half_bath_line_items_global:{reader:"get-half-bath-line-items",consumed:["labor_unit_price","material_unit_price","labor_allowance","material_allowance","allowance_good","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},hardwood_line_items_global:{reader:"get-hardwood-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},hvac_extension_line_items_global:{reader:"get-hvac-extension-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},interior_building_line_items_global:{reader:"get-interior-building-line-items",consumed:["labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_labor_rate","entry_material_rate","entry_allowance_labor","entry_allowance_material","good_labor_rate","good_material_rate","good_allowance_labor","good_allowance_material","better_labor_rate","better_material_rate","better_allowance_labor","better_allowance_material","best_labor_rate","best_material_rate","best_allowance_labor","best_allowance_material"]},kitchen_line_items_global:{reader:"get-kitchen-line-items",consumed:["labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_labor_rate","entry_material_rate","entry_allowance_labor","entry_allowance_material","entry_allowance_total","good_labor_rate","good_material_rate","good_allowance_labor","good_allowance_material","good_allowance_total","better_labor_rate","better_material_rate","better_allowance_labor","better_allowance_material","better_allowance_total","best_labor_rate","best_material_rate","best_allowance_labor","best_allowance_material","best_allowance_total"]},laundry_line_items_global:{reader:"get-laundry-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},millwork_line_items_global:{reader:"get-millwork-line-items",consumed:["labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_labor_rate","entry_material_rate","entry_allowance_labor","entry_allowance_material","good_labor_rate","good_material_rate","good_allowance_labor","good_allowance_material","better_labor_rate","better_material_rate","better_allowance_labor","better_allowance_material","best_labor_rate","best_material_rate","best_allowance_labor","best_allowance_material"]},mudroom_line_items_global:{reader:"get-mudroom-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},patio_doors_line_items_global:{reader:"get-patio-doors-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},paver_patio_line_items_global:{reader:"get-paver-patio-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},paver_patio_line_items_global_remodel:{reader:"get-paver-patio-line-items-remodel",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},primary_bath_line_items_global:{reader:"get-primary-bath-line-items",consumed:["labor_unit_price","material_unit_price","labor_allowance","material_allowance","allowance_good","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},roofing_line_items_global:{reader:"get-roofing-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},seepage_pit_line_items_global:{reader:"get-seepage-pit-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},septic_line_items_global:{reader:"get-septic-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},siding_line_items_global:{reader:"get-siding-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},skylights_line_items_global:{reader:"get-skylights-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowanc
9e_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},structural_line_items_global:{reader:"get-structural-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_labor_rate","entry_material_rate","entry_allowance_labor","entry_allowance_material","good_labor_rate","good_material_rate","good_allowance_labor","good_allowance_material","better_labor_rate","better_material_rate","better_allowance_labor","better_allowance_material","best_labor_rate","best_material_rate","best_allowance_labor","best_allowance_material"]},window_well_line_items_global:{reader:"get-window-well-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},window_well_line_items_global_remodel:{reader:"get-window-well-line-items-remodel",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]},windows_line_items_global:{reader:"get-windows-line-items",consumed:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price","labor_allowance","material_allowance","entry_allowance_labor","entry_allowance_material","good_allowance_labor","good_allowance_material","better_allowance_labor","better_allowance_material","best_allowance_labor","best_allowance_material"]}},$o=new Set(So);function jn(a){return $o.has(a)}function Ao(a,t){if(!jn(t))return!0;const s=yn[a];return s?s.consumed.includes(t):!0}function Eo(a,t){return t.filter(s=>jn(s)&&!Ao(a,s))}function Ro(a,t){var r;const s=((r=yn[a])==null?void 0:r.reader)??gr(a);return s?`${t} is never read by ${s}, so editing it cannot change any estimate. Locked to keep the catalog honest.`:`${t} is not consumed by any live V2 reader, so editing it cannot change any estimate.`}const vn=["addition","remodel","add","rem"];function nt(a){if(!a)return"";let t=String(a).toLowerCase();for(const s of vn)t=t.replace(new RegExp(`(^|[_\\-\\s])${s}([_\\-\\s]|$)`,"g"),"_");return t.replace(/[^a-z0-9]+/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,"")}
9function Nn(a){if(!a)return"";let t=String(a).toLowerCase();for(const s of vn)t=t.replace(new RegExp(`\\b${s}\\b`,"g")," ");return t.replace(/[^a-z0-9]+/g," ").trim().replace(/\s+/g," ")}function kn(a){return a.replace(/_remodel$/,"")}const Bt=(a,t)=>t.some(s=>new RegExp(`(^|[_\\-\\s])${s}([_\\-\\s]|$)`).test(a));function wr(a){const t=(a.card_code||"").toLowerCase();if(t){if(Bt(t,["addition","add"]))return"addition";if(Bt(t,["remodel","rem"]))return"remodel"}const s=a.source_table.toLowerCase();if(/_remodel$/.test(s))return"remodel";const r=(a.item_code||"").toLowerCase();return Bt(r,["addition","add"])?"addition":Bt(r,["remodel","rem"])?"remodel":a.side==="addition"||a.side==="remodel"?a.side:"unknown"}function To(a){if(wr(a)==="unknown")return null;const s=nt(a.item_code),r=Nn(a.item_name);if(!s&&!r)return null;const l=nt(a.card_code)||nt(a.card_label);return`${kn(a.source_table)}|${l}|${s}|${r}`}const el=a=>Math.round(Number(a??0)*100)/100;function Lo(a,t){const s=Array.from(new Set([...a.editable_columns,...t.editable_columns]));return s.length?s.every(r=>el(a.values[r])===el(t.values[r])):!1}function al(a){const t=new Map,s=new Map;return a.forEach(r=>{const l=wr(r),o=r.read_only?null:To(r);if(s.set(r.key,{pairId:o,side:l}),!o||l==="unknown")return;const i=t.get(o)||{addition:[],remodel:[]};i[l].push(r),t.set(o,i)}),a.map(r=>{const l=s.get(r.key);let o=null;if(l.pairId&&l.side!=="unknown"){const d=t.get(l.pairId),_=l.side==="addition"?d==null?void 0:d.addition:d==null?void 0:d.remodel,n=l.side==="addition"?d==null?void 0:d.remodel:d==null?void 0:d.addition;n&&n.length===1&&_&&_.length===1&&(o=n[0])}const i=o?Lo(r,o):!1;return{...r,side_pair_id:l.pairId,side:r.side,pair_side:l.side,side_partner_key:(o==null?void 0:o.key)??null,side_money_matches:i,side_divergent:!!o&&!i}})}function Mo(a,t={enabled:!0}){const s=new Set,r=new Set,l=new Set;let o=0;if(!t.enabled)return a.forEach(n=>{const c=n.side_pair_id;c&&n.side_divergent&&!l.has(c)&&(l.add(c),o+=1)}),{rows:a,mergedKeys:s,hiddenKeys:r,collapsed:0,divergentPairs:o};const i=new Set(a.map(n=>n.key)),d=[];return a.forEach(n=>{var x;const c=n.side_pair_id,m=n.side_partner_key,h=!!n.side_money_matches,j=!!n.side_divergent;if(c&&j&&!l.has(c)&&(l.add(c),o+=1),!(!!c&&!!m&&h&&i.has(m)&&!((x=t.unmerged)!=null&&x.has(c)))){d.push(n);return}if(!r.has(n.key)){if(n.pair_side==="remodel"){r.add(n.key);return}s.add(n.key),r.add(m),d.push(n)}}),{rows:d.filter(n=>!r.has(n.key)||s.has(n.key)),mergedKeys:s,hiddenKeys:r,collapsed:s.size,divergentPairs:o}}function tl(a){const t=new Map;a.forEach(r=>{if(r.read_only||r.is_active===!1)return;const l=wr(r),o=nt(r.item_code),i=Nn(r.item_name);if(!o&&!i)return;const d=nt(r.card_code)||nt(r.card_label),_=`${kn(r.source_table)}|${d}|${l}|${o||i}`,n=t.get(_);n?n.push(r):t.set(_,[r])});const s=new Map;return t.forEach(r=>{r.length<2||r.forEach(l=>s.set(l.key,r.filter(o=>o.key!==l.key).map(o=>o.key)))}),s.size?a.map(r=>s.has(r.key)?{...r,same_side_duplicate_keys:s.get(r.key)}:r):a}function Po(a){const t=new Map;a.forEach(l=>t.set(l.key,l));const s=new Set,r=[];return a.forEach(l=>{if(s.has(l.key))return;s.add(l.key),r.push(l);const o=l.side_partner_key;if(!o||s.has(o))return;const i=t.get(o);i&&(s.add(i.key),r.push(i))}),r}const Vt=(a,t)=>{for(const s of t){const r=a[s];if(r!=null)return r}return null};function Io(a,t="good"){const s=a.values,r=Vt(s,[`${t}_labor_rate`,"base_labor_rate","labor_unit_price"]),l=Vt(s,[`${t}_material_rate`,"base_material_rate","material_unit_price"]),o=Vt(s,[`${t}_allowance_labor`,"labor_allowance"]),i=Vt(s,[`${t}_allowance_material`,"material_allowance"]);return{baseLabor:r,baseMaterial:l,allowanceLabor:o,allowanceMaterial:i,total:(r??0)+(l??0)+(o??0)+(i??0)}}const yr=a=>a.includes("allowance"),Cn=a=>/^(entry|good|better|best)_/.test(a);function Fo(a){let t=!1,s=!1,r=!1;for(const l of a.editable_columns){const o=a.values[l];o==null||Number(o)===0||(yr(l)?s=!0:t=!0,Cn(l)&&(r=!0))}return!t&&!s?"empty":r?"tiered":t&&s?"base_and_allowance":s?"allowance_only":"base_only"}function Oo(a){let t=!1,s=!1,r=!1;for(const o of a.editable_columns){const i=a.values[o];i==null||Number(i)===0||(yr(o)?s=!0:t=!0,Cn(o)&&(r=!0))}if(!t&&!s)return["empty"];const l=[];return t&&s&&l.push("base_and_allowance"),t&&l.push("base_only"),s&&l.push("allowance_only"),r&&l.push("tiered"),l}function Sn(a){return a.source!=="company"?!1:a.editable_columns.some(t=>{const s=a.values[t],r=a.global_values[t];return Number(s??0)!==Number(r??0)})}function sl(a){if(a==null||a==="")return null;const t=Number(a);return Number.isFinite(t)?t:null}async function rl(a,t,s){const r=await fr(a,(l,o)=>{let i=ge.from(a).select("*").range(l,o);return s&&(i=i.eq("company_id",s)),i});return s?r.filter(l=>l.company_id===s):r}function Do(a,t){const s=["id","item_code","updated_at"];return Za(t,"card_code")&&s.push("card_code"),a.nameColumn&&t.includes("_global")&&s.push(a.nameColumn),a.categoryColumn&&t.includes("_global")&&s.push(a.categoryColumn),Array.from(new Set(s))}function Ts(a,t,s){return`${a}:${t}:${s||""}`}function Bo(a){return a?a.estimateRows>0||a.allTimeProjects>0?"estimates":a.snapshotProjects>0?"snapshot":a.overrideProjects>0?"override":"none":"none"}const lr={provenanceByCode:new Map,auditedCodes:new Set,usage:new Map};async function zt(a,t){return fr(`${a} (provenance)`,(s,r)=>ge.from(a).select(t).range(s,r))}async function Vo(){const a=new Map,t=new Set,s=new Map,r=(n,c)=>{if(!n)return;const m=a.get(n)||[];m.includes(c)||m.push(c),a.set(n,m)},l=n=>n?n==="ai_generated"?"ai_generated":n==="bulk_updated"?"bulk_updated":n==="system"?"system":n==="company"?"company":null:null,[o,i,d,_]=await Promise.all([zt("base_pricing","item_code, pricing_source"),zt("finish_allowances","item_code, pricing_source"),zt("catalog_price_change_items","item_code"),zt("pricing_item_usage","item_code, live_projects, all_time_projects, estimate_rows, money_projects, snapshot_projects, override_projects, last_used_at").catch(n=>[])]);
9return[...o,...i].forEach(n=>{const c=l(n.pricing_source);c&&r(n.item_code,c)}),d.forEach(n=>n.item_code&&t.add(n.item_code)),(_||[]).forEach(n=>{n!=null&&n.item_code&&s.set(n.item_code,{liveProjects:Number(n.live_projects||0),allTimeProjects:Number(n.all_time_projects||0),estimateRows:Number(n.estimate_rows||0),moneyProjects:Number(n.money_projects||0),snapshotProjects:Number(n.snapshot_projects||0),overrideProjects:Number(n.override_projects||0),lastUsedAt:n.last_used_at||null})}),{provenanceByCode:a,auditedCodes:t,usage:s}}async function ll(a,t,s,r=lr,l){const o=a.table,i=l?rr(a,"global").filter(N=>$t.includes(N)):Jr(o);if(!i.length)return[];const d=(l==null?void 0:l.globalRows)??await rl(o,[...Do(a,o),...i]),_=t==="company"&&Ei(a,"company")?sn(o,"company"):null,n=_?l?rr(a,"company").filter(N=>$t.includes(N)):Jr(_):[],c=_&&s?(l==null?void 0:l.companyRows)??await rl(_,["id","item_code","updated_at",...Za(_,"card_code")?["card_code"]:[],...n],s):[],m=new Map;c.forEach(N=>m.set(Ts("c",N.item_code,N.card_code??null),N));const h=_||o,j=t==="company"&&_?i.filter(N=>n.includes(N)):i,b=Eo(o,j),x=new Set(b),u=j.filter(N=>!x.has(N));return d.map(N=>{const y=N.card_code??null,L=m.get(Ts("c",N.item_code,y)),I={};i.forEach(J=>I[J]=sl(N[J]));const $={};j.forEach(J=>{$[J]=L&&L[J]!==null&&L[J]!==void 0?sl(L[J]):I[J]});const ee=a.categoryColumn&&N[a.categoryColumn]||a.category,U=[...r.provenanceByCode.get(N.item_code)||[]];L&&!U.includes("company")&&U.unshift("company"),r.auditedCodes.has(N.item_code)&&!U.includes("audited")&&U.push("audited"),U.length||U.push("seeded");const E=r.usage.get(N.item_code);return{key:Ts(o,N.item_code,y),source_table:o,target_table:t==="company"&&_?_:o,global_row_id:N.id,company_row_id:(L==null?void 0:L.id)??null,item_code:N.item_code,item_name:N[a.nameColumn]||N.item_code,card_code:y,category_display:xr(ee),card_label:a.category,trade:No(o),side:ko(o),finish_sensitive:l?i.includes("good_labor_rate"):xn(o),has_tier_allowance:l?j.includes("good_allowance_labor"):ro(h),has_flat_allowance:l?j.includes("labor_allowance"):lo(h),values:$,global_values:I,source:L?"company":"global",editable_columns:u,inert_columns:b,updated_at:l?null:(L==null?void 0:L.updated_at)||N.updated_at||null,provenance:l?[]:U,ai_generated:l?!1:U.includes("ai_generated"),engine:qr(o),reader:gr(o),read_only:!!l||qr(o)!=="v2_backend",is_active:(L??N).is_active!==!1,supports_activation:!l&&Za(h,"is_active"),usage_projects:(E==null?void 0:E.liveProjects)??0,usage_all_time_projects:(E==null?void 0:E.allTimeProjects)??0,usage_estimate_rows:(E==null?void 0:E.estimateRows)??0,usage_money_projects:(E==null?void 0:E.moneyProjects)??0,usage_snapshot_projects:(E==null?void 0:E.snapshotProjects)??0,usage_basis:Bo(E),last_used_at:(E==null?void 0:E.lastUsedAt)??null}})}function zo(a,t){var m,h,j,b,x,u,N;const s=((m=t.searchText)==null?void 0:m.trim().toLowerCase())||"",r=s?s.split(/\s+/).filter(Boolean):[],l=(h=t.trades)!=null&&h.length?new Set(t.trades):null,o=(j=t.cards)!=null&&j.length?new Set(t.cards):null,i=(b=t.itemCodes)!=null&&b.length?new Set(t.itemCodes):null,d=(x=t.shapes)!=null&&x.length?new Set(t.shapes):null,_=(u=t.provenances)!=null&&u.length?new Set(t.provenances):null,n=(N=t.engines)!=null&&N.length?new Set(t.engines):null,c=t.modifiedWithinDays?Date.now()-t.modifiedWithinDays*864e5:null;return a.filter(y=>{if(!t.includeLegacy&&y.engine==="legacy_retired"||!t.includeInactive&&y.is_active===!1||n&&!n.has(y.engine))return!1;if(r.length){const I=`${y.item_code} ${y.item_name} ${y.trade} ${y.card_label} ${y.card_code||""} ${y.category_display} ${y.source_table} ${y.reader||""} ${y.provenance.join(" ")}`.toLowerCase();if(!r.every($=>I.includes($)))return!1}if(l&&!l.has(y.trade)||o&&!o.has(y.card_label)||i&&!i.has(y.item_code)||t.side&&t.side!=="all"&&y.side!=="both"&&y.side!==t.side||t.finishSensitiveOnly&&!y.finish_sensitive||t.hasAllowanceOnly&&!y.editable_columns.filter(yr).some($=>(y.values[$]??0)>0)||d&&!Oo(y).some(I=>d.has(I))||_&&!y.provenance.some(I=>_.has(I)))return!1;const L=y.usage_basis!=="none";return!(t.usage==="in_use"&&!L||t.usage==="live"&&y.usage_projects<=0||t.usage==="unused"&&L||t.divergedOnly&&!Sn(y)||t.cardCoverage&&t.cardCoverage!=="all"&&!so(y,t.cardCoverage)||c&&(!y.updated_at||new Date(y.updated_at).getTime()<c)||t.predicate&&!t.predicate(y))})}function $n(a,t,s,r={}){var x,u,N,y;const{user:l,session:o,loading:i,authSessionVersion:d}=ur(),_=l==null?void 0:l.id,n=(o==null?void 0:o.user.id)===_?o==null?void 0:o.access_token:void 0,c=r.gcCatalogOnly===!0,m=!c&&!!s.includeLegacy,h=Ke({queryKey:["pricing-catalog",a,t,m,c,_,d,(x=r.actualCompanyScope)==null?void 0:x.allowedStateCodes,(u=r.actualCompanyScope)==null?void 0:u.defaultStateCode],queryFn:async({signal:L})=>{if(a==="company"&&!t)throw new Error("Confirm company access before loading company pricing.");if(c){const U=r.actualCompanyScope;if(a!=="company"||!U||U.actorId!==_||U.companyId!==t||!n||i)throw new Error("Confirm your current approved company scope before loading company pricing.");const E=mi(n),J=await Promise.all(vt.map(async be=>{const F=await vo(E,be,U,L);return ll(be,"company",t,lr,F)}));return tl(al(J.flat()))}
9const I=a==="global"?await Vo():lr,$=m?[...vt,...Ai]:vt,ee=await Promise.all($.map(U=>ll(U,a,t,I)));return tl(al(ee.flat()))},staleTime:c?0:3e4,...c?{gcTime:0,retry:!1,refetchOnMount:"always"}:{},enabled:c?!i&&!!n&&a==="company"&&!!t&&((N=r.actualCompanyScope)==null?void 0:N.actorId)===_&&((y=r.actualCompanyScope)==null?void 0:y.companyId)===t:a==="global"||!!t}),j=c&&(h.isFetching||!h.isSuccess)?void 0:h.data,b=j?zo(j,s):[];return{...h,isLoading:c?h.isFetching||h.isPending:h.isLoading,items:b,universe:j||[]}}const nr=[{id:"base_labor",label:"Base Labor",candidates:a=>[`${a}_labor_rate`,"base_labor_rate","labor_unit_price"]},{id:"base_material",label:"Base Material",candidates:a=>[`${a}_material_rate`,"base_material_rate","material_unit_price"]},{id:"allowance_labor",label:"Allowance Labor",candidates:a=>[`${a}_allowance_labor`,"labor_allowance"]},{id:"allowance_material",label:"Allowance Material",candidates:a=>[`${a}_allowance_material`,"material_allowance"]}];function Uo(a,t,s){var o;const r=nr.find(i=>i.id===t);if(!r)return null;const l=r.candidates(s);for(const i of l)if(a.editable_columns.includes(i))return{column:i,inert:!1};for(const i of l)if((o=a.inert_columns)!=null&&o.includes(i))return{column:i,inert:!0};return null}const An=[{id:"retired_but_consumed",title:"Retired price still being used",meaning:"The row is retired, so the V2 readers skip it â yet a live project still prices with it. New projects lose that money silently.",action:"Open the Related pricing panel and either restore the row or map a replacement, so future projects switch to a live price.",movesMoney:!0,flags:["retired_but_consumed"],order:120},{id:"family_duplicate",title:"Two live prices for the same thing",meaning:"Two live rows in the same related-pricing family cover the same side (addition, remodel or demo) under different names.",action:"Compare them in the Related pricing panel, keep the one in use, and retire the other with a replacement mapping.",movesMoney:!1,flags:["family_role_duplicate"],order:105},{id:"duplicate_rows",title:"Duplicate rows (same card, same side)",meaning:"Two live rows on the same card and the same side price the same item. This is NOT an addition/remodel pair â those are two correct rows. Only one of these can be the row the card reader consumes.",action:"Compare project usage on the two rows, keep the one being used, and retire the other. Retiring is audited, reversible and never changes an existing project.",movesMoney:!1,flags:["same_side_duplicate"],order:110},{id:"broken_math",title:"Broken finish-tier math",meaning:"A richer finish tier costs less than a cheaper one, or one tier is $0 while its siblings carry money.",action:"Re-enter all four tiers (entry â good â better â best) together so the ladder climbs.",movesMoney:!0,flags:["tier_reversal","dead_tier"],order:100},{id:"bad_row",title:"Not a usable row",meaning:"The item code is numeric, empty or too short to be a real code â almost always a bad import that no card reads by name.",action:"Retire it. Retiring is audited and reversible, and it never touches an existing project.",movesMoney:!1,flags:["invalid_code"],order:90},{id:"no_money",title:"Priced at zero",meaning:"Every rate and allowance on the row is zero or empty, so the item can never add a dollar.",action:"Either enter the real labor and material rates, or retire the row if it is not a real item.",movesMoney:!1,flags:["no_money"],order:80},{id:"tier_inert",title:"Finish level has no effect",meaning:"The row carries money, but changing the clientâs finish level will not change what it costs â the tier columns are empty or copy-pasted.",action:"Enter per-tier labor and material amounts separately so Good, Better and Best actually differ.",movesMoney:!0,flags:["flat_allowance_not_tiered","copy_paste_tiers"],order:70},{id:"mixed_allowance",title:"Two allowance definitions on one row",meaning:"The row carries both a flat allowance labor/material pair and per-tier allowance money. The backend prices the per-tier value, so the flat pair is dead money that still shows on legacy reports.",action:"Decide which model this item should use and clear the other â keep the per-tier amounts unless the item is genuinely tier-insensitive.",movesMoney:!0,flags:["mixed_allowance_model"],order:65},{id:"side_mismatch",title:"Addition and remodel priced differently",meaning:"The same item exists on both sides with different money. Sometimes correct (demo differs), often an edit applied to one side only.",action:"Compare the pair and, if it should match, edit the merged row so both sides move together.",movesMoney:!0,flags:["side_divergence"],order:60},{id:"old",title:"Not reviewed in over a year",meaning:"Nothing is wrong with the math â the price simply has not been checked against the market.",action:"Spot-check against a current quote; leave it alone if it still holds.",movesMoney:!1,flags:["stale"],order:10}];function qo(a){return An.find(t=>t.flags.includes(a))}function Ko(a){return An.map(t=>{const s=a.filter(r=>t.flags.some(l=>r.flags.includes(l)));return{...t,count:s.length,liveCount:s.filter(r=>(r.item.usage_projects??0)>0).length}}).filter(t=>t.count>0).sort((t,s)=>s.order-t.order)}const nl=a=>
9a==null?"â":`$${Number(a).toLocaleString(void 0,{maximumFractionDigits:2})}`,il=a=>a==="addition"?"Addition":a==="remodel"?"Remodel":"This";function Wo(a,t){if(!t)return"The matching row on the opposite side (addition vs remodel) carries different money, so the two sides price differently.";const r=Array.from(new Set([...a.editable_columns,...t.editable_columns])).filter(i=>Number(a.values[i]??0)!==Number(t.values[i]??0)).slice(0,3).map(i=>`${i.replace(/_/g," ")} ${nl(a.values[i])} vs ${nl(t.values[i])}`),l=il(a.pair_side).toLowerCase(),o=il(t.pair_side).toLowerCase();return r.length?`Same item on both sides, priced differently (${l} vs ${o}): ${r.join("; ")}.`:`Same item exists on the ${o} side with different money.`}function En(a,t,s={}){var n;const r=a.usage_projects??0,l=s.duplicates??[];if((n=a.same_side_duplicate_keys)!=null&&n.length)return{title:"Duplicate row on the same card and side",detail:`This is the same item as ${l.length?l.map(m=>`${m.item_code} (${m.usage_projects??0} project${(m.usage_projects??0)===1?"":"s"})`).join(", "):`${a.same_side_duplicate_keys.length} other row${a.same_side_duplicate_keys.length===1?"":"s"}`}, on the same card and the same side â not an addition/remodel pair. Only one of them can be the row the card's reader consumes.`,action:`Keep the row with project usage (this one: ${r}) and retire the other. Retiring is audited and reversible and never changes an existing project.`,movesMoney:!1,liveProjects:r};const o=t.topFlag;if(o.id==="healthy")return{title:"No issues found",detail:"Rates, allowances and finish tiers all look consistent on this row.",action:"Nothing to do.",movesMoney:!1,liveProjects:r};const i=qo(o.id),d=t.findings.filter(c=>c.flag===o.id).map(c=>c.detail),_=o.id==="side_divergence"?Wo(a,s.partner):d.length?d.join(" "):o.description;return{title:(i==null?void 0:i.title)??o.label,detail:_,action:(i==null?void 0:i.action)??o.description,movesMoney:(i==null?void 0:i.movesMoney)??!1,liveProjects:r}}const Rn=864e5;function Go(a){if(!a)return"never";const t=Date.parse(a);if(!Number.isFinite(t))return"never";const s=Math.max(0,Math.floor((Date.now()-t)/Rn));return s===0?"today":s===1?"yesterday":s<14?`${s}d ago`:s<60?`${Math.round(s/7)}w ago`:s<365?`${Math.round(s/30)}mo ago`:`${Math.max(1,Math.round(s/365))}y ago`}function Ho(a){if(!a)return We.gold;const t=(Date.now()-Date.parse(a))/Rn;return Number.isFinite(t)?t<=30?We.green:t<=180?We.teal:We.gold:We.gold}const Ut="inline-flex items-center rounded border px-1.5 py-0 text-[10px] leading-[18px] whitespace-nowrap";function Tn({usage:a,className:t=""}){var i;const s=(a==null?void 0:a.allTimeProjects)??0,r=(a==null?void 0:a.liveProjects)??0,l=(a==null?void 0:a.lastUsedAt)??null;if(s===0&&r===0&&!l)return e.jsxs(Na,{children:[e.jsx(ka,{asChild:!0,children:e.jsx("span",{className:`${Ut} ${We.gold} ${t}`,children:"never used"})}),e.jsx(Ca,{className:"max-w-xs text-xs",children:"No generated estimate, project snapshot or override has ever priced with this item."})]});const o=l?new Date(l).toLocaleString():"never priced";return e.jsxs(Na,{children:[e.jsx(ka,{asChild:!0,children:e.jsxs("span",{className:`inline-flex flex-wrap items-center gap-1 ${t}`,children:[e.jsxs("span",{className:`${Ut} ${We.violet}`,children:[s," all-time"]}),r>0&&e.jsxs("span",{className:`${Ut} ${We.primary}`,children:[r," live"]}),e.jsx("span",{className:`${Ut} ${Ho(l)}`,children:Go(l)})]})}),e.jsxs(Ca,{className:"max-w-xs text-xs space-y-0.5",children:[e.jsxs("div",{children:["Last priced: ",o]}),e.jsxs("div",{children:[s," all-time project",s===1?"":"s"," · ",r," live",(a==null?void 0:a.estimateRows)!==void 0?` · ${a.estimateRows} estimate line(s)`:"",(a==null?void 0:a.moneyProjects)!==void 0?` · ${a.moneyProjects} with money`:""]}),(i=a==null?void 0:a.cardCodes)!=null&&i.length?e.jsxs("div",{children:["Cards: ",a.cardCodes.join(", ")]}):null]})]})}const Qo=80,Jo=44,Ls=a=>a==null?"â":`$${Number(a).toLocaleString(void 0,{maximumFractionDigits:2})}`;function Yo({platformMetadata:a=!0,canEdit:t=!0,items:s,visibleColumns:r,prettyCol:l,staged:o,onCell:i,onEdit:d,onToggleActive:_,isLoading:n,healthFor:c,tier:m,selectedKeys:h,onToggleRow:j,onToggleAll:b,onToggleMany:x,mergedKeys:u,onUnmergePair:N,bandCodes:y,onOpenBands:L,narrativeFirst:I=!1,breakdown:$="flat",height:ee,collapsedGroups:U,onCollapsedGroupsChange:E,unfilteredItems:J,incompleteFamiliesFirst:be=!1}){const F=p.useRef(null),[se,V]=p.useState(new Set),z=U??se,Se=T=>{E?E(T(z)):V(T)},[re,$e]=p.useState(!1),{data:g,isSuccess:S}=Rt(a&&s.length>0),R=T=>
9c(T).topFlag.id!=="healthy",v=p.useMemo(()=>{const T=new Map;return s.forEach(ce=>T.set(ce.key,ce)),T},[s]),G=(T,ce)=>{const X=En(T,ce,{partner:T.side_partner_key?v.get(T.side_partner_key):void 0,duplicates:(T.same_side_duplicate_keys??[]).map(B=>v.get(B)).filter(B=>!!B)});return e.jsxs("div",{className:"min-w-0",title:`${X.detail} â ${X.action}`,children:[e.jsx("div",{className:"text-xs font-medium truncate",children:X.title}),e.jsx("div",{className:"text-[10px] text-muted-foreground truncate",children:X.detail}),e.jsxs("div",{className:"text-[10px] truncate",children:[e.jsx("span",{className:X.movesMoney?"text-destructive":"text-muted-foreground",children:X.movesMoney?"Can move money":"No money impact"}),e.jsxs("span",{className:"text-muted-foreground",children:[" · ",X.action]})]})]})},{entries:te,groups:oe}=p.useMemo(()=>hn(s,$,{selectedKeys:h,needsAttention:R,collapsed:z,unfilteredItems:J,incompleteFirst:be}),[s,$,h,z,c,J,be]),A=p.useMemo(()=>{const T=new Map;return oe.forEach(ce=>T.set(ce.id,ce.tintIndex??0)),T},[oe]),de=p.useMemo(()=>{const T=new Map;return te.forEach(ce=>{if(ce.kind!=="item"||!ce.groupId)return;const X=T.get(ce.groupId);X?X.push(ce.item):T.set(ce.groupId,[ce.item])}),T},[te]),O=ki({count:te.length,getScrollElement:()=>F.current,estimateSize:T=>{var ce;return((ce=te[T])==null?void 0:ce.kind)==="group"?Jo:Qo},overscan:14}),he=p.useMemo(()=>[{id:"__sel",label:"",width:36},{id:"__item",label:"Item",width:260,grow:2},...I?[{id:"__why",label:"What to address",width:280,grow:2}]:[],...nr.map(T=>({id:`slot:${T.id}`,label:T.label,width:124,align:"right"})),{id:"__card",label:"Used by card",width:160,grow:1},...r.map(T=>({id:`col:${T}`,label:l(T),width:112,align:"right"})),{id:"__trade",label:"Trade / Card",width:120},{id:"__scope",label:"Scope",width:96},{id:"__engine",label:"Engine",width:120},{id:"__prov",label:"Source",width:112},{id:"__usage",label:"Backend use",width:96,align:"right"},...I?[]:[{id:"__why",label:"What to address",width:280,grow:2}],{id:"__health",label:"Health",width:120},{id:"__status",label:"Status",width:108},{id:"__code",label:"Backend code",width:150,grow:1},{id:"__actions",label:"",width:70}],[r,l,I]),Ie=he.map(T=>T.grow?`minmax(${T.width}px, ${T.grow}fr)`:`${T.width}px`).join(" "),Ge=he.reduce((T,ce)=>T+ce.width,0)+(he.length-1)*8+24,Oe=s.length>0&&s.every(T=>h.has(T.key)),k=!Oe&&s.some(T=>h.has(T.key)),w=T=>Se(ce=>{const X=new Set(ce);return X.has(T)?X.delete(T):X.add(T),X}),P=re?"shadow-[6px_0_6px_-6px_hsl(var(--foreground)/0.18)]":"",M="sticky left-0 z-20 bg-card self-stretch flex items-center",D=`sticky left-[44px] z-20 bg-card border-r border-primary/25 self-stretch ${P}`,fe="sticky left-0 z-40 bg-card",ve=`sticky left-[44px] z-40 bg-card border-r border-primary/25 ${P}`,ue=(T,ce)=>{var K,_e;if(!ce)return e.jsx("span",{className:"text-xs text-muted-foreground",children:"â"});if((K=T.inert_columns)!=null&&K.includes(ce))return e.jsx("span",{className:"text-xs text-muted-foreground/60 line-through decoration-muted-foreground/40",title:Ro(T.source_table,ce),children:Ls(T.values[ce])});const X=t&&T.editable_columns.includes(ce)&&!T.read_only&&T.is_active!==!1,B=(_e=o[T.key])==null?void 0:_e[ce],f=T.global_values[ce],q=T.source==="company"&&Number(T.values[ce]??0)!==Number(f??0);return X?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"relative w-[114px] ml-auto",children:[e.jsx("span",{className:"pointer-events-none absolute left-2 top-1/2 -translate-y-1/2 text-[11px] text-primary/70",children:"$"}),e.jsx(Pe,{type:"number",min:0,step:"0.01",placeholder:"â",className:`h-8 w-[114px] pl-5 pr-1.5 text-right ${B!==void 0?"border-primary ring-1 ring-primary":""}`,value:B!==void 0?B:T.values[ce]??"",onChange:pe=>i(T,ce,pe.target.value)})]}),q&&e.jsxs("div",{className:"text-[10px] text-muted-foreground mt-0.5",children:["global ",Ls(f)]})]}):e.jsx("span",{className:"text-xs text-muted-foreground",title:t?T.read_only?"Retired source â edit in the Legacy tab":"Retired row â restore it to edit":"Company editing requires a reviewed company-scoped pricing service",children:Ls(T.values[ce])})};return e.jsx("div",{className:"border border-primary/20 rounded-md overflow-hidden bg-card",children:n?e.jsxs("div",{className:"py-12 text-center text-sm text-muted-foreground",children:[e.jsx(Fe,{className:"h-5 w-5 animate-spin inline mr-2"})," Reading every pricing tableâ¦"]}):s.length===0?e.jsx("div",{className:"py-12 text-center text-sm text-muted-foreground",children:"No pricing items match these filters."}):e.jsx("div",{ref:F,"data-scroll-rail":!0,className:"overflow-auto",style:{height:ee},onScroll:T=>{const ce=T.target.scrollLeft;$e(X=>X===ce>2?X:ce>2)},children:e.jsxs("div",{className:"w-full",style:{minWidth:Ge},children:[e.jsx("div",{className:"grid items-center gap-2 px-3 h-10 border-b-2 border-primary/25 bg-card text-xs font-semibold text-primary sticky top-0 z-30 shadow-sm",style:{gridTemplateColumns:Ie},children:he.map(T=>T.id==="__sel"?e.jsx("div",{className:`${fe} flex items-center h-10`,children:e.jsx(ca,{checked:Oe?!0:k?"indeterminate":!1,onCheckedChange:ce=>b(!!ce),"aria-label":"Select all matching items"})},T.id):e.jsx("div",{className:`flex items-center h-10 whitespace-nowrap overflow-hidden ${T.align==="right"?"justify-end":""} ${T.id==="__item"?`${ve} text-primary`:""}`,title:T.label,children:e.jsx("span",{className:"truncate",children:T.label})},T.id))}),e.jsx("div",{style:{height:O.getTotalSize(),position:"relative"},children:O.getVirtualItems().map(T=>{var Ee;const ce=te[T.index];if(!ce)return null;if(ce.kind==="group"){const ne=ce.stats,Ae=de.get(ne.id)||[],Ne=ne.total>0&&ne.selected===ne.total,He=ne.depth??0;return e.jsx("div",{className:`border-b border-primary/15 text-xs font-medium ${He>0?"bg-primary/[0.04]":"bg-accent/10"}`,style:{position:"absolute",top:0,left:0,width:"100%",height:T.size,transform:`translateY(${T.start}px)`},children:e.jsxs("div",{className:"sticky left-0 flex h-full items-center gap-3 px-3 w-max max-w-full",style:{paddingLeft:12+He*22},children:[e.jsx(ca,{checked:Ne?!0:ne.selected>0?"indeterminate":!1,onCheckedChange:Me=>x==null?void 0:x(Ae,!!Me),"aria-label":`Select all in ${ne.label}`,disabled:!x||ce.collapsed}),e.jsxs("button",{className:"flex items-center gap-1 hover:underline",onClick:()=>w(ne.id),"aria-label":`${ce.collapsed?"Expand":"Collapse"} ${ne.label}`,children:[ce.collapsed?e.jsx(fa,{className:"h-3.5 w-3.5"}):e.jsx(ha,{className:"h-3.5 w-3.5"}),e.jsx("span",{className:"text-sm whitespace-nowrap",children:ne.label})]}),e.jsxs("span",{className:"text-muted-foreground whitespace-nowrap",children:[ne.total.toLocaleStr
9ing()," items"]}),(((Ee=ne.sides)==null?void 0:Ee.length)??0)>0&&e.jsx("span",{className:"flex items-center gap-1",children:ne.sides.map(Me=>e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded border border-primary/30 text-primary capitalize whitespace-nowrap",title:`This group contains ${Me==="unknown"?"rows with no side":`${Me} rows`}.`,children:Me==="unknown"?"no side":Me},Me))}),(ne.demo??0)>0&&e.jsxs("span",{className:"text-[10px] px-1.5 py-0.5 rounded border border-accent/50 text-accent whitespace-nowrap",title:"Demolition / removal rows in this group.",children:[ne.demo," demo"]}),ne.flags?ne.flags.map(Me=>e.jsx("span",{className:`text-[10px] px-1.5 py-0.5 rounded border whitespace-nowrap ${Me.tone==="warn"?"border-destructive/40 text-destructive":Me.tone==="ok"?"border-primary/40 text-primary":"border-muted-foreground/30 text-muted-foreground"}`,title:Me.title,children:Me.label},Me.id)):ne.demoGap&&e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded border border-destructive/40 text-destructive whitespace-nowrap",title:"The remodel side of this item is priced but no demolition / removal row here carries money. That usually reads low on a remodel card.",children:"no demo priced"}),e.jsxs("span",{className:`px-1.5 py-0.5 rounded border whitespace-nowrap ${ne.fullyV2?ua.v2_backend.className:ua.legacy_retired.className}`,title:ne.fullyV2?"Every row in this group is priced by the V2 backend.":"Some rows in this group live in sources the V2 backend does not read.",children:["V2 backend ",ne.v2,"/",ne.total,ne.legacy>0?` â ${ne.legacy} legacy`:""]}),ne.ai>0&&e.jsxs("span",{className:"px-1.5 py-0.5 rounded border border-destructive/40 text-destructive flex items-center gap-1 whitespace-nowrap",children:[e.jsx(ys,{className:"h-3 w-3"})," ",ne.ai," AI"]}),ne.attention>0&&e.jsxs("span",{className:"text-accent whitespace-nowrap",children:[ne.attention," need attention"]}),ne.selected>0&&e.jsxs("span",{className:"text-primary whitespace-nowrap",children:[ne.selected," selected"]})]})},ce.id)}const X=ce.item,B=c(X),f=Sn(X),q=h.has(X.key),K=X.is_active===!1,_e=ja(X),pe=$==="family"?_e==="teardown"?"bg-accent/[0.10]":(A.get(ce.groupId)??0)===1?"bg-primary/[0.05]":"bg-primary/[0.02]":"",W=no[B.topFlag.tone],we=K?"bg-destructive/[0.05]":X.ai_generated?"bg-destructive/[0.04]":W||pe;return e.jsxs("div",{className:`grid items-center gap-2 px-3 border-b border-primary/10 text-sm [&>*]:min-w-0 [&>*]:overflow-hidden ${we} ${q?"ring-1 ring-inset ring-primary/40":""} ${K?"opacity-70":""}`,style:{gridTemplateColumns:Ie,position:"absolute",top:0,left:0,width:"100%",height:T.size,transform:`translateY(${T.start}px)`},children:[e.jsxs("div",{className:`${M} relative`,children:[e.jsx("span",{"aria-hidden":!0,className:`absolute inset-0 ${we}`}),e.jsx(ca,{className:"relative",checked:q,onCheckedChange:ne=>j(X,!!ne),"aria-label":`Select ${X.item_name}`})]}),e.jsxs("div",{className:`min-w-0 flex items-center relative ${D}`,children:[e.jsx("span",{"aria-hidden":!0,className:`absolute inset-0 ${we}`}),e.jsxs("div",{className:"relative font-medium text-sm truncate flex items-center gap-1 min-w-0",title:X.item_name,children:[X.ai_generated&&e.jsx("span",{title:"AI generated pricing â verify before relying on it",className:"shrink-0",children:e.jsx(ys,{className:"h-3.5 w-3.5 text-destructive"})}),e.jsx("span",{className:"truncate",children:X.item_name}),(X.pair_side==="addition"||X.pair_side==="remodel")&&e.jsx("span",{className:"shrink-0 text-[10px] px-1 py-0.5 rounded border border-primary/30 text-primary capitalize",title:`This row prices the ${X.pair_side} side. The opposite side is a separate, equally live row â not a duplicate.`,children:X.pair_side}),_e!=="other"&&e.jsx("span",{className:`shrink-0 text-[10px] px-1 py-0.5 rounded border ${_e==="teardown"?"border-accent/60 text-accent":"border-muted-foreground/30 text-muted-foreground"}`,title:Hi[_e],children:Gi[_e]}),(y==null?void 0:y.has(X.item_code))&&e.jsx("button",{type:"button",className:"shrink-0 text-[10px] px-1 py-0.5 rounded border border-primary/40 text-primary hover:bg-primary/10",title:"This rate steps by project area â open the band ladder that decides it",onClick:ne=>{ne.stopPropagation(),L==null||L(X)},disabled:!L,children:"bands"})]})]}),I&&G(X,B),nr.map(ne=>{var Ae;return e.jsx("div",{className:"text-right",children:ue(X,((Ae=Uo(X,ne.id,m))==null?void 0:Ae.column)??null)},ne.id)}),(()=>{const ne=_n(X);return e.jsxs("div",{className:"min-w-0",title:ne.narration,children:[e.jsx("span",{className:`text-[10px] px-1.5 py-0.5 rounded border inline-block max-w-full truncate ${ne.className}`,children:ne.card??"No card yet"}),e.jsx("div",{className:"text-[10px] text-muted-foreground truncate",children:ne.coverage==="card"?ne.sides==="both"?"card covers addition + remodel":`card covers ${ne.sides} only`:"not priced by any card"})]})})(),r.map(ne=>{var Ae;return e.jsx("div",{className:"text-right",children:ue(X,X.editable_columns.includes(ne)||(Ae=X.inert_columns)!=null&&Ae.includes(ne)?ne:null)},ne)}),e.jsxs("div",{className:"text-xs min-w-0",children:[e.jsx("div",{className:"truncate",title:X.trade,children:X.trade}),e.jsxs("div",{className:"text-muted-foreground truncate",children:[X.card_label,X.card_code?` · ${X.card_code}`:""]})]}),e.jsxs("div",{className:"flex flex-col items-start gap-0.5 min-w-0 overflow-hidden max-h-full",children:[e.jsx(ie,{variant:X.source==="company"?"default":"secondary",className:"text-[10px]",children:X.source==="company"?"Company":"Global"}),(u==null?void 0:u.has(X.key))&&e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded border border-primary/40 text-primary whitespace-nowrap",title:"Addition and remodel are priced i
9dentically â editing this row writes both sides.",children:"Both sides"}),N&&e.jsx("button",{type:"button",className:"text-[10px] underline text-muted-foreground hover:text-foreground",onClick:ne=>{ne.stopPropagation(),N(X)},children:"split"})]}),X.side_divergent&&e.jsx("span",{className:"text-[10px] text-destructive",title:"This item's addition and remodel money differ.",children:"sides differ"}),f&&e.jsx("span",{className:"text-[10px] text-primary",children:"differs from global"})]}),e.jsxs("div",{className:"min-w-0 overflow-hidden max-h-full",children:[e.jsx("span",{className:`text-[10px] px-1.5 py-0.5 rounded border whitespace-nowrap ${ua[X.engine].className}`,title:Wi(X.source_table),children:ua[X.engine].label}),e.jsx("div",{className:"text-[10px] text-muted-foreground truncate mt-0.5",title:X.reader||X.source_table,children:X.reader||X.source_table})]}),e.jsxs("div",{className:"flex flex-wrap gap-1 overflow-hidden max-h-full content-center",children:[X.ai_generated&&e.jsxs("span",{className:"text-[10px] px-1.5 py-0.5 rounded border border-destructive/40 text-destructive flex items-center gap-1",title:Da.ai_generated.description,children:[e.jsx(ys,{className:"h-3 w-3"})," AI"]}),X.provenance.filter(ne=>ne!=="ai_generated").map(ne=>e.jsx("span",{title:Da[ne].description,className:`text-[10px] px-1.5 py-0.5 rounded border ${Da[ne].className}`,children:Da[ne].short},ne))]}),e.jsx("div",{className:"flex justify-end text-xs",children:a?e.jsx(Tn,{usage:X.usage_basis==="none"?null:{allTimeProjects:X.usage_all_time_projects,liveProjects:X.usage_projects,lastUsedAt:X.last_used_at,estimateRows:X.usage_estimate_rows,moneyProjects:X.usage_money_projects},className:"justify-end"}):e.jsx("span",{className:"text-[10px] text-muted-foreground",children:"Unavailable"})}),!I&&G(X,B),(()=>{const ne=B.flags.slice(0,2),Ae=B.flags.slice(2),Ne=Ae.map(He=>ga[He].label).join(" · ");return e.jsxs("div",{className:"flex flex-col items-start gap-1 min-w-0 overflow-hidden",children:[ne.map(He=>e.jsx("span",{title:B.findings.filter(Me=>Me.flag===He).map(Me=>Me.detail).join(" ")||ga[He].description,className:`text-[10px] px-1.5 py-0.5 rounded border whitespace-nowrap max-w-full truncate ${bn[ga[He].tone]}`,children:ga[He].label},He)),Ae.length>0&&e.jsxs("span",{className:"text-[10px] px-1.5 py-0.5 rounded border border-muted-foreground/40 text-muted-foreground whitespace-nowrap cursor-help",title:Ne,children:["+",Ae.length," more"]})]})})(),e.jsxs("div",{className:"flex flex-col items-start gap-1",children:[e.jsx("span",{className:`text-[10px] px-1.5 py-0.5 rounded border whitespace-nowrap ${K?"border-destructive/40 text-destructive":"border-primary/30 text-primary bg-primary/5"}`,title:K?"Retired â the V2 backend readers skip this row, so it prices nothing today.":"Active â the V2 backend readers price with this row.",children:K?"Retired":"Active"}),t&&_&&X.supports_activation&&!X.read_only&&e.jsx("button",{type:"button",className:"text-[10px] underline text-muted-foreground hover:text-foreground",title:K?"Restore this price so the V2 readers pick it up again.":"Retire this price â audited and revertible like a money change.",onClick:()=>_(X),children:K?"Restore":"Retire"})]}),e.jsxs("div",{className:"min-w-0 flex items-center",children:[e.jsx("button",{type:"button",className:"text-xs text-muted-foreground font-mono truncate max-w-full text-left hover:text-foreground",title:`${X.item_code} â click to copy the backend item code`,onClick:ne=>{var Ae;ne.stopPropagation(),(Ae=navigator.clipboard)==null||Ae.writeText(X.item_code)},children:X.item_code}),a&&e.jsx(_s,{itemCode:X.item_code,preloaded:(g==null?void 0:g.get(X.item_code))??null,preloadedReady:S})]}),e.jsx("div",{children:X.read_only||!t?e.jsx("span",{className:"text-[10px] text-muted-foreground",children:t?"Legacy tab":"Read only"}):e.jsx(H,{size:"sm",variant:"outline",onClick:()=>d(X),children:"Edit"})})]},ce.id)})})]})})})}const Ln={verdict:null,aiNotes:[],reviewerNote:null,reverted:!1,dirty:!1,errorMessage:null,details:[],runId:null};function ol(a){return!a||typeof a!="object"?Ln:{verdict:a.verdict??null,aiNotes:Array.isArray(a.ai_notes)?a.ai_notes:[],reviewerNote:a.reviewer_note??null,reverted:a.status==="reverted_wiring_failure"||!!a.reverted,dirty:!!a.dirty,errorMessage:typeof a.error=="string"?a.error:null,details:Array.isArray(a.details)?a.details.filter(t=>typeof t=="string"):[],runId:a.run_id??null}}
9async function wa(a,t){if(a)return ol(a);const s=t==null?void 0:t.context;if(s&&typeof s.json=="function")try{return ol(await s.json())}catch{}return{...Ln,errorMessage:(t==null?void 0:t.message)??null}}const Xo={psf_rates_first_floor_addition:{rateRuleCode:"psf_rates_first_floor_addition",thresholdRuleCode:"pricing.bands.single_level",label:"First Floor Addition â PSF by size",cards:["Addition â Structural","Addition â Interior Building"],trade:"Structure",unit:"per sf",inputs:["singleLevelArea","twoLevelFirstFloor","threeLevelFirstFloor"]},psf_rates_second_level_addition:{rateRuleCode:"psf_rates_second_level_addition",thresholdRuleCode:"pricing.bands.second_level",label:"Second Level Addition â PSF by size",cards:["Addition â Structural","Addition â Interior Building"],trade:"Structure",unit:"per sf",inputs:["secondOnlyArea","twoLevelSecondFloor","threeLevelSecondFloor"]},psf_rates_third_floor_addition:{rateRuleCode:"psf_rates_third_floor_addition",thresholdRuleCode:"pricing.bands.third_only",label:"Third Floor Addition â PSF by size",cards:["Addition â Structural"],trade:"Structure",unit:"per sf",inputs:["thirdOnlyArea","threeLevelThirdFloor"]},psf_rates_two_level_addition:{rateRuleCode:"psf_rates_two_level_addition",thresholdRuleCode:"pricing.bands.two_level",label:"Two Level Addition â PSF by combined size",cards:["Addition â Structural"],trade:"Structure",unit:"per sf",inputs:["twoLevelFirstFloor","twoLevelSecondFloor"]},psf_rates_three_level_addition:{rateRuleCode:"psf_rates_three_level_addition",thresholdRuleCode:"pricing.bands.three_level",label:"Three Level Addition â PSF by combined size",cards:["Addition â Structural"],trade:"Structure",unit:"per sf",inputs:["threeLevelFirstFloor","threeLevelSecondFloor","threeLevelThirdFloor"]},psf_rates_unfinished_basement:{rateRuleCode:"psf_rates_unfinished_basement",thresholdRuleCode:"pricing.bands.general",label:"Unfinished Basement â PSF by size",cards:["Addition â Structural","Basement"],trade:"Foundation",unit:"per sf",inputs:["basementUnfinishedArea"]},psf_rates_finished_basement:{rateRuleCode:"psf_rates_finished_basement",thresholdRuleCode:"pricing.bands.general",label:"Finished Basement â PSF by size",cards:["Addition â Structural","Basement","Basement Flooring"],trade:"Foundation",unit:"per sf",inputs:["basementFinishedArea"]}},Zo={"pricing.bands.general":"General band ladder (basements, fallback)","pricing.bands.single_level":"Single level addition band ladder","pricing.bands.second_level":"Second level addition band ladder","pricing.bands.third_only":"Third floor only band ladder","pricing.bands.two_level":"Two level addition band ladder","pricing.bands.three_level":"Three level addition band ladder","pricing.bands.attached_adu":"Attached ADU band ladder"},va=a=>a.toLocaleString("en-US");function ec(a,t){const s=(a||[]).filter(r=>Number.isFinite(r));return s.length?t<=0?`up to ${va(s[0])} sf`:t>=s.length?`${va(s[s.length-1]+1)} sf and up`:`${va(s[t-1]+1)} â ${va(s[t])} sf`:`Band ${t+1}`}function ac(a,t,s){const r=(a||[]).filter(i=>Number.isFinite(i));if(!r.length||!Number.isFinite(s))return!1;const l=t===0?0:r[Math.min(t,r.length)-1]+1,o=t>=r.length?1/0:r[t];return s>=l&&s<=o}function Qt(a){const t=a.match(/^(rates|thresholds|addon)\[(\d+)\]$/);return t?{kind:t[1]==="rates"?"rate":t[1]==="thresholds"?"threshold":"addon",index:Number(t[2])}:a==="rate"?{kind:"rate",index:null}:{kind:"other",index:null}}function tc(a,t){const{kind:s,index:r}=Qt(a);if(s==="rate"&&r===null)return"Flat rate (all sizes)";if(r===null)return a;
9if(s==="threshold")return`Band ${r+1} upper limit (sf)`;const l=ec(t,r);return s==="addon"?`${l} â band surcharge`:l}function sc(a){const t=[],s=a.map(r=>r==null?NaN:Number(r));for(let r=1;r<s.length;r+=1)!Number.isFinite(s[r])||!Number.isFinite(s[r-1])||s[r]<=s[r-1]&&t.push(`Band ${r+1} upper limit (${va(s[r])}) must be greater than band ${r} (${va(s[r-1])})`);return t}function rc(a){if(!a||typeof a!="object")return[];const t=[],s=Object.keys(a).filter(r=>r!=="fixed"&&Number.isFinite(Number(r))).map(Number).sort((r,l)=>r-l);return a.fixed&&t.push(cl(a,"fixed",null,"Flat rate (all sizes)")),s.forEach((r,l)=>{const o=l===0?0:s[l-1]+1,d=l===s.length-1?`${va(o)} sf and up`:l===0?`up to ${va(r)} sf`:`${va(o)} â ${va(r)} sf`;t.push(cl(a,String(r),r,d))}),t}function cl(a,t,s,r){const l=a[t]||{},o=i=>i==null||i===""?null:Number(i);return{bandKey:t,upperSf:s,label:r,ratePsf:o(l.rate_psf),laborPct:o(l.labor_pct),materialPct:o(l.material_pct),paths:{ratePsf:`area_band_pricing.${t}.rate_psf`,laborPct:`area_band_pricing.${t}.labor_pct`,materialPct:`area_band_pricing.${t}.material_pct`}}}function lc(a,t){if(!a||typeof a!="object")return null;if(a.fixed)return"fixed";const s=Object.keys(a).filter(l=>Number.isFinite(Number(l))).map(Number).sort((l,o)=>l-o);if(!s.length||!Number.isFinite(t))return null;let r=s[0];for(const l of s)t>=l&&(r=l);return String(r)}function nc(a,t){if(a===null||t===null)return null;const s=a+t;return Math.abs(s-1)<=.005?null:`Labor ${Math.round(a*100)}% + material ${Math.round(t*100)}% = ${Math.round(s*100)}% (must be 100%)`}const ic=[{global:"structural_line_items_global",company:"structural_line_items_company",card:"Structural"}];function Mn(a,t,s={}){var n;const r=s.enabled!==!1,l=Ke({queryKey:["area-band-catalog",a,t,r],enabled:r&&(a==="global"||!!t),queryFn:async()=>{if(!r)throw new Error("Platform area-band access is unavailable.");const{data:c,error:m}=await ge.from("business_logic_rules").select("id, rule_code, rule_name, rule_config, is_active").or("rule_code.ilike.pricing.bands%,rule_code.ilike.psf_rates%").eq("is_active",!0).order("rule_code");if(m)throw m;const h=[];for(const j of ic){const b=a==="company"?j.company:j.global,x=await fr(b,(u,N)=>{let y=ge.from(b).select(`id, item_code, item_name, category, addition_type, unit, is_active, area_band_pricing${a==="company"?", company_id":""}`).not("area_band_pricing","is",null).order("item_code").range(u,N);return a==="company"&&(y=y.eq("company_id",t)),y});for(const u of x){if(a==="company"&&u.company_id!==t)continue;const N=rc(u.area_band_pricing);N.length&&h.push({id:u.id,source_table:j.global,item_code:u.item_code,item_name:u.item_name||u.item_code,card:j.card,trade:u.category||"Uncategorized",unit:u.unit||"sf",addition_type:u.addition_type??null,is_active:u.is_active!==!1,cells:N})}}return{rules:c||[],items:h}}}),o=p.useMemo(()=>{var h,j;const c=r?((h=l.data)==null?void 0:h.rules)||[]:[],m=new Map;for(const b of c){const x=(j=b.rule_config)==null?void 0:j.thresholds;Array.isArray(x)&&m.set(b.rule_code,x.map(Number))}return c.map(b=>{const x=Xo[b.rule_code]??null,u=m.get(b.rule_code),N=u??(x?m.get(x.thresholdRuleCode)??[]:[]);return{id:b.id,rule_code:b.rule_code,rule_name:Zo[b.rule_code]||(x==null?void 0:x.label)||b.rule_name,rule_config:b.rule_config,thresholds:N,isThresholdRule:!!u,context:x,cards:(x==null?void 0:x.cards)??(u?["Addition â Structural"]:[]),trade:(x==null?void 0:x.trade)??"Structure",unit:(x==null?void 0:x.unit)??"per sf"}})},[l.data,r]),i=r?((n=l.data)==null?void 0:n.items)??[]:[],d=p.useMemo(()=>{const c=new Map;return o.forEach(m=>m.cards.forEach(h=>c.set(h,(c.get(h)||0)+1))),i.forEach(m=>c.set(m.card,(c.get(m.card)||0)+1)),Array.from(c.entries()).sort((m,h)=>m[0].localeCompare(h[0])).map(([m,h])=>({value:m,label:m,count:h}))},[o,i]),_=p.useMemo(()=>{const c=new Map;return o.forEach(m=>
9c.set(m.trade,(c.get(m.trade)||0)+1)),i.forEach(m=>c.set(m.trade,(c.get(m.trade)||0)+1)),Array.from(c.entries()).sort((m,h)=>m[0].localeCompare(h[0])).map(([m,h])=>({value:m,label:m,count:h}))},[o,i]);return{rules:o,items:i,cardOptions:d,tradeOptions:_,isLoading:l.isLoading,refetch:l.refetch}}const Pn=(a,...t)=>!a||t.some(s=>(s||"").toLowerCase().includes(a.toLowerCase()));function oc(a,t){var s;return t.source==="items"?[]:(s=t.items)!=null&&s.length?[]:a.filter(r=>{var l,o;return t.cards.length&&!r.cards.some(i=>t.cards.includes(i))||t.trades.length&&!t.trades.includes(r.trade)?!1:Pn(t.search,r.rule_code,r.rule_name,(l=r.context)==null?void 0:l.label,...((o=r.context)==null?void 0:o.inputs)??[])})}function cc(a,t){var r;if(t.source==="rules")return[];const s=(r=t.items)!=null&&r.length?new Set(t.items):null;return a.filter(l=>s&&!s.has(l.item_code)||t.cards.length&&!t.cards.includes(l.card)||t.trades.length&&!t.trades.includes(l.trade)?!1:Pn(t.search,l.item_code,l.item_name,l.trade,l.addition_type))}function Xt(a,t=""){return a==null?[]:typeof a=="number"?t?[{path:t,value:a}]:[]:Array.isArray(a)?a.flatMap((s,r)=>Xt(s,`${t}[${r}]`)):typeof a=="object"?Object.entries(a).flatMap(([s,r])=>Xt(r,t?`${t}.${s}`:s)):[]}const dc=.01;function In(a){return Number((a+dc).toFixed(2))}const dl=(a,t)=>a!==null&&Math.abs(a-t)<.005,Ms=(a,t,s)=>{const r=(a==null?void 0:a.message)||(t==null?void 0:t.error)||(t==null?void 0:t.message);return r?typeof r=="string"?r:JSON.stringify(r):s};async function mc(a,t){const s=t.now??(()=>new Date().toISOString()),r=[],l=In(a.original);let o=null,i=!1;const d=(n,c,m,h)=>{r.push({key:n,label:c,state:m,detail:h})},_=()=>({ok:!1,runId:o,dirty:i,steps:r,finishedAt:s()});try{const{data:n,error:c}=await t.invoke("apply-catalog-price-update",{kind:"area_band_item",scope:a.scope,notes:`[self-test] apply -> verify -> revert probe on ${a.itemCode} (${a.path})`,item_band_changes:[{source_table:a.sourceTable,global_row_id:a.globalRowId,item_code:a.itemCode,item_name:a.itemName,values:{[a.path]:l}}]});if(o=(n==null?void 0:n.run_id)??null,c||!(n!=null&&n.success)||(n==null?void 0:n.status)!=="verified")return d("apply","Apply probe change","fail",Ms(c,n,`status ${(n==null?void 0:n.status)??"unknown"}`)),(n==null?void 0:n.status)==="partially_applied"&&(i=!0),_();d("apply","Apply probe change","pass",`${a.original} -> ${l} · run ${String(o).slice(0,8)} · ${n.fields_verified}/${n.fields_changed} field(s) verified by the backend`),i=!0}catch(n){return d("apply","Apply probe change","fail",(n==null?void 0:n.message)||"apply threw"),_()}try{const n=await t.readLive();dl(n,l)?d("read","Read the live value back","pass",`table holds ${l}`):d("read","Read the live value back","fail",`expected ${l}, table holds ${n??"null"}`)}catch(n){d("read","Read the live value back","fail",(n==null?void 0:n.message)||"read threw")}try{const{data:n,error:c}=await t.invoke("audit-catalog-price-history",{run_id:o});c||(n==null?void 0:n.status)!=="verified"?d("reverify","Re-verify the run","fail",Ms(c,n,`status ${(n==null?void 0:n.status)??"unknown"}`)):d("reverify","Re-verify the run","pass",`${n.fields_matching??n.fields_checked??"?"} of ${n.fields_checked??"?"} recorded field(s) still match`)}catch(n){d("reverify","Re-verify the run","fail",(n==null?void 0:n.message)||"re-verify threw")}try{const{data:n,error:c}=await t.invoke("revert-catalog-price-change",{run_id:o,reason:`[self-test] restoring ${a.itemCode} after the apply -> verify -> revert proof`});if(c||!(n!=null&&n.success))return d("revert","Revert the run","fail",Ms(c,n,"revert did not verify")),d("restore","Confirm the original value is back","skipped","revert did not complete"),_();d("revert","Revert the run","pass",`revert run ${String(n.run_id??"").slice(0,8)} verified`)}catch(n){return d("revert","Revert the run","fail",(n==null?void 0:n.message)||"revert threw"),d("restore","Confirm the original value is back","skipped","revert did not complete"),_()}try{const n=await t.readLive();if(!dl(n,a.original))return d("restore","Confirm the original value is back","fail",`expected ${a.original}, table holds ${n??"null"}`),_();d("restore","Confirm the original value is back","pass",`${a.original} restored â net change $0.00`),i=!1}catch(n){return d("restore","Confirm the original value is back","fail",(n==null?void 0:n.message)||"read threw"),_(
9)}return{ok:r.every(n=>n.state==="pass"),runId:o,dirty:i,steps:r,finishedAt:s()}}function uc({item:a,scope:t,onFinished:s}){const[r,l]=p.useState(!1),[o,i]=p.useState(null),d=a.cells.find(c=>c.ratePsf!==null&&c.ratePsf!==void 0),_=async c=>{const m=t==="company"?a.source_table.replace("_global","_company"):a.source_table,{data:h,error:j}=await ge.from(m).select("area_band_pricing").eq("item_code",a.item_code).limit(1).maybeSingle();if(j)throw new Error(j.message);const b=c.split(".").slice(1);let x=h==null?void 0:h.area_band_pricing;for(const u of b)x=x==null?void 0:x[u];return x==null?null:Number(x)},n=async()=>{if(d){l(!0),i(null);try{const c=await mc({sourceTable:a.source_table,globalRowId:a.id,itemCode:a.item_code,itemName:a.item_name,scope:t,path:d.paths.ratePsf,original:Number(d.ratePsf)},{invoke:(m,h)=>ge.functions.invoke(m,{body:h}),readLive:()=>_(d.paths.ratePsf)});i(c),c.ok?le.success("Self-test passed",{description:`${a.item_code} applied, verified and restored â net change $0.00.`}):c.dirty?le.error("Self-test failed and the probe value is still in place",{description:"Revert the run from Change History before pricing from this item."}):le.error("Self-test failed",{description:"No pricing was left changed."}),s==null||s()}catch(c){le.error("Self-test could not run",{description:c==null?void 0:c.message})}finally{l(!1)}}};return d?e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs(H,{size:"sm",variant:"outline",disabled:r,onClick:n,children:[r?e.jsx(Fe,{className:"h-3.5 w-3.5 mr-1 animate-spin"}):e.jsx(Ht,{className:"h-3.5 w-3.5 mr-1"}),"Run apply â verify â revert proof"]}),e.jsxs("span",{className:"text-[11px] text-muted-foreground",children:["Probes ",d.label," rate ",d.ratePsf," â ",In(Number(d.ratePsf)),", then restores it."]}),o&&e.jsx(ie,{variant:o.ok?"default":"destructive",className:"text-[10px]",children:o.ok?"PASS":"FAIL"})]}),o&&e.jsxs(da,{variant:o.ok?"default":"destructive",children:[e.jsx(Sa,{className:"text-xs",children:o.ok?"Applied, verified by the backend, and restored":o.dirty?"Failed â probe value may still be live":"Failed â nothing was left changed"}),e.jsxs(ma,{children:[e.jsx("ul",{className:"space-y-1 text-xs mt-1",children:o.steps.map(c=>e.jsxs("li",{className:"flex items-start gap-1.5",children:[c.state==="pass"?e.jsx(hr,{className:"h-3.5 w-3.5 mt-0.5 shrink-0"}):c.state==="fail"?e.jsx(Et,{className:"h-3.5 w-3.5 mt-0.5 shrink-0"}):e.jsx(Ul,{className:"h-3.5 w-3.5 mt-0.5 shrink-0"}),e.jsxs("span",{children:[e.jsx("span",{className:"font-medium",children:c.label})," â ",c.detail]})]},c.key))}),o.dirty&&e.jsxs("p",{className:"mt-2 flex items-center gap-1 text-xs font-medium",children:[e.jsx(Xe,{className:"h-3.5 w-3.5"})," Revert run"," ",String(o.runId??"").slice(0,8)," from Change History."]})]})]})]}):null}const hc={structural:"border-l-primary bg-primary/5",structure:"border-l-primary bg-primary/5",mechanical:"border-l-accent bg-accent/[0.07]",hvac:"border-l-accent bg-accent/[0.07]",plumbing:"border-l-accent bg-accent/[0.07]",electrical:"border-l-destructive bg-destructive/5",finishes:"border-l-secondary-foreground bg-secondary/20",interior:"border-l-secondary-foreground bg-secondary/20",exterior:"border-l-ring bg-ring/5",roofing:"border-l-ring bg-ring/5",siding:"border-l-ring bg-ring/5",demolition:"border-l-muted-foreground bg-muted/20"},_c="border-l-muted-foreground bg-muted/20";function Fn(a,t){if(a==="rule")return _c;const s=(t||"").toLowerCase().trim();return hc[s]||"border-l-primary/40 bg-primary/[0.04]"}function ml(a,t,s){return["border-l-4 transition-shadow",Fn(a,t).split(" ")[0],s?"ring-1 ring-primary shadow-sm":""].filter(Boolean).join(" ")}function ul(a,t){return Fn(a,t).split(" ")[1]||""}function Zt(a){return Object.values(a).reduce((t,s)=>t+Object.keys(s).length,0)}function jr(a,t){return Object.keys(a[t]||{}).length}function hl(a){return Object.keys(a).filter(t=>jr(a,t)>0)}function ft(a,t){if(!jr(a,t))return a;const s={...a};return delete s[t],s}function pc(a,t){const s=Zt(a),r=Zt(t);if(s+r===0)return"Nothing staged â every value already matches the backend.";const o=[];if(r){const i=hl(t).length;o.push(`${r} item band value${r===1?"":"s"} on ${i} item${i===1?"":"s"}`)}if(s){const i=hl(a).length;o.push(`${s} rule band value${s===1?"":"s"} on ${i} rate set${i===1?"":"s"}`)}return`Discarded ${o.join(" and ")}. Restored the last verified pricing.`}const On="HOMEESTIMATOR_PRICING_V1",ir=["row_uid","kind","source_table","item_code","item_name","card","side","scope"],Dn="(info) ";function Bn(a){const t=a.map(l=>`${l.kind}|${l.row_uid}|${l.source_table}|${l.item_code}`).sort().join(` 10`);let s=2166136261,r=16777619;for(let l=0;l<t.length;l+=1){const o=t.charCodeAt(l);s=(s^o)*16777619>>>0,r=r+o*(l+1)>>>0}return`${s.toString(16)}${r.toString(16)}-${a.length}`}function xc(a){const t=a.infoColumns??[],s=[...ir,...t.map(l=>`${Dn}${l}`),...a.fieldColumns],r=a.rows.map(l=>[l.row_uid,l.kind,l.source_table,l.item_code,l.item_name,l.card_code??"",l.side??"",l.scope,...t.map(o=>{var i;return((i=l.info)==null?void 0:i[o])??""}),...a.fieldColumns.map(o=>{const i=l.fields[o];return i??""})]);return[s,...r]}function gc(a,t){const s=a.flatMap(d=>
10d.rows),r={...t,exportedAt:t.exportedAt??new Date().toISOString(),checksum:Bn(s),rowCount:s.length},l=sa.book_new();a.forEach(d=>{const _=sa.aoa_to_sheet(xc(d));sa.book_append_sheet(l,_,d.name.slice(0,31))});const o=[["key","value"],["magic",On],["view",r.view],["scope",r.scope],["company",r.companyName??""],["filters",r.filterSummary??"none"],["exported_at",r.exportedAt],["row_count",r.rowCount],["checksum",r.checksum],[],["HOW TO USE",""],["1","Edit only the money columns. Leave a cell blank to keep the current price."],["2","Never edit or reorder the identity columns (row_uid ⦠scope) or this tab."],["3","Finish tiers must move together â fill entry, good, better and best."],["4","Re-import this same file. Imports write your company pricing only."],...a.map(d=>[`tab: ${d.name}`,`${d.rows.length} row(s) â ${d.importable===!1?"reference only, not imported":"importable"}${d.note?` â ${d.note}`:""}`])],i=sa.aoa_to_sheet(o);return i["!protect"]={password:"",selectLockedCells:!0,selectUnlockedCells:!0,formatCells:!1,insertRows:!1,deleteRows:!1,sort:!1},sa.book_append_sheet(l,i,"_key"),{workbook:l,meta:r}}function _l(a,t){Mi(a,t.endsWith(".xlsx")?t:`${t}.xlsx`)}function bc(a){const t=a.Sheets._key;if(!t)return{};const s=sa.sheet_to_json(t,{header:1,blankrows:!1}),r=new Map;return s.forEach(l=>{l&&l.length>=2&&typeof l[0]=="string"&&r.set(String(l[0]).trim(),String(l[1]??"").trim())}),{magic:r.get("magic"),view:r.get("view"),scope:r.get("scope"),companyName:r.get("company"),filterSummary:r.get("filters"),exportedAt:r.get("exported_at"),checksum:r.get("checksum"),rowCount:Number(r.get("row_count")??0)||0}}const fc="Use only a file exported from this view and change only the price columns â if this file came from your administrator, contact them to resolve the format.";function Ia(a,...t){return{meta:a,rows:[],errors:[...t.filter(Boolean),fc]}}function wc(a,t){var d;const s=[],r=Pi(a,{type:"array"}),l=bc(r);if(l.magic!==On)return Ia(l,"This file was not produced by the Pricing Control Center export (its identity tab is missing or changed). Export the view first, edit that file, then import it back.");if(t!=null&&t.scope&&l.scope&&l.scope!==t.scope)return Ia(l,`This file was exported from ${l.scope} scope but the view is showing ${t.scope} scope.`);const o=[],i=new Set;
10for(const _ of r.SheetNames){if(_==="_key")continue;const n=sa.sheet_to_json(r.Sheets[_],{header:1,blankrows:!1});if(!n.length)continue;const c=(n[0]||[]).map(b=>String(b??"").trim()),m=ir.filter(b=>!c.includes(b));if(m.length)return Ia(l,`Tab "${_}": identity column(s) missing or renamed (${m.join(", ")}).`);const h=b=>c.indexOf(b),j=c.map((b,x)=>({h:b,i:x})).filter(({h:b})=>b&&!ir.includes(b)&&!b.startsWith(Dn));if(t!=null&&t.allowedColumns){const b=j.map(({h:x})=>x).filter(x=>!t.allowedColumns.includes(x));if(b.length)return Ia(l,`Tab "${_}": unknown price column(s) ${b.join(", ")} â a column was renamed or added.`)}for(let b=1;b<n.length;b+=1){const x=n[b]||[],u=String(x[h("row_uid")]??"").trim();if(!u)continue;if(i.has(u))return Ia(l,`Tab "${_}" row ${b+1}: duplicate row_uid ${u} â a row was copied.`);i.add(u);const N=[],y={};j.forEach(({h:L,i:I})=>{const $=x[I];if($===""||$===null||$===void 0)return;const ee=typeof $=="number"?$:Number(String($).replace(/[$,\s]/g,""));if(!Number.isFinite(ee)){N.push(`${L}: "${String($)}" is not a number`);return}if(ee<0){N.push(`${L}: negative values are not allowed`);return}y[L]=ee}),o.push({sheet:_,kind:String(x[h("kind")]??"catalog").trim()||"catalog",row_uid:u,source_table:String(x[h("source_table")]??"").trim(),item_code:String(x[h("item_code")]??"").trim(),item_name:String(x[h("item_name")]??"").trim(),card_code:String(x[h("card")]??"").trim()||null,side:String(x[h("side")]??"").trim()||null,scope:String(x[h("scope")]??"").trim(),fields:y,problems:N})}}if((d=t==null?void 0:t.kinds)!=null&&d.length){const _=Array.from(new Set(o.map(n=>n.kind).filter(n=>!t.kinds.includes(n))));if(_.length)return Ia(l,`This file contains ${_.join(", ")} row(s), which this view cannot write. Import it from the view it was exported from.`)}if(l.rowCount&&o.length!==l.rowCount)return Ia(l,`This file has ${o.length} row(s) but was exported with ${l.rowCount} â rows were added or removed.`);if(l.checksum){const _=Bn(o.map(n=>({kind:n.kind,row_uid:n.row_uid,source_table:n.source_table,item_code:n.item_code})));if(_!==l.checksum)return Ia(l,...s,`The identity columns were edited or reordered (checksum ${_} does not match the exported ${l.checksum}).`)}return{meta:l,rows:o,errors:s}}const Vn=["entry","good","better","best"];function yc(a){for(const t of Vn)if(a.endsWith(`_${t}`))return{family:a.slice(0,-(t.length+1)),tier:t};return null}function jc(a,t){const s=new Map;Object.keys(a).forEach(i=>{const d=yc(i);if(!d)return;const _=s.get(d.family)??new Set;_.add(d.tier),s.set(d.family,_)});const r=[],l=[],o=[];return s.forEach((i,d)=>{const _=Vn.filter(m=>t.editableColumns.includes(`${d}_${m}`));if(_.length<2)return;const n=_.filter(m=>!i.has(m));if(n.length){_.forEach(m=>{i.has(m)&&r.push(`${d}_${m}`)}),l.push(`${d}: fill all finish tiers together â missing ${n.join(", ")}`);return}const c=_.map(m=>a[`${d}_${m}`]);for(let m=1;m<c.length;m+=1)if(c[m]<c[m-1]){o.push(`${t.item_code} · ${d}: ${_[m]} ($${c[m]}) is below ${_[m-1]} ($${c[m-1]})`);break}}),{blockedColumns:r,problems:l,warnings:o}}const vc=.005;function Nc(a,t){const s=[],r=[],l=[],o=[];let i=0;return a.forEach(d=>{const _=t.get(d.row_uid);if(!_){r.push({row_uid:d.row_uid,item_code:d.item_code,reason:"row no longer in this view â re-export and try again"});return}if(_.importable===!1){l.push({row_uid:d.row_uid,item_code:d.item_code,reason:_.blockedReason||"this row is reference-only and cannot be imported"});return}d.problems.forEach(h=>r.push({row_uid:d.row_uid,item_code:d.item_code,reason:h}));const n=jc(d.fields,_);n.problems.forEach(h=>r.push({row_uid:d.row_uid,item_code:d.item_code,reason:h})),o.push(...n.warnings);const c={};Object.entries(d.fields).forEach(([h,j])=>{if(!_.editableColumns.includes(h)){r.push({row_uid:d.row_uid,item_code:d.item_code,reason:`${h} is not editable on this row`});return}if(n.blockedColumns.includes(h))return;const b=_.values[h]??null;b!==null&&Math.abs(b-j)<vc||b===null&&j===0||(c[h]={old:b,next:j})});const m=Object.keys(c).length;m&&(i+=m,s.push({kind:_.kind,row_uid:d.row_uid,source_table:_.source_table,item_code:_.item_code,item_name:_.item_name,card_code:_.card_code??null,changes:c}))}),{changed:s,skipped:r,blocked:l,warnings:o,fieldCount:i}}function za(a,t,s){return s?`${a}:${t}:${s}`:`${a}:${t}`}function pl(a){return a.split(":")[1]??""}const Ps=200;function kc(a,t,s){const r={scope:"company",notes:s};return a==="area_band_item"?{...r,kind:"area_band_item",item_band_changes:t.map(l=>({source_table:l.source_table,global_row_id:pl(l.row_uid),item_code:l.item_code,item_name:l.item_name,card_code:l.card_code,values:Object.fromEntries(Object.entries(l.changes).map(([o,i])=>[o,i.next]))}))}:{...r,kind:a==="legacy"?"legacy":"catalog",changes:t.map(l=>({source_table:l.source_table,global_row_id:pl(l.row_uid),item_code:l.item_code,item_name:l.item_name,card_code:l.card_code,fields:Object.fromEntries(Object.entries(l.changes).map(([o,i])=>[o,i.next]))}))}}const xl={pass:0,warn:1,fail:2};async function Cc(a,t,s){const r={fieldsChanged:0,itemsAffected:0,analysesMarkedStale:0,runIds:[],errors:[],verdicts:[],worst:null},l=new Map;a.forEach(d=>{const _=l.get(d.kind)??[];_.push(d),l.set(d.kind,_)});const o=Array.from(l.values()).reduce((d,_)=>d+Math.ceil(_.length/Ps),0);let i=0;s==null||s(0,o);for(const[d,_]of l)for(let n=0;n<_.length;n+=Ps){const c=_.slice(n,n+Ps),{data:m,error:h}=await ge.functions.invoke("apply-catalog-price-update",{body:kc(d,c,t)});i+=1,s==null||s(i,o);const j=await wa(m,h);if(r.verdicts.push(j),j.verdict){const b=j.verdict.state;(!r.worst||xl[b]>xl[r.worst])&&(r.worst=b)}if(j.runId&&r.runIds.push(j.runId),h||m!=null&&m.error&&!(m!=null&&m.success)){const b=[j.errorMessage,...j.details].filter(
10Boolean).join(" â ")||(h==null?void 0:h.message)||"Import batch rejected";r.errors.push(b);continue}r.fieldsChanged+=Number((m==null?void 0:m.fields_changed)??0),r.itemsAffected+=Number((m==null?void 0:m.items_affected)??0),r.analysesMarkedStale+=Number((m==null?void 0:m.analyses_marked_stale)??0),Array.isArray(m==null?void 0:m.errors)&&r.errors.push(...m.errors.filter(b=>typeof b=="string"))}return r}const Sc=["unit","trade","engine","is_active","usage_projects"];function gl(a,t,s,r){const l=[];t.forEach(i=>i.editable_columns.forEach(d=>{l.includes(d)||l.push(d)}));const o=t.filter(i=>!i.read_only&&i.global_row_id).map(i=>{var d;return{kind:"catalog",row_uid:za(i.source_table,i.global_row_id),source_table:i.source_table,item_code:i.item_code,item_name:i.item_name,card_code:i.card_code,side:i.side,scope:s,info:{unit:((d=i.values)==null?void 0:d.unit)??"",trade:i.trade,engine:i.engine,is_active:i.is_active===!1?"retired":"active",usage_projects:i.usage_projects??0},fields:Object.fromEntries(l.map(_=>[_,i.values[_]??null]))}});return{name:a,kind:"catalog",rows:o,fieldColumns:l,infoColumns:Sc,note:r}}function $c(a){const t=new Map;return a.forEach(s=>{if(!s.global_row_id)return;const r=za(s.source_table,s.global_row_id);t.set(r,{kind:"catalog",row_uid:r,source_table:s.source_table,item_code:s.item_code,item_name:s.item_name,card_code:s.card_code,values:s.values,editableColumns:s.editable_columns,importable:!s.read_only,blockedReason:s.read_only?"retired/legacy row â read-only in this grid":void 0})}),t}function Ac(a,t){const s=[];return a.forEach(l=>l.editable_columns.forEach(o=>{s.includes(o)||s.push(o)})),{name:"Legacy & allowances",kind:"legacy",rows:a.map(l=>{var o;return{kind:"legacy",row_uid:za(l.source_table,l.row_id),source_table:l.source_table,item_code:l.item_code,item_name:l.item_name,card_code:null,side:null,scope:t,info:{table:l.table_label,category:l.category_display,is_active:l.is_active===!1?"retired":"active",live_projects:((o=l.usage)==null?void 0:o.live_projects)??0},fields:Object.fromEntries(s.map(i=>[i,l.values[i]??null]))}}),fieldColumns:s,infoColumns:["table","category","is_active","live_projects"],note:"finish tiers must move together"}}function Ec(a){const t=new Map;return a.forEach(s=>{const r=za(s.source_table,s.row_id);t.set(r,{kind:"legacy",row_uid:r,source_table:s.source_table,item_code:s.item_code,item_name:s.item_name,values:s.values,editableColumns:s.editable_columns})}),t}function zn(a){const t=[];return a.forEach(s=>s.cells.forEach(r=>{t.includes(r.path)||t.push(r.path)})),t}function Rc(a,t){const s=zn(a);return{name:"Area bands (items)",kind:"area_band_item",fieldColumns:s,infoColumns:["card","unit","is_active"],rows:a.map(r=>({kind:"area_band_item",row_uid:za(r.source_table,r.id),source_table:r.source_table,item_code:r.item_code,item_name:r.item_name,card_code:r.card,side:null,scope:t,info:{card:r.card,unit:r.unit,is_active:r.is_active===!1?"retired":"active"},fields:Object.fromEntries(s.map(l=>{var o;return[l,((o=r.cells.find(i=>i.path===l))==null?void 0:o.value)??null]}))}))}}function Tc(a){const t=zn(a);return{name:"Area bands (rules)",kind:"area_band",importable:!1,note:"rule ladders are global â edit them in the grid, not by import",fieldColumns:t,infoColumns:["rule_code"],rows:a.map(s=>({kind:"area_band",row_uid:za("business_logic_rules",s.id),source_table:"business_logic_rules",item_code:s.rule_code,item_name:s.rule_name,card_code:null,side:null,scope:"global",info:{rule_code:s.rule_code},fields:Object.fromEntries(t.map(r=>{var l;return[r,((l=s.cells.find(o=>o.path===r))==null?void 0:l.value)??null]}))}))}}function Lc(a,t){const s=new Map;return a.forEach(r=>{const l=za(r.source_table,r.id);s.set(l,{kind:"area_band_item",row_uid:l,source_table:r.source_table,item_code:r.item_code,item_name:r.item_name,card_code:r.card,values:Object.fromEntries(r.cells.map(o=>[o.path,o.value??null])),editableColumns:r.cells.map(o=>o.path)})}),t.forEach(r=>{const l=za("business_logic_rules",r.id);s.set(l,{kind:"area_band",row_uid:l,source_table:"business_logic_rules",item_code:r.rule_code,item_name:r.rule_name,values:Object.fromEntries(r.cells.map(o=>[o.path,o.value??null])),editableColumns:r.cells.map(o=>o.path),importable:!1,blockedReason:"rule-level band ladders are global â change them in the grid, not by import"})}),s}function es(a,t=""){const s=[];return a==null?s:typeof a=="number"&&Number.isFinite(a)?(t&&s.push({path:t,value:a}
10),s):Array.isArray(a)?(a.forEach((r,l)=>s.push(...es(r,t?`${t}.${l}`:String(l)))),s):(typeof a=="object"&&Object.entries(a).forEach(([r,l])=>s.push(...es(l,t?`${t}.${r}`:r))),s)}function bl(a){const t=[];return a.forEach(s=>{t.push({path:s.paths.ratePsf,value:s.ratePsf}),t.push({path:s.paths.laborPct,value:s.laborPct}),t.push({path:s.paths.materialPct,value:s.materialPct})}),t}function Mc(a,t,s){const r=sa.book_new(),l=[["view",a],["imported_at",new Date().toISOString()],["fields_changed",s.fieldsChanged],["items_affected",s.itemsAffected],["projects_marked_stale",s.analysesMarkedStale],["audit_runs",s.runIds.join(", ")],["wiring_verdict",s.worst??"n/a"],["batch_errors",s.errors.length]];sa.book_append_sheet(r,sa.aoa_to_sheet(l),"Summary");const o=[["item_code","item_name","source_table","field","old_value","new_value"]];t.changed.forEach(d=>Object.entries(d.changes).forEach(([_,n])=>o.push([d.item_code,d.item_name,d.source_table,_,n.old,n.next]))),sa.book_append_sheet(r,sa.aoa_to_sheet(o),"Applied");const i=[["kind","row_uid","item_code","reason"]];return t.blocked.forEach(d=>i.push(["not importable",d.row_uid,d.item_code,d.reason])),t.skipped.forEach(d=>i.push(["skipped",d.row_uid,d.item_code,d.reason])),t.warnings.forEac
10h(d=>i.push(["warning","","",d])),s.errors.forEach(d=>i.push(["batch error","","",d])),sa.book_append_sheet(r,sa.aoa_to_sheet(i),"Not applied"),r}function Un(a,t,s){return{name:a,kind:"catalog",fieldColumns:[],infoColumns:s,rows:t.map((r,l)=>({kind:"catalog",row_uid:`reference:${a}:${l+1}`,source_table:a,item_code:String(r[s[0]]??`row_${l+1}`),item_name:String(r[s[1]]??""),card_code:null,side:null,scope:"global",fields:{},info:Object.fromEntries(s.map(o=>[o,r[o]??""])),importable:!1,blockedReason:"reference-only export"}))}}function fl(a){return a==null?"â":`$${a.toLocaleString(void 0,{maximumFractionDigits:2})}`}function Tt({view:a,scope:t,companyName:s,filterSummary:r,filenameBase:l,buildSheets:o,liveRows:i,onImported:d,canImport:_=!0,disabled:n,importKinds:c,allowedColumns:m,extraExports:h}){const j=$a(),b=p.useRef(null),[x,u]=p.useState(!1),[N,y]=p.useState(""),[L,I]=p.useState([]),[$,ee]=p.useState(null),[U,E]=p.useState(""),[J,be]=p.useState(!1),[F,se]=p.useState(null),[V,z]=p.useState(null),Se=_&&t==="company",re=(A,de,O,he)=>{try{const Ie=A(),Ge=Ie.reduce((P,M)=>P+M.rows.length,0);if(!Ge){le.warning("Nothing to export",{description:"This view has no rows with the current filters."});return}const{workbook:Oe,meta:k}=gc(Ie,{view:he??a,scope:t,companyName:s,filterSummary:O??r}),w=new Date().toISOString().slice(0,10);_l(Oe,`${de}-${w}.xlsx`),le.success(`Exported ${Ge.toLocaleString()} row(s)`,{description:`Edit the price columns and import the same file back. Checksum ${k.checksum}.`})}catch(Ie){le.error("Could not export",{description:(Ie==null?void 0:Ie.message)||"Unexpected error"})}},$e=()=>re(o,l,r,a),g=()=>{y(""),I([]),ee(null),E(""),z(null),se(null),b.current&&(b.current.value="")},S=()=>{if(m)return m;try{const A=[o,...(h??[]).map(O=>O.buildSheets)].flatMap(O=>O()),de=Array.from(new Set(A.flatMap(O=>O.fieldColumns)));return de.length?de:void 0}catch{return}},R=async A=>{if(A){z(null),y(A.name);try{const de=wc(await A.arrayBuffer(),{scope:t,kinds:c,allowedColumns:S()});if(de.errors.length&&!de.rows.length){I(de.errors),ee(null);return}const O=i(),he=Nc(de.rows,O);I(de.errors),ee(he)}catch(de){I([(de==null?void 0:de.message)||"Could not read this file â is it an .xlsx workbook?"]),ee(null)}}},v=A=>{$&&_l(Mc(a,$,A),`${l}-import-result-${new Date().toISOString().slice(0,10)}.xlsx`)},G=async()=>{if($!=null&&$.changed.length){be(!0),se({done:0,total:1});try{const A=await Cc($.changed,U.trim(),(de,O)=>se({done:de,total:O}));z(A),A.errors.length?le.warning(`${A.errors.length} batch problem(s)`,{description:A.errors[0]}):le.success(`Imported ${A.fieldsChanged} price change(s) across ${A.itemsAffected} item(s)`,{description:`Company pricing updated. ${A.analysesMarkedStale} existing project(s) marked stale â future projects only.`}),j.invalidateQueries({queryKey:["catalog-price-change-runs"]}),await(d==null?void 0:d())}catch(A){le.error("Import failed",{description:(A==null?void 0:A.message)||"Unexpected error"})}finally{be(!1)}}},te=p.useMemo(()=>$?$.changed.slice(0,60):[],[$]),oe=p.useMemo(()=>V?V.verdicts.find(A=>{var de;return((de=A.verdict)==null?void 0:de.state)==="fail"})??V.verdicts.find(A=>{var de;return((de=A.verdict)==null?void 0:de.state)==="warn"})??V.verdicts.find(A=>A.verdict)??null:null,[V]);return e.jsxs(e.Fragment,{children:[e.jsxs(Qs,{children:[e.jsx(Js,{asChild:!0,children:e.jsxs(H,{size:"sm",variant:"outline",disabled:n,title:"Export these prices to Excel, edit them offline, then import the same file back",children:[e.jsx(Ys,{className:"h-4 w-4 mr-1"})," Excel"]})}),e.jsxs(Xs,{align:"end",className:"w-72",children:[e.jsx(Zs,{className:"text-xs",children:"Export"}),e.jsxs(Oa,{onClick:$e,children:[e.jsx(Wa,{className:"h-4 w-4 mr-2"})," Export ",a.toLowerCase()," (current filters)"]}),(h??[]).map(A=>e.jsxs(Oa,{onClick:()=>re(A.buildSheets,A.filenameBase,A.filterSummary,A.view),children:[e.jsx(Wa,{className:"h-4 w-4 mr-2"})," ",A.label]},A.label)),_&&e.jsxs(e.Fragment,{children:[e.jsx(ql,{}),e.jsx(Zs,{className:"text-xs",children:"Import"}),e.jsxs(Oa,{disabled:!Se,onClick:()=>{g(),u(!0)},children:[e.jsx(nn,{className:"h-4 w-4 mr-2"})," Import filled sheet"]}),e.jsx("p",{className:"px-2 py-1.5 text-[11px] text-muted-foreground",children:Se?"Only a file exported from this view can be imported â edit its price columns only.":"Imports write company pricing only â switch to a company scope to import."})]})]})]}),e.jsx(Ha,{open:x,onOpenChange:A=>{u(A),A||g()},children:e.jsxs(Qa,{className:"max-w-3xl",children:[e.jsxs(Ja,{children:[e.jsxs(Ya,{className:"flex items-center gap-2",children:[e.jsx(Ys,{className:"h-4 w-4"})," Import ",a," pricing"]}),e.jsxs(it,{children:["Sheet values ",e.jsx("span",{className:"font-medium text-foreground",children:"replace"})," the current price for each row. A blank cell leaves that price unchanged. Imports write"," ",e.jsx("span",{className:"font-medium text-foreground",children:"your company's pricing only"})," â the global baseline is never changed by an import, and existing projects keep their totals until they are regenerated."]})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsxs("ol",{className:"rounded-md border border-primary/15 bg-muted/30 p-2 text-[11px] text-muted-foreground space-y-0.5 list-decimal pl-5",children:[e.jsx("li",{children:"Export this view first â that file carries the row IDs the import matches on."}),e.jsx("li",{children:"In Excel change only the price columns; a blank cell keeps the current price."}),e.jsxs("li",{children:["Never edit the identity columns, the header row or the ",e.jsx("span",{className:"font-mono",children:"_key"})," tab, and never add or delete rows."]}),e.jsx("li",{children:"Import the same file, review the old â new preview, add a reason and apply."})]}),e.jsxs("div",{children:[e.jsx(xe,{htmlFor:"pricing-workbook-file",className:"text-xs",children:"Workbook exported from this view"}),e.jsx(Pe,{id:"pricing-workbook-file",ref:b,type:"file",accept:".xlsx",onChange:A=>{var de;return R((de=A.target.files)==null?void 0:de[0])}}),N&&e.jsx("p",{className:"text-[11px] text-muted-foreground mt-1",children:N})]}),L.length>0&&e.jsxs(da,{variant:"destructive",children:[e.jsx(Xe,{className:"h-4 w-4"}),e.jsx(Sa,{children:"File problems"}),e.jsx(ma,{children:e.jsx("ul",{className:"list-disc pl-4 space-y-0.5 text-xs",children:L.slice(0,6).map((A,de)=>e.jsx("li",{children:A},de))})})]}),$&&e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-xs",children:[e.jsxs(ie,{variant:"secondary",children:[$.changed.length.toLocaleStr
10ing()," row(s) changed"]}),e.jsxs(ie,{variant:"secondary",children:[$.fieldCount.toLocaleString()," field(s)"]}),$.skipped.length>0&&e.jsxs(ie,{variant:"outline",children:[$.skipped.length," skipped"]}),$.blocked.length>0&&e.jsxs(ie,{variant:"outline",children:[$.blocked.length," not importable"]})]}),$.warnings.length>0&&e.jsxs(da,{children:[e.jsx(Xe,{className:"h-4 w-4"}),e.jsx(Sa,{children:"Check these finish tiers"}),e.jsx(ma,{children:e.jsx("ul",{className:"list-disc pl-4 space-y-0.5 text-xs",children:$.warnings.slice(0,5).map((A,de)=>e.jsx("li",{children:A},de))})})]}),$.changed.length>0&&e.jsx(Ma,{className:"h-56 rounded-md border border-primary/15",children:e.jsxs("table",{className:"w-full text-xs",children:[e.jsx("thead",{className:"sticky top-0 bg-card",children:e.jsxs("tr",{className:"text-left text-muted-foreground",children:[e.jsx("th",{className:"px-2 py-1",children:"Item"}),e.jsx("th",{className:"px-2 py-1",children:"Field"}),e.jsx("th",{className:"px-2 py-1 text-right",children:"Current"}),e.jsx("th",{className:"px-2 py-1 text-right",children:"Sheet"})]})}),e.jsx("tbody",{children:te.flatMap(A=>Object.entries(A.changes).map(([de,O])=>e.jsxs("tr",{className:"border-t border-border/40",children:[e.jsxs("td",{className:"px-2 py-1",children:[e.jsx("span",{className:"font-medium",children:A.item_name||A.item_code}),e.jsxs("span",{className:"text-muted-foreground",children:[" · ",A.item_code]})]}),e.jsx("td",{className:"px-2 py-1 font-mono",children:de}),e.jsx("td",{className:"px-2 py-1 text-right text-muted-foreground",children:fl(O.old)}),e.jsx("td",{className:"px-2 py-1 text-right font-medium text-primary",children:fl(O.next)})]},`${A.row_uid}:${de}`)))})]})}),$.changed.length>te.length&&e.jsxs("p",{className:"text-[11px] text-muted-foreground",children:["Showing the first ",te.length," of ",$.changed.length," changed rows â all of them are applied."]}),($.skipped.length>0||$.blocked.length>0)&&e.jsx("div",{className:"rounded-md border border-primary/15 p-2 text-[11px] text-muted-foreground space-y-0.5",children:[...$.blocked,...$.skipped].slice(0,6).map((A,de)=>e.jsxs("p",{children:[e.jsx("span",{className:"font-mono",children:A.item_code||A.row_uid})," â ",A.reason]},de))}),e.jsxs("div",{children:[e.jsx(xe,{htmlFor:"pricing-workbook-reason",className:"text-xs",children:"Reason for this change (recorded in the audit trail)"}),e.jsx(Pe,{id:"pricing-workbook-reason",value:U,onChange:A=>E(A.target.value),placeholder:`Excel import â ${a}`})]})]}),J&&F&&e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Writing batch ",F.done," of ",F.total,"â¦"]}),V&&e.jsxs("div",{className:"space-y-2",children:[e.jsxs(H,{size:"sm",variant:"outline",onClick:()=>v(V),children:[e.jsx(Wa,{className:"h-4 w-4 mr-1"})," Download import result"]}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[V.fieldsChanged.toLocaleString()," field(s) across ",V.itemsAffected.toLocaleString()," item(s) · ",V.analysesMarkedStale.toLocaleString()," project(s) marked stale",V.runIds.length?` · audit run ${V.runIds[0]}`:""]}),V.errors.length>0&&e.jsxs(da,{variant:"destructive",children:[e.jsx(Xe,{className:"h-4 w-4"}),e.jsx(Sa,{children:"Some changes were rejected"}),e.jsx(ma,{children:e.jsx("ul",{className:"list-disc pl-4 text-xs space-y-0.5",children:V.errors.slice(0,5).map((A,de)=>e.jsx("li",{children:A},de))})})]}),(oe==null?void 0:oe.verdict)&&e.jsx(Ua,{verdict:oe.verdict,aiNotes:oe.aiNotes,reviewerNote:oe.reviewerNote,reverted:oe.reverted,defaultOpen:oe.verdict.state!=="pass"})]})]}),e.jsxs(Xa,{children:[e.jsx(H,{variant:"outline",onClick:()=>u(!1),disabled:J,children:"Close"}),e.jsx(H,{onClick:G,disabled:J||!($!=null&&$.changed.length)||!U.trim(),children:J?"Applyingâ¦":`Apply ${($==null?void 0:$.fieldCount)??0} change(s) to company pricing`})]})]})})]})}const Ea="sticky top-0 z-20 h-9 px-3 bg-card text-primary text-[11px] font-semibold shadow-[0_1px_0_hsl(var(--border))]",Ra=a=>a===null?"â":`$${a.toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2})}`;function Pc(a){if(!a.length)return{sizeSpan:"no bands",rateSpan:"â"};const t=a.map(i=>i.upperSf).filter(i=>Number.isFinite(i)),s=i=>
10i.toLocaleString("en-US"),r=t.length?`up to ${s(Math.min(...t))} â ${s(Math.max(...t))} sf and up`:"flat rate (all sizes)",l=a.map(i=>i.ratePsf).filter(i=>i!==null&&Number.isFinite(i)),o=l.length?(()=>{const i=Math.min(...l),d=Math.max(...l);return i===d?Ra(i):`${Ra(i)} â ${Ra(d)}`})():"not priced";return{sizeSpan:r,rateSpan:o}}function Ic({canEdit:a,focusItemCode:t,companyId:s}){var B;const[r,l]=p.useState("global"),[o,i]=p.useState(null),[d,_]=p.useState(!1),[n,c]=p.useState({cards:[],trades:[],search:t||"",items:t?[t]:[],source:t?"items":"all"}),[m,h]=p.useState(""),[j,b]=p.useState({}),[x,u]=p.useState({}),[N,y]=p.useState(""),[L,I]=p.useState(!1),[$,ee]=p.useState(()=>new Set),[U,E]=p.useState(!1),[J,be]=p.useState(""),F=$a(),{rules:se,items:V,cardOptions:z,tradeOptions:Se,isLoading:re,refetch:$e}=Mn(r,s),g=p.useMemo(()=>{const f=new Map;return V.forEach(q=>{const K=f.get(q.item_code)||{label:q.item_name||q.item_code,count:0};K.count+=1,f.set(q.item_code,K)}),Array.from(f.entries()).map(([q,K])=>({value:q,label:K.label,count:K.count,description:q})).sort((q,K)=>q.label.localeCompare(K.label))},[V]),S=p.useMemo(()=>oc(se,n),[se,n]),R=p.useMemo(()=>cc(V,n),[V,n]),v=p.useMemo(()=>U?S.filter(f=>j[f.id]):S,[S,U,j]),G=p.useMemo(()=>U?R.filter(f=>x[f.id]):R,[R,U,x]),te=Number(m),oe=m.trim()!==""&&Number.isFinite(te)&&te>0,A=Zt(j),de=Zt(x),O=A+de,he=(f,q)=>q||$.has(f),Ie=f=>ee(q=>{const K=new Set(q);return K.has(f)?K.delete(f):K.add(f),K}),Ge=()=>ee(new Set([...G.map(f=>f.id),...v.map(f=>f.id)])),Oe=()=>ee(new Set),[k,w]=p.useState(!1),P=async()=>{const f=pc(j,x);b({}),u({}),y(""),w(!0);try{await $e(),le.success("Staged band changes discarded",{description:f})}finally{w(!1)}},M=(f,q,K,_e)=>{const pe=Number(K);b(W=>{const we={...W},Ee={...we[f]||{}};return K===""||!Number.isFinite(pe)||pe<0||pe===_e?delete Ee[q]:Ee[q]=pe,Object.keys(Ee).length?we[f]=Ee:delete we[f],we})},D=(f,q,K,_e)=>{const pe=Number(K);u(W=>{const we={...W},Ee={...we[f]||{}};return K===""||!Number.isFinite(pe)||pe<0||pe===_e?delete Ee[q]:Ee[q]=pe,Object.keys(Ee).length?we[f]=Ee:delete we[f],we})},fe=(f,q)=>{if(!Number.isFinite(q)||q===0){le.error("Enter a percentage first",{description:"e.g. 3 for +3%, -2 for a 2% cut."});return}u(K=>{const _e={...K[f.id]||{}};let pe=0;for(const W of f.cells){if(W.ratePsf===null)continue;const we=Math.round(W.ratePsf*(1+q/100)*100)/100;we>=0&&we!==W.ratePsf&&(_e[W.paths.ratePsf]=we,pe+=1)}return pe?{...K,[f.id]:_e}:K}),le.success(`Staged ${q>0?"+":""}${q}% on ${f.item_name}`,{description:"Nothing has reached the backend yet â review, then Save."})},ve=f=>{var _e;const q=f.cells[0];if(!q||q.ratePsf===null){le.error("Nothing to fill down",{description:"The first band has no rate."});return}const K=((_e=x[f.id])==null?void 0:_e[q.paths.ratePsf])??q.ratePsf;u(pe=>{const W={...pe[f.id]||{}};for(const we of f.cells.slice(1))K!==we.ratePsf?W[we.paths.ratePsf]=K:delete W[we.paths.ratePsf];if(!Object.keys(W).length){const we={...pe};return delete we[f.id],we}return{...pe,[f.id]:W}}),le.success(`Filled ${Ra(K)} down every band`,{description:f.item_name})},ue=async()=>{const f=["type,item_or_rule,code,card,trade,band,rate,labor_pct,material_pct"];for(const q of R)for(const K of q.cells)f.push(["item",`"${q.item_name}"`,q.item_code,q.card,q.trade,`"${K.label}"`,K.ratePsf??"",K.laborPct??"",K.materialPct??""].join(","));for(const q of S)for(const K of Xt(q.rule_config).filter(_e=>Qt(_e.path).kind!=="other"))f.push(["rule",`"${q.rule_name}"`,q.rule_code,q.cards.join("|"),q.trade,`"${K.path}"`,K.value,"",""].join(","));try{await navigator.clipboard.writeText(f.join(` 11`)),le.success(`Copied ${f.length-1} band row(s) as CSV`)}catch{le.error("Clipboard unavailable in this browser")}},T=p.useMemo(()=>{var q;const f=[];for(const K of se){const _e=j[K.id];if(!_e||!K.isThresholdRule)continue;const pe=(((q=K.rule_config)==null?void 0:q.thresholds)||[]).map((W,we)=>{const Ee=`thresholds[${we}]`;return _e[Ee]!==void 0?_e[Ee]:Number(W)});sc(pe).forEach(W=>f.push(`${K.rule_name}: ${W}`))}for(const K of V){const _e=x[K.id];if(_e)for(const pe of K.cells){const W=_e[pe.paths.laborPct]??pe.laborPct,we=_e[pe.paths.materialPct]??pe.materialPct,Ee=nc(W,we);Ee&&f.push(`${K.item_name} â ${pe.label}: ${Ee}`)}}return f},[se,V,j,x]),ce=async f=>{var _e,pe;if(T.length){le.error("Fix the flagged values first",{description:T[0]});return}const q=Object.entries(j).filter(([W])=>!f||f.ruleId===W),K=Object.entries(x).filter(([W])=>!f||f.itemId===W);if(!(!q.length&&!K.length)){I(!0);try{const W=[],we=N.trim()||void 0;if(q.length){const Ae=q.map(([ra,Qe])=>{var ya;return{rule_id:ra,rule_code:((ya=se.find(mt=>mt.id===ra))==null?void 0:ya.rule_code)||ra,values:Qe}}),{data:Ne,error:He}=await ge.functions.invoke("apply-catalog-price-update",{body:{kind:"area_band",scope:"global",notes:we,band_changes:Ae}}),Me=await wa(Ne,He);if(Me.verdict&&i(Me),He)throw He;if(Ne!=null&&Ne.error&&!(Ne!=null&&Ne.success))throw new Error(typeof Ne.error=="string"?Ne.error:"Band rule update rejected");W.push({label:"rule bands",fields:Ne.fields_changed,stale:Ne.analyses_marked_stale}),(_e=Ne.errors)!=null&&_e.length&&le.warning("Some rule band values were skipped",{description:Ne.errors[0]})}if(K.length){const Ae=K.map(([ra,Qe])=>{const ya=V.find(mt=>mt.id===ra);return{source_table:ya.source_table,global_row_id:ra,item_code:ya.item_code,item_name:ya.item_name,values:Qe}}),{data:Ne,error:He}=await ge.functions.invoke("apply-catalog-price-update",{body:{kind:"area_band_item",scope:r,notes:we,item_band_changes:Ae}}),Me=await wa(Ne,He);if(Me.verdict&&i(Me),He)throw He;if(Ne!=null&&Ne.error&&!(Ne!=null&&Ne.success))throw new Error(typeof Ne.error=="string"?Ne.error:"Item band update rejected");W.push({label:"item bands",fields:Ne.fields_changed,stale:Ne.analyses_marked_stale}),(pe=Ne.errors)!=null&&pe.length&&le.warning("Some item band values were skipped",{description:Ne.errors[0]})}const Ee=W.reduce((Ae,Ne)=>Ae+(Ne.fields||0),0),ne=W.reduce((Ae,Ne)=>Ae+(Ne.stale||0),0);le.success(`Saved ${Ee} band value${Ee===1?"":"s"}`,{description:`Verified against the backend. New rates apply to future estimates. ${ne} existing project(s) marked stale.`}),f?(f.ruleId&&b(Ae=>ft(Ae,f.ruleId)),f.itemId&&u(Ae=>ft(Ae,f.itemId))):(b({}),u({}),y("")),await $e(),F.invalidateQueries({queryKey:["catalog-price-change-runs"]})}catch(W){le.error("Could not save band rates",{description:W==null?void 0:W.message})}finally{I(!1)}}};if(re)return e.jsxs("div",{className:"py-10 text-center text-sm text-muted-foreground",children:[e.jsx(Fe,{className:"h-4 w-4 animate-spin inline mr-2"})," Loading area bandsâ¦"]});const X=R.length+S.length;return e.jsxs("div",{className:"space-y-4",children:[o&&e.jsx(Ua,{verdict:o.verdict,aiNotes:o.aiNotes,reviewerNote:o.reviewerNote,reverted:o.reverted,rechecking:d,onRecheck:o.runId?async()=>{_(!0);const f=await qa({run_id:o.runId,scope:r});
11i({...o,verdict:f.verdict,aiNotes:f.ai_notes,reviewerNote:f.reviewer_note}),_(!1)}:void 0}),e.jsxs(da,{children:[e.jsx(Ba,{className:"h-4 w-4"}),e.jsx(Sa,{children:"Square-footage bands"}),e.jsx(ma,{children:"Pricing changes with project size in two places: the per-band rate ladders in the business rules engine, and the per-item band tables the V2 structural reader prices from. Both are shown here with the item name, card, trade, size range and unit. Edits are audited, verified by reading the value back out of the backend, and apply to future estimates â existing projects keep their frozen totals and are flagged stale."})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("div",{className:"relative",children:[e.jsx(Va,{className:"absolute left-2 top-2.5 h-3.5 w-3.5 text-muted-foreground"}),e.jsx(Pe,{value:n.search,onChange:f=>c(q=>({...q,search:f.target.value})),placeholder:"Search item or rate setâ¦",className:"h-9 w-[240px] pl-7"})]}),e.jsx(xa,{label:"Items",allLabel:"All items",options:g,selected:n.items??[],onChange:f=>c(q=>({...q,items:f})),width:"w-[200px]"}),e.jsx(xa,{label:"Cards",allLabel:"All cards",options:z,selected:n.cards,onChange:f=>c(q=>({...q,cards:f}))}),e.jsx(xa,{label:"Trades",allLabel:"All trades",options:Se,selected:n.trades,onChange:f=>c(q=>({...q,trades:f})),width:"w-[180px]"}),e.jsxs(dt,{type:"single",size:"sm",value:n.source,onValueChange:f=>f&&c(q=>({...q,source:f})),className:"flex-wrap",children:[e.jsx(ta,{value:"all",className:"h-9 whitespace-nowrap px-3 text-xs",children:"Both sources"}),e.jsx(ta,{value:"items",className:"h-9 whitespace-nowrap px-3 text-xs",children:"Item bands"}),e.jsx(ta,{value:"rules",className:"h-9 whitespace-nowrap px-3 text-xs",children:"Rule bands"})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(xe,{className:"text-xs text-muted-foreground whitespace-nowrap",children:"Size probe"}),e.jsx(Pe,{type:"number",value:m,onChange:f=>h(f.target.value),placeholder:"sf",className:"h-9 w-[90px]"})]}),a&&e.jsxs(dt,{type:"single",size:"sm",value:r,onValueChange:f=>f&&l(f),className:"ml-auto flex-wrap",children:[e.jsx(ta,{value:"global",className:"h-9 whitespace-nowrap px-3 text-xs",children:"Global"}),e.jsx(ta,{value:"company",disabled:!s,className:"h-9 whitespace-nowrap px-3 text-xs",children:"My company"})]})]}),r==="company"&&!s&&e.jsx("p",{role:"status",children:"An active actual company must be confirmed before company bands can be loaded."}),r==="company"&&e.jsxs(da,{children:[e.jsx(Ba,{className:"h-4 w-4"}),e.jsx(ma,{className:"text-xs",children:"Company scope covers item band tables only â the rule-engine ladders are global by design. Editing an item band at company scope clones the global row first, so your company starts from the same numbers."})]}),e.jsx("div",{className:"sticky top-0 z-20 -mx-1 rounded-md border bg-background/95 px-3 py-2 backdrop-blur supports-[backdrop-filter]:bg-background/80",children:e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("span",{className:"text-xs text-muted-foreground whitespace-nowrap",children:[X," rate set",X===1?"":"s"]}),e.jsxs(H,{size:"sm",variant:"outline",className:"h-8 whitespace-nowrap text-xs",onClick:Ge,children:[e.jsx(ha,{className:"mr-1 h-3.5 w-3.5"})," Expand all"]}),e.jsxs(H,{size:"sm",variant:"outline",className:"h-8 whitespace-nowrap text-xs",onClick:Oe,children:[e.jsx(fa,{className:"mr-1 h-3.5 w-3.5"})," Collapse all"]}),e.jsxs(H,{size:"sm",variant:U?"default":"outline",className:"h-8 whitespace-nowrap text-xs",onClick:()=>E(f=>!f),disabled:O===0&&!U,children:["Only staged",O>0?` (${O})`:""]}),e.jsxs(H,{size:"sm",variant:"ghost",className:"h-8 whitespace-nowrap text-xs",onClick:ue,children:[e.jsx(Ii,{className:"mr-1 h-3.5 w-3.5"})," Copy CSV"]}),e.jsx(Tt,{view:"Area bands",scope:r,filterSummary:`source ${n.source}${n.search?` · search "${n.search}"`:""}${(B=n.cards)!=null&&B.length?` · ${n.cards.length} card(s)`:""}`,filenameBase:`pricing-area-bands-${r}`,buildSheets:()=>[Rc(R.map(f=>({id:f.id,source_table:f.source_table,item_code:f.item_code,item_name:f.item_name,card:f.card,unit:f.unit,is_active:f.is_active,cells:bl(f.cells)})),r),Tc(S.map(f=>({id:f.id,rule_code:f.rule_code,rule_name:f.rule_name,cells:es(f.rule_config)})))],liveRows:()=>Lc(R.map(f=>({id:f.id,source_table:f.source_table,item_code:f.item_code,item_name:f.item_name,card:f.card,unit:f.unit,is_active:f.is_active,cells:bl(f.cells)})),S.map(f=>({id:f.id,rule_code:f.rule_code,rule_name:f.rule_name,cells:es(f.rule_config)}))),importKinds:["area_band_item"],canImport:a,onImported:async()=>{await $e()}}),a&&e.jsxs("div",{className:"ml-auto flex flex-wrap items-center gap-2",children:[e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(Or,{className:"h-3.5 w-3.5 text-muted-foreground"}),e.jsx(Pe,{type:"number",step:"0.1",value:J,onChange:f=>be(f.target.value),placeholder:"±%",className:"h-8 w-[72px] text-xs",title:"Percentage used by the per-card Apply % button"})]}),e.jsx(Pe,{value:N,onChange:f=>y(f.target.value),placeholder:"Reason (optional, recorded in the audit trail)",className:"h-8 min-w-[240px] flex-1 text-xs"}),e.jsxs(H,{size:"sm",variant:"outline",className:"h-8 whitespace-nowrap text-xs",disabled:O===0||L||k,onClick:P,title:"Drop every staged band edit and restore the last verified pricing",children:[k?e.jsx(Fe,{className:"mr-1 h-3.5 w-3.5 animate-spin"}):e.jsx(ot,{className:"mr-1 h-3.5 w-3.5"}),"Revert",O>0?` (${O})`:""]}),e.jsxs(H,{size:"sm",className:"h-8 whitespace-nowrap text-xs",disabled:O===0||L,onClick:()=>ce(),children:[L?e.jsx(Fe,{className:"mr-1 h-3.5 w-3.5 animate-spin"}):e.jsx(lt,{className:"mr-1 h-3.5 w-3.5"}),"Save ",O>0?O:""," change",O===1?"":"s"]})]})]})}),a&&O>0&&e.jsxs(da,{children:[e.jsx(Ba,{className:"h-4 w-4"}),e.jsxs(ma,{className:"text-xs",children:[O," value",O===1?"":"s"," staged and not yet saved â nothing has reached the backend. Revert puts every field back to the last verified pricing. A reason is optional; leave it blank and the audit trail records an automatic note."]})]}),T.length>0&&e.jsxs(da,{variant:"destructive",children:[e.jsx(Xe,{className:"h-4 w-4"}),e.jsxs(Sa,{children:[T.length," staged value(s) need attention"]}),e.jsx(ma,{children:e.jsx("ul",{className:"list-disc pl-4 text-xs space-y-0.5",children:T.slice(0,6).map(f=>e.jsx("li",{children:f},f))})})]}),G.map(f=>{const q=oe?lc(Object.fromEntries(f.cells.map(W=>[W.bandKey,{}])),te):null,K=jr(x,f.id),_e=he(f.id,K>0),pe=Pc(f.cells);return e.jsx(ye,{className:ml("item",f.trade,K>0),children:e.jsxs(Ks,{open:_e,onOpenChange:()=>Ie(f.id),children:[e.jsx(Ws,{asChild:!0,children:e.jsxs(ke,{className:`curs
11or-pointer py-2 space-y-1 ${ul("item",f.trade)}`,children:[e.jsxs(Ce,{className:"text-sm flex flex-wrap items-center gap-2",children:[_e?e.jsx(ha,{className:"h-4 w-4 shrink-0 text-muted-foreground"}):e.jsx(fa,{className:"h-4 w-4 shrink-0 text-muted-foreground"}),f.item_name,e.jsx(ie,{variant:"secondary",className:"font-mono text-[10px]",children:f.item_code}),e.jsx(ie,{variant:"outline",className:"text-[10px]",children:f.card}),e.jsx(ie,{variant:"outline",className:"text-[10px]",children:f.trade}),f.addition_type&&e.jsx(ie,{variant:"outline",className:"text-[10px]",children:f.addition_type}),e.jsx(ie,{className:"text-[10px]",children:"V2 backend"}),e.jsxs(ie,{variant:"outline",className:"text-[10px]",children:[f.cells.length," bands"]}),!f.is_active&&e.jsx(ie,{variant:"destructive",className:"text-[10px]",children:"deactivated"}),K>0&&e.jsxs(ie,{variant:"outline",className:"text-[10px] border-primary text-primary",children:[K," staged"]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-0.5 pl-6 text-[11px] text-muted-foreground tabular-nums",children:[e.jsxs("span",{children:["Sizes: ",e.jsx("span",{className:"text-foreground",children:pe.sizeSpan})]}),e.jsxs("span",{children:["Rate/",f.unit,": ",e.jsx("span",{className:"text-foreground",children:pe.rateSpan})]})]})]})}),e.jsx(Gs,{children:e.jsxs(je,{className:"space-y-3",children:[a&&e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(uc,{item:f,scope:r,onFinished:()=>$e()}),e.jsxs(H,{size:"sm",variant:"outline",className:"h-7 whitespace-nowrap px-2 text-[11px]",onClick:()=>fe(f,Number(J)),title:"Stage every band rate of this item at the percentage in the toolbar",children:[e.jsx(Or,{className:"mr-1 h-3 w-3"})," Apply ",J||"±","% to all bands"]}),e.jsxs(H,{size:"sm",variant:"outline",className:"h-7 whitespace-nowrap px-2 text-[11px]",onClick:()=>ve(f),title:"Copy the first band's rate into every other band",children:[e.jsx(Fi,{className:"mr-1 h-3 w-3"})," Fill down"]}),K>0&&e.jsxs(e.Fragment,{children:[e.jsxs(H,{size:"sm",className:"h-7 whitespace-nowrap px-2 text-[11px]",disabled:L,onClick:()=>ce({itemId:f.id}),children:[e.jsx(lt,{className:"mr-1 h-3 w-3"})," Save this item"]}),e.jsxs(H,{size:"sm",variant:"ghost",className:"h-7 whitespace-nowrap px-2 text-[11px]",onClick:()=>u(W=>ft(W,f.id)),children:[e.jsx(Rr,{className:"mr-1 h-3 w-3"})," Revert this item"]})]})]}),e.jsxs(Ze,{className:"no-mobile-scroll border-separate border-spacing-0 [&_tbody_tr:nth-child(even)]:bg-muted/25 [&_td]:py-2 [&_td]:px-3 [&_td]:border-b [&_td]:border-border/60",children:[e.jsx(ea,{children:e.jsxs(Le,{children:[e.jsx(Z,{className:Ea,children:"Size band"}),e.jsxs(Z,{className:`${Ea} text-right w-32`,children:["Rate (",f.unit,")"]}),e.jsx(Z,{className:`${Ea} text-right w-24`,children:"Labor %"}),e.jsx(Z,{className:`${Ea} text-right w-24`,children:"Material %"}),e.jsx(Z,{className:`${Ea} text-right w-24`,children:"Current"})]})}),e.jsx(aa,{children:f.cells.map(W=>{const we=x[f.id]||{},Ee=q===W.bandKey,ne=Ne=>`h-8 w-24 px-1.5 text-right tabular-nums ml-auto ${we[Ne]!==void 0?"border-primary ring-1 ring-primary":""}`,Ae=Ne=>He=>{He.key==="Escape"&&u(Me=>{const ra={...Me},Qe={...ra[f.id]||{}};return delete Qe[Ne],Object.keys(Qe).length?ra[f.id]=Qe:delete ra[f.id],ra})};return e.jsxs(Le,{className:Ee?"bg-primary/5":void 0,children:[e.jsxs(Q,{className:"text-xs",children:[W.label,Ee&&e.jsxs(ie,{variant:"outline",className:"ml-2 text-[10px]",children:["applies at ",te," sf"]})]}),e.jsx(Q,{className:"text-right",children:e.jsx(Pe,{type:"number",step:"0.01",disabled:!a,className:ne(W.paths.ratePsf),value:we[W.paths.ratePsf]??W.ratePsf??"",onKeyDown:Ae(W.paths.ratePsf),onChange:Ne=>D(f.id,W.paths.ratePsf,Ne.target.value,W.ratePsf)})}),e.jsx(Q,{className:"text-right",children:e.jsx(Pe,{type:"number",step:"0.01",max:"1",disabled:!a||W.laborPct===null,className:ne(W.paths.laborPct),value:we[W.paths.laborPct]??W.laborPct??"",onKeyDown:Ae(W.paths.laborPct),onChange:Ne=>D(f.id,W.paths.laborPct,Ne.target.value,W.laborPct)})}),e.jsx(Q,{className:"text-right",children:e.jsx(Pe,{type:"number",step:"0.01",max:"1",disabled:!a||W.materialPct===null,className:ne(W.paths.materialPct),value:we[W.paths.materialPct]??W.materialPct??"",onKeyDown:Ae(W.paths.materialPct),onChange:Ne=>D(f.id,W.paths.materialPct,Ne.target.value,W.materialPct)})}),e.jsx(Q,{className:"text-right text-xs text-muted-foreground",children:Ra(W.ratePsf)})]},W.bandKey)})})]})]})})]})},f.id)}),v.map(f=>{const q=Xt(f.rule_config).filter(W=>Qt(W.path).kind!=="other");if(!q.length)return null;const K=j[f.id]||{},_e=Object.keys(K).length,pe=he(f.id,_e>0);return e.jsx(ye,{className:ml("rule",f.trade,_e>0),children:e.jsxs(Ks,{open:pe,onOpenChange:()=>Ie(f.id),children:[e.jsx(Ws,{asChild:!0,children:e.jsxs(ke,{className:`curs
11or-pointer py-2 space-y-1 ${ul("rule",f.trade)}`,children:[e.jsxs(Ce,{className:"text-sm flex flex-wrap items-center gap-2",children:[pe?e.jsx(ha,{className:"h-4 w-4 shrink-0 text-muted-foreground"}):e.jsx(fa,{className:"h-4 w-4 shrink-0 text-muted-foreground"}),f.rule_name,e.jsx(ie,{variant:"secondary",className:"font-mono text-[10px]",children:f.rule_code}),f.cards.map(W=>e.jsx(ie,{variant:"outline",className:"text-[10px]",children:W},W)),e.jsx(ie,{variant:"outline",className:"text-[10px]",children:f.trade}),e.jsx(ie,{variant:"outline",className:"text-[10px]",children:f.unit}),e.jsx(ie,{variant:"outline",className:"text-[10px]",children:"rule engine"}),e.jsxs(ie,{variant:"outline",className:"text-[10px]",children:[q.length," rates"]}),_e>0&&e.jsxs(ie,{variant:"outline",className:"text-[10px] border-primary text-primary",children:[_e," staged"]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-0.5 pl-6 text-[11px] text-muted-foreground tabular-nums",children:[e.jsxs("span",{children:["Rate/",f.unit,":"," ",e.jsx("span",{className:"text-foreground",children:(()=>{const W=q.map(ne=>Number(ne.value)).filter(ne=>Number.isFinite(ne));if(!W.length)return"not priced";const we=Math.min(...W),Ee=Math.max(...W);return we===Ee?Ra(we):`${Ra(we)} â ${Ra(Ee)}`})()})]}),f.context&&e.jsxs("span",{className:"truncate",children:["Size from ",f.context.inputs.join(", ")," â bands"," ",e.jsx("span",{className:"font-mono",children:f.context.thresholdRuleCode})]})]})]})}),e.jsx(Gs,{children:e.jsxs(je,{className:"space-y-3",children:[a&&_e>0&&e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs(H,{size:"sm",className:"h-7 whitespace-nowrap px-2 text-[11px]",disabled:L,onClick:()=>ce({ruleId:f.id}),children:[e.jsx(lt,{className:"mr-1 h-3 w-3"})," Save this rate set"]}),e.jsxs(H,{size:"sm",variant:"ghost",className:"h-7 whitespace-nowrap px-2 text-[11px]",onClick:()=>b(W=>ft(W,f.id)),children:[e.jsx(Rr,{className:"mr-1 h-3 w-3"})," Revert this rate set"]})]}),e.jsxs(Ze,{className:"no-mobile-scroll border-separate border-spacing-0 [&_tbody_tr:nth-child(even)]:bg-muted/25 [&_td]:py-2 [&_td]:px-3 [&_td]:border-b [&_td]:border-border/60",children:[e.jsx(ea,{children:e.jsxs(Le,{children:[e.jsx(Z,{className:Ea,children:"Size band / field"}),e.jsx(Z,{className:`${Ea} w-28`,children:"Kind"}),e.jsx(Z,{className:`${Ea} text-right w-36`,children:"Value"}),e.jsx(Z,{className:`${Ea} text-right w-24`,children:"Current"})]})}),e.jsx(aa,{children:q.map(W=>{const{kind:we,index:Ee}=Qt(W.path),ne=oe&&we!=="threshold"&&Ee!==null?ac(f.thresholds,Ee,te):!1;return e.jsxs(Le,{className:ne?"bg-primary/5":void 0,children:[e.jsxs(Q,{className:"text-xs",children:[tc(W.path,f.thresholds),ne&&e.jsxs(ie,{variant:"outline",className:"ml-2 text-[10px]",children:["applies at ",te," sf"]}),e.jsx("span",{className:"ml-2 font-mono text-[10px] text-muted-foreground",children:W.path})]}),e.jsx(Q,{children:e.jsx(ie,{variant:"outline",className:"text-[10px] capitalize",children:we==="threshold"?"band limit":we==="addon"?"surcharge":"rate"})}),e.jsx(Q,{className:"text-right",children:e.jsx(Pe,{type:"number",step:"0.01",disabled:!a||r==="company",className:`h-8 w-32 text-right ml-auto ${K[W.path]!==void 0?"border-primary ring-1 ring-primary":""}`,value:K[W.path]??W.value,onKeyDown:Ae=>{Ae.key==="Escape"&&b(Ne=>ft(Ne,f.id))},onChange:Ae=>M(f.id,W.path,Ae.target.value,W.value)})}),e.jsx(Q,{className:"text-right text-xs text-muted-foreground",children:we==="threshold"?`${W.value.toLocaleString("en-US")} sf`:Ra(W.value)})]},W.path)})})]})]})})]})},f.id)}),v.length===0&&G.length===0&&e.jsx("p",{className:"text-sm text-muted-foreground",children:U?"No cards have staged edits.":"No area bands match these filters."})]})}const Fc=36;function qn(a,t=Date.now()){return a!=null&&a.swept_at?new Date(t).getTime()-new Date(a.swept_at).getTime()>Fc*36e5?"stale":"fresh":"never"}function Oc(a,t=Date.now()){const s=qn(a,t);if(s==="never")return"Automated nightly audit has not reported yet.";const r=new Date(a.swept_at).toLocaleString(),l=a.healthy?"no drift found":`${a.drift_count} drifted · ${a.stuck_count} interrupted · ${a.failed_count} failed`;return s==="stale"?`Automated nightly audit is stale â last reported ${r} (${l}).`:`Automated nightly audit last reported ${r} â ${l}.`}const Kn=new Set(["allowance_override_save","line_item_override_save","estimate_cache_invalidation","corpus_crawl","selection_provenance","tile_sourcing","tile_matrix_overlay","navbar.hash_drift_no_user_edit"]),Wn=new Set(["allProjectLineItems_card_reconcile","navbar.project-total","navbar_guard","navbar.missing_project_inputs_hash","combined_item_details","backend.calculate-all-card-totals","contract_editor_init"]),Dc={allowance_3way:{at:"2026-08-30T13:00:00Z",change:"Exclusive variant groups + option-gate defaults aligned with projectInputsMapper (kitchen island, laundry/mudroom built-ins)."},allowance_option_gate:{at:"2026-08-30T13:00:00Z",change:"cardOptionFlags defaults made symmetrical with the backend card request (kitch_island_pendant)."},card_quantity:{at:"2026-08-30T13:00:00Z",change:"Seepage-pit catalog variants corrected and non-countable mappings removed from the quantity parity map."},exec_summary_rule:{at:"2026-08-30T13:00:00Z",change:"assertAppliedRuleTagParity n
11o longer treats fixed/manual tags as rule engines; Executive Summary trusts the persisted applied_rule_type."},generate_qty_reconciliation:{at:"2026-08-30T14:30:00Z",change:"Benign card-off and legacy-mirror corrections now log at info level instead of warn."},modal_grid_allowance:{at:"2026-08-30T13:00:00Z",change:"Grid allowance totals delegate to the shared allowance selector (verify:money check #8)."}};function Bc(a,t){const s=Dc[a];if(!s)return{fixed:!1};const r=new Date(t).getTime();return Number.isFinite(r)?r<new Date(s.at).getTime()?{fixed:!0,change:s.change,at:s.at}:{fixed:!1,change:s.change,at:s.at}:{fixed:!1}}function Gn(a){return Kn.has(a.surface)?"activity":Wn.has(a.surface)?"retired":(a.severity||"").toLowerCase()==="info"?"activity":"issue"}const Hn={profit_config_parity:"Saved profit percentages do not reproduce the saved total",allowance_3way:"Allowance dollars disagree between card, grand total and line items",card_allowance_parity:"Card allowance total disagrees with its line items",modal_grid:"View Line Items grid total disagrees with the card total",modal_grid_allowance:"Line-items grid allowance total disagrees with the card",line_item_sheet:"Excel Line Items cell disagrees with the backend after saving",tile_overlay:"A tile selection had no priced catalog row, so it moved no money",allowance_option_gate:"An allowance row survived an option that is switched off",card_quantity:"Card header quantity disagrees with its priced line items",generate_qty_reconciliation:"Quantities changed between generate and persist",grand_total_parity:"Displayed total disagrees with the persisted backend total",project_total_drift:"Persisted project total moved without a user edit",exec_summary_rule:"Executive summary figure does not match the backend rule output",catalog_price_drift:"Catalog price in the backend differs from the applied change",allowance_override_save:"Allowance override saved (audit trail)",line_item_override_save:"Line-item override saved (audit trail)",estimate_cache_invalidation:"Estimate cache invalidated (audit trail)",allProjectLineItems_card_reconcile:"Retired reconciliation surface","navbar.project-total":"Retired navbar total guard",navbar_guard:"Retired navbar total guard",implausible_persisted_total:"A persisted total or card base cost broke the residential ceiling and was refused by a read surface",implausible_total:"Backend refused to persist a total above the residential ceiling",generate_preflight:"Pre-generate preflight rejected the inputs before pricing",generate_verification:"Verification army pass that runs on every Generate Estimate (run summary + per-check findings)",verify_cards:"Generate-time sweep: a card total disagrees with its line items",verify_excel_sheet:"Generate-time sweep: the Excel line-items sheet disagrees with the backend",verify_custom_line_items:"Generate-time sweep: a custom line item is inconsistent or orphaned",verify_combined_details:"Generate-time sweep: Combined Item Details does not conserve the card totals",verify_price_analysis:"Generate-time sweep: Price Analysis figures disagree with the backend cards",verify_scope_of_work:"Generate-time sweep: scope of work and priced cards disagree",verify_allowances:"Generate-time sweep: allowance rows or overrides disagree with the cards",verify_report_snapshot:"Generate-time sweep: a report snapshot total drifted from the committed total",verify_gut_cascade:"Generate-time sweep: a gut-to-studs floor is missing the scope it must carry",verify_project_total:"Generate-time sweep: the project total is not supported by the cards","navbar.hash_drift_no_user_edit":"Persisted inputs fingerprint moved with no user edit (receipt)","navbar.missing_project_inputs_hash":"Project has no persisted inputs fingerprint (degraded, accepted)","navbar.sync_timeout":"Pre-generate sync gate timed out",navbar_render_guard:"Navbar rendered a total from a non-backend source",agent:"AI agent tool reported a money disagreement",allowances:"Allowances surface disagreed with the backend card feed",custom_line_items:"Custom line items surface disagreed with the backend card feed",scope_of_work:"Scope of work surface disagreed with the backend card feed",allowances_row_math:"An allowance row extended to different money than the shared math",allowances_trade_view:"By-Trade allowance rollup disagrees with the card totals",allowance_autoflush:"Stale allowance override rows auto-flushed (audit trail)",allowance_panel_zero:"Allowance panel showed $0 while catalog money exists",allowance_row_count:"Allowance row count disagrees with the selected options",combined_orphan_card:"Combined Item Details received priced rows from a card the backend reported as disabled",combined_unselected_card:"Combined Item Details received priced rows from a card the user has deselected (stale estimate)",combined_item_details:"Combined Item Details total disagrees with the card totals",combined_summary:"Combined item details total disagrees with the backend card rows",combined_summary_coverage:"Combined item details is missing a selected card that carries money",cost_summary:"Cost summary block disagrees with the persisted totals",customize_sheet:"Customize sheet displayed money outside the backend result",floor_area_netting:"Floor-area netting produced a quantity the backend did not",missing_item_code:"A priced row arrived without an item code",profitability_drift:"Profitability stack drifted from the persisted configuration",profitability_rules:"Applied profitability rule disagrees with the resolver",profitability_summary:"Profitability summary disagrees with the persisted totals","restore.profit_override_snapback":"Restored project snapped back a profit override",scope_grid:"Scope grid dis
11played money outside the backend result",selection_provenance:"Selection provenance recorded (audit trail)","backend.calculate-all-card-totals":"Backend orchestrator reported an internal disagreement",contract_editor_init:"Retired contract editor guard",corpus_crawl:"Corpus crawl sweep (audit trail)",tile_sourcing:"Tile sourcing run staged or approved vendor evidence (audit trail)",tile_matrix_overlay:"Tile matrix selection repriced its mapped catalog rows (audit trail)"};[...Object.keys(Hn),...Kn,...Wn];const Vc=a=>Hn[a]||a.replace(/_/g," "),zc={combined_summary:"Combined item details summed rows the backend card feed does not agree with. Needs a code fix in the combined builder, then re-price the project.",combined_summary_coverage:"A selected card with money is missing from Combined item details â usually a registry/pairing gap. Needs a code fix, then re-price.",allowance_3way:"A reader is summing allowance dollars on its own instead of using the shared allowance selector. Needs a code fix, then re-price the project.",card_allowance_parity:"Card allowance total and its line items came from different reads. Needs a code fix, then re-price the project.",modal_grid:"The View Line Items grid was not self-sourcing from the backend card feed. Re-open the card after a fresh estimate; if it recurs, it needs a code fix.",modal_grid_allowance:"Grid allowance total disagreed with the card. Re-price the project and re-check; a recurrence needs a code fix.",tile_overlay:'A client selected a tile for a surface that has no priced catalog row, so nothing reached the card total or Allowances by Trade. Add a priced item to that card catalog and map it on the tile surface (or the surface stays labelled "Selection only â not yet priced").',line_item_sheet:"A cell in Excel Line Items did not match the backend after Save all. The sheet repaints and re-saves the row once automatically; an unresolved row means the write was rejected and needs a code or permission fix.",allowance_option_gate:"An allowance row survived an option that is switched off â the option flag is not reaching the backend card request. Needs a code fix (option-gate symmetry), then re-price.",card_quantity:"Card header quantity and the priced rows resolve from different sources. Needs a code fix in the countable-item map, then re-price.",generate_qty_reconciliation:"Quantities changed between generate and persist. Benign when the reason is card-off or a legacy mirror; anything else needs the card quantity source checked.",profit_config_parity:"The saved profit percentages no longer reproduce the saved total â stale config for that project. Clears when the project is re-priced (or the profit stack re-applied).",project_total_drift:"The persisted project total moved without a user edit. Confirm the contract anchor on that project, re-price, then re-check.",exec_summary_rule:"The Executive Summary named a different profit engine than the backend persisted. Fixed in code â re-check to close.",grand_total_parity:"Displayed total disagreed with the persisted backend total. Re-price the project, then re-check.",catalog_price_drift:"A catalog price in the backend differs from the applied change. Re-run the catalog price update; do not edit prices outside the audited path."},Uc=a=>zc[a]||"Re-check after re-pricing the project. If it still reproduces, the reader that renders this number needs a code fix.",qc=a=>`${a.analysis_id||"global"}::${a.surface}::${a.field_path||"-"}`,Kc={windows_addition:["win_add_standard"],windows_remodel:["win_rem_replacement","win_rem_new_opening"],patio_doors_remodel:["pdoor_rem_replacement","pdoor_rem_new_opening"],fireplace_addition:["fp_gas_unit_addition","fp_electric_unit_addition"],fireplace_remodel:["fp_gas_unit_remodel","fp_electric_unit_remodel"],seepage_pit_addition:["seepage_pit_500","seepage_pit_1000","seepage_pit_1500"],septic_system_addition:["septic_new","septic_replacement"],window_well_addition:["window_well"],window_well_remodel:["window_well"]};function Wc(a){var o,i;if(a.surface!=="card_quantity")return null;const t=String(((o=a.context)==null?void 0:o.card_code)||""),s=Array.isArray((i=a.context)==null?void 0:i.countable_codes)?a.context.countable_codes:[];if(!t||s.length===0)return null;const r=Kc[t];if(!r)return null;const l=s.filter(d=>!r.includes(d));return l.length!==s.length?null:`none of the item codes it checked (${l.join(", ")}) exist in the current parity map for ${t} â emitted by a superseded bundle`}async function Is(a){var c,m;const t=Gn(a);if(t!=="issue")return{verdict:"stale",reason:t==="activity"?"Audit-trail entry, not a price disagreement â safe to clear.":"Logged by a retired surface that no longer renders money."};const s=Bc(a.surface,a.created_at);if(s.fixed)return{verdict:"stale",reason:`Predates the fix that closed this class (${s.at}): ${s.change}`};const r=Wc(a);if(r)return{verdict:"stale",reason:`Cannot reproduce: ${r}.`};
11if(!a.analysis_id)return{verdict:"unknown",reason:"No project on this finding â cannot re-verify automatically."};const{data:l,error:o}=await ge.from("analysis_grand_totals").select("updated_at, created_at").eq("analysis_id",a.analysis_id).order("updated_at",{ascending:!1}).limit(1);if(o)return{verdict:"unknown",reason:`Could not read the persisted total: ${o.message}`};const i=((c=l==null?void 0:l[0])==null?void 0:c.updated_at)||((m=l==null?void 0:l[0])==null?void 0:m.created_at)||null;if(!i)return{verdict:"unknown",reason:"This project has no persisted estimate to compare against.",lastPricedAt:null};if(new Date(i)<=new Date(a.created_at))return{verdict:"reproducing",reason:"The finding is newer than the last pricing run â regenerate the estimate, then re-check.",lastPricedAt:i};let d=ge.from("money_invariant_log").select("created_at").eq("analysis_id",a.analysis_id).eq("surface",a.surface).is("resolved_at",null).gte("created_at",i).order("created_at",{ascending:!1}).limit(1);d=a.field_path?d.eq("field_path",a.field_path):d.is("field_path",null);const{data:_,error:n}=await d;return n?{verdict:"unknown",reason:`Could not re-check occurrences: ${n.message}`,lastPricedAt:i}:_&&_.length>0?{verdict:"reproducing",reason:"The same disagreement was logged again after the latest pricing run.",lastPricedAt:i,latestOccurrenceAt:_[0].created_at}:{verdict:"stale",reason:"The project was re-priced after this finding and it has not recurred since.",lastPricedAt:i}}async function Gc(a){const t=[...new Set(a.filter(Boolean))];if(t.length===0)return{};const{data:s}=await ge.from("saved_analyses").select("id, analysis_name, user_id, company_id").in("id",t),r=s||[],l=[...new Set(r.map(m=>m.company_id).filter(Boolean))],o=[...new Set(r.map(m=>m.user_id).filter(Boolean))],[i,d]=await Promise.all([l.length?ge.from("companies").select("id, company_name").in("id",l):Promise.resolve({data:[]}),o.length?ge.from("profiles").select("id, full_name").in("id",o):Promise.resolve({data:[]})]),_=new Map((i.data||[]).map(m=>[m.id,m.company_name??null])),n=new Map((d.data||[]).map(m=>[m.id,m.full_name??null])),c={};for(const m of r)c[m.id]={analysisId:m.id,projectName:m.analysis_name??null,companyId:m.company_id??null,companyName:m.company_id?_.get(m.company_id)??null:null,userId:m.user_id??null,userName:m.user_id?n.get(m.user_id)??null:null};return c}function Hc(a){const t=[...new Set(a.filter(Boolean))].sort().join(",");return Ke({queryKey:["pricing-issue-attribution",t],queryFn:()=>Gc(a),enabled:t.length>0,staleTime:6e4})}const Fs=a=>a==null?"â":`$${Number(a).toLocaleString(void 0,{maximumFractionDigits:2})}`;function Qc(a){const t=new Map;for(const s of a){const r=qc(s),l=t.get(r);l?(l.ids.push(s.id),l.occurrences+=1,new Date(s.created_at)>new Date(l.newest.created_at)&&(l.newest=s),new Date(s.created_at)<new Date(l.firstSeen)&&(l.firstSeen=s.created_at)):t.set(r,{key:r,newest:s,ids:[s.id],occurrences:1,firstSeen:s.created_at,klass:Gn(s)})}return[...t.values()].sort((s,r)=>new Date(r.newest.created_at).getTime()-new Date(s.newest.created_at).getTime())}function Jc(){const a=$a(),[t,s]=p.useState(!0),[r,l]=p.useState(!1),[o,i]=p.useState({}),[d,_]=p.useState({}),[n,c]=p.useState(null),[m,h]=p.useState({}),{data:j=[],isLoading:b}=Ke({queryKey:["open-pricing-issues"],queryFn:async()=>{const{data:E,error:J}=await ge.from("money_invariant_log").select("id, analysis_id, user_id, surface, field_path, backend_value, frontend_value, delta, severity, context, created_at").is("resolved_at",null).order("created_at",{ascending:!1}).limit(1e3);if(J)throw J;return E||[]},staleTime:3e4}),{issues:x,noise:u}=p.useMemo(()=>{const E=Qc(j);return{issues:E.filter(J=>J.klass==="issue"),noise:E.filter(J=>J.klass!=="issue")}},[j]),N=p.useMemo(()=>j.map(E=>E.analysis_id).filter(Boolean),[j]),{data:y={}}=Hc(N),L=async E=>{c(E.key);try{const J=await Is(E.newest);return _(be=>({...be,[E.key]:J})),J}finally{c(null)}},I=Ta({mutationFn:async E=>{var V,z;const J=d[E.key]??await Is(E.newest);if(_(Se=>({...Se,[E.key]:J})),J.verdict==="reproducing")throw new Error(`Still reproducing â ${J.reason}`);const be=((V=o[E.key])==null?void 0:V.trim())||null;if(J.verdict==="unknown"&&!be)throw new Error("Could not auto-verify this finding â add a resolution note explaining the fix.");const{data:F}=await ge.auth.getUser(),{error:se}=await ge.from("money_invariant_log").update({resolved_at:new Date().toISOString(),resolved_by:((z=F==null?void 0:F.user)==null?void 0:z.id)??null,resolution_note:[be,`verified: ${J.verdict} â ${J.reason}
11`].filter(Boolean).join(" | ")}).in("id",E.ids);if(se)throw se;return E.ids.length},onSuccess:E=>{le.success(`Verified and resolved (${E} occurrence(s))`),a.invalidateQueries({queryKey:["open-pricing-issues"]})},onError:E=>le.error((E==null?void 0:E.message)||"Could not resolve issue")}),$=Ta({mutationFn:async E=>{var se;const J=E.flatMap(V=>V.ids);if(J.length===0)return 0;const{data:be}=await ge.auth.getUser(),F=((se=be==null?void 0:be.user)==null?void 0:se.id)??null;for(const V of E){const z=await Is(V.newest);if(z.verdict!=="stale")continue;const{error:Se}=await ge.from("money_invariant_log").update({resolved_at:new Date().toISOString(),resolved_by:F,resolution_note:`bulk closure â verified: stale â ${z.reason}`}).in("id",V.ids);if(Se)throw Se}return J.length},onSuccess:E=>{le.success(`Cleared ${E} audit/retired entr${E===1?"y":"ies"}`),a.invalidateQueries({queryKey:["open-pricing-issues"]})},onError:E=>le.error((E==null?void 0:E.message)||"Could not clear the audit backlog")});if(b)return e.jsxs("div",{className:"rounded-md border border-border bg-muted/30 p-3 text-sm flex items-center gap-2",children:[e.jsx(Fe,{className:"h-4 w-4 animate-spin"})," Loading open pricing issuesâ¦"]});const ee=x.filter(E=>E.newest.severity==="error").length,U=E=>{var V;const J=E.newest,be=d[E.key],F=J.analysis_id?y[J.analysis_id]:void 0,se=!!m[E.key];return e.jsxs("div",{className:"rounded border border-border/60 p-2 space-y-1",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-2",children:[e.jsxs("button",{type:"button",className:"min-w-0 text-left flex items-start gap-1",onClick:()=>h(z=>({...z,[E.key]:!z[E.key]})),children:[se?e.jsx(ha,{className:"h-3.5 w-3.5 mt-0.5 shrink-0 text-muted-foreground"}):e.jsx(fa,{className:"h-3.5 w-3.5 mt-0.5 shrink-0 text-muted-foreground"}),e.jsxs("span",{className:"min-w-0",children:[e.jsx("span",{className:"block text-xs font-medium break-words",children:Vc(J.surface)}),e.jsx("span",{className:"block text-[11px] text-muted-foreground font-mono break-all",children:J.surface})]})]}),E.occurrences>1&&e.jsxs(ie,{variant:"outline",className:"text-[11px]",children:[E.occurrences,"à occurrences"]})]}),e.jsxs("div",{className:"text-[11px] text-muted-foreground flex flex-wrap gap-x-2",children:[e.jsx("span",{children:new Date(J.created_at).toLocaleString()}),(F==null?void 0:F.projectName)&&e.jsx("span",{className:"break-words",children:F.projectName}),(F==null?void 0:F.companyName)&&e.jsx("span",{className:"break-words",children:F.companyName}),(F==null?void 0:F.userName)&&e.jsx("span",{className:"break-words",children:F.userName}),J.severity&&e.jsx("span",{className:"uppercase",children:J.severity})]}),se&&e.jsxs("div",{className:"rounded bg-muted/40 p-2 space-y-1 text-[11px]",children:[e.jsxs("div",{className:"grid gap-x-4 gap-y-0.5 sm:grid-cols-2",children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground",children:"Company: "}),e.jsx("span",{className:"font-medium break-words",children:(F==null?void 0:F.companyName)||"â"})]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground",children:"Project: "}),e.jsx("span",{className:"font-medium break-words",children:(F==null?void 0:F.projectName)||"â"})]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground",children:"User: "}),e.jsx("span",{className:"font-medium break-words",children:(F==null?void 0:F.userName)||"â"})]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground",children:"Occurrences: "}),e.jsx("span",{className:"font-medium",children:E.occurrences})]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground",children:"First seen: "}),e.jsx("span",{className:"font-medium",children:new Date(E.firstSeen).toLocaleString()})]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground",children:"Last seen: "}),e.jsx("span",{className:"font-medium",children:new Date(J.created_at).toLocaleString()})]}),J.analysis_id&&e.jsxs("div",{className:"sm:col-span-2 font-mono break-all",children:[e.jsx("span",{className:"text-muted-foreground",children:"Project id: "}
11),J.analysis_id]})]}),e.jsxs("div",{className:"pt-1 break-words",children:[e.jsx("span",{className:"text-muted-foreground",children:"How this gets resolved: "}),Uc(J.surface)]})]}),J.field_path&&e.jsx("div",{className:"text-xs font-mono break-all",children:J.field_path}),(J.backend_value!=null||J.frontend_value!=null||J.delta!=null)&&e.jsxs("div",{className:"text-xs",children:["backend ",e.jsx("span",{className:"font-semibold",children:Fs(J.backend_value)})," · frontend"," ",e.jsx("span",{className:"font-semibold",children:Fs(J.frontend_value)})," · delta"," ",e.jsx("span",{className:"font-semibold text-destructive",children:Fs(J.delta)})]}),((V=J.context)==null?void 0:V.stage)&&e.jsxs("div",{className:"text-[11px] text-muted-foreground break-words",children:["stage: ",String(J.context.stage)]}),be&&e.jsxs("div",{className:`text-[11px] break-words ${be.verdict==="reproducing"?"text-destructive":"text-muted-foreground"}`,children:["re-check: ",e.jsx("span",{className:"font-medium uppercase",children:be.verdict})," â ",be.reason]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2 pt-1",children:[e.jsx(Pe,{value:o[E.key]??"",onChange:z=>i(Se=>({...Se,[E.key]:z.target.value})),placeholder:"Resolution note (required when it can't be auto-verified)",className:"h-7 text-xs flex-1 min-w-[160px]"}),e.jsxs(H,{variant:"outline",size:"sm",className:"h-7 px-2 text-xs",disabled:n===E.key,onClick:()=>L(E),children:[n===E.key?e.jsx(Fe,{className:"h-3.5 w-3.5 mr-1 animate-spin"}):e.jsx(Ga,{className:"h-3.5 w-3.5 mr-1"}),"Re-check"]}),e.jsxs(H,{variant:"ghost",size:"sm",className:"h-7 px-2 text-xs",disabled:I.isPending||(be==null?void 0:be.verdict)==="reproducing",onClick:()=>I.mutate(E),children:[e.jsx(ba,{className:"h-3.5 w-3.5 mr-1"})," Verify & resolve"]})]})]},E.key)};return x.length===0?e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"rounded-md border border-border bg-muted/30 p-3 text-sm flex items-center gap-2",children:[e.jsx(ms,{className:"h-4 w-4 text-emerald-600 shrink-0"}),e.jsxs("span",{className:"min-w-0 break-words",children:["No open pricing issues â every money invariant currently agrees with the backend.",u.length>0&&` ${u.length} audit/retired entr${u.length===1?"y":"ies"} on file.`]})]}),u.length>0&&e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsxs("button",{type:"button",className:"text-xs text-muted-foreground underline",onClick:()=>l(E=>!E),children:[r?"Hide":"Show"," audit & retired entries"]}),e.jsxs(H,{variant:"outline",size:"sm",className:"h-7 px-2 text-xs",disabled:$.isPending,onClick:()=>$.mutate(u),children:[$.isPending?e.jsx(Fe,{className:"h-3.5 w-3.5 mr-1 animate-spin"}):e.jsx(ba,{className:"h-3.5 w-3.5 mr-1"}),"Verify & clear all"]})]}),r&&e.jsx("div",{className:"space-y-2",children:u.slice(0,25).map(U)})]}):e.jsxs("div",{className:"rounded-md border border-amber-500/40 bg-amber-500/5 p-3 space-y-3",children:[e.jsxs("button",{type:"button",onClick:()=>s(E=>!E),className:"w-full flex items-center justify-between gap-2 text-left",children:[e.jsxs("span",{className:"flex items-center gap-2 text-sm font-medium",children:[e.jsx(Xe,{className:"h-4 w-4 text-amber-600 shrink-0"}),e.jsxs("span",{className:"min-w-0 break-words",children:[x.length," open pricing issue(s)",ee>0?` · ${ee} error-level`:"",u.length>0?` · ${u.length} audit/retired`:""]})]}),t?e.jsx(ha,{className:"h-4 w-4 shrink-0"}):e.jsx(fa,{className:"h-4 w-4 shrink-0"})]}),t&&e.jsxs("div",{className:"space-y-3",children:[x.length>0&&e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[e.jsxs("span",{className:"text-[11px] text-muted-foreground",children:[x.filter(E=>m[E.key]).length," of ",x.length," finding(s) expanded"]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(H,{variant:"outline",size:"sm",className:"h-7 px-2 text-xs",onClick:()=>h(E=>{const J={...E};return[...x,...u].forEach(be=>{J[be.key]=!0}),J}),children:"Expand all"}),e.jsxs(H,{variant:"outline",size:"sm",className:"h-7 px-2 text-xs",disabled:$.isPending,onClick:()=>$.mutate(x),title:"Re-checks every finding and closes only the ones that no longer reproduce",children:[$.isPending?e.jsx(Fe,{className:"h-3.5 w-3.5 mr-1 animate-spin"}):e.jsx(ba,{className:"h-3.5 w-3.5 mr-1"}),"Verify & close stale"]}),e.jsx(H,{variant:"outline",size:"sm",className:"h-7 px-2 text-xs",onClick:()=>h({}),children:"Collapse all"})]})]}),e.jsx("div",{className:"space-y-2",children:x.map(U)}),u.length>0&&e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsxs("button",{type:"button",className:"text-xs text-muted-foreground underline",onClick:()=>l(E=>!E),children:[r?"Hide":"Show"," ",u.length," audit & retired entr",u.length===1?"y":"ies"]}),e.jsxs(H,{variant:"outline",size:"sm",className:"h-7 px-2 text-xs",disabled:$.isPending,onClick:()=>$.mutate(u),children:[$.isPending?e.jsx(Fe,{className:"h-3.5 w-3.5 mr-1 animate-spin"}):e.jsx(ba,{className:"h-3.5 w-3.5 mr-1"}),"Verify & clear all"]})]}),r&&e.jsx("div",{className:"space-y-2",children:u.slice(0,25).map(U)})]})]})]})}const Yc=5;function kt(a,t=Date.now()){return(a.status||"verified")!=="pending"?!1:t-ne
11w Date(a.created_at).getTime()>Yc*6e4}function ps(a){var s,r;if(a.status==="rejected_pre_write"||((s=a.verification_result)==null?void 0:s.classification)==="rejected_pre_write")return!0;const t=(r=a.verification_result)==null?void 0:r.write_errors;return(a.fields_changed_count??0)===0&&Array.isArray(t)&&t.length>0}function Xc(a){var s;const t=(s=a.verification_result)==null?void 0:s.write_errors;return Array.isArray(t)?t.map(r=>String(r)):[]}function Qn(a,t=Date.now()){const s=a.status||"verified";return ps(a)?!1:s==="failed_verification"||s==="partially_applied"?!0:kt(a,t)}function Zc(a,t=Date.now()){return a.filter(s=>Qn(s,t))}function wl(a,t,s=Date.now()){var u;const r=a.status||"verified",l=t||[];if(ps(a)){const N=Xc(a);return[{id:"intent",label:"Change requested",state:"done",detail:"Request recorded before any write",at:a.created_at},{id:"write",label:"Write refused by guard",state:"done",detail:N.length?N.join(" · "):"A validation guard refused the write",at:a.created_at},{id:"verify",label:"Nothing to verify",state:"done",detail:"No field was written, so no price changed and nothing needs restoring",at:a.created_at}]}const o=l.length,i=l.filter(N=>N.persisted_value!==null&&N.persisted_value!==void 0).length,d=l.filter(N=>N.verified===!1).length,_=a.fields_changed_count??o,n={id:"intent",label:"Intent recorded",state:o>0||_>0?"done":"unknown",detail:o>0?`${o} field(s) recorded before any write`:"No ledger rows recorded for this run",at:a.created_at};let c,m;o===0?(c="unknown",m="Nothing to write"):i===0?(c=r==="pending"?kt(a,s)?"failed":"active":"failed",m=r==="pending"&&!kt(a,s)?"Write in flight":"No field was ever read back â the write may not have landed"):i<o?(c="failed",m=`Only ${i} of ${o} field(s) were read back â write interrupted`):(c="done",m=`All ${o} field(s) written`);const h={id:"write",label:"Write attempted",state:c,detail:m,at:null};let j,b;r==="verified"?(j="done",b=`Read-back matched on ${o-d} field(s)`):r==="reverted"?(j="done",b="Verified, then intentionally reverted"):r==="failed_verification"||r==="partially_applied"?(j="failed",b=d?`${d} field(s) did not match after the write`:"Verification failed"):kt(a,s)?(j="failed",b="Never reached read-back verification"):(j="active",b="Waiting on read-back verification");const x={id:"verify",label:"Read-back verified",state:j,detail:b,at:a.verified_at??((u=a.verification_result)==null?void 0:u.reverified_at)??null};return[n,h,x]}function ed(a,t=Date.now()){const s=a.status||"verified";return ps(a)?"Rejected before any write â no money changed":s==="failed_verification"?"Failed read-back verification â fields were restored to their old values":s==="partially_applied"?"Partially applied â some fields landed and some did not":kt(a,t)?`Interrupted ${Math.floor((t-new Date(a.created_at).getTime())/6e4)} minute(s) ago and never completed verification`:"Write in flight"}const Fa=a=>a==null?"â":`$${Number(a).toLocaleString(void 0,{maximumFractionDigits:2})}`,yl={verified:{label:"Verified in backend",className:"bg-emerald-500/10 text-emerald-700 dark:text-emerald-400 border-emerald-500/30"},pending:{label:"Pending â write in flight",className:"bg-amber-500/10 text-amber-700 dark:text-amber-400 border-amber-500/30"},failed_verification:{label:"Failed verification â rolled back",className:"bg-destructive/10 text-destructive border-destructive/30"},partially_applied:{label:"Partially applied",className:"bg-destructive/10 text-destructive border-destructive/30"},reverted:{label:"Reverted",className:"bg-muted text-muted-foreground border-border"},rejected_pre_write:{label:"Refused before any write â nothing changed",className:"bg-muted text-muted-foreground border-border"}},ad={done:e.jsx(ba,{className:"h-3.5 w-3.5 text-emerald-600"}),active:e.jsx(Fe,{className:"h-3.5 w-3.5 animate-spin text-amber-600"}),failed:e.jsx(ui,{className:"h-3.5 w-3.5 text-destructive"}),unknown:e.jsx(_r,{className:"h-3.5 w-3.5 text-muted-foreground"})};function jl({phases:a}){return e.jsx("ol",{className:"space-y-1.5",children:a.map(t=>e.jsxs("li",{className:"flex items-start gap-2 text-xs",children:[e.jsx("span",{className:"mt-0.5 shrink-0",children:ad[t.state]}),e.jsxs("span",{children:[e.jsx("span",{className:"font-medium",children:t.label}),t.at?e.jsxs("span",{className:"text-muted-foreground",children:[" · ",new Date(t.at).toLocaleStr
11ing()]}):null,e.jsx("span",{className:`block ${t.state==="failed"?"text-destructive":"text-muted-foreground"}`,children:t.detail})]})]},t.id))})}const Jn="catalog_price_history_open_runs_v1",td=()=>{try{const a=localStorage.getItem(Jn),t=a?JSON.parse(a):[];return new Set(Array.isArray(t)?t.map(String):[])}catch{return new Set}};function Yn(){var Se,re,$e;const[a,t]=p.useState(td),s=g=>t(S=>{const R=typeof g=="function"?g(S):g;try{localStorage.setItem(Jn,JSON.stringify(Array.from(R)))}catch{}return R}),[r,l]=p.useState(!1),[o,i]=p.useState(null),[d,_]=p.useState(""),[n,c]=p.useState({}),m=$a(),h=g=>s(S=>{const R=new Set(S);return R.has(g)?R.delete(g):R.add(g),R}),{data:j,isLoading:b}=Ke({queryKey:["catalog-price-change-runs"],queryFn:async()=>{const{data:g,error:S}=await ge.from("catalog_price_change_runs").select("*").order("created_at",{ascending:!1}).limit(100);if(S)throw S;return g||[]}}),x=Array.from(a).sort(),{data:u,isLoading:N}=Ke({queryKey:["catalog-price-change-items",x.join(",")],enabled:x.length>0,queryFn:async()=>{const{data:g,error:S}=await ge.from("catalog_price_change_items").select("*").in("run_id",x).order("created_at");if(S)throw S;const R={};return(g||[]).forEach(v=>{var G;(R[G=v.run_id]||(R[G]=[])).push(v)}),R}}),{data:y,isFetching:L,refetch:I}=Ke({queryKey:["catalog-price-history-sweep"],staleTime:6e4,queryFn:async()=>{const{data:g,error:S}=await ge.functions.invoke("audit-catalog-price-history",{body:{}});if(S)throw S;if(g!=null&&g.error)throw new Error(g.error);return g}}),{data:$}=Ke({queryKey:["catalog-price-audit-sweeps","cron"],staleTime:6e4,queryFn:async()=>{const{data:g,error:S}=await ge.from("catalog_price_audit_sweeps").select("swept_at, healthy, drift_count, stuck_count, failed_count, triggered_by").eq("triggered_by","cron").order("swept_at",{ascending:!1}).limit(1).maybeSingle();if(S)throw S;return g??null}}),ee=(j||[]).filter(g=>Qn(g)).map(g=>g.id),{data:U}=Ke({queryKey:["catalog-price-change-items","attention",ee.join(",")],enabled:ee.length>0,queryFn:async()=>{const{data:g,error:S}=await ge.from("catalog_price_change_items").select("id, run_id, persisted_value, verified, new_value").in("run_id",ee);if(S)throw S;const R={};return(g||[]).forEach(v=>{var G;(R[G=v.run_id]||(R[G]=[])).push(v)}),R}}),E=(j||[]).map(g=>g.id),{data:J}=Ke({queryKey:["pricing-wiring-verdicts","by-run",E.join(",")],enabled:E.length>0,queryFn:async()=>{const{data:g,error:S}=await ge.from("pricing_wiring_verdicts").select("run_id, state, summary, checks_passed, checks_total, reverted, created_at").in("run_id",E).order("created_at",{ascending:!1});if(S)throw S;const R={};return(g||[]).forEach(v=>{v.run_id&&(R[v.run_id]||(R[v.run_id]=v))}),R}}),be=Ta({mutationFn:async g=>qa({run_id:g}),onSuccess:g=>{var R;const S=(R=g==null?void 0:g.verdict)==null?void 0:R.state;S==="pass"?le.success("Wired everywhere â all checks pass"):S?le.error(`Wiring check ${S}`,{description:g.verdict.summary||void 0}):le.error("Re-check returned no verdict"),m.invalidateQueries({queryKey:["pricing-wiring-verdicts"]})},onError:g=>le.error((g==null?void 0:g.message)||"Wiring re-check failed")}),F=Ta({mutationFn:async({runId:g,why:S})=>{const{data:R,error:v}=await ge.functions.invoke("revert-catalog-price-change",{body:{run_id:g,reason:S}});if(v)throw v;if(!(R!=null&&R.success))throw new Error((R==null?void 0:R.error)||"Revert failed backend verification");return R},onSuccess:g=>{le.success(`Restored ${g.fields_restored} field(s)`,{description:`Recorded as revert run and verified in the backend. ${g.analyses_marked_stale} project(s) marked stale.`}),i(null),_(""),m.invalidateQueries({queryKey:["catalog-price-change-runs"]}),m.invalidateQueries({queryKey:["catalog-price-change-items"]}),m.invalidateQueries({queryKey:["pricing-catalog"]}),I()},onError:g=>le.error((g==null?void 0:g.message)||"Revert failed")}),se=Ta({mutationFn:async g=>{const{data:S,error:R}=await ge.functions.invoke("audit-catalog-price-history",{body:{run_id:g}});if(R)throw R;if(S!=null&&S.error)throw new Error(S.error);return S},onSuccess:g=>{c(S=>({...S,[g.run_id]:g})),g.healthy?le.success(`Run verified â ${g.fields_matching}/${g.fields_checked} field(s) match the backend`):le.error(`${g.mismatches.length} field(s) do not match the backend`,{description:"The run is marked failed verification and cannot be reverted until it matches."}
11),m.invalidateQueries({queryKey:["catalog-price-change-runs"]}),m.invalidateQueries({queryKey:["catalog-price-change-items"]})},onError:g=>le.error((g==null?void 0:g.message)||"Re-verify failed")});if(b)return e.jsxs("div",{className:"py-10 text-center text-sm text-muted-foreground",children:[e.jsx(Fe,{className:"h-4 w-4 animate-spin inline mr-2"})," Loading change historyâ¦"]});const V=y==null?void 0:y.healthy,z=Zc(j||[]);return e.jsxs("div",{className:"space-y-3",children:[e.jsx(Jc,{}),e.jsx("div",{className:"flex justify-end",children:e.jsx(Tt,{view:"Change history",scope:"global",filterSummary:`${(j||[]).length} most recent run(s)`,filenameBase:"pricing-change-history",canImport:!1,buildSheets:()=>[Un("Change history",(j||[]).map(g=>({run_id:g.id,change_kind:g.change_kind??"",status:g.status??"",reason:g.reason??"",fields_changed:g.fields_changed??0,items_affected:g.items_affected??0,analyses_marked_stale:g.analyses_marked_stale??0,created_at:g.created_at??""})),["run_id","change_kind","status","reason","fields_changed","items_affected","analyses_marked_stale","created_at"])],liveRows:()=>new Map})}),e.jsxs("div",{className:`rounded-md border p-3 flex items-start justify-between gap-3 ${y&&!V?"border-destructive/40 bg-destructive/5":"border-border bg-muted/30"}`,children:[e.jsxs("div",{className:"flex items-start gap-3",children:[L?e.jsx(Fe,{className:"h-4 w-4 animate-spin mt-0.5"}):V?e.jsx(ms,{className:"h-4 w-4 text-emerald-600 mt-0.5"}):e.jsx(Xe,{className:"h-4 w-4 text-destructive mt-0.5"}),e.jsxs("div",{className:"text-sm",children:[L&&e.jsx("span",{children:"Re-verifying every recorded change against the backendâ¦"}),!L&&y&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"font-medium",children:V?`All ${y.fields_matching} live change(s) still match the backend`:`${y.drift.length} drifted · ${y.stuck.length} interrupted · ${y.failed.length} failed verification`}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:[(((Se=y.rejected)==null?void 0:Se.length)??0)>0&&`${y.rejected.length} request(s) refused by a guard before any write â no money changed. `,(((re=y.unreadable)==null?void 0:re.length)??0)>0&&`${y.unreadable.length} recorded field name(s) cannot be read back (audit defect, not drift).`]}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:[y.runs_reviewed," run(s) reviewed · ",y.fields_checked," field(s) re-read ·"," ",new Date(y.swept_at).toLocaleString()]})]}),!L&&!y&&e.jsx("span",{className:"text-muted-foreground",children:"Backend verification not run yet."}),e.jsx("div",{className:`text-xs mt-1 ${qn($)==="fresh"&&($!=null&&$.healthy)?"text-muted-foreground":"text-amber-700 dark:text-amber-400"}`,children:Oc($)})]})]}),e.jsx(H,{variant:"outline",size:"sm",onClick:()=>I(),disabled:L,children:"Re-verify all"})]}),y&&!V&&e.jsxs("div",{className:"rounded-md border border-destructive/30",children:[e.jsxs("button",{type:"button",className:"w-full flex items-center gap-2 p-3 text-left text-xs font-medium hover:bg-muted/40",onClick:()=>l(g=>!g),children:[r?e.jsx(ha,{className:"h-3.5 w-3.5"}):e.jsx(fa,{className:"h-3.5 w-3.5"}),y.drift.length," drifted field(s) · ",y.stuck.length," interrupted run(s)"]}),r&&e.jsxs("div",{className:"p-3 pt-0 space-y-2",children:[y.drift.slice(0,25).map((g,S)=>e.jsxs("div",{className:"text-xs",children:[e.jsx("span",{className:"font-mono",children:g.item_code})," · ",g.target_table,".",String(g.field).replace(/_/g," ")," â expected"," ",e.jsx("span",{className:"font-semibold",children:Fa(g.expected)}),", backend holds"," ",e.jsx("span",{className:"font-semibold text-destructive",children:Fa(g.actual)})]},`d${S}`)),y.stuck.map((g,S)=>e.jsxs("div",{className:"text-xs flex items-center gap-1",children:[e.jsx(_r,{className:"h-3 w-3"})," Interrupted run ",String(g.run_id).slice(0,8)," from"," ",new Date(g.created_at).toLocaleString()," never completed verification"]},`s${S}`)),(y.unreadable??[]).slice(0,25).map((g,S)=>e.jsxs("div",{className:"text-xs text-muted-foreground",children:[e.jsx("span",{className:"font-mono",children:g.item_code})," · ",g.target_table,".",String(g.field)," â this recorded field name does not address a readable column, so no price claim can be made from it. Audit record defect, not drift."]},`u${S}`))]})]}),((($e=y==null?void 0:y.rejected)==null?void 0:$e.length)??0)>0&&e.jsxs("div",{className:"rounded-md border border-border bg-muted/30 p-3 space-y-2",children:[e.jsxs("div",{className:"text-sm font-medium",children:[y.rejected.length," request(s) refused before any write"]}),e.jsx("div",{className:"text-xs text-muted-foreground",children:"A validation guard stopped these requests, so no field was written and no price changed. There is nothing to restore."}),y.rejected.slice(0,10).map((g,S)=>e.jsxs("div",{className:"text-xs",children:["Run ",String(g.run_id).slice(0,8)," · ",new Date(g.created_at).toLocaleStr
11ing()," â"," ",(g.rejected_because||[]).map(R=>String(R)).join(" · ")||"refused by guard"]},`rej${S}`))]}),z.length>0&&e.jsxs("div",{className:"rounded-md border border-amber-500/40 bg-amber-500/5 p-3 space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm font-medium",children:[e.jsx(Xe,{className:"h-4 w-4 text-amber-600"}),z.length," run(s) need attention"]}),z.map(g=>{const S=n[g.id],R=U==null?void 0:U[g.id];return e.jsxs("div",{className:"rounded border bg-background p-3 space-y-2",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{className:"text-xs",children:[e.jsxs("div",{className:"font-medium",children:["Run ",String(g.id).slice(0,8)," · ",new Date(g.created_at).toLocaleString()]}),e.jsx("div",{className:"text-muted-foreground",children:ed(g)})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(H,{variant:"outline",size:"sm",className:"h-7 px-2",disabled:se.isPending,onClick:()=>se.mutate(g.id),children:[e.jsx(Ga,{className:`h-3.5 w-3.5 mr-1 ${se.isPending?"animate-spin":""}`})," Re-verify"]}),e.jsxs(H,{variant:"ghost",size:"sm",className:"h-7 px-2",onClick:()=>{i(g),_("")},children:[e.jsx(ot,{className:"h-3.5 w-3.5 mr-1"})," Restore old values"]})]})]}),e.jsx(jl,{phases:wl(g,R)}),S&&e.jsxs("div",{className:`text-xs ${S.healthy?"text-emerald-700 dark:text-emerald-400":"text-destructive"}`,children:["Re-verified ",new Date(S.reverified_at).toLocaleString()," â ",S.fields_matching,"/",S.fields_checked," field(s) match · status ",S.previous_status," â ",S.status]})]},`att-${g.id}`)})]}),j!=null&&j.length?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("div",{className:"text-xs text-muted-foreground",children:[a.size," of ",j.length," run(s) expanded"]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(H,{variant:"outline",size:"sm",className:"h-7 px-2",onClick:()=>s(new Set(j.map(g=>g.id))),children:"Expand all"}),e.jsx(H,{variant:"outline",size:"sm",className:"h-7 px-2",onClick:()=>s(new Set),children:"Collapse all"})]})]}),j.map(g=>{var oe,A,de;const S=ps(g)?"rejected_pre_write":g.status||"verified",R=yl[S]??yl.verified,v=S==="verified"&&!g.reverts_run_id&&!g.reverted_by_run_id,G=a.has(g.id),te=u==null?void 0:u[g.id];return e.jsxs("div",{className:"border rounded-md",children:[e.jsxs("button",{type:"button",className:"w-full flex items-center justify-between gap-3 p-3 text-left hover:bg-muted/50",onClick:()=>
11h(g.id),children:[e.jsxs("div",{className:"flex items-center gap-3",children:[G?e.jsx(ha,{className:"h-4 w-4"}):e.jsx(fa,{className:"h-4 w-4"}),e.jsxs("div",{children:[e.jsxs("div",{className:"text-sm font-medium",children:[g.items_affected_count," item(s) · ",g.fields_changed_count," field(s)",g.notes?` â ${g.notes}`:""]}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:[new Date(g.created_at).toLocaleString()," · ",((oe=g.tables_touched)==null?void 0:oe.length)||0," table(s)",g.analyses_marked_stale?` · ${g.analyses_marked_stale} project(s) marked stale`:"",g.reverts_run_id?" · revert of an earlier run":""]})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(ie,{variant:"outline",className:`text-[10px] ${R.className}`,children:[S==="verified"&&e.jsx(ba,{className:"h-3 w-3 mr-1 inline"}),R.label]}),(()=>{const O=J==null?void 0:J[g.id],he=Yt(O),Ie=hs(he);return e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsxs(ie,{variant:"outline",className:`text-[10px] ${Ie.chipClass}`,title:O?`${Ie.hint}${O.summary?` â ${O.summary}`:""}`:"No final wiring check has run for this change yet.",children:[Ie.label,O!=null&&O.checks_total?` ${O.checks_passed??0}/${O.checks_total}`:""]}),e.jsx(H,{variant:"ghost",size:"sm",className:"h-6 px-1.5 text-[10px]",disabled:be.isPending,onClick:Ge=>{Ge.stopPropagation(),be.mutate(g.id)},children:be.isPending?e.jsx(Fe,{className:"h-3 w-3 animate-spin"}):"Re-check"})]})})(),e.jsx(ie,{variant:g.scope==="global"?"default":"secondary",className:"text-[10px] uppercase",children:g.scope}),g.kind&&g.kind!=="catalog"&&e.jsx(ie,{variant:"outline",className:"text-[10px] uppercase",children:g.kind==="area_band"?"area band":g.kind}),e.jsxs("span",{className:`text-sm ${Number(g.total_delta)>=0?"text-primary":"text-destructive"}`,children:[Number(g.total_delta)>=0?"+":"",Fa(g.total_delta)]}),e.jsxs(H,{variant:"outline",size:"sm",className:"h-7 px-2",disabled:se.isPending,title:"Re-read this run's fields from the backend and settle its status",onClick:O=>{O.stopPropagation(),se.mutate(g.id)},children:[e.jsx(Ga,{className:`h-3.5 w-3.5 mr-1 ${se.isPending&&se.variables===g.id?"animate-spin":""}`}),"Re-verify"]}),v&&e.jsxs(H,{variant:"ghost",size:"sm",className:"h-7 px-2",onClick:O=>{O.stopPropagation(),i(g),_("")},children:[e.jsx(ot,{className:"h-3.5 w-3.5 mr-1"})," Revert"]})]})]}),G&&e.jsxs("div",{className:"border-t",children:[e.jsxs("div",{className:"p-3 border-b",children:[e.jsx(jl,{phases:wl(g,te)}),n[g.id]&&e.jsxs("div",{className:`text-xs mt-2 ${n[g.id].healthy?"text-emerald-700 dark:text-emerald-400":"text-destructive"}`,children:["Re-verified ",new Date(n[g.id].reverified_at).toLocaleString()," â"," ",n[g.id].fields_matching,"/",n[g.id].fields_checked," field(s) match · status ",n[g.id].previous_status," â ",n[g.id].status,n[g.id].mismatches.slice(0,10).map((O,he)=>e.jsxs("div",{children:[e.jsx("span",{className:"font-mono",children:O.item_code})," · ",String(O.field).replace(/_/g," ")," â recorded ",Fa(O.expected),", backend holds ",Fa(O.actual)]},`rv${he}`))]})]}),(de=(A=g.verification_result)==null?void 0:A.mismatches)!=null&&de.length?e.jsxs("div",{className:"p-3 text-xs text-destructive border-b",children:["Backend verification found ",g.verification_result.mismatches.length," mismatch(es); the affected fields were restored to their previous values."]}):null,N?e.jsxs("div",{className:"p-4 text-sm text-muted-foreground",children:[e.jsx(Fe,{className:"h-4 w-4 animate-spin inline mr-2"})," Loading rowsâ¦"]}):e.jsx(Ma,{className:"max-h-[320px]",children:e.jsxs(Ze,{children:[e.jsx(ea,{children:e.jsxs(Le,{children:[e.jsx(Z,{children:"Item"}),e.jsx(Z,{children:"Table"}),e.jsx(Z,{children:"Field"}),e.jsx(Z,{className:"text-right",children:"Old"}),e.jsx(Z,{className:"text-right",children:"New"}),e.jsx(Z,{className:"text-right",children:"In backend"})]})}),e.jsx(aa,{children:(te||[]).map(O=>e.jsxs(Le,{className:O.verified===!1?"bg-destructive/5":"",children:[e.jsxs(Q,{className:"text-xs",children:[e.jsx("div",{className:"font-medium",children:O.item_name||O.item_code}),e.jsxs("div",{className:"text-muted-foreground font-mono",children:[O.item_code,O.card_code?` · ${O.card_code}`:""]})]}),e.jsx(Q,{className:"text-xs font-mono",children:O.target_table}),e.jsx(Q,{className:"text-xs",children:String(O.field).replace(/_/g," ")}),e.jsx(Q,{className:"text-right text-xs",children:Fa(O.old_value)}),e.jsx(Q,{className:"text-right text-xs font-semibold",children:Fa(O.new_value)}),e.jsxs(Q,{className:`text-right text-xs ${O.verified===!1?"text-destructive font-semibold":"text-muted-foreground"}`,children:[O.persisted_value===null||O.persisted_value===void 0?"â":Fa(O.persisted_value),O.verified===!1?" â":O.verified?" â":""]})]},O.id))})]})})]})]},g.id)})]}):e.jsx("p",{className:"text-sm text-muted-foreground py-6",children:"No catalog price changes recorded yet."}),e.jsx("div",{className:"flex justify-end",children:e.jsx(H,{variant:"ghost",size:"sm",disabled:!0,children:"Showing the 100 most recent runs"})}),e.jsx(Kl,{open:!!o,onOpenChange:g=>!g&&i(null),children:e.jsxs(Wl,{children:[e.jsxs(Gl,{children:[e.jsx(Hl,{children:"Restore the previous prices?"}),e.jsx(Ql,{children:"Every field in this run goes back to the value recorded before it. The restore is written as its own verified, audited run â existing projects keep their totals and are marked stale."})]}),e.jsx(ct,{placeholder:"Reason for restoring these prices (required)",value:d,onChange:g=>_(g.target.value),rows:3}),e.jsxs(Jl,{children:[e.jsx(Yl,{children:"Cancel"}),e.jsx(Xl,{disabled:d.trim().length<3||F.isPending,onClick:g=>{g.preventDefault(),o&&F.mutate({runId:o.id,why:d.trim()})},children:F.isPending?"Restoringâ¦":"Restore previous prices"})]})]})})]})}const At=[{table:"base_pricing",label:"Base Pricing (legacy)",description:"Per-unit labor & material for legacy catalog items.",nameColumn:"item_name",categoryColumn:"category",tiered:!1,columns:[{
11column:"labor_cost",label:"Labor"},{column:"base_rate",label:"Material"},{column:"demo_cost",label:"Demo"},{column:"additional_cost",label:"Additional"}]},{table:"finish_allowances",label:"Finish Allowances",description:"Per-tier finish allowance amounts (material-equivalent).",nameColumn:"item_name",tiered:!0,columns:[{column:"entry_price",label:"Entry",tier:"entry"},{column:"good_price",label:"Good",tier:"good"},{column:"better_price",label:"Better",tier:"better"},{column:"best_price",label:"Best",tier:"best"}]}];function sd(a){return At.some(t=>t.table===a)}function vr(a){return At.find(t=>t.table===a)}function rd(a){var t;return((t=vr(a))==null?void 0:t.columns.map(s=>s.column))??[]}const La=1e3;function vl(a){if(a==null||a==="")return null;const t=Number(a);return Number.isFinite(t)?t:null}async function ld(a){const t=[];for(let s=0;;s+=La){const{data:r,error:l}=await ge.from(a).select("*").range(s,s+La-1);if(l)break;const o=r||[];if(t.push(...o),o.length<La)break}return t}async function nd(){const a=new Map;for(let t=0;;t+=La){const{data:s,error:r}=await ge.from("pricing_item_usage").select("item_code, all_time_projects, live_projects, card_codes, last_used_at, first_used_at").range(t,t+La-1);if(r)break;const l=s||[];if(l.forEach(o=>{a.set(o.item_code,{all_time_projects:o.all_time_projects??0,live_projects:o.live_projects??0,card_codes:o.card_codes||[],last_used_at:o.last_used_at??null,first_used_at:o.first_used_at??null})}),l.length<La)break}return a}
11async function id(a){const t=new Map;for(let s=0;;s+=La){const{data:r,error:l}=await ge.from("company_pricing_overrides").select("item_code, source_table, override_data").eq("company_id",a).eq("is_active",!0).range(s,s+La-1);if(l)break;const o=r||[];if(o.forEach(i=>{t.set(`${i.source_table}:${i.item_code}`,i.override_data||{})}),o.length<La)break}return t}function od(a,t,s,r,l){const o=rd(a.table);return t.map(i=>{const d={};o.forEach(m=>d[m]=vl(i[m]));const _=r==="company"?s.get(`${a.table}:${i.item_code}`):void 0,n={};o.forEach(m=>{n[m]=_&&_[m]!==null&&_[m]!==void 0?vl(_[m]):d[m]});const c=a.categoryColumn&&i[a.categoryColumn]||a.label;return{key:`${a.table}:${i.item_code}`,source_table:a.table,row_id:i.id,item_code:i.item_code,item_name:i[a.nameColumn]||i.item_code,category_display:xr(c),table_label:a.label,editable_columns:o,values:n,global_values:d,source:_&&Object.keys(_).length?"company":"global",updated_at:i.updated_at||null,is_active:i.is_active===null||i.is_active===void 0?!0:!!i.is_active,usage:l.get(i.item_code)??null}})}function cd(a,t,s){const r=Ke({queryKey:["legacy-pricing-catalog",a,t],queryFn:async()=>{const[i,d]=await Promise.all([a==="company"&&t?id(t):Promise.resolve(new Map),nd()]);return(await Promise.all(At.map(async n=>{const c=await ld(n.table);return od(n,c,i,a,d)}))).flat()},staleTime:3e4}),l=s.trim().toLowerCase(),o=(r.data||[]).filter(i=>l?`${i.item_code} ${i.item_name} ${i.category_display}`.toLowerCase().includes(l):!0);return{...r,items:o,universe:r.data||[]}}function xs({className:a}){return e.jsxs(ss,{children:[e.jsx(rs,{asChild:!0,children:e.jsxs(H,{variant:"ghost",size:"sm",className:Tr("h-7 gap-1 text-xs text-muted-foreground",a),children:[e.jsx(ms,{className:"h-3.5 w-3.5"})," Wiring flags"]})}),e.jsxs(ls,{align:"end",className:"w-80 text-xs",children:[e.jsx("p",{className:"font-semibold text-sm mb-2",children:"What the wiring flag means"}),e.jsx("ul",{className:"space-y-2",children:wn.map(t=>{const s=hs(t);return e.jsxs("li",{className:"flex items-start gap-2",children:[e.jsx("span",{className:Tr("mt-0.5 rounded border px-1.5 py-0 text-[10px] whitespace-nowrap",s.chipClass),children:s.label}),e.jsx("span",{className:"text-muted-foreground leading-snug",children:s.hint})]},t)})}),e.jsx("p",{className:"text-muted-foreground mt-3 leading-snug",children:"Every audited price write runs 11 checks â money read-back, scope, card registration, tier ladder, allowance shape, reader emission, card and grand-total parity, staleness, frozen totals and the audit trail. A failure reverts the change."})]})]})}const dd=a=>a==null?"â":`$${Number(a).toLocaleString(void 0,{maximumFractionDigits:2})}`,Os=a=>{var t;return(((t=a.usage)==null?void 0:t.all_time_projects)??0)>0},at="sticky top-0 z-20 h-9 px-3 bg-card text-primary text-[11px] font-semibold shadow-[0_1px_0_hsl(var(--border))]",Nl="bg-primary/[0.04]",md=a=>a.replace(/Material/i,"Matl").replace(/Additional/i,"Add'l").replace(/Demolition/i,"Demo").replace(/\s*Cost$/i,"").replace(/\s*Rate$/i,""),ud=a=>a.usage?{allTimeProjects:a.usage.all_time_projects,liveProjects:a.usage.live_projects,lastUsedAt:a.usage.last_used_at,cardCodes:a.usage.card_codes}:null,hd={base_pricing:"Read by the attic-ladder line-item reader only; every other card now prices from the per-card catalog.",finish_allowances:"Read by the millwork reader, project inflation and the grand-total roll-up."};function _d({catalogCodes:a}={}){var T,ce,X;const{isSuperAdmin:t,isAdmin:s}=ns(),r=$a(),[l,o]=p.useState(t?"global":"company"),[i,d]=p.useState(null),[_,n]=p.useState(!1),{data:c,isSuccess:m}=Rt(!0),[h,j]=p.useState(At[0].table),[b,x]=p.useState(""),[u,N]=p.useState([]),[y,L]=p.useState("name"),[I,$]=p.useState({}),[ee,U]=p.useState(""),[E,J]=p.useState(!1),[be,F]=p.useState(!1),[se,V]=p.useState(!1),[z,Se]=p.useState(!1),[re,$e]=p.useState(null),[g,S]=p.useState(""),{data:R}=Ke({queryKey:["catalog-my-company"],queryFn:async()=>{const{data:B}=await ge.auth.getUser();if(!(B!=null&&B.user))return null;const{data:f}=await ge.rpc("get_company_id",{uid:B.user.id});return f||null}}),{items:v,universe:G,isLoading:te,refetch:oe}=cd(l,R??null,b),A=vr(h),de=p.useCallback(B=>!!(a!=null&&a.has(B)),[a]),O=p.useMemo(()=>v.filter(B=>B.source_table===h),[v,h]),he=p.useMemo(()=>O.filter(B=>de(B.item_code)).length,[O,de]),Ie=p.useMemo(()=>O.filter(B=>B.is_active&&!Os(B)).length,[O]),Ge=p.useMemo(()=>O.filter(B=>!B.is_active).length,[O]),Oe=p.useMemo(()=>O.filter(B=>{var f;return B.is_active&&!Os(B)&&(((f=B.usage)==null?void 0:f.live_projects)??0)===0}),[O]),k=p.useMemo(()=>{const B=new Map;return G.filter(f=>
11f.source_table===h).forEach(f=>{const q=B.get(f.item_code)||{label:f.item_name||f.item_code,count:0};q.count+=1,B.set(f.item_code,q)}),Array.from(B.entries()).map(([f,q])=>({value:f,label:q.label,count:q.count,description:f})).sort((f,q)=>f.label.localeCompare(q.label))},[G,h]),w=p.useMemo(()=>new Set(u),[u]),P=p.useMemo(()=>{const B=O.filter(K=>w.size?w.has(K.item_code):K.is_active?be||Os(K):se),f=K=>{var _e;return(_e=K.usage)!=null&&_e.last_used_at?Date.parse(K.usage.last_used_at):-1/0},q=[...B];return y==="recent"?q.sort((K,_e)=>f(_e)-f(K)):y==="most_used"?q.sort((K,_e)=>{var pe,W;return(((pe=_e.usage)==null?void 0:pe.all_time_projects)??0)-(((W=K.usage)==null?void 0:W.all_time_projects)??0)}):q.sort((K,_e)=>K.item_name.localeCompare(_e.item_name)),q},[O,be,se,y,w]),M=p.useMemo(()=>{const B=new Map;return G.forEach(f=>B.set(f.key,f)),B},[G]),D=Object.values(I).reduce((B,f)=>B+Object.keys(f).length,0),fe=(B,f,q)=>{$(K=>{const _e={...K},pe={..._e[B.key]||{}};if(q.trim()==="")delete pe[f];else{const W=Number(q);if(!Number.isFinite(W)||W<0)return K;W===(B.values[f]??null)?delete pe[f]:pe[f]=W}return Object.keys(pe).length?_e[B.key]=pe:delete _e[B.key],_e})},ve=async()=>{var B;J(!0);try{const f=Object.entries(I).map(([pe,W])=>{const we=M.get(pe);return we?{source_table:we.source_table,global_row_id:we.row_id,item_code:we.item_code,item_name:we.item_name,fields:W}:null}).filter(Boolean),{data:q,error:K}
11=await ge.functions.invoke("apply-catalog-price-update",{body:{kind:"legacy",scope:l,notes:ee||null,changes:f}}),_e=await wa(q,K);if(_e.verdict&&d(_e),K)throw K;if(q!=null&&q.error&&!(q!=null&&q.success))throw new Error(typeof q.error=="string"?q.error:"Update rejected");le.success(`Applied ${q.fields_changed} change${q.fields_changed===1?"":"s"}`,{description:l==="global"?"New prices apply to future projects. Existing projects were marked stale.":`Company overrides saved. ${q.analyses_marked_stale} existing project(s) marked stale.`}),(B=q.errors)!=null&&B.length&&le.warning(`${q.errors.length} change(s) were skipped`,{description:q.errors[0]}),$({}),U(""),await oe(),r.invalidateQueries({queryKey:["catalog-price-change-runs"]})}catch(f){le.error("Could not apply changes",{description:(f==null?void 0:f.message)||"Unexpected error"})}finally{J(!1)}},ue=async()=>{var q;const B=(re==null?void 0:re.targets)??[],f=!!(re!=null&&re.next);if(!(!B.length||!g.trim())){Se(!0);try{const{data:K,error:_e}=await ge.functions.invoke("apply-catalog-price-update",{body:{kind:"activation",scope:l,notes:g.trim(),activation_changes:B.map(W=>({source_table:W.source_table,global_row_id:W.row_id,item_code:W.item_code,item_name:W.item_name,is_active:f}))}}),pe=await wa(K,_e);if(pe.verdict&&d(pe),_e)throw _e;if(K!=null&&K.error&&!(K!=null&&K.success))throw new Error(typeof K.error=="string"?K.error:"Update rejected");le.success(`${B.length} item${B.length===1?"":"s"} ${f?"restored":"retired"}`,{description:"Recorded in the price-change audit trail. Future projects only."}),(q=K==null?void 0:K.errors)!=null&&q.length&&le.warning(`${K.errors.length} row(s) were skipped`,{description:K.errors[0]}),$e(null),S(""),await oe(),r.invalidateQueries({queryKey:["catalog-price-change-runs"]})}catch(K){le.error(`Could not ${f?"restore":"retire"} item(s)`,{description:(K==null?void 0:K.message)||"Unexpected error"})}finally{Se(!1)}}};return!t&&!s?null:e.jsxs("div",{className:"space-y-4",children:[i&&e.jsx(Ua,{verdict:i.verdict,aiNotes:i.aiNotes,reviewerNote:i.reviewerNote,reverted:i.reverted,rechecking:_,onRecheck:i.runId?async()=>{n(!0);const B=await qa({run_id:i.runId,scope:l});d({...i,verdict:B.verdict,aiNotes:B.ai_notes,reviewerNote:B.reviewer_note}),n(!1)}:void 0}),e.jsxs(da,{children:[e.jsx(Ba,{className:"h-4 w-4"}),e.jsx(Sa,{children:"Legacy money tables â a different set of items, not a copy of the catalog"}),e.jsxs(ma,{className:"space-y-1.5",children:[e.jsxs("p",{children:[A==null?void 0:A.description," These rows live in their own table and are mostly ",e.jsx("strong",{children:"different items"})," ","from the per-card catalog: of ",O.length.toLocaleString()," rows here,"," ",he.toLocaleString()," share an item code with the catalog (marked"," ",e.jsx("span",{className:"font-medium",children:"also in catalog"})," below) and the rest exist only here. That is why a row you see here may be missing when you search the Prices view."]}),e.jsx("p",{children:hd[h]}),e.jsx("p",{children:"No company sibling table exists, so company-scope edits are stored as company overrides. Every change is audited and applies to future estimates only."})]})]}),e.jsxs("div",{className:"flex flex-wrap items-end gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Scope"}),e.jsxs(Be,{value:l,onValueChange:B=>{o(B),$({})},children:[e.jsx(Ve,{className:"w-[210px]",children:e.jsx(ze,{})}),e.jsxs(Ue,{children:[t&&e.jsx(me,{value:"global",children:"Global (all companies)"}),e.jsx(me,{value:"company",children:"My company"})]})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Table"}),e.jsxs(Be,{value:h,onValueChange:B=>{j(B),$({}),N([])},children:[e.jsx(Ve,{className:"w-[240px]",children:e.jsx(ze,{})}),e.jsx(Ue,{children:At.map(B=>e.jsx(me,{value:B.table,children:B.label},B.table))})]})]}),e.jsxs("div",{className:"space-y-1 flex-1 min-w-[180px]",children:[e.jsx(xe,{className:"text-xs",children:"Search"}),e.jsx(Pe,{value:b,onChange:B=>x(B.target.value),placeholder:"Item code or name"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Items"}),e.jsx(xa,{label:"Items",allLabel:"All items",width:"w-[200px]",options:k,selected:u,onChange:N})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Sort"}),e.jsxs(Be,{value:y,onValueChange:B=>L(B),children:[e.jsx(Ve,{className:"w-[170px]",children:e.jsx(ze,{})}),e.jsxs(Ue,{children:[e.jsx(me,{value:"name",children:"Item name"}),e.jsx(me,{value:"recent",children:"Recently used"}),e.jsx(me,{value:"most_used",children:"Most used"})]})]})]}),e.jsxs("div",{className:"space-y-1 flex-1 min-w-[240px]",children:[e.jsx(xe,{className:"text-xs",children:"Reason (audit trail)"}),e.jsx(ct,{rows:2,value:ee,onChange:B=>U(B.target.value),placeholder:"Why this change?"})]}),e.jsxs(H,{size:"sm",disabled:D===0||E,onClick:ve,children:[E?e.jsx(Fe,{className:"h-4 w-4 mr-1 animate-spin"}):e.jsx(lt,{className:"h-4 w-4 mr-1"}),"Apply ",D>0?D:""," change",D===1?"":"s"]}),e.jsx(Tt,{view:"Legacy & allowances",scope:l,filterSummary:`table ${h}${b?` · search "${b}"`:""}${u.length?` · ${u.length} item(s)`:""}`,filenameBase:`pricing-legacy-${h}`,buildSheets:()=>[Ac(P,l)],liveRows:()=>Ec(P),importKinds:["legacy"],onImported:async()=>{await oe()}})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-4 text-sm",children:[e.jsxs("label",{className:"flex items-center gap-2",children:[e.jsx(ca,{checked:be,onCheckedChange:B=>F(!!B)}),"Show unused ",Ie>0&&e.jsxs("span",{className:"text-muted-foreground",children:["(",Ie,")"]})]}),e.jsxs("label",{className:"flex items-center gap-2",children:[e.jsx(ca,{checked:se,onCheckedChange:B=>V(!!B)}),"Show retired ",Ge>0&&e.jsxs("span",{className:"text-muted-foreground",children:["(",Ge,")"]})]}),e.jsxs("span",{className:"text-xs text-muted-foreground",children:[P.length," of ",O.length," rows â unused rows (never priced on a project) are hidden by default."]}),Oe.length>0&&e.jsxs(H,{size:"sm",variant:"outline",disabled:z,onClick:()=>{S(""),$e({targets:Oe,next:!1})},children:[e.jsx(tr,{className:"h-3.5 w-3.5 mr-1"}),"Retire all unused (",Oe.length,")"]})]}),te?e.jsxs("div",{className:"py-10 text-center text-sm text-muted-foreground",children:[e.jsx(Fe,{className:"h-4 w-4 animate-spin inline mr-2"})," Loading legacy pricingâ¦"]}):e.jsx(mr,{children:e.jsx("div",{className:"rounded-md border overflow-hidden [&>div]:max-h-[60vh] [&>div]:overflow-auto",children:e.jsxs(Ze,{className:"no-mobile-scroll border-separate border-spacing-0",children:[e.jsx(ea,{children:e.jsxs(Le,{children:[e.jsx(Z,{className:`${at} min-w-[220px]`,children:"Item"}),e.jsx(Z,{className:`${at} w-[120px]`,children:"Category"}),e.jsx(Z,{className:`${at}
11 w-[190px] whitespace-nowrap`,children:"Used by"}),((A==null?void 0:A.columns)||[]).map(B=>e.jsxs(Na,{children:[e.jsx(ka,{asChild:!0,children:e.jsx(Z,{className:`${at} ${Nl} text-right w-[92px]`,children:md(B.label)})}),e.jsx(Ca,{className:"text-xs",children:B.label})]},B.column)),e.jsx(Z,{className:`${at} w-[92px] whitespace-nowrap`,children:e.jsxs("span",{className:"inline-flex items-center gap-1",children:["Wiring ",e.jsx(xs,{className:"px-1"})]})}),e.jsx(Z,{className:`${at} text-right w-[64px]`,children:"Status"})]})}),e.jsxs(aa,{children:[P.map(B=>e.jsxs(Le,{className:`even:bg-muted/25 ${B.is_active?"":"opacity-60"}`,children:[e.jsxs(Q,{className:"py-2 px-3",children:[e.jsx("div",{className:"font-medium text-sm leading-tight",children:B.item_name}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-mono text-[10px] text-muted-foreground",children:B.item_code}),B.source==="company"&&e.jsx(ie,{variant:"secondary",className:"text-[10px]",children:"override"}),de(B.item_code)&&e.jsxs(Na,{children:[e.jsx(ka,{asChild:!0,children:e.jsx(ie,{variant:"outline",className:"text-[10px]",children:"also in catalog"})}),e.jsx(Ca,{className:"max-w-xs text-xs",children:"The same item code exists in the per-card catalog, which is what the live engine prices from. Edit it in the Prices view; this legacy row is only read by the components listed above."})]})]})]}),e.jsx(Q,{className:"py-2 px-3 text-[11px] leading-tight text-muted-foreground",children:B.category_display}),e.jsx(Q,{className:"py-2 px-3",children:e.jsx(Tn,{usage:ud(B)})}),((A==null?void 0:A.columns)||[]).map(f=>{var _e;const q=(_e=I[B.key])==null?void 0:_e[f.column],K=B.values[f.column]??null;return e.jsx(Q,{className:`py-2 px-1.5 text-right ${Nl}`,children:e.jsx(Pe,{type:"number",step:"0.01",disabled:!B.is_active,className:`h-8 w-20 px-1.5 text-right tabular-nums ml-auto ${q!==void 0?"border-primary ring-1 ring-primary":""}`,value:q!==void 0?q:K??"",placeholder:dd(B.global_values[f.column]),onChange:pe=>fe(B,f.column,pe.target.value)})},f.column)}),e.jsx(Q,{className:"py-2 px-2",children:e.jsx(_s,{itemCode:B.item_code,preloaded:(c==null?void 0:c.get(B.item_code))??null,preloadedReady:m})}),e.jsx(Q,{className:"py-2 px-2 text-right whitespace-nowrap",children:e.jsxs(Na,{children:[e.jsx(ka,{asChild:!0,children:e.jsx(H,{size:"sm",variant:"ghost",className:"h-8 w-8 p-0",disabled:z,onClick:()=>{S(""),$e({targets:[B],next:!B.is_active})},children:B.is_active?e.jsx(tr,{className:"h-3.5 w-3.5"}):e.jsx(on,{className:"h-3.5 w-3.5 text-primary"})})}),e.jsx(Ca,{className:"text-xs",children:B.is_active?"Retire this row":"Retired â restore it"})]})})]},B.key)),P.length===0&&e.jsx(Le,{children:e.jsxs(Q,{colSpan:((A==null?void 0:A.columns.length)||0)+5,className:"text-center text-sm text-muted-foreground py-8",children:["No items match",!be&&Ie>0?' â try "Show unused".':"."]})})]})]})})}),e.jsx(Ha,{open:!!re,onOpenChange:B=>{!B&&!z&&$e(null)},children:e.jsxs(Qa,{children:[e.jsxs(Ja,{children:[e.jsxs(Ya,{children:[re!=null&&re.next?"Restore":"Retire"," ",re&&re.targets.length>1?`${re.targets.length} legacy rows`:(T=re==null?void 0:re.targets[0])==null?void 0:T.item_name]}),e.jsx(it,{children:re!=null&&re.next?"The row becomes available to future estimates again.":"Retiring hides the row from pricing readers. Existing projects keep their persisted totals â this applies to future projects only."})]}),re&&re.targets.length===1?e.jsxs("div",{className:"text-xs text-muted-foreground space-y-1",children:[e.jsx("div",{className:"font-mono",children:re.targets[0].item_code}),e.jsxs("div",{children:["Usage: ",((ce=re.targets[0].usage)==null?void 0:ce.all_time_projects)??0," all-time ·"," ",((X=re.targets[0].usage)==null?void 0:X.live_projects)??0," live project(s)"]})]}):e.jsxs("div",{className:"text-xs text-muted-foreground max-h-40 overflow-auto rounded border p-2 space-y-0.5",children:[re==null?void 0:re.targets.slice(0,60).map(B=>e.jsx("div",{className:"font-mono truncate",children:B.item_code},B.key)),((re==null?void 0:re.targets.length)??0)>60&&e.jsxs("div",{children:["+ ",(re.targets.length-60).toLocaleStr
11ing()," moreâ¦"]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Reason (required for the audit trail)"}),e.jsx(ct,{rows:3,value:g,onChange:B=>S(B.target.value),placeholder:re!=null&&re.next?"Item is needed again becauseâ¦":"Unused legacy pricing rowâ¦"})]}),e.jsxs(Xa,{children:[e.jsx(H,{variant:"outline",onClick:()=>$e(null),disabled:z,children:"Cancel"}),e.jsxs(H,{onClick:ue,disabled:z||!g.trim(),children:[z&&e.jsx(Fe,{className:"h-4 w-4 mr-1 animate-spin"}),re!=null&&re.next?"Restore":"Retire",re&&re.targets.length>1?` ${re.targets.length} rows`:""]})]})]})})]})}const pd=[{label:"Base rate",columns:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price"]},{label:"Tier labor rate",columns:qe.map(a=>`${a}_labor_rate`)},{label:"Tier material rate",columns:qe.map(a=>`${a}_material_rate`)},{label:"Allowance labor (per tier)",columns:qe.map(a=>`${a}_allowance_labor`),hint:"Entered separately from material â never split a combined allowance."},{label:"Allowance material (per tier)",columns:qe.map(a=>`${a}_allowance_material`)},{label:"Legacy flat allowance",columns:["labor_allowance","material_allowance"],hint:"Kept aligned with the Good tier for older readers."}],qt=a=>a.replace(/_/g," ").replace("allowance labor","allow. labor").replace("allowance material","allow. material").replace(" rate","").replace(" unit price",""),tt=a=>a==null?"â":`$${Number(a).toLocaleString(void 0,{maximumFractionDigits:2})}`;function xd({item:a,scope:t,open:s,onOpenChange:r,onApplied:l,allItems:o}){var J,be;const i=$a(),[d,_]=p.useState({}),[n,c]=p.useState(""),[m,h]=p.useState(!1),[j,b]=p.useState(null),[x,u]=p.useState(!1);p.useEffect(()=>{s&&a&&(_({}),c(""))},[s,a==null?void 0:a.key]);const N=p.useMemo(()=>a?fn(a):null,[a]),y=p.useMemo(()=>a!=null&&a.side_partner_key&&o?o.find(F=>F.key===a.side_partner_key)??void 0:void 0,[a,o]),L=p.useMemo(()=>{const F=(a==null?void 0:a.same_side_duplicate_keys)??[];return!F.length||!o?[]:o.filter(se=>F.includes(se.key))},[a,o]),I=p.useMemo(()=>a&&N?En(a,N,{partner:y,duplicates:L}):null,[a,N,y,L]),$=(a==null?void 0:a.inert_columns)??[],ee=p.useMemo(()=>a?pd.map(F=>({...F,columns:F.columns.filter(se=>a.editable_columns.includes(se))})).filter(F=>F.columns.length>0):[],[a]),U=p.useMemo(()=>a?Object.entries(d).map(([F,se])=>{if(se.trim()==="")return null;const V=Number(se);if(!Number.isFinite(V)||V<0)return null;const z=a.values[F]??null;return z!==null&&Math.abs(V-z)<1e-4?null:{column:F,oldValue:z,newValue:V}}).filter(Boolean):[],[d,a]),E=async()=>{var F;if(!(!a||!U.length)){h(!0);try{const se={};U.forEach(re=>se[re.column]=re.newValue),b(null);const{data:V,error:z}=await ge.functions.invoke("apply-catalog-price-update",{body:{scope:t,notes:n||null,changes:[{source_table:a.source_table,global_row_id:a.global_row_id,item_code:a.item_code,item_name:a.item_name,card_code:a.card_code,fields:se}]}}),Se=await wa(V,z);if(Se.verdict&&b(Se),z)throw z;if(V!=null&&V.error&&!(V!=null&&V.success))throw new Error(typeof V.error=="string"?V.error:"Update rejected");(F=V==null?void 0:V.errors)!=null&&F.length&&le.warning("Some fields were skipped",{description:V.errors[0]}),le.success(`${a.item_name} updated`,{description:`${(V==null?void 0:V.fields_changed)??U.length} field(s) written · ${(V==null?void 0:V.analyses_marked_stale)??0} existing project(s) flagged to regenerate · audit run ${String((V==null?void 0:V.run_id)??"").slice(0,8)}`}),i.invalidateQueries({queryKey:["pricing-catalog"]}),i.invalidateQueries({queryKey:["catalog-price-change-runs"]}),l==null||l(),(!Se.verdict||Se.verdict.state==="pass")&&r(!1)}catch(se){le.error("Could not update this item",{description:(se==null?void 0:se.message)||"Unexpected error"})}finally{h(!1)}}};return a?e.jsx(Ha,{open:s,onOpenChange:r,children:e.jsxs(Qa,{className:"max-w-4xl max-h-[92vh] flex flex-col",children:[e.jsxs(Ja,{children:[e.jsxs(Ya,{className:"flex items-center gap-2 flex-wrap",children:[a.item_name,e.jsx(ie,{variant:"outline",className:"font-mono text-[10px]",children:a.item_code}),e.jsx(ie,{variant:"secondary",className:"text-[10px]",children:a.trade}),a.side!=="both"&&e.jsx(ie,{variant:"outline",className:"text-[10px] capitalize",children:a.side})]}),e.jsxs(it,{className:"flex items-center gap-1.5",children:[t==="global"?e.jsx(us,{className:"h-3.5 w-3.5"}):e.jsx(is,{className:"h-3.5 w-3.5"}),t==="global"?"Global scope â every company inherits this on new projects.":"C
11ompany scope â only your company; the row is cloned from global if it does not exist yet."," · ",a.card_label,a.card_code?` · ${a.card_code}`:""]})]}),e.jsx(Ma,{className:"flex-1 pr-3",children:e.jsxs("div",{className:"space-y-4",children:[N&&N.findings.length>0&&e.jsxs(da,{children:[e.jsx(Xe,{className:"h-4 w-4"}),e.jsxs(Sa,{className:"flex flex-wrap gap-1.5 items-center",children:["Flagged for attention",N.flags.map(F=>e.jsx("span",{className:`text-[10px] px-1.5 py-0.5 rounded border ${bn[ga[F].tone]}`,children:ga[F].label},F))]}),e.jsx(ma,{children:e.jsx("ul",{className:"list-disc pl-4 space-y-0.5 text-xs",children:N.findings.map((F,se)=>e.jsx("li",{children:F.detail},se))})})]}),I&&e.jsxs("div",{className:"rounded-md border border-primary/25 bg-primary/[0.04] p-3 space-y-1",children:[e.jsx("h4",{className:"text-sm font-semibold",children:I.title}),e.jsx("p",{className:"text-xs text-muted-foreground",children:I.detail}),e.jsxs("p",{className:"text-xs",children:[e.jsx("span",{className:"font-medium",children:"Do this: "}),I.action]})]}),e.jsxs("div",{className:"rounded-md border p-3",children:[e.jsx("h4",{className:"text-sm font-semibold mb-2",children:"Where this item lives"}),e.jsx("dl",{className:"grid gap-x-6 gap-y-1.5 text-xs sm:grid-cols-2 lg:grid-cols-3",children:[["Card",`${a.card_label}${a.card_code?` (${a.card_code})`:""}`],["Trade / category",`${a.trade} · ${a.category_display}`],["Side",a.pair_side&&a.pair_side!=="unknown"?a.pair_side:a.side],["Pricing engine",((J=ua[a.engine])==null?void 0:J.label)??a.engine],["Live reader",a.reader??"no V2 reader"],["Table written",a.target_table],["Source of values",a.source==="company"?"company override":"global template"],["Status",a.is_active?"Active":"Retired (readers skip it)"],["Backend use",`${a.usage_projects} live project${a.usage_projects===1?"":"s"} · ${a.usage_estimate_rows} estimate row${a.usage_estimate_rows===1?"":"s"}`],["Last priced",a.last_used_at?new Date(a.last_used_at).toLocaleDateString():"never recorded"],["Last edited",a.updated_at?new Date(a.updated_at).toLocaleDateString():"unstamped"],["Money shape",[a.finish_sensitive?"finish-sensitive tiers":"flat rate",a.has_tier_allowance?"per-tier allowance":null,a.has_flat_allowance?"legacy flat allowance":null].filter(Boolean).join(" · ")]].map(([F,se])=>e.jsxs("div",{className:"min-w-0",children:[e.jsx("dt",{className:"text-muted-foreground",children:F}),e.jsx("dd",{className:"font-medium break-words",children:se||"â"})]},String(F)))}),$.length>0&&e.jsxs("p",{className:"text-[11px] text-muted-foreground mt-2",children:["Columns this card's reader never consumes (editing them changes nothing):"," ",$.map(qt).join(", "),"."]}),((be=a.provenance)==null?void 0:be.length)>0&&e.jsxs("p",{className:"text-[11px] text-muted-foreground mt-1",children:["Last change source: ",a.provenance.join(" â "),a.ai_generated?" · AI generated â verify before relying on it":""]})]}),y&&e.jsxs("div",{className:"rounded-md border p-3",children:[e.jsxs("h4",{className:"text-sm font-semibold mb-1",children:["Opposite side: ",y.item_name," (",y.pair_side,")"]}),e.jsx("p",{className:"text-[11px] text-muted-foreground mb-2",children:"A legitimate side partner, not a duplicate. Editing this row does not move the other side."}),e.jsx("div",{className:"grid gap-x-6 gap-y-1 text-xs sm:grid-cols-2",children:Array.from(new Set([...a.editable_columns,...y.editable_columns])).filter(F=>Number(a.values[F]??0)!==Number(y.values[F]??0)).map(F=>e.jsxs("div",{className:"flex justify-between gap-2",children:[e.jsx("span",{className:"capitalize text-muted-foreground",children:qt(F)}),e.jsxs("span",{children:[tt(a.values[F])," ",e.jsx("span",{className:"text-muted-foreground",children:"vs"})," ",tt(y.values[F])]})]},F))})]}),L.length>0&&e.jsxs("div",{className:"rounded-md border border-destructive/40 p-3",children:[e.jsx("h4",{className:"text-sm font-semibold mb-1",children:"Same-side duplicates"}),e.jsx("ul",{className:"text-xs space-y-1",children:L.map(F=>e.jsxs("li",{className:"flex justify-between gap-2",children:[e.jsx("span",{className:"font-mono",children:F.item_code}),e.jsxs("span",{className:"text-muted-foreground",children:[F.usage_projects," live project",F.usage_projects===1?"":"s"," ·"," ",F.is_active?"Active":"Retired"]})]},F.key))})]}),ee.map(F=>e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"text-sm font-semibold",children:F.label}),F.hint&&e.jsx("p",{className:"text-xs text-muted-foreground",children:F.hint})]}),e.jsx("div",{className:"grid gap-3 sm:grid-cols-2 lg:grid-cols-4",children:F.columns.map(se=>{const V=a.values[se]??null,z=a.global_values[se]??null,Se=U.some(re=>re.column===se);return e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs capitalize",children:qt(se)}),e.jsx(Pe,{type:"number",min:0,step:"0.01",className:Se?"border-primary ring-1 ring-primary":"",placeholder:V===null?"not set":String(V),value:d[se]??(V===null?"":String(V)),onChange:re=>_($e=>({...$e,[se]:re.target.value}))}),e.jsxs("p",{className:"text-[10px] text-muted-foreground",children:["current ",tt(V),t==="company"&&z!==null&&z!==V?` · global ${tt(z)}`:""]})]},se)})})]},F.label)),U.length>0&&e.jsxs("div",{className:"border rounded-md p-3 space-y-2 bg-muted/40",children:[e.jsxs("h4",{className:"text-sm font-semibold",children:["You are about to change ",U.length," field(s)"]}),e.jsx("ul",{className:"text-xs space-y-1",children:U.map(F=>e.jsxs("li",{className:"flex justify-between gap-2",children:[e.jsx("span",{className:"capitalize",children:qt(F.column)}),e.jsxs("span",{children:[tt(F.oldValue)," â ",e.jsx("span",{className:"font-semibold",children:tt(F.newValue)})]})]},F.column))}),e.jsx("p",{className:"text-[11px] text-muted-foreground",children:"Existing projects keep their frozen totals and are flagged so the estimate can be regenerated deliberately. New projects pick this up immediately."})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Reason (stored
11in the audit trail)"}),e.jsx(ct,{rows:2,value:n,onChange:F=>c(F.target.value),placeholder:"e.g. corrected transposed Good tier â supplier quote 08/2026"})]})]})}),j&&e.jsx(Ua,{verdict:j.verdict,aiNotes:j.aiNotes,reviewerNote:j.reviewerNote,reverted:j.reverted,rechecking:x,onRecheck:j.runId?async()=>{u(!0);const F=await qa({run_id:j.runId,scope:t});b({...j,verdict:F.verdict,aiNotes:F.ai_notes,reviewerNote:F.reviewer_note}),u(!1)}:void 0,className:"mx-6"}),e.jsxs(Xa,{children:[e.jsx(H,{variant:"outline",onClick:()=>r(!1),disabled:m,children:"Cancel"}),e.jsx(H,{onClick:E,disabled:m||U.length===0,children:m?e.jsxs(e.Fragment,{children:[e.jsx(Fe,{className:"h-4 w-4 mr-1 animate-spin"})," Applyingâ¦"]}):e.jsxs(e.Fragment,{children:["Apply ",U.length||""," change",U.length===1?"":"s"]})})]})]})}):null}const kl=a=>Math.round(a*100)/100;function gd({items:a,columns:t,mode:s,value:r}){const l=Number(r),o={edits:{},fields:0,rows:0,skippedEmpty:0};if(r===""||r===null||r===void 0||!Number.isFinite(l)||s==="set"&&l<0)return o;const i={};let d=0,_=0;return a.forEach(n=>{const c={};t.forEach(m=>{if(!n.editable_columns.includes(m))return;const h=n.values[m];let j;if(s==="percent"){if(h==null||Number(h)===0){_+=1;return}j=kl(Number(h)*(1+l/100))}else j=kl(l);j<0||h!=null&&Number(h)===j||(c[m]=j,d+=1)}),Object.keys(c).length&&(i[n.key]=c)}),{edits:i,fields:d,rows:Object.keys(i).length,skippedEmpty:_}}function bd(a,t){const s={...a};return Object.entries(t).forEach(([r,l])=>{s[r]={...s[r]||{},...l}}),s}function fd(a,t){const s=r=>t instanceof Map?t.get(r):t[r];return Object.entries(a).flatMap(([r,l])=>{const o=s(r);return o?!l||Object.keys(l).length===0?[]:[{source_table:o.source_table,global_row_id:o.global_row_id,item_code:o.item_code,item_name:o.item_name,card_code:o.card_code,fields:l}]:[]})}const yt=-70,jt=300,as=.5;function or(a){const t=Number(a);if(!Number.isFinite(t))return 0;const s=Math.round(t/as)*as,r=Math.min(jt,Math.max(yt,s));return Math.round(r*100)/100}function wd({percent:a,onChange:t}){return e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-end justify-between gap-3",children:[e.jsxs(xe,{className:"text-xs",children:["Percent change (",yt,"% to +",jt,"%)"]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Pe,{type:"number",step:as,min:yt,max:jt,className:"h-8 w-[96px] text-right",value:a,onChange:s=>t(or(s.target.value)),"aria-label":"Percent change"}),e.jsx("span",{className:"text-xs text-muted-foreground",children:"%"}),e.jsxs(H,{type:"button",size:"sm",variant:"ghost",className:"h-8",onClick:()=>t(0),disabled:a===0,children:[e.jsx(ot,{className:"h-3.5 w-3.5 mr-1"})," Reset"]})]})]}),e.jsx(Ct,{value:[a],min:yt,max:jt,step:as,onValueChange:([s])=>t(or(s)),"aria-label":"Percent change slider"}),e.jsxs("div",{className:"flex justify-between text-[10px] text-muted-foreground",children:[e.jsxs("span",{children:[yt,"%"]}),e.jsx("span",{children:"0%"}),e.jsxs("span",{children:["+",jt,"%"]})]})]})}const Cl=a=>a==null?"â":`$${Number(a).toLocaleString(void 0,{maximumFractionDigits:2})}`;function yd({open:a,onOpenChange:t,selectedItems:s,fieldGroups:r,onStage:l}){const[o,i]=p.useState("__all__"),[d,_]=p.useState("percent"),[n,c]=p.useState(0),[m,h]=p.useState(""),j=p.useMemo(()=>{var y;return o==="__all__"?r.flatMap(L=>L.columns):((y=r.find(L=>L.label===o))==null?void 0:y.columns)??[]},[o,r]),b=d==="percent"?n:m,x=p.useMemo(()=>gd({items:s,columns:j,mode:d,value:b}),[s,j,d,b]),u=p.useMemo(()=>{const y=[];for(const L of s){const I=x.edits[L.key];if(I){for(const[$,ee]of Object.entries(I))if(y.push({item:L,column:$,from:L.values[$]??null,to:ee}),y.length>=40)return y}}return y},[x.edits,s]),N=x.fields===0;return e.jsx(Ha,{open:a,onOpenChange:t,children:e.jsxs(Qa,{className:"max-w-2xl",children:[e.jsxs(Ja,{children:[e.jsxs(Ya,{children:["Bulk edit ",s.length," selected item",s.length===1?"":"s"]}),e.jsx(it,{children:"Stage the same change across every selected row, then review and apply it with a reason â exactly like a single edit."})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Money fields"}),e.jsxs(Be,{value:o,onValueChange:i,children:[e.jsx(Ve,{children:e.jsx(ze,{})}),e.jsxs(Ue,{children:[e.jsx(me,{value:"__all__",children:"All money fields"}),r.map(y=>e.jsx(me,{value:y.label,children:y.label},y.label))]})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Change type"}),e.jsxs(Be,{value:d,onValueChange:y=>_(y),children:[e.jsx(Ve,{children:e.jsx(ze,{})}),e.jsxs(Ue,{children:[e.jsx(me,{value:"percent",children:"Percent change (slider)"}),e.jsx(me,{value:"set",children:"Set exact amount"})]})]})]})]}),d==="percent"?e.jsx(wd,{percent:n,onChange:y=>c(or(y))}):e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Amount ($)"}),e.jsx(Pe,{type:"number",step:"0.01",min:0,value:m,onChange:y=>h(y.target.value),placeholder:"125.00"})]}),u.length>0&&e.jsxs("div",{className:"border rounded-md",children:[e.jsxs("div",{className:"px-3 py-1.5 text-xs font-medium border-b bg-primary/5",children:["Preview â first ",u.length.toLocaleStr
11ing()," of ",x.fields.toLocaleString()," field change",x.fields===1?"":"s"]}),e.jsx(Ma,{className:"h-[180px]",children:e.jsx("div",{className:"divide-y",children:u.map(y=>e.jsxs("div",{className:"flex items-center justify-between gap-3 px-3 py-1.5 text-xs",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"truncate font-medium",children:y.item.item_name}),e.jsx("div",{className:"text-muted-foreground capitalize",children:y.column.replace(/_/g," ")})]}),e.jsxs("div",{className:"whitespace-nowrap",children:[e.jsx("span",{className:"text-muted-foreground",children:Cl(y.from)}),e.jsx("span",{className:"mx-1",children:"â"}),e.jsx("span",{className:"font-semibold",children:Cl(y.to)})]})]},`${y.item.key}-${y.column}`))})})]}),e.jsxs(da,{children:[e.jsx(Ba,{className:"h-4 w-4"}),e.jsxs(ma,{className:"text-xs",children:[d==="percent"?"Rows with no value in the chosen fields are skipped â a percent move never creates a price out of nothing.":"The exact amount is written to every chosen field that exists on the selected rows."," ","Staging ",x.fields.toLocaleString()," field change",x.fields===1?"":"s"," across"," ",x.rows.toLocaleString()," row",x.rows===1?"":"s",x.skippedEmpty>0?`, skipping ${x.skippedEmpty.toLocaleString()} empty field${x.skippedEmpty===1?"":"s"}`:"","."]})]})]}),e.jsxs(Xa,{children:[e.jsx(H,{variant:"outline",onClick:()=>t(!1),children:"Cancel"}),e.jsxs(H,{disabled:N,onClick:()=>{l(x.edits),c(0),h(""),t(!1)},children:["Stage ",x.fields.toLocaleString()," change",x.fields===1?"":"s"]})]})]})})}const jd=["labor_rate","material_rate","allowance_labor","allowance_material"],Sl={entry:"Entry",good:"Good",better:"Better",best:"Best"};function $l(a){if(a==null||a==="")return null;const t=Number(a);return Number.isFinite(t)?t:null}function vd(a){if(sd(a)){const t=vr(a);if(!(t!=null&&t.tiered))return[];const s=t.columns.filter(r=>r.tier).map(r=>[r.tier,r.column]).sort((r,l)=>qe.indexOf(r[0])-qe.indexOf(l[0]));return s.length?[{label:"finish allowance",columns:s}]:[]}return xn(a)?jd.map(t=>({label:t.replace(/_/g," "),columns:qe.map(s=>[s,`${s}_${t}`])})):[]}function Nd(a,t,s={}){const r=vd(a);if(!r.length)return[];const l=[];for(const o of r){if(!o.columns.some(([,n])=>n in t))continue;let d=null,_=null;for(const[n,c]of o.columns){const m=c in t?$l(t[c]):$l(s[c]);m!==null&&(_!==null&&m<_-.005&&l.push(`${o.label}: ${Sl[n]??n} $${m} is below ${Sl[d]??d} $${_}`),d=n,_=m)}}return l}function kd({buckets:a,activeFlags:t,onSelect:s,onClear:r,totalRows:l}){if(!a.length)return e.jsxs(ye,{className:"p-3 flex items-center gap-2 text-sm",children:[e.jsx(hr,{className:"h-4 w-4 text-primary"}),e.jsx("span",{children:"Nothing needs attention in the current filter â every visible row passes the health checks."})]});const o=i=>t.length>0&&i.every(d=>t.includes(d))&&i.length===t.length;return e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[e.jsxs("p",{className:"text-xs text-muted-foreground",children:[l.toLocaleString()," row",l===1?"":"s"," flagged. A row can appear in more than one group. Nothing here changes a price until you edit and save."]}),t.length>0&&e.jsx(H,{size:"sm",variant:"ghost",onClick:r,children:"Show all groups"})]}),e.jsx("div",{className:"grid gap-2 sm:grid-cols-2 xl:grid-cols-3",children:a.map(i=>e.jsxs(ye,{role:"button",tabIndex:0,onClick:()=>o(i.flags)?r():s(i.flags),onKeyDown:d=>{(d.key==="Enter"||d.key===" ")&&(d.preventDefault(),o(i.flags)?r():s(i.flags))},className:`p-3 cursor-pointer transition-colors hover:border-primary/50 ${o(i.flags)?"border-primary bg-primary/[0.04]":""}`,children:[e.jsxs("div",{className:"flex items-start justify-between gap-2",children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[i.movesMoney?e.jsx(Xe,{className:"h-4 w-4 shrink-0 text-destructive"}):e.jsx(Ba,{className:"h-4 w-4 shrink-0 text-muted-foreground"}),e.jsx("span",{className:"text-sm font-medium truncate",children:i.title})]}),e.jsx(ie,{variant:"secondary",className:"shrink-0",children:i.count.toLocaleStr
11ing()})]}),e.jsx("p",{className:"mt-1.5 text-xs text-muted-foreground",children:i.meaning}),e.jsxs("p",{className:"mt-1.5 text-xs",children:[e.jsx("span",{className:"font-medium",children:"Do this: "}),i.action]}),e.jsxs("p",{className:"mt-1.5 text-[11px] text-muted-foreground",children:[i.liveCount>0?`${i.liveCount.toLocaleString()} of these price on a live project today`:"None of these price on a live project today",i.movesMoney?" · can move a project total":" · cannot move a project total on its own"]})]},i.id))})]})}const Cd=(a,t)=>a==null?!1:typeof a=="number"&&typeof t=="number"?Math.abs(a-t)<.005:a===t,Ds=(a,t,s)=>{var l;const r=(a==null?void 0:a.message)||(t==null?void 0:t.error)||(t==null?void 0:t.message)||((l=t==null?void 0:t.errors)==null?void 0:l[0]);return r?typeof r=="string"?r:JSON.stringify(r):s};async function Al(a,t){const s=t.now??(()=>new Date().toISOString()),r=t.equals??Cd,l=[];let o=null,i=!1;const d=(n,c,m,h)=>l.push({key:n,label:c,state:m,detail:h}),_=()=>({kind:a.kind,ok:!1,runId:o,dirty:i,steps:l,finishedAt:s()});try{const{data:n,error:c}=await t.invoke(a.applyFn,a.applyBody);if(o=(n==null?void 0:n.run_id)??null,!(!c&&(n==null?void 0:n.success)!==!1&&((n==null?void 0:n.status)??"verified")==="verified")||!o)return d("apply",`Apply probe (${a.subject})`,"fail",Ds(c,n,`status ${(n==null?void 0:n.status)??"unknown"}`)),((n==null?void 0:n.status)==="partially_applied"||(n==null?void 0:n.status)==="failed_verification")&&(i=!0),_();i=!0;const h=n.fields_verified??n.fields_changed??n.fields_changed_count??"?";d("apply",`Apply probe (${a.subject})`,"pass",`${a.format(a.original)} â ${a.format(a.probe)} · run ${String(o).slice(0,8)} · ${h} field(s) recorded and verified by the backend`)}catch(n){return d("apply",`Apply probe (${a.subject})`,"fail",(n==null?void 0:n.message)||"apply threw"),_()}try{const n=await t.readLive();r(n,a.probe)?d("read","Read the live value back","pass",`table holds ${a.format(a.probe)}`):d("read","Read the live value back","fail",`expected ${a.format(a.probe)}, table holds ${a.format(n)}`)}catch(n){d("read","Read the live value back","fail",(n==null?void 0:n.message)||"read threw")}try{const{data:n,error:c}=await t.invoke("audit-catalog-price-history",{run_id:o});c||(n==null?void 0:n.status)!=="verified"?d("reverify","Re-verify the run","fail",Ds(c,n,`status ${(n==null?void 0:n.status)??"unknown"}`)):d("reverify","Re-verify the run","pass",`${n.fields_matching??n.fields_checked??"?"} of ${n.fields_checked??"?"} recorded field(s) still match`)}catch(n){d("reverify","Re-verify the run","fail",(n==null?void 0:n.message)||"re-verify threw")}try{const{data:n,error:c}=await t.invoke("revert-catalog-price-change",{run_id:o,reason:a.revertReason});if(c||!(n!=null&&n.success))return d("revert","Revert the run","fail",Ds(c,n,"revert did not verify")),d("restore","Confirm the original value is back","skipped","revert did not complete"),_();d("revert","Revert the run","pass",`revert run ${String(n.run_id??"").slice(0,8)} verified`)}catch(n){return d("revert","Revert the run","fail",(n==null?void 0:n.message)||"revert threw"),d("restore","Confirm the original value is back","skipped","revert did not complete"),_()}try{const n=await t.readLive();if(!r(n,a.original))return d("restore","Confirm the original value is back","fail",`expected ${a.format(a.original)}, table holds ${a.format(n)}`),_();d("restore","Confirm the original value is back","pass",`${a.format(a.original)} restored â net change none`),i=!1}catch(n){return d("restore","Confirm the original value is back","fail",(n==null?void 0:n.message)||"read threw"),_()}return{kind:a.kind,ok:l.every(n=>n.state==="pass"),runId:o,dirty:i,steps:l,finishedAt:s()}}const Bs=.01,Sd={labor:["base_labor_rate","good_labor_rate","labor_unit_price","labor_cost"],material:["base_material_rate","good_material_rate","material_unit_price","base_rate","good_price"]};function El(a,t){for(const s of["labor","material"])for(const r of Sd[s]){if(!a.includes(r))continue;const l=Number(t[r]??0);if(l>0)return{column:r,appliesTo:s,current:l}}return null}const Vs=a=>a==null?"empty":`$${Number(a).toFixed(2)}`;function Rl({result:a}){return e.jsxs(da,{variant:a.ok?"default":"destructive",className:"mt-2",children:[e.jsx(Sa,{className:"text-xs",children:a.ok?"Applied, verified by the backend, and restored":a.dirty?"Failed â the probe value may still be live":"Failed â nothing was left changed"}),e.jsxs(ma,{children:[e.jsx("ul",{className:"space-y-1 text-xs mt-1",children:a.steps.map(t=>e.jsxs("li",{className:"flex items-start gap-1.5",children:[t.state==="pass"?e.jsx(hr,{className:"h-3.5 w-3.5 mt-0.5 shrink-0"}):t.state==="fail"?e.jsx(Et,{className:"h-3.5 w-3.5 mt-0.5 shrink-0"}):e.jsx(Ul,{className:"h-3.5 w-3.5 mt-0.5 shrink-0"}),e.jsxs("span",{children:[e.jsx("span",{className:"font-medium",children:t.label})," â ",t.detail]})]},t.key))}),a.dirty&&e.jsxs("p",{className:"mt-2 flex items-center gap-1 text-xs font-medium",children:[e.jsx(Xe,{className:"h-3.5 w-3.5"}
11)," Revert run ",String(a.runId??"").slice(0,8)," from the History tab before pricing from this item."]})]})]})}function $d({universe:a,scope:t,canRunBulk:s,onFinished:r}){const[l,o]=p.useState(null),[i,d]=p.useState({}),_=p.useMemo(()=>{const h=a.filter(j=>j.supports_activation&&!j.read_only);return h.find(j=>j.is_active===!1)??h.find(j=>j.usage_all_time_projects===0&&j.usage_projects===0)??null},[a]),n=p.useMemo(()=>{for(const h of a){if(h.read_only||h.is_active===!1||h.usage_projects>0)continue;const j=El(h.editable_columns,h.values);if(j)return{item:h,...j}}return null},[a]),c=async()=>{if(!_)return;const h=_,j=h.is_active!==!1;o("activation"),d(b=>({...b,activation:void 0}));try{const b=await Al({kind:"activation",subject:`${h.item_code} is_active`,applyFn:"apply-catalog-price-update",applyBody:{kind:"activation",scope:t,notes:`[self-test] retire â verify â restore probe on ${h.item_code}`,activation_changes:[{source_table:h.source_table,global_row_id:h.global_row_id,item_code:h.item_code,item_name:h.item_name,card_code:h.card_code,is_active:!j}]},original:j,probe:!j,format:x=>x===null?"empty":x?"active":"retired",revertReason:`[self-test] restoring ${h.item_code} activation after the retire â verify â restore proof`},{invoke:(x,u)=>ge.functions.invoke(x,{body:u}),readLive:async()=>{const x=t==="company"?h.source_table.replace("_global","_company"):h.source_table,{data:u,error:N}=await ge.from(x).select("is_active").eq(t==="company"?"item_code":"id",t==="company"?h.item_code:h.global_row_id).limit(1).maybeSingle();if(N)throw new Error(N.message);const y=u==null?void 0:u.is_active;return y==null?null:!!y}});d(x=>({...x,activation:b})),b.ok?le.success("Activation proof passed",{description:`${h.item_code} retired/restored, verified and put back â net change none.`}):le.error("Activation proof failed",{description:b.dirty?"Revert the run from History.":"No pricing was left changed."}),r==null||r()}catch(b){le.error("Activation proof could not run",{description:b==null?void 0:b.message})}finally{o(null)}},m=async()=>{if(!n)return;const{item:h,column:j,appliesTo:b,current:x}=n,u=El(h.editable_columns,h.values);o("bulk"),d(L=>({...L,bulk:void 0}));let N=null,y=null;try{const L=await Al({kind:"bulk",subject:`${h.item_code} ${j}`,applyFn:"apply-bulk-price-adjustment",applyBody:{items:[{source_table:h.source_table,id:h.global_row_id,item_code:h.item_code,item_name:h.item_name,card_code:h.card_code,current_labor:Number(h.values[(u==null?void 0:u.column)??j]??x)||0,current_material:Number(h.values[j]??x)||0}],state_codes:["NJ"],mode:"fixed",value:Bs,applies_to:b,notes:`[self-test] bulk apply â verify â revert probe on ${h.item_code}`},original:x,probe:+(x+Bs).toFixed(2),format:Vs,revertReason:`[self-test] restoring ${h.item_code} after the bulk apply â verify â revert proof`},{invoke:async(I,$)=>{var U;const ee=await ge.functions.invoke(I,{body:$});return I==="apply-bulk-price-adjustment"&&((U=ee.data)!=null&&U.run_id)&&(y=ee.data.run_id),ee},readLive:async()=>{if(!N&&y){const{data:E}=await ge.from("catalog_price_change_items").select("field").eq("run_id",y).limit(1).maybeSingle();N=(E==null?void 0:E.field)??j}const I=N??j,{data:$,error:ee}=await ge.from(h.source_table).select(I).eq("id",h.global_row_id).limit(1).maybeSingle();if(ee)throw new Error(ee.message);const U=$==null?void 0:$[I];return U==null?null:Number(U)}});d(I=>({...I,bulk:L})),L.ok?le.success("Bulk proof passed",{description:`${h.item_code} adjusted by one cent, verified and reverted â net change $0.00.`}):le.error("Bulk proof failed",{description:L.dirty?"Revert the run from History.":"No pricing was left changed."}),r==null||r()}catch(L){le.error("Bulk proof could not run",{description:L==null?void 0:L.message})}finally{o(null)}};return e.jsxs(ye,{className:"p-3 space-y-3",children:[e.jsxs("div",{children:[e.jsxs("p",{className:"text-sm font-medium flex items-center gap-2",children:[e.jsx(Ht,{className:"h-4 w-4"})," Ledger proofs"]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5",children:"Each proof writes a reversible probe through the audited pricing service, reads it back out of the table, re-verifies the run, reverts it and confirms the original value is back. Net pricing change is zero, and both the apply and the revert stay in the History tab."})]}),e.jsxs("div",{className:"rounded-md border border-primary/15 p-2.5",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs(H,{size:"sm",variant:"outline",disabled:!_||l!==null,onClick:c,children:[l==="activation"?e.jsx(Fe,{className:"h-3.5 w-3.5 mr-1 animate-spin"}):e.jsx(Ht,{className:"h-3.5 w-3.5 mr-1"}),"Run retire â verify â restore proof"]}),i.activation&&e.jsx(ie,{variant:i.activation.ok?"default":"destructive",className:"text-[10px]",children:i.activation.ok?"PASS":"FAIL"})]}),e.jsx("p",{className:"text-[11px] text-muted-foreground mt-1.5",children:_?e.jsxs(e.Fragment,{children:["Probes ",e.jsx("span",{className:"font-mono",children:_.item_code})," (",_.is_active===!1?"currently retired â restores then retires again":"unused row â retires then restores","), then puts it back."]}):"No eligible row in the current scope â a retirable row needs an is_active column and a V2 reader."}),i.activation&&e.jsx(Rl,{result:i.activation})]}),e.jsxs("div",{className:"rounded-md border border-primary/15 p-2.5",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs(H,{size:"sm",variant:"outline",disabled:!n||!s||l!==null,onClick:m,children:[l==="bulk"?e.jsx(Fe,{className:"h-3.5 w-3.5 mr-1 animate-spin"}):e.jsx(Ht,{className:"h-3.5 w-3.5 mr-1"}),"Run bulk apply â verify â revert proof"]}),i.bulk&&e.jsx(ie,{variant:i.bulk.ok?"default":"destructive",className:"text-[10px]",children:i.bulk.ok?"PASS":"FAIL"})]}),e.jsx("p",{className:"text-[11px] text-muted-foreground mt-1.5",children:s?n?e.jsxs(e.Fragment,{children:["Probes ",e.jsx("span",{className:"font-mono",children:n.item.item_code})," ",n.column," ",Vs(n.current)," â ",Vs(+(n.current+Bs).toFixed(2))," (no live project uses this row), then restores it."]}):"No unused priced row available in the current filter to probe safely.":"Bulk adjustments are super-admin only."}),i.bulk&&e.jsx(Rl,{result:i.bulk})]})]})}const zs=[{label:"Tier allowances (labor + material)",columns:[...qe.flatMap(a=>[`${a}_allowance_labor`,`${a}_allowance_material`]),"labor_allowance","material_allowance"]},{label:"Tier rates (labor + material)",columns:qe.flatMap(a=>[`${a}_labor_rate`,`${a}_material_rate`])},{label:"Base rate",columns:["base_labor_rate","base_material_rate","labor_unit_price","material_unit_price"]},{label:"Tier labor rate only",columns:qe.map(a=>`${a}_labor_rate`)},{label:"Tier material rate only",columns:qe.map(a=>`${a}_material_rate`)},{label:"Allowance labor only",columns:[...qe.map(a=>`${a}_allowance_labor`),"labor_allowance"]},{label:"Allowance material only",columns:[...qe.map(a=>`${a}_allowance_material`),"material_allowance"]}],Tl=a=>a.replace(/_/g," ").replace("allowance labor","allow. L").replace("allowance material","allow. M").replace("labor rate","labor").replace("material rate","material").replace("labor unit price","labor").replace("material unit price","material"),Us=a=>
11a==null?"â":`$${Number(a).toLocaleString(void 0,{maximumFractionDigits:2})}`;function Ad({catalogOnly:a=!1}={}){const t=Zl(),{user:s,authSessionVersion:r}=ur(),l=t.actualIsSuperAdmin&&t.effectiveIsSuperAdmin,o=!t.isLoading&&(t.actualIsAdmin||t.actualIsSuperAdmin)&&t.effectiveIsAdmin,i=ln(o);return o?!l&&!i.scope?e.jsx("p",{role:"status",children:i.isFetching?"Confirming company pricing coverageâ¦":"An active company with approved states is required. Company pricing has not been loaded."}):e.jsx(Ed,{catalogOnly:a,isSuperAdmin:l,companyScope:i.scope??void 0},`${s==null?void 0:s.id}:${r}:${l?"platform":i.scope.companyId}`):e.jsx("p",{role:"status",children:"Company pricing is unavailable for this role or preview."})}function Ed({catalogOnly:a,isSuperAdmin:t,companyScope:s}){var Ar,Er;const r=s==null?void 0:s.companyId,l=$a(),[o,i]=Vl(),[d,_]=p.useState(t?"global":"company"),[n,c]=p.useState({}),[m,h]=p.useState(!1),[j,b]=p.useState(!1),[x,u]=p.useState(null),[N,y]=p.useState(!1),[L,I]=p.useState(""),[$,ee]=p.useState(!1),[U,E]=p.useState(null),be=["prices","attention","legacy","bands"].includes(o.get("view")||"")?o.get("view"):"prices",F=!t&&be!=="prices"?"prices":be,se=(C,Y)=>{if(C!=="prices"&&!t)return;const ae=new URLSearchParams(o);C==="prices"?ae.delete("view"):ae.set("view",C),Y!=null&&Y.bandFocus?ae.set("bandItem",Y.bandFocus):ae.delete("bandItem"),i(ae,{replace:!0})},V=o.get("bandItem"),z=p.useMemo(()=>{const C=ae=>o.get(ae)?o.get(ae).split("|").filter(Boolean):[],Y=ae=>o.get(ae)==="1";return{...bt,searchText:o.get("q")||"",trades:C("trade"),cards:C("card"),items:C("item"),side:o.get("side")||"all",flags:C("flag"),shapes:C("shape"),provenances:C("prov"),usage:o.get("usage")||"all",cardCoverage:o.get("cardcov")||"all",engines:C("engine"),includeLegacy:Y("legacy"),includeInactive:Y("inactive"),mergeSides:o.get("pair")!=="0",breakdown:o.get("by")||"family",divergedOnly:Y("diverged"),finishOnly:Y("finish"),allowanceOnly:Y("allow"),areaBandOnly:Y("band"),modifiedWithinDays:o.get("days")?Number(o.get("days")):null,groupColumn:o.get("cols")||bt.groupColumn,tier:o.get("tier")||bt.tier}},[o]),Se=C=>{const Y={...z,...C},ae=new URLSearchParams(o),Re=(Je,la)=>la.length?ae.set(Je,la.join("|")):ae.delete(Je),Te=(Je,la,Ka)=>la&&la!==Ka?ae.set(Je,la):ae.delete(Je);Te("q",Y.searchText,""),Re("trade",Y.trades),Re("card",Y.cards),Re("item",Y.items),Te("side",Y.side,"all"),Re("flag",Y.flags),Re("shape",Y.shapes),Re("prov",Y.provenances),Te("usage",Y.usage,"all"),Te("cardcov",Y.cardCoverage,"all"),Re("engine",Y.engines),Y.includeLegacy?ae.set("legacy","1"):ae.delete("legacy"),Y.includeInactive?ae.set("inactive","1"):ae.delete("inactive"),Y.mergeSides?ae.delete("pair"):ae.set("pair","0"),Te("by",Y.breakdown,"family"),Y.divergedOnly?ae.set("diverged","1"):ae.delete("diverged"),Y.finishOnly?ae.set("finish","1"):ae.delete("finish"),Y.allowanceOnly?ae.set("allow","1"):ae.delete("allow"),Y.areaBandOnly?ae.set("band","1"):ae.delete("band"),Y.modifiedWithinDays?ae.set("days",String(Y.modifiedWithinDays)):ae.delete("days"),Te("cols",Y.groupColumn,bt.groupColumn),Te("tier",Y.tier,bt.tier),i(ae,{replace:!0})},re=()=>{const C=new URLSearchParams(o);["q","trade","card","item","side","flag","shape","prov","usage","cardcov","engine","legacy","pair","by","diverged","finish","allow","band","days"].forEach(Y=>C.delete(Y)),i(C,{replace:!0})},$e=Ni(z.searchText,250),g=p.useRef(new WeakMap),S=p.useCallback(C=>{const Y=g.current.get(C);if(Y)return Y;const ae=fn(C);return g.current.set(C,ae),ae},[]),{items:R}=Mn(d==="company"?"company":"global",r,{enabled:t}),v=p.useMemo(()=>new Set(R.map(C=>C.item_code)),[R]),G=p.useCallback(C=>{if(!t)return!0;const Y=S(C);return F==="attention"&&!gn.some(ae=>Y.flags.includes(ae))||z.areaBandOnly&&!v.has(C.item_code)?!1:z.flags.length?z.flags.some(ae=>Y.flags.includes(ae)):!0},[t,z.flags,z.areaBandOnly,v,S,F]),{items:te,isLoading:oe,universe:A,refetch:de}=$n(d,r??null,{searchText:$e,trades:z.trades,cards:z.cards,itemCodes:z.items,side:z.side,finishSensitiveOnly:z.finishOnly,hasAllowanceOnly:z.allowanceOnly,shapes:z.shapes,provenances:t?z.provenances:[],usage:t?z.usage:"all",cardCoverage:z.cardCoverage,engines:z.engines,includeLegacy:t&&z.includeLegacy,includeInactive:z.includeInactive,divergedOnly:z.divergedOnly,modifiedWithinDays:z.modifiedWithinDays,predicate:G},{gcCatalogOnly:!t,actualCompanyScope:s}),O=p.useMemo(()=>new Set(A.map(C=>C.item_code)),[A]),he=p.useMemo(()=>{const C=new Map;return A.forEach(Y=>C.set(Y.key,Y)),C},[A]),[Ie,Ge]=p.useState(new Set),Oe=p.useMemo(()=>Mo(te,{enabled:z.mergeSides&&z.breakdown!=="family",unmerged:Ie}),[te,z.mergeSides,z.breakdown,Ie]),k=p.useMemo(()=>Po(Oe.rows),[Oe.rows]);p.useEffect(()=>{const C=z.breakdown||"family";pe.current!==C&&(pe.current=C,C==="flat"||C==="family"?B(new Set):k.length&&B(new Set(Gr(k,C))))},[z.breakdown,k]);const w=p.useCallback(C=>Oe.mergedKeys.has(C.key)&&C.side_partner_key?[C.key,C.side_partner_key]:[C.key],[Oe.mergedKeys]),P=p.useCallback(C=>{C.side_pair_id&&(Ge(Y=>
11new Set(Y).add(C.side_pair_id)),le.info("Sides split",{description:"The addition and remodel rows can now be priced separately."}))},[]),[M,D]=p.useState(new Set),[fe,ve]=p.useState("fit"),[ue,T]=p.useState(()=>typeof window>"u"?900:window.innerHeight);p.useEffect(()=>{const C=()=>T(window.innerHeight);return window.addEventListener("resize",C),()=>window.removeEventListener("resize",C)},[]);const ce=fe==="fit"?Math.max(420,ue-300):Number(fe),[X,B]=p.useState(new Set),[f,q]=p.useState(!1),[K,_e]=p.useState(!1),pe=p.useRef(null),W=z.items.length;p.useEffect(()=>{W>0&&B(new Set)},[W]);const we=p.useCallback((C,Y)=>{D(ae=>{const Re=new Set(ae);return w(C).forEach(Te=>Y?Re.add(Te):Re.delete(Te)),Re})},[w]),Ee=p.useCallback((C,Y)=>{D(ae=>{const Re=new Set(ae);return C.forEach(Te=>w(Te).forEach(Je=>Y?Re.add(Je):Re.delete(Je))),Re})},[w]),ne=p.useCallback(C=>Ee(k,C),[k,Ee]),Ae=z.groupColumn,Ne=p.useMemo(()=>k.reduce((C,Y)=>C+(S(Y).topFlag.id==="healthy"?0:1),0),[k,S]),He=p.useMemo(()=>Ko(k.map(C=>({item:C,...S(C)}))),[k,S]),Me=p.useMemo(()=>eo(k),[k]),ra=p.useMemo(()=>{if(!Ae||Ae==="None")return[];const C=zs.find(ae=>ae.label===Ae);if(!C)return[];const Y=new Set;return k.forEach(ae=>ae.editable_columns.forEach(Re=>C.columns.includes(Re)&&Y.add(Re))),C.columns.filter(ae=>Y.has(ae))},[k,Ae]),Qe=p.useMemo(()=>Object.values(n).reduce((C,Y)=>C+Object.keys(Y).length,0),[n]),ya=p.useMemo(()=>[...M].map(C=>he.get(C)).filter(Boolean),[M,he]),mt=p.useCallback(C=>{if(!t)return;c(ae=>bd(ae,C));const Y=Object.values(C).reduce((ae,Re)=>ae+Object.keys(Re).length,0);le.success(`Staged ${Y.toLocaleString()} change${Y===1?"":"s"}`,{description:"Review & apply to write them through the audited pricing service."})},[t]),ti=p.useMemo(()=>{const C=new Set;return k.forEach(Y=>{Oe.mergedKeys.has(Y.key)&&Y.side_partner_key&&C.add(Y.side_partner_key)}),Object.entries(n).flatMap(([Y,ae])=>{if(C.has(Y))return[];const Re=he.get(Y);if(!Re)return[];const Te=Oe.mergedKeys.has(Y);return Object.entries(ae).map(([Je,la])=>({key:Y,item:Re,bothSides:Te,column:Je,oldValue:Re.values[Je]??null,newValue:la}))})},[n,he,k,Oe.mergedKeys]),si=(C,Y,ae)=>{if(!t)return;const Re=w(C).map(Te=>he.get(Te)).filter(Te=>!!Te&&Te.editable_columns.includes(Y));c(Te=>{const Je={...Te};return Re.forEach(la=>{const Ka={...Je[la.key]||{}};if(ae.trim()==="")delete Ka[Y];else{const Pt=Number(ae);if(!Number.isFinite(Pt)||Pt<0)return;Pt===(la.values[Y]??null)?delete Ka[Y]:Ka[Y]=Pt}Object.keys(Ka).length?Je[la.key]=Ka:delete Je[la.key]}),Je})},[_a,ut]=p.useState([]),[ht,kr]=p.useState(!1),[gs,Lt]=p.useState(""),[Cr,Sr]=p.useState(!1),Mt=p.useMemo(()=>ya.filter(C=>C.supports_activation&&!C.read_only),[ya]),bs=p.useMemo(()=>Mt.filter(C=>C.is_active!==!1),[Mt]),fs=p.useMemo(()=>Mt.filter(C=>C.is_active===!1),[Mt]),$r=C=>{Lt(""),kr(C),ut(C?fs:bs)},ri=async()=>{var C;if(t&&_a.length){Sr(!0);try{const{data:Y,error:ae}=await ge.functions.invoke("apply-catalog-price-update",{body:{kind:"activation",scope:d,notes:gs,activation_changes:_a.map(Te=>({source_table:Te.source_table,global_row_id:Te.global_row_id,item_code:Te.item_code,item_name:Te.item_name,card_code:Te.card_code,is_active:ht}))}}),Re=await wa(Y,ae);if(Re.verdict&&u(Re),ae)throw ae;if((Y==null?void 0:Y.success)!==!0||Y!=null&&Y.error)throw new Error(typeof(Y==null?void 0:Y.error)=="string"?Y.error:"Activation save was not confirmed");if((C=Y==null?void 0:Y.errors)!=null&&C.length)throw new Error(Y.errors[0]);le.success(ht?`Restored ${_a.length} price${_a.length===1?"":"s"}`:`Retired ${_a.length} price${_a.length===1?"":"s"}`,{description:"Audited and revertible from the History tab. Future projects only."}),ut([]),Lt(""),await de(),l.invalidateQueries({queryKey:["catalog-price-change-runs"]})}catch(Y){le.error("Could not change activation",{description:(Y==null?void 0:Y.message)||"Unexpected error"})}finally{Sr(!1)}}},ws=p.useMemo(()=>{const C=[];return Object.entries(n).forEach(([Y,ae])=>{const Re=he.get(Y);if(!Re||!ae||!Object.keys(ae).length)return;const Te=Nd(Re.source_table,ae,Re.values||{});Te.length&&C.push({item:Re,problems:Te})}),C},[n,he]),li=async()=>{var C;if(t){ee(!0);try{const Y=fd(n,he);u(null);const{data:ae,error:Re}=await ge.functions.invoke("apply-catalog-price-update",{body:{scope:d,notes:L||null,changes:Y,...j?{allow_partial_tiers:!0}:{}}}),Te=await wa(ae,Re);if(Te.verdict&&u(Te),Re){const Je=[Te.errorMessage,...Te.details].filter(
11Boolean).join(" â ");throw new Error(Je||Re.message||"Update rejected")}if((ae==null?void 0:ae.success)!==!0||ae!=null&&ae.error||!Number.isSafeInteger(ae==null?void 0:ae.fields_changed)||!Number.isSafeInteger(ae==null?void 0:ae.items_affected))throw new Error(typeof(ae==null?void 0:ae.error)=="string"?ae.error:"Price save was not confirmed");le.success(`Applied ${ae.fields_changed} price change${ae.fields_changed===1?"":"s"} across ${ae.items_affected} item(s)`,{description:d==="global"?"New prices apply to future projects. Existing projects were marked stale.":`Company pricing updated. ${ae.analyses_marked_stale} existing project(s) marked stale.`}),(C=ae.errors)!=null&&C.length&&le.warning(`${ae.errors.length} change(s) were skipped`,{description:ae.errors[0]}),c({}),I(""),b(!1),(!Te.verdict||Te.verdict.state==="pass")&&h(!1),await de(),l.invalidateQueries({queryKey:["catalog-price-change-runs"]})}catch(Y){le.error("Could not apply price changes",{description:(Y==null?void 0:Y.message)||"Unexpected error"})}finally{ee(!1)}}};return e.jsxs(os,{defaultValue:"catalog",className:"space-y-4",children:[!a&&t&&e.jsxs(cs,{children:[e.jsx(ia,{value:"catalog",children:"Catalog"}),e.jsx(ia,{value:"history",children:"History"})]}),e.jsxs(oa,{value:"catalog",className:"space-y-3",children:[!t&&e.jsxs("p",{className:"rounded border p-3 text-sm text-muted-foreground",children:["Approved company coverage: ",s.allowedStateCodes.join(", "),". This is one company pricing baseline; no unapproved state selector is available. Company edits await a reviewed company-scoped pricing service. Platform project usage, history, legacy and area-band tools are not loaded here."]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("span",{className:"text-xs font-medium text-muted-foreground mr-1",children:"View"}),e.jsxs(dt,{type:"single",value:F,onValueChange:C=>C&&se(C),className:"flex flex-wrap justify-start gap-1",children:[e.jsx(ta,{value:"prices",className:"h-10 px-4 text-sm whitespace-nowrap border border-primary/20",children:"Prices"}),t&&e.jsxs(ta,{value:"attention",className:"h-10 px-4 text-sm whitespace-nowrap border border-primary/20",children:["Needs attention",Ne?` (${Ne})`:""]}),t&&e.jsx(ta,{value:"legacy",className:"h-10 px-4 text-sm whitespace-nowrap border border-primary/20",children:"Legacy & allowances"}),t&&e.jsx(ta,{value:"bands",className:"h-10 px-4 text-sm whitespace-nowrap border border-primary/20",children:"Area bands"})]})]}),t&&F==="legacy"&&e.jsx(_d,{catalogCodes:O}),t&&F==="bands"&&e.jsx(Ic,{canEdit:t,focusItemCode:V,companyId:r},V||"all"),F==="attention"&&!oe&&e.jsx(kd,{buckets:He,activeFlags:z.flags,onSelect:C=>Se({...z,flags:C}),onClear:()=>Se({...z,flags:[]}),totalRows:k.length}),e.jsxs("div",{className:F==="prices"||F==="attention"?"space-y-3":"hidden",children:[F==="prices"&&e.jsxs("p",{className:"text-[11px] text-muted-foreground rounded-md border border-primary/15 bg-accent/[0.05] px-3 py-2",children:[e.jsx("span",{className:"font-medium text-foreground",children:"Reading this grid."})," An item that exists on both sides shows two rows â one tagged ",e.jsx("span",{className:"text-primary",children:"addition"}),", one"," ",e.jsx("span",{className:"text-primary",children:"remodel"}),". Both are live and both are read by the card; they are not duplicates, and they sit next to each other. They only merge into one row when their money matches exactly. A genuine duplicate (same card, same side, same item) is flagged âDuplicate rowâ and listed under Needs attention. Allowances are shown as labor ",e.jsx("em",{children:"and"})," material per tier â many items are legitimately material-only, so a column of $0 labor is normal. Rows in âLegacy & allowancesâ are mostly a different item set (29 of 193 base-pricing codes and 8 of 139 finish-allowance codes also exist here), so an item here usually has no legacy twin."]}),e.jsx(co,{filters:z,setFilters:Se,reset:re,universe:A,healthFor:S,columnGroups:zs,summary:oe?"Loading catalogâ¦":`${k.length.toLocaleString()}
11 of ${A.length.toLocaleString()} items · ${Ne.toLocaleString()} need attention${M.size?` · ${M.size.toLocaleString()} selected`:""}${Qe?` · ${Qe.toLocaleString()} unsaved`:""}`,scopeControl:e.jsxs(Be,{value:d,onValueChange:C=>{C==="global"&&!t||C==="company"&&!r||(_(C),c({}))},children:[e.jsx(Ve,{"aria-label":"Pricing scope",className:"w-[210px] h-9 whitespace-nowrap [&>span]:truncate",children:e.jsx(ze,{})}),e.jsxs(Ue,{children:[t&&e.jsx(me,{value:"global",children:e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(us,{className:"h-3.5 w-3.5"})," Global (all companies)"]})}),e.jsx(me,{value:"company",disabled:!r,children:e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(is,{className:"h-3.5 w-3.5"})," My company"]})})]})]})}),e.jsxs("div",{className:"sticky top-0 z-40 flex flex-wrap items-center justify-between gap-3 rounded-md border border-primary/20 bg-card/95 backdrop-blur px-3 py-2",children:[e.jsxs("div",{className:"text-xs text-muted-foreground space-y-0.5",children:[e.jsx("p",{children:oe?"Loading catalogâ¦":`${k.length.toLocaleString()} of ${A.length.toLocaleString()} items â ${Ne.toLocaleString()} need attention${Oe.collapsed?` â ${Oe.collapsed.toLocaleString()} shared add/remodel pair${Oe.collapsed===1?"":"s"} shown once`:""}${Oe.divergentPairs?` â ${Oe.divergentPairs.toLocaleString()} pair${Oe.divergentPairs===1?"":"s"} differ by side`:""}${M.size?` â ${M.size.toLocaleString()} selected`:""}`}),z.breakdown==="family"&&e.jsxs("p",{className:"text-[11px]",children:["Grouped by item family: each block holds the same material across sides â the"," ",e.jsx("span",{className:"font-medium",children:"addition install"}),", the"," ",e.jsx("span",{className:"font-medium",children:"remodel install"})," and its"," ",e.jsx("span",{className:"font-medium",children:"tear-out / demo"})," row. Chips on each row name that row's role; header flags call out a family that is addition-only, remodel-only, or has no tear-out priced."]}),!oe&&k.length>0&&e.jsxs("p",{children:[e.jsx("span",{className:`px-1.5 py-0.5 rounded border ${Me.fullyV2?ua.v2_backend.className:ua.legacy_retired.className}`,children:Me.fullyV2?`100% V2 backend (${Me.v2}/${Me.total})`:`V2 backend ${Me.v2}/${Me.total} â ${Me.legacy} retired/legacy`}),Me.ai>0&&e.jsxs("span",{className:"ml-2 text-destructive",children:[Me.ai.toLocaleString()," AI generated"]}),e.jsx("span",{className:"ml-2 inline-flex align-middle",children:t&&e.jsx(_o,{canRefresh:!0})})]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(xe,{className:"text-xs text-muted-foreground",children:"Group by"}),e.jsxs(Be,{value:z.breakdown||"family",onValueChange:C=>Se({breakdown:C}),children:[e.jsx(Ve,{className:"w-[230px] h-9 whitespace-nowrap [&>span]:truncate",children:e.jsx(ze,{})}),e.jsx(Ue,{children:Object.keys(Nt).map(C=>e.jsx(me,{value:C,children:Nt[C]},C))})]}),e.jsx(xe,{className:"text-xs text-muted-foreground",children:"Grid height"}),e.jsxs(Be,{value:fe,onValueChange:ve,children:[e.jsx(Ve,{"aria-label":"Grid height",className:"w-[150px] h-9 whitespace-nowrap [&>span]:truncate",children:e.jsx(ze,{})}),e.jsxs(Ue,{children:[e.jsx(me,{value:"fit",children:"Fit to window"}),e.jsx(me,{value:"560",children:"Compact"}),e.jsx(me,{value:"760",children:"Tall"}),e.jsx(me,{value:"1040",children:"Full page"}),e.jsx(me,{value:"1400",children:"Extra tall"})]})]}),z.breakdown&&z.breakdown!=="flat"&&e.jsxs(e.Fragment,{children:[e.jsx(H,{size:"sm",variant:"outline",onClick:()=>B(new Set),title:"Open every group in the grid.",children:"Expand all"}),e.jsx(H,{size:"sm",variant:"outline",onClick:()=>B(new Set(Gr(k,z.breakdown||"flat"))),title:"Close every group so you can scan the group headers only.",children:"Collapse all"})]}),z.breakdown==="family"&&e.jsx(H,{size:"sm",variant:K?"secondary":"outline",onClick:()=>_e(C=>!C),title:"Float families with a warning â no tear-out priced, addition-only, remodel-only â to the top of the grid.",children:"Incomplete families first"}),e.jsxs(H,{size:"sm",variant:"outline",onClick:()=>Ee(k,!0),disabled:!k.length,children:["Select all ",k.length.toLocaleStr
11ing()]}),M.size>0&&e.jsxs(e.Fragment,{children:[e.jsxs(H,{size:"sm",variant:"secondary",disabled:!t,onClick:()=>q(!0),children:[e.jsx(en,{className:"h-4 w-4 mr-1"})," Bulk edit ",M.size]}),t&&bs.length>0&&e.jsxs(H,{size:"sm",variant:"outline",onClick:()=>$r(!1),title:"Retire every selected active row â one audited run.",children:[e.jsx(tr,{className:"h-4 w-4 mr-1"})," Retire ",bs.length]}),t&&fs.length>0&&e.jsxs(H,{size:"sm",variant:"outline",onClick:()=>$r(!0),title:"Restore every selected retired row â one audited run.",children:[e.jsx(on,{className:"h-4 w-4 mr-1"})," Restore ",fs.length]}),e.jsx(H,{variant:"ghost",size:"sm",onClick:()=>D(new Set),children:"Clear selection"})]}),Qe>0&&e.jsxs(H,{variant:"ghost",size:"sm",onClick:()=>c({}),children:[e.jsx(ot,{className:"h-4 w-4 mr-1"})," Discard all (",Qe,")"]}),e.jsxs(H,{size:"sm",disabled:!t||Qe===0,onClick:()=>h(!0),children:[e.jsx(lt,{className:"h-4 w-4 mr-1"})," Save all changes ",Qe>0?`(${Qe})`:""]}),e.jsx(Tt,{view:F==="attention"?"Needs attention":"Prices",scope:d,filterSummary:`${k.length} of ${A.length} rows · view ${F}${z.searchText?` · search "${z.searchText}"`:""}${(Ar=z.cards)!=null&&Ar.length?` · ${z.cards.length} card(s)`:""}${(Er=z.trades)!=null&&Er.length?` · ${z.trades.length} trade(s)`:""}`,filenameBase:`pricing-${F}-${d}`,buildSheets:()=>[gl(F==="attention"?"Needs attention":"Prices",k,d)],liveRows:()=>$c(k),importKinds:["catalog"],extraExports:[{label:`Export entire catalog (${A.length} rows)`,filenameBase:`pricing-all-${d}
11`,filterSummary:`entire catalog · ${A.length} rows`,view:"All prices",buildSheets:()=>[gl("All prices",A,d)]}],onImported:async()=>{c({}),await de()},disabled:oe})]})]}),e.jsx(Yo,{platformMetadata:t,canEdit:t,items:k,mergedKeys:Oe.mergedKeys,onUnmergePair:P,bandCodes:v,onOpenBands:t?C=>se("bands",{bandFocus:C.item_code}):void 0,narrativeFirst:F==="attention",visibleColumns:ra,prettyCol:Tl,staged:n,onCell:si,onEdit:E,onToggleActive:C=>{Lt(""),kr(C.is_active===!1),ut([C])},isLoading:oe,healthFor:S,tier:z.tier,selectedKeys:M,onToggleRow:we,onToggleAll:ne,onToggleMany:Ee,breakdown:z.breakdown,unfilteredItems:A,incompleteFamiliesFirst:K,height:ce,collapsedGroups:X,onCollapsedGroupsChange:B})]})]}),t&&e.jsxs(oa,{value:"history",className:"space-y-3",children:[e.jsx($d,{universe:A,scope:d,canRunBulk:t,onFinished:()=>{de(),l.invalidateQueries({queryKey:["catalog-price-change-runs"]})}}),e.jsx(Yn,{})]}),e.jsx(Ha,{open:_a.length>0,onOpenChange:C=>!C&&ut([]),children:e.jsxs(Qa,{className:"max-w-md",children:[e.jsxs(Ja,{children:[e.jsx(Ya,{children:ht?`Restore ${_a.length} price${_a.length===1?"":"s"}`:`Retire ${_a.length} price${_a.length===1?"":"s"}`}),e.jsx(it,{children:ht?"The V2 readers will price these rows again on new projects.":"The V2 readers will skip these rows on new projects. Existing projects keep their frozen totals."})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(Ma,{className:"max-h-[160px] rounded-md border border-primary/20 p-2",children:_a.map(C=>e.jsxs("div",{className:"text-xs py-0.5",children:[e.jsx("span",{className:"font-medium",children:C.item_name})," ",e.jsx("span",{className:"text-muted-foreground font-mono",children:C.item_code})]},C.key))}),e.jsx(xe,{className:"text-xs",children:"Reason (required)"}),e.jsx(ct,{value:gs,onChange:C=>Lt(C.target.value),placeholder:"Why are these prices leaving or re-entering the catalog?",rows:3})]}),e.jsxs(Xa,{children:[e.jsx(H,{variant:"outline",onClick:()=>ut([]),children:"Cancel"}),e.jsx(H,{disabled:Cr||gs.trim().length<3,onClick:ri,children:Cr?"Applyingâ¦":ht?"Restore":"Retire"})]})]})}),e.jsx(yd,{open:f,onOpenChange:q,selectedItems:ya,fieldGroups:zs,onStage:mt}),t&&e.jsx(xd,{item:U,scope:d,allItems:te,open:!!U,onOpenChange:C=>!C&&E(null),onApplied:()=>de()}),x&&e.jsx(Ua,{verdict:x.verdict,aiNotes:x.aiNotes,reviewerNote:x.reviewerNote,reverted:x.reverted,rechecking:N,onRecheck:x.runId?async()=>{y(!0);const C=await qa({run_id:x.runId,scope:d});u({...x,verdict:C.verdict,aiNotes:C.ai_notes,reviewerNote:C.reviewer_note}),y(!1)}:void 0}),e.jsx(Ha,{open:m,onOpenChange:h,children:e.jsxs(Qa,{className:"max-w-3xl",children:[e.jsxs(Ja,{children:[e.jsxs(Ya,{children:["Review ",Qe," price change",Qe===1?"":"s"]}),e.jsx(it,{children:d==="global"?"Global catalog rows will be updated for every company. New projects inherit the new prices.":"Company catalog rows will be updated for your company only. Missing company rows are cloned from the global template first."})]}),e.jsx(Ma,{className:"max-h-[360px] border rounded-md",children:e.jsxs(Ze,{children:[e.jsx(ea,{children:e.jsxs(Le,{children:[e.jsx(Z,{children:"Item"}),e.jsx(Z,{children:"Field"}),e.jsx(Z,{className:"text-right",children:"Old"}),e.jsx(Z,{className:"text-right",children:"New"}),e.jsx(Z,{className:"text-right",children:"Î"})]})}),e.jsx(aa,{children:ti.map(C=>e.jsxs(Le,{children:[e.jsxs(Q,{className:"text-xs",children:[e.jsx("div",{className:"font-medium",children:C.item.item_name}),e.jsx("div",{className:"text-muted-foreground font-mono",children:C.item.item_code}),C.bothSides&&e.jsx("div",{className:"text-primary",children:"Applies to addition and remodel"})]}),e.jsx(Q,{className:"text-xs capitalize",children:Tl(C.column)}),e.jsx(Q,{className:"text-right text-xs",children:Us(C.oldValue)}),e.jsx(Q,{className:"text-right text-xs font-semibold",children:Us(C.newValue)}),e.jsxs(Q,{className:`text-right text-xs ${C.newValue-(C.oldValue??0)>=0?"text-primary":"text-destructive"}`,children:[C.newValue-(C.oldValue??0)>=0?"+":"",Us(C.newValue-(C.oldValue??0))]})]},`${C.key}-${C.column}`))})]})}),ws.length>0&&e.jsxs(da,{variant:"destructive",children:[e.jsx(Xe,{className:"h-4 w-4"}),e.jsx(Sa,{children:"Finish tiers would go out of order"}),e.jsxs(ma,{className:"space-y-2",children:[e.jsx("div",{className:"text-xs",children:"Tier pricing must stay Entry ⤠Good ⤠Better ⤠Best within each money family. You can edit any subset of tiers as long as the result stays in order."}),e.jsx("ul",{className:"text-xs list-disc pl-4 space-y-0.5",children:ws.map(C=>e.jsxs("li",{children:[e.jsx("span",{className:"font-medium",children:C.item.item_name})," ",e.jsx("span",{className:"font-mono",children:C.item.item_code})," â ",C.problems.join("; ")]},C.item.key))}),t&&e.jsxs("label",{className:"flex items-start gap-2 text-xs pt-1",children:[e.jsx("input",{type:"checkbox",className:"mt-0.5",checked:j,onChange:C=>b(C.target.checked)}),e.jsx("span",{children:"Apply anyway â I am deliberately re-baselining these tiers. A reason is required and this override is recorded in the price-change audit trail."})]})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Reason / notes (stored
11in the audit trail)"}),e.jsx(ct,{value:L,onChange:C=>I(C.target.value),rows:2,placeholder:"e.g. 2026 Q3 supplier increase on cabinetry"})]}),e.jsxs(Xa,{children:[e.jsx(H,{variant:"outline",onClick:()=>h(!1),disabled:$,children:"Cancel"}),e.jsx(H,{onClick:li,disabled:$||ws.length>0&&(!j||!L.trim()),children:$?e.jsxs(e.Fragment,{children:[e.jsx(Fe,{className:"h-4 w-4 mr-1 animate-spin"})," Applyingâ¦"]}):e.jsxs(e.Fragment,{children:["Apply ",Qe," change",Qe===1?"":"s"]})})]})]})})]})}const Kt=["border-primary/40 bg-primary/10 text-primary","border-accent/50 bg-accent/20 text-accent-foreground","border-ring/40 bg-ring/10 text-foreground","border-destructive/40 bg-destructive/10 text-destructive","border-secondary-foreground/30 bg-secondary/50 text-secondary-foreground","border-muted-foreground/30 bg-muted/60 text-muted-foreground"],Rd={structural:0,kitchen:1,bar:1,hvac:1,"hvac extension":1,roofing:2,siding:2,windows:2,"patio doors":2,skylights:2,electrical:3,"full baths":4,"half baths":4,"primary baths":4,"base pricing":5,"finish allowances":5};function Td(a){let t=0;for(let s=0;s<a.length;s+=1)t=(t*31+a.charCodeAt(s))%100003;return t}function Nr(a){const t=(a||"").toLowerCase().trim();if(!t)return Kt[5];const s=Rd[t];return s!==void 0?Kt[s]:Kt[Td(t)%Kt.length]}const Wt={searchText:"",stateCode:"NJ",categories:[],costType:"both",finishLevels:[],priceRange:[0,1e4],modifiedWithinDays:null},Ld=["NJ","NY","PA","CT","MA","CA","TX","FL","IL","OH","GA","NC","MI","VA","WA","AZ","TN","IN","MO","MD","WI","CO","MN","SC","AL","LA","KY","OR","OK","UT","IA","NV","AR","MS","KS","NM","NE","WV","ID","HI","NH","ME","MT","RI","DE","SD","ND","AK","VT","WY","DC"],Md=["Entry","Good","Better","Best"];function Pd({onFiltersChange:a,resultCount:t,availableCategories:s=[],canEditStates:r=!1}){const[l,o]=p.useState(Wt),i=(c,m)=>{const h={...l,[c]:m};o(h),a(h)},d=(c,m)=>{const h=l[c],j=h.includes(m)?h.filter(b=>b!==m):[...h,m];i(c,j)},_=()=>{o(Wt),a(Wt)};p.useEffect(()=>{a(Wt)},[]),p.useEffect(()=>{!r&&l.stateCode!=="NJ"&&i("stateCode","NJ")},[r,l.stateCode]);const n=p.useMemo(()=>{let c=0;return l.searchText&&c++,l.stateCode!=="NJ"&&c++,l.categories.length&&c++,l.costType!=="both"&&c++,l.finishLevels.length&&c++,(l.priceRange[0]>0||l.priceRange[1]<1e4)&&c++,l.modifiedWithinDays!==null&&c++,c},[l]);return e.jsx(ye,{className:"border-l-4 border-l-primary/60",children:e.jsxs(je,{className:"p-4 space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2 flex-wrap",children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx(an,{className:"h-4 w-4 text-primary"}),e.jsx("h3",{className:"font-semibold truncate",children:"Search & Filter"}),n>0&&e.jsxs(ie,{variant:"secondary",className:"whitespace-nowrap",children:[n," active"]}),t!==void 0&&e.jsxs(ie,{variant:"outline",className:"whitespace-nowrap",children:[t," items"]})]}),e.jsxs(H,{variant:"ghost",size:"sm",onClick:_,disabled:n===0,children:[e.jsx(Et,{className:"h-4 w-4 mr-1"})," Reset"]})]}),e.jsxs("div",{className:`grid grid-cols-1 gap-4 md:grid-cols-2 ${r?"lg:grid-cols-3":""}`,children:[e.jsxs("div",{className:"space-y-2 min-w-0",children:[e.jsx(xe,{children:"Search"}),e.jsxs("div",{className:"relative",children:[e.jsx(Va,{className:"absolute left-2 top-2.5 h-4 w-4 text-muted-foreground"}),e.jsx(Pe,{placeholder:"Item code or name...",value:l.searchText,onChange:c=>i("searchText",c.target.value),className:"pl-8"})]})]}),r&&e.jsxs("div",{className:"space-y-2 min-w-0",children:[e.jsx(xe,{children:"State"}),e.jsxs(Be,{value:l.stateCode,onValueChange:c=>i("stateCode",c),children:[e.jsx(Ve,{children:e.jsx(ze,{})}),e.jsx(Ue,{className:"max-h-[300px]",children:Ld.map(c=>e.jsxs(me,{value:c,children:[c," ",c==="NJ"&&"(Baseline)"]},c))})]})]}),e.jsxs("div",{className:"space-y-2 min-w-0",children:[e.jsx(xe,{children:"Cost Type"}),e.jsxs(Be,{value:l.costType,onValueChange:c=>i("costType",c),children:[e.jsx(Ve,{children:e.jsx(ze,{})}),e.jsxs(Ue,{children:[e.jsx(me,{value:"both",children:"Labor + Material"}),e.jsx(me,{value:"labor",children:"Labor Only"}),e.jsx(me,{value:"material",children:"Material Only"})]})]})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2 flex-wrap",children:[e.jsxs(xe,{children:["Categories (",s.length," sources)"]}),l.categories.length>0&&e.jsxs(H,{variant:"ghost",size:"sm",className:"h-6 px-2 text-xs",onClick:()=>i("categories",[]),children:["Clear ",l.categories.length]})]}),e.jsxs("div",{className:"flex flex-wrap gap-2 max-h-40 overflow-y-auto overflow-x-hidden",children:[s.map(({label:c,count:m})=>{const h=l.categories.includes(c);return e.jsxs("button",{type:"button",onClick:()=>d("categories",c),className:["inline-flex items-center gap-1 rounded-full border px-2.5 py-0.5 text-xs font-medium transition-colors max-w-full",Nr(c),h?"ring-2 ring-primary ring-offset-1 ring-offset-background":"opacity-80 hover:opacity-100"].join(" "),children:[e.jsx("span",{className:"truncate",children:c}),e.jsxs("span",{className:"opacity-70",children:["(",m,")"]})]},c)}),s.length===0&&e.jsx("span",{className:"text-xs text-muted-foreground",children:"Loading c
11ategoriesâ¦"})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(xe,{children:"Finish Levels (applies only to tiered tables)"}),e.jsx("div",{className:"flex flex-wrap gap-2",children:Md.map(c=>e.jsx(ie,{variant:l.finishLevels.includes(c)?"default":"outline",className:"cursor-pointer",onClick:()=>d("finishLevels",c),children:c},c))})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex justify-between",children:[e.jsx(xe,{children:"Price Range"}),e.jsxs("span",{className:"text-sm text-muted-foreground font-mono",children:["$",l.priceRange[0]," â $",l.priceRange[1]]})]}),e.jsx(Ct,{min:0,max:1e4,step:50,value:l.priceRange,onValueChange:c=>i("priceRange",c)})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(ca,{id:"modified-recent",checked:l.modifiedWithinDays!==null,onCheckedChange:c=>i("modifiedWithinDays",c?30:null)}),e.jsx(xe,{htmlFor:"modified-recent",className:"cursor-pointer",children:"Modified in last"}),e.jsx(Pe,{type:"number",min:1,max:365,disabled:l.modifiedWithinDays===null,value:l.modifiedWithinDays??30,onChange:c=>i("modifiedWithinDays",parseInt(c.target.value)||30),className:"w-20"}),e.jsx("span",{className:"text-sm",children:"days"})]})]})})}const Id=[-10,-5,-2,2,5,10],Ll=-70,Ml=200;function Fd({items:a,stateCodes:t,scope:s="global",filterSnapshot:r,onApplied:l,layout:o="vertical",onPreviewChange:i}){const{toast:d}=pr(),[_,n]=p.useState("percentage"),[c,m]=p.useState(0),[h,j]=p.useState("both"),[b,x]=p.useState(!1),[u,N]=p.useState(null),[y,L]=p.useState(!1),I=_==="percentage"?Ll:-500,$=_==="percentage"?Ml:500,ee=_==="percentage"?.5:5,U=g=>Math.min($,Math.max(I,g)),E=g=>{const S=U(Number.isFinite(g)?g:0);m(S),i==null||i({mode:_,value:S,appliesTo:h})},J=g=>{n(g);const S=g==="percentage"?Math.min(Ml,Math.max(Ll,c)):c;m(S),i==null||i({mode:g,value:S,appliesTo:h})},be=g=>{j(g),i==null||i({mode:_,value:c,appliesTo:g})},F=p.useMemo(()=>{let g=0,S=0;return a.forEach(R=>{g+=R.labor_rate||0,S+=R.material_rate||0}),{labor:g,material:S,total:g+S}},[a]),se=p.useMemo(()=>{if(!a.length||c===0)return{totalImpact:0,perItemAvg:0,sampleNew:0,sampleOld:0};let g=0;a.forEach(te=>{const oe=[];(h==="labor"||h==="both")&&oe.push(te.labor_rate||0),(h==="material"||h==="both")&&oe.push(te.material_rate||0),oe.forEach(A=>{const de=_==="percentage"?A*(1+c/100):A+c;g+=de-A})});const S=Math.max(t.length,1);g*=S;const R=a[0],v=h==="material"?R.material_rate:R.labor_rate,G=_==="percentage"?v*(1+c/100):v+c;return{totalImpact:g,perItemAvg:g/Math.max(a.length,1),sampleOld:v,sampleNew:G}},[a,c,_,h,t]),V=async()=>{if(!a.length||c===0){d({title:"Nothing to apply",description:"Select items and set a non-zero value.",variant:"destructive"});return}x(!0),N(null);try{const g={items:a.map(oe=>({source_table:oe.source_table,id:oe.id,item_code:oe.item_code,current_labor:oe.labor_rate,current_material:oe.material_rate})),state_codes:t,mode:_,value:c,applies_to:h,scope:s,filter_snapshot:r||{}},{data:S,error:R}=await ge.functions.invoke("apply-bulk-price-adjustment",{body:g}),v=await wa(S,R);if(v.verdict&&N(v),R)throw R;if(S!=null&&S.error)throw new Error(S.error);const G=(S==null?void 0:S.updated_count)??0,te=(S==null?void 0:S.errors)??[];
11d({title:te.length?"Bulk Update Partially Applied":"Bulk Update Applied",description:`Updated ${G} row(s) across ${t.length} state(s). Total impact: $${((S==null?void 0:S.total_impact)??0).toFixed(2)}${te.length?` â ${te.length} error(s)`:""}`,variant:te.length?"destructive":"default"}),E(0),l==null||l()}catch(g){d({title:"Update Failed",description:g.message||"Failed to apply bulk update",variant:"destructive"})}finally{x(!1)}},z=c>0,Se=c<0,re=u?e.jsx(Ua,{verdict:u.verdict,aiNotes:u.aiNotes,reviewerNote:u.reviewerNote,reverted:u.reverted,rechecking:y,onRecheck:u.runId?async()=>{L(!0);const g=await qa({run_id:u.runId,scope:s==="company"?"company":"global"});N({...u,verdict:g.verdict,aiNotes:g.ai_notes,reviewerNote:g.reviewer_note}),L(!1)}:void 0,className:"mt-3"}):null,$e=e.jsxs(Kl,{children:[e.jsx(hi,{asChild:!0,children:e.jsx(H,{disabled:!a.length||c===0||b,size:o==="horizontal"?"default":"lg",className:"w-full max-w-full justify-center whitespace-nowrap",children:b?e.jsxs(e.Fragment,{children:[e.jsx(Fe,{className:"h-4 w-4 mr-2 animate-spin"})," Applying..."]}):e.jsxs(e.Fragment,{children:[e.jsx(lt,{className:"h-4 w-4 mr-2"})," Apply Bulk Update"]})})}),e.jsxs(Wl,{children:[e.jsxs(Gl,{children:[e.jsxs(Hl,{className:"flex items-center gap-2",children:[e.jsx(Xe,{className:"h-5 w-5 text-amber-500"}),"Confirm Bulk Price Update"]}),e.jsx(Ql,{asChild:!0,children:e.jsxs("div",{className:"space-y-2 pt-2",children:[e.jsxs("div",{children:["You are about to update ",e.jsxs("strong",{children:[a.length," items"]})," across ",e.jsxs("strong",{children:[t.length," state(s)"]}),"."]}),e.jsxs("div",{className:"bg-muted p-3 rounded space-y-1 text-sm font-mono",children:[e.jsxs("div",{children:["Mode: ",_==="percentage"?`${c}%`:`$${c}`]}),e.jsxs("div",{children:["Applies To: ",h]}),e.jsxs("div",{children:["Total Impact: ",e.jsxs("span",{className:z?"text-success":"text-destructive",children:[z?"+":"","$",se.totalImpact.toFixed(2)]})]})]}),e.jsxs("div",{className:"bg-muted p-3 rounded text-sm",children:["Scope: ",e.jsx("strong",{children:s==="company"?"Your company pricing only":"Global catalog (all companies)"})]}),e.jsx("div",{className:"text-xs text-muted-foreground",children:"This will be logged in the audit trail and can be rolled back."})]})})]}),e.jsxs(Jl,{children:[e.jsx(Yl,{children:"Cancel"}),e.jsx(Xl,{onClick:V,children:"Confirm & Apply"})]})]})]});return o==="horizontal"?e.jsxs(ye,{className:"border-primary/30",children:[e.jsx(ke,{className:"pb-3",children:e.jsxs(Ce,{className:"flex items-center justify-between flex-wrap gap-2",children:[e.jsxs("span",{className:"flex items-center gap-2",children:["Bulk Price Adjustment",c!==0&&e.jsxs(ie,{variant:z?"default":"destructive",className:"font-mono",children:[z?"+":"",c,_==="percentage"?"%":"$"]})]}),e.jsxs("div",{className:"flex gap-2 flex-wrap",children:[e.jsxs(ie,{variant:"secondary",children:[a.length," items"]}),e.jsxs(ie,{variant:"outline",children:[t.length," state",t.length!==1?"s":""]}),a.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs(ie,{variant:"outline",className:"font-mono",children:["L: $",F.labor.toFixed(0)]}),e.jsxs(ie,{variant:"outline",className:"font-mono",children:["M: $",F.material.toFixed(0)]})]})]})]})}),e.jsxs(je,{children:[e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-12 gap-4 items-end",children:[e.jsxs("div",{className:"lg:col-span-3 space-y-2",children:[e.jsx(xe,{className:"text-xs",children:"Mode"}),e.jsxs(dt,{type:"single",value:_,onValueChange:g=>g&&J(g),className:"justify-start",children:[e.jsx(ta,{value:"percentage",size:"sm",children:"%"}),e.jsx(ta,{value:"fixed",size:"sm",children:"$"})]}),e.jsxs("div",{className:"flex flex-wrap gap-1 pt-1",children:[Id.map(g=>e.jsxs(H,{type:"button",size:"sm",variant:c===g&&_==="percentage"?"default":"outline",className:"h-6 px-2 text-xs font-mono",onClick:()=>{J("percentage"),E(g)},children:[g>0?`+${g}`:g,"%"]},g)),e.jsx(H,{type:"button",size:"sm",variant:"ghost",className:"h-6 px-2 text-xs",onClick:()=>E(0),disabled:c===0,children:e.jsx(ot,{className:"h-3 w-3"})})]})]}),e.jsxs("div",{className:"lg:col-span-5 space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(xe,{className:"text-xs",children:"Adjustment Value"}),e.jsxs("div",{className:"flex items-center gap-1",children:[z&&e.jsx(er,{className:"h-3 w-3 text-success"}),Se&&e.jsx(Lr,{className:"h-3 w-3 text-destructive"}),e.jsx(Pe,{type:"number",value:c,onChange:g=>E(parseFloat(g.target.value)||0),step:ee,min:I,max:$,className:`w-24 h-8 font-mono text-right ${z?"text-success":Se?"text-destructive":""}`}),e.jsx("span",{className:"text-xs text-muted-foreground w-3",children:_==="percentage"?"%":"$"})]})]}),e.jsx(Ct,{min:I,max:$,step:ee,value:[c],onValueChange:g=>E(g[0])}),e.jsxs("div",{className:"flex justify-between text-[10px] text-muted-foreground font-mono",children:[e.jsxs("span",{children:[I,_==="percentage"?"%":"$"]}),e.jsx("span",{children:"0"}),e.jsxs("span",{children:["+",$,_==="percentage"?"%":"$"]})]})]}),e.jsxs("div",{className:"lg:col-span-2 space-y-2",children:[e.jsx(xe,{className:"text-xs",children:"Apply To"}),e.jsxs(Mr,{value:h,onValueChange:g=>be(g),className:"flex flex-col gap-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(et,{value:"both",id:"h-both"}),e.jsx(xe,{htmlFor:"h-both",className:"cursor-pointer text-xs",children:"Labor + Material"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(et,{value:"labor",id:"h-labor"}),e.jsx(xe,{htmlFor:"h-labor",className:"cursor-pointer text-xs",children:"Labor"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(et,{value:"material",id:"h-material"}),e.jsx(xe,{htmlFor:"h-material",className:"cursor-pointer text-xs",children:"Material"})]})]})]}),e.jsxs("div",{className:"lg:col-span-2 space-y-2 min-w-0",children:[c!==0&&a.length>0&&e.jsxs("div",{className:"text-xs",children:[e.jsx("div",{className:"text-muted-foreground",children:"Total Impact"}),e.jsxs("div",{className:`font-mono font-bold text-base ${z?"text-success":"text-destructive"}`,children:[z?"+":"","$",se.totalImpact.toFixed(2)]})]}),$e]})]}),re]}
11)]}):e.jsxs(ye,{children:[e.jsx(ke,{children:e.jsxs(Ce,{className:"flex items-center justify-between",children:[e.jsx("span",{children:"Bulk Price Adjustment"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(ie,{variant:"secondary",children:[a.length," items"]}),e.jsxs(ie,{variant:"outline",children:[t.length," state",t.length!==1?"s":""]})]})]})}),e.jsxs(je,{className:"space-y-6",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(xe,{children:"Adjustment Mode"}),e.jsxs(dt,{type:"single",value:_,onValueChange:g=>g&&J(g),children:[e.jsx(ta,{value:"percentage",children:"Percentage (%)"}),e.jsx(ta,{value:"fixed",children:"Fixed $ Amount"})]})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(xe,{children:"Adjustment Value"}),e.jsxs("div",{className:"flex items-center gap-2",children:[z&&e.jsx(er,{className:"h-4 w-4 text-success"}),Se&&e.jsx(Lr,{className:"h-4 w-4 text-destructive"}),e.jsx(Pe,{type:"number",value:c,onChange:g=>E(parseFloat(g.target.value)||0),step:ee,min:I,max:$,className:`w-28 font-mono text-right ${z?"text-success":Se?"text-destructive":""}`}),e.jsx("span",{className:"text-sm text-muted-foreground w-4",children:_==="percentage"?"%":"$"})]})]}),e.jsx(Ct,{min:I,max:$,step:ee,value:[c],onValueChange:g=>E(g[0])})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(xe,{children:"Apply To"}),e.jsxs(Mr,{value:h,onValueChange:g=>be(g),className:"flex gap-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(et,{value:"both",id:"both"}),e.jsx(xe,{htmlFor:"both",className:"cursor-pointer",children:"Labor + Material"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(et,{value:"labor",id:"labor"}),e.jsx(xe,{htmlFor:"labor",className:"cursor-pointer",children:"Labor Only"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(et,{value:"material",id:"material"}),e.jsx(xe,{htmlFor:"material",className:"cursor-pointer",children:"Material Only"})]})]})]}),$e,re]})]})}const Pl=1e3,Il=5e3;async function Od(a){const t=Ri(a.pattern),s=["id","item_code",`${a.nameColumn}`,a.categoryColumn?a.categoryColumn:null,t.labor,t.material,"updated_at"].filter(Boolean).join(", "),r=[];for(let l=0;l<Il;l+=Pl){const o=Math.min(l+Pl,Il)-1,{data:i,error:d}=await ge.from(a.table).select(s).eq("is_active",!0).range(l,o);if(d)break;const _=i||[];if(r.push(..._),_.length<o-l+1)break}return r.map(l=>{const o=a.categoryColumn&&l[a.categoryColumn]||a.category;return{id:l.id,source_table:a.table,source_label:a.category,item_code:l.item_code,item_name:l[a.nameColumn]||l.item_code,category:o,category_display:xr(o),labor_rate:Number(t.labor?l[t.labor]:0)||0,material_rate:Number(t.material?l[t.material]:0)||0,updated_at:l.updated_at||null}})}function cr(a){return Ke({queryKey:["bulk-pricing-unified",a],queryFn:async()=>{var _,n,c;const t=(await Promise.all(rn.map(Od))).flat(),s=((_=a.searchText)==null?void 0:_.trim().toLowerCase())||"",r=((n=a.priceRange)==null?void 0:n[0])??0,l=((c=a.priceRange)==null?void 0:c[1])??Number.POSITIVE_INFINITY,o=a.costType||"both",i=a.modifiedWithinDays?Date.now()-a.modifiedWithinDays*864e5:null,d=a.categories&&a.categories.length?new Set(a.categories.map(m=>m.toLowerCase())):null;return t.filter(m=>{if(s&&!`${m.item_code} ${m.item_name}`.toLowerCase().includes(s)||d&&!(d.has(m.source_label.toLowerCase())||d.has(m.category_display.toLowerCase()))||i&&m.updated_at&&new Date(m.updated_at).getTime()<i)return!1;const h=j=>j>=r&&j<=l;return!(o==="labor"&&!h(m.labor_rate)||o==="material"&&!h(m.material_rate)||o==="both"&&!(h(m.labor_rate)||h(m.material_rate)))})},staleTime:6e4})}const Dd={searchText:"",stateCode:"NJ",categories:[],costType:"both",finishLevels:[],priceRange:[0,1e4],modifiedWithinDays:null};function Bd(){const{showBulkPriceEditor:a}=ds(),{isAdmin:t,isSuperAdmin:s,isLoading:r}=ns(),l=Zl(),o=s&&l.effectiveIsSuperAdmin,i=!r&&(t||s)&&l.effectiveIsAdmin&&a,d=ln(i&&!o);return r?e.jsx("div",{role:"status",children:"Checking bulk pricing accessâ¦"}):i?o?e.jsx(Vd,{}):e.jsxs(ye,{children:[e.jsx(ke,{children:e.jsx(Ce,{children:"Company bulk pricing"})}),e.jsxs(je,{children:[e.jsx("p",{role:"status",children:d.isFetching?"Confirming company pricing coverageâ¦":d.scope?`Approved coverage: ${d.scope.allowedStateCodes.join(", ")}. Company bulk edits await a reviewed company-scoped pricing service.`:"An active company with approved states is required."}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"The company baseline remains available in Catalog. Platform bulk queries and writes are not loaded here."})]})]}):e.jsxs(ye,{children:[e.jsx(ke,{children:e.jsx(Ce,{children:"Bulk Price Editor unavailable"})}),e.jsx(je,{children:"This account does not have access to bulk pricing adjustments."})]})}function Vd(){const{showBulkPriceEditor:a}=ds(),{isSuperAdmin:t}=ns(),{toast:s}=pr(),[r,l]=p.useState(t?"global":"company"),[o,i]=p.useState(Dd),[d,_]=p.useState(new Set),[n,c]=p.useState(null),[m,h]=p.useState("category"),[j,b]=p.useState("asc");p.useEffect(()=>{!t&&r!=="company"&&l("company")},[t,r]);const{data:x}=cr({priceRange:[0,Number.POSITIVE_INFINITY]}),{data:u,isLoading:N,refetch:y}=cr({searchText:o.searchText,categories:o.categories,costType:o.costType,priceRange:o.priceRange,modifiedWithinDays:o.modifiedWithinDays}),L=p.useMemo(()=>(u||[]).map(v=>({id:v.id,source_table:v.source_table,item_code:v.item_code,item_name:v.item_name,labor_rate:v.labor_rate,material_rate:v.material_rate,category:v.source_label})),[u]),I=p.useMemo(()=>{const v=[...L];return v.sort((G,te)=>{let oe,A;switch(m){case"total":oe=G.labor_rate+G.material_rate,A=te.labor_rate+te.material_rate;break;case"labor_rate":case"material_rate":oe=G[m],A=te[m];break;default:oe=G[m]||"",A=te[m]||""}const de=typeof oe=="number"&&typeof A=="number"?oe-A:String(oe).localeCompare(String(A));return j==="asc"?de:-de}),v},[L,m,j]),$=p.useMemo(()=>{const v=new Map;
11return(x||[]).forEach(G=>v.set(G.source_label,(v.get(G.source_label)||0)+1)),Array.from(v.entries()).sort((G,te)=>G[0].localeCompare(te[0])).map(([G,te])=>({label:G,count:te}))},[x]),ee=p.useMemo(()=>L.filter(v=>d.has(v.id)),[L,d]),U=!!n&&n.value!==0,E=v=>{if(!n||!d.has(v.id))return{applies:!1,labor:v.labor_rate,material:v.material_rate,total:v.labor_rate+v.material_rate};const G=A=>n.mode==="percentage"?A*(1+n.value/100):A+n.value,te=n.appliesTo==="material"?v.labor_rate:G(v.labor_rate),oe=n.appliesTo==="labor"?v.material_rate:G(v.material_rate);return{applies:!0,labor:te,material:oe,total:te+oe}},J=p.useMemo(()=>{let v=0,G=0;I.forEach(A=>{v+=A.labor_rate,G+=A.material_rate});let te=0,oe=0;return ee.forEach(A=>{te+=A.labor_rate,oe+=A.material_rate}),{labor:v,material:G,total:v+G,selLabor:te,selMaterial:oe,selTotal:te+oe}},[I,ee]),be=I.length>0&&d.size===I.length,F=d.size>0&&!be,se=o.stateCode!=="NJ",V=()=>{_(be?new Set:new Set(I.map(v=>v.id)))},z=v=>{const G=new Set(d);G.has(v)?G.delete(v):G.add(v),_(G)},Se=v=>{const G=new Set(d);I.filter(te=>te.category===v).forEach(te=>G.add(te.id)),_(G)},re=()=>{const v=new Set;I.forEach(G=>{d.has(G.id)||v.add(G.id)}),_(v)},$e=v=>{v===m?b(G=>G==="asc"?"desc":"asc"):(h(v),b("asc"))},g=v=>m!==v?e.jsx(Di,{className:"h-3 w-3 opacity-40"}):j==="asc"?e.jsx(pi,{className:"h-3 w-3"}):e.jsx(Bi,{className:"h-3 w-3"}),S=v=>{const G=v==="selected"?ee:I;if(!G.length){s({title:"Nothing to export",variant:"destructive"});return}const oe=[["Source","Item Code","Item Name","Labor","Material","Total"].join(",")].concat(G.map(he=>[he.category||"",he.item_code,`"${(he.item_name||"").replace(/"/g,'""')}"`,he.labor_rate.toFixed(2),he.material_rate.toFixed(2),(he.labor_rate+he.material_rate).toFixed(2)].join(","))).join(` 12`),A=new Blob([oe],{type:"text/csv"}),de=URL.createObjectURL(A),O=document.createElement("a");O.href=de,O.download=`pricing-${v}-${new Date().toISOString().slice(0,10)}.csv`,O.click(),URL.revokeObjectURL(de),s({title:"CSV exported",description:`${G.length} rows downloaded.`})},R=async()=>{if(!ee.length){s({title:"No selection",variant:"destructive"});return}await navigator.clipboard.writeText(ee.map(v=>v.item_code).join(` 13`)),s({title:"Copied",description:`${ee.length} item codes copied to clipboard.`})};return a?e.jsxs("div",{className:"space-y-4",children:[e.jsx(Pd,{onFiltersChange:i,resultCount:I.length,availableCategories:$,canEditStates:t}),e.jsx(ye,{className:r==="company"?"border-l-4 border-l-accent":"border-l-4 border-l-primary",children:e.jsxs(je,{className:"p-3 flex flex-wrap items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[r==="company"?e.jsx(is,{className:"h-4 w-4 text-accent-foreground"}):e.jsx(us,{className:"h-4 w-4 text-primary"}),e.jsx("span",{className:"text-sm font-medium truncate",children:"Write scope"}),e.jsx("span",{className:"text-xs text-muted-foreground truncate",children:r==="company"?"Only your companyâs pricing changes. Global rates stay untouched.":"The shared catalog â every company inherits these rates."})]}),t?e.jsxs(dt,{type:"single",value:r,onValueChange:v=>v&&l(v),className:"flex-shrink-0",children:[e.jsx(ta,{value:"global",size:"sm",className:"whitespace-nowrap",children:"Global catalog"}),e.jsx(ta,{value:"company",size:"sm",className:"whitespace-nowrap",children:"My company"})]}):e.jsx(ie,{variant:"outline",className:"whitespace-nowrap",children:"Company scope"})]})}),se&&t&&e.jsx(ye,{className:"border-amber-500/50 bg-amber-500/10",children:e.jsxs(je,{className:"p-3 flex items-start gap-2 text-sm",children:[e.jsx(Xe,{className:"h-4 w-4 text-amber-600 mt-0.5 flex-shrink-0"}),e.jsxs("span",{children:[e.jsxs("strong",{children:["State = ",o.stateCode,"."]})," Edits will adjust the state pricing ratios for ",o.stateCode,"â the NJ baseline rates are NOT modified."]})]})}),e.jsx(Fd,{items:ee,stateCodes:[t?o.stateCode:"NJ"],scope:r,filterSnapshot:o,layout:"horizontal",onPreviewChange:c,onApplied:()=>{_(new Set),c(null),y()}}),e.jsxs(ye,{children:[e.jsx(ke,{className:"pb-3",children:e.jsxs(Ce,{className:"flex items-center justify-between flex-wrap gap-2",children:[e.jsxs("span",{className:"flex items-center gap-2",children:["Filtered Results",e.jsxs(ie,{variant:"secondary",children:[I.length," rows"]}),d.size>0&&e.jsxs(ie,{children:[d.size," selected"]})]}),e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsxs(ie,{variant:"outline",className:"font-mono text-xs",children:["Σ Labor $",J.labor.toFixed(0)," · Material $",J.material.toFixed(0)]}),d.size>0&&e.jsxs(ie,{variant:"default",className:"font-mono text-xs",children:["Selected: $",J.selTotal.toFixed(0)]}),e.jsxs(Qs,{children:[e.jsx(Js,{asChild:!0,children:e.jsxs(H,{variant:"outline",size:"sm",className:"h-8",children:[e.jsx(Dr,{className:"h-3 w-3 mr-1"})," Select"]})}),e.jsxs(Xs,{align:"end",className:"w-56 max-h-80 overflow-y-auto",children:[e.jsxs(Oa,{onClick:V,children:[be?e.jsx(Oi,{className:"h-4 w-4 mr-2"}):e.jsx(Dr,{className:"h-4 w-4 mr-2"}),be?"Clear all":"Select all filtered"]}),e.jsx(Oa,{onClick:re,children:"Invert selection"}),e.jsx(ql,{}),e.jsx(Zs,{className:"text-xs",children:"By category"}),$.filter(v=>I.some(G=>G.category===v.label)).map(v=>e.jsxs(Oa,{onClick:()=>Se(v.label),children:[v.label," ",e.jsx(ie,{variant:"secondary",className:"ml-auto",children:v.count})]},v.label))]})]}),e.jsxs(Qs,{children:[e.jsx(Js,{asChild:!0,children:e.jsxs(H,{variant:"outline",size:"sm",className:"h-8",children:[e.jsx(Wa,{className:"h-3 w-3 mr-1"})," Export"]})}),e.jsxs(Xs,{align:"end",children:[e.jsxs(Oa,{onClick:()=>S("filtered"),children:["Export filtered (",I.length,") as CSV"]}),e.jsxs(Oa,{onClick:()=>S("selected"),disabled:!ee.length,children:["Export selected (",ee.length,") as CSV"]})]})]}),e.jsxs(H,{variant:"outline",size:"sm",className:"h-8",onClick:R,disabled:!ee.length,children:[e.jsx(_i,{className:"h-3 w-3 mr-1"})," Copy codes"]})]})]})}),e.jsx(je,{children:N?e.jsx("div",{className:"flex justify-center p-8",children:e.jsx(Fe,{className:"h-6 w-6 animate-spin"})}):e.jsx("div",{className:"max-h-[600px] overflow-y-auto overflow-x-hidden border rounded-lg",children:e.jsxs(Ze,{className:"w-full table-fixed",children:[e.jsx(ea,{className:"sticky top-0 bg-background z-10",children:e.jsxs(Le,{children:[e.jsx(Z,{className:"w-10",children:e.jsx(ca,{checked:be?!0:F?"indeterminate":!1,onCheckedChange:V})}),e.jsx(Z,{className:"w-[16%] cursor-pointer",onClick:()=>$e("category"),children:e.jsxs("span",{className:"inline-flex items-center gap-1",children:["Source ",g("category")]})}
13),e.jsx(Z,{className:"w-[18%] cursor-pointer",onClick:()=>$e("item_code"),children:e.jsxs("span",{className:"inline-flex items-center gap-1",children:["Code ",g("item_code")]})}),e.jsx(Z,{className:"cursor-pointer",onClick:()=>$e("item_name"),children:e.jsxs("span",{className:"inline-flex items-center gap-1",children:["Name ",g("item_name")]})}),e.jsx(Z,{className:"w-[11%] text-right cursor-pointer",onClick:()=>$e("labor_rate"),children:e.jsxs("span",{className:"inline-flex items-center gap-1 justify-end w-full",children:["Labor $ ",g("labor_rate")]})}),e.jsx(Z,{className:"w-[11%] text-right cursor-pointer",onClick:()=>$e("material_rate"),children:e.jsxs("span",{className:"inline-flex items-center gap-1 justify-end w-full",children:["Material $ ",g("material_rate")]})}),e.jsx(Z,{className:"w-[11%] text-right cursor-pointer",onClick:()=>$e("total"),children:e.jsxs("span",{className:"inline-flex items-center gap-1 justify-end w-full",children:["Total $ ",g("total")]})}),U&&e.jsx(Z,{className:"w-[13%] text-right text-primary",children:e.jsx("span",{className:"inline-flex items-center gap-1 justify-end w-full",children:"New total $"})})]})}),e.jsxs(aa,{children:[I.map(v=>e.jsxs(Le,{className:"cursor-pointer",onClick:()=>z(v.id),"data-state":d.has(v.id)?"selected":void 0,children:[e.jsx(Q,{children:e.jsx(ca,{checked:d.has(v.id),onCheckedChange:()=>z(v.id),onClick:G=>G.stopPropagation()})}),e.jsx(Q,{className:"min-w-0",children:e.jsx("span",{className:`inline-flex max-w-full items-center rounded-full border px-2 py-0.5 text-[10px] font-medium ${Nr(v.category)}`,title:v.category,children:e.jsx("span",{className:"truncate",children:v.category})})}),e.jsx(Q,{className:"font-mono text-xs truncate",title:v.item_code,children:v.item_code}),e.jsx(Q,{className:"text-sm truncate",title:v.item_name,children:v.item_name}),e.jsxs(Q,{className:"text-right font-mono",children:["$",v.labor_rate.toFixed(2)]}),e.jsxs(Q,{className:"text-right font-mono",children:["$",v.material_rate.toFixed(2)]}),e.jsxs(Q,{className:"text-right font-mono font-semibold",children:["$",(v.labor_rate+v.material_rate).toFixed(2)]}),U&&(()=>{const G=E(v),te=G.total-(v.labor_rate+v.material_rate);return e.jsx(Q,{className:"text-right font-mono",children:G.applies?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:te>=0?"text-success font-semibold":"text-destructive font-semibold",children:["$",G.total.toFixed(2)]}),e.jsxs("div",{className:"text-[10px] text-muted-foreground",children:["L $",G.labor.toFixed(2)," · M $",G.material.toFixed(2)]})]}):e.jsx("span",{className:"text-[10px] text-muted-foreground",children:"not selected"})})})()]},`${v.source_table}:${v.id}`)),I.length===0&&e.jsx(Le,{children:e.jsx(Q,{colSpan:U?8:7,className:"text-center text-muted-foreground py-8",children:"No items match the current filters."})})]})]})})})]})]}):e.jsxs(ye,{children:[e.jsx(ke,{children:e.jsxs(Ce,{className:"flex items-center gap-2",children:[e.jsx(tn,{className:"h-5 w-5 text-amber-500"}),"Bulk Price Editor not included"]})}),e.jsx(je,{children:e.jsx("p",{className:"text-sm text-muted-foreground",children:"Bulk price adjustments via slider are available on Enterprise plans. Upgrade to apply % or $ changes across many items at once."})})]})}const ts=["entry","good","better","best"],Xn=a=>ts.reduce((t,s)=>t+Math.abs(Number(a[`${s}_price`]??0)),0),Zn=a=>Math.abs(Number(a.base_rate_money??0))+Math.abs(Number(a.flat_allowance_money??0)),Fl=a=>Xn(a)===0&&Zn(a)===0,Ol=a=>Xn(a)===0&&Zn(a)>0,zd=a=>{const t=ts.map(s=>Math.abs(Number(a[`${s}_price`]??0)));return t.some(s=>s>0)&&t.some(s=>s===0)},Dl=["hsl(var(--primary))","hsl(var(--accent))","#f59e0b","#10b981","#6366f1","#ec4899","#14b8a6","#f97316","#8b5cf6","#06b6d4","#84cc16","#e11d48","#0ea5e9","#a855f7","#22c55e","#ef4444"],Ud=()=>{const[a,t]=p.useState(""),[s,r]=p.useState("all"),[l,o]=p.useState("all"),[i,d]=p.useState("active"),[_,n]=p.useState("all"),[c,m]=p.useState("global"),[h,j]=p.useState(!1),[b,x]=p.useState(null),[u,N]=p.useState({}),[y,L]=p.useState(""),[I,$]=p.useState(!1),[ee,U]=p.useState("overview"),[E,J]=p.useState(null),[be,F]=p.useState(!1),se=$a(),{profile:V}=ur(),{data:z,isSuccess:Se}=Rt(!0),{data:re,isLoading:$e,refetch:g}=Ke({queryKey:["v2-allowances-audit",c,V==null?void 0:V.company_id],queryFn:async()=>{const k={};
13c==="company"&&(V!=null&&V.company_id)&&(k.companyId=V.company_id);const{data:w,error:P}=await ge.functions.invoke("get-unified-v2-allowances",{body:k});if(P)throw P;return{items:(w==null?void 0:w.items)||[],stats:(w==null?void 0:w.stats)||{totalItems:0,tablesQueried:0}}}}),S=p.useMemo(()=>(re==null?void 0:re.items)??[],[re==null?void 0:re.items]),{data:R=[]}=Ke({queryKey:["missing-pricing-items-audit"],queryFn:async()=>{const{data:k,error:w}=await ge.from("missing_pricing_items").select("*").eq("status","pending").order("reference_count",{ascending:!1}).returns();if(w)throw w;return k}}),{data:v}=Ke({queryKey:["company-info-audit",V==null?void 0:V.company_id],queryFn:async()=>{if(!(V!=null&&V.company_id))return null;const{data:k,error:w}=await ge.from("companies").select("id, company_name").eq("id",V.company_id).maybeSingle();if(w)throw w;return k},enabled:!!(V!=null&&V.company_id)}),G=p.useCallback(async()=>{j(!0);try{await se.invalidateQueries({queryKey:["v2-allowances-audit"]}),await se.invalidateQueries({queryKey:["missing-pricing-items-audit"]}),await g(),le.success("Pricing data synced fresh from all V2 tables")}catch{le.error("Failed to sync pricing data")}finally{j(!1)}},[se,g]),te=k=>{x(k),L("");const w={};for(const P of ts)w[`${P}_allowance_labor`]=String(Number(k[`${P}_allowance_labor`]??0)),w[`${P}_allowance_material`]=String(Number(k[`${P}_allowance_material`]??0));N(w)},oe=async()=>{var k,w;if(b){$(!0),J(null);try{const P={};for(const[ue,T]of Object.entries(u)){const ce=parseFloat(T);if(!Number.isFinite(ce)||ce<0)throw new Error(`"${ue.replace(/_/g," ")}" must be a number of $0 or more`);const X=Number(b[ue]??0);ce!==X&&(P[ue]=ce)}if(!Object.keys(P).length){le.info("Nothing changed"),x(null);return}const{data:M,error:D}=await ge.functions.invoke("apply-catalog-price-update",{body:{scope:c,notes:y||null,allow_partial_tiers:!0,changes:[{source_table:b.source_table,global_row_id:b.id,item_code:b.item_code,item_name:b.item_name,fields:P}]}}),fe=await wa(M,D);if(fe.verdict&&J(fe),se.invalidateQueries({queryKey:["pricing-wiring-verdicts","latest"]}),D&&!fe.verdict)throw new Error((M==null?void 0:M.error)||Ir(D)||"Update rejected");if(M!=null&&M.error&&!(M!=null&&M.success)&&!fe.verdict)throw new Error(typeof M.error=="string"?M.error:"Update rejected");const ve=(k=fe.verdict)==null?void 0:k.state;ve==="fail"?le.error("Change reverted â the final wiring check failed",{description:((w=fe.verdict)==null?void 0:w.failingSurfaces.join(", "))||"See the verdict panel for the failing surface."}):ve==="warn"?le.warning(`Applied with cautions for ${b.item_name}`,{description:"Read the verdict panel before relying on it."}):le.success(`Updated allowances for ${b.item_name}`,{description:"Applies to future estimates. Existing projects keep their totals and are flagged stale."}),(!ve||ve==="pass")&&x(null),g()}catch(P){le.error(`Failed to update: ${Ir(P)}`)}finally{$(!1)}}},A=p.useMemo(()=>{const k=S.filter(ue=>ue.is_active).length,w=S.length-k,P=new Set(S.map(ue=>ue.source_table)).size,M=S.filter(ue=>Number(ue.good_price??0)>0).map(ue=>Number(ue.good_price)).sort((ue,T)=>ue-T),D=M.length?M.length%2?M[(M.length-1)/2]:(M[M.length/2-1]+M[M.length/2])/2:0,fe=S.filter(ue=>ue.is_active&&Fl(ue)).length,ve=S.filter(ue=>ue.is_active&&Ol(ue)).length;return{activeItems:k,inactiveItems:w,sourceTables:P,medianPrice:D,noMoney:fe,baseRatePriced:ve,allowancePriced:M.length,total:S.length}},[S]),de=p.useMemo(()=>{var ue;const k=[],w=S.filter(T=>T.is_active&&Fl(T));k.push({name:"Active items with no money at all (no allowance, no base rate)",count:w.length,severity:w.length>20?"error":w.length>0?"warning":"success",items:w.slice(0,5).map(T=>T.item_code)});const P=S.filter(T=>T.is_active&&zd(T));k.push({name:"Allowance-priced items with a $0 tier gap",count:P.length,severity:P.length>0?"error":"success",items:P.slice(0,5).map(T=>T.item_code)});const M=S.filter(T=>T.is_active&&Ol(T));k.push({name:"Priced from base labor + material rates (no finish allowance â expected)",count:M.length,severity:"success",items:M.slice(0,5).map(T=>T.item_code)});const D=S.filter(T=>!T.entry_price||!T.best_price||T.entry_price===0?!1:T.best_price/T.entry_price>10);k.push({name:"Allowance spreads over 10x between entry and best",count:D.length,severity:D.length>0?"warning":"success",items:D.slice(0,5).map(T=>`${T.item_code} (${(T.best_price/T.entry_price).toFixed(1)}x)`)});const fe=S.filter(T=>!T.is_active).length;k.push({name:"Inactive (retired) catalog items",count:fe,severity:"success"}),k.push({name:"Missing pricing items (referenced in calculations)",count:R.length,severity:R.length>10?"error":R.length>0?"warning":"success",items:R.slice(0,5).map(T=>T.item_code)});const ve=((ue=re==null?void 0:re.stats)==null?void 0:ue.tablesQueried)||0;return k.push({name:"V2 allowance source tables covered",count:ve,severity:ve>=20?"success":ve>=10?"warning":"error"}),k},[S,R,re]),O=p.useMemo(()=>{const k=new Map;
13return S.forEach(w=>{const P=w.source_table||"unknown",M=w.good_price||w.entry_price||0,D=k.get(P)||{count:0,avgPrice:0,minPrice:1/0,maxPrice:0,activeCount:0};D.count+=1,D.avgPrice+=M,D.minPrice=Math.min(D.minPrice,M),D.maxPrice=Math.max(D.maxPrice,M),w.is_active&&(D.activeCount+=1),k.set(P,D)}),k.forEach(w=>{w.avgPrice=w.avgPrice/w.count}),Array.from(k.entries()).map(([w,P])=>({category:w,...P})).sort((w,P)=>P.count-w.count)},[S]),he=p.useMemo(()=>{const k=O.slice(0,10).map(D=>({name:D.category.replace("_line_items_global","").replace(/_/g," "),items:D.count,avgPrice:Math.round(D.avgPrice),maxPrice:Math.round(D.maxPrice)})),w=[{name:"Addition",value:S.filter(D=>D.mode==="addition").length},{name:"Remodel",value:S.filter(D=>D.mode==="remodel").length},{name:"Both",value:S.filter(D=>D.mode==="both"||!D.mode).length}].filter(D=>D.value>0),P=[{tier:"Entry",avg:S.reduce((D,fe)=>D+(fe.entry_price||0),0)/(S.length||1)},{tier:"Good",avg:S.reduce((D,fe)=>D+(fe.good_price||0),0)/(S.length||1)},{tier:"Better",avg:S.reduce((D,fe)=>D+(fe.better_price||0),0)/(S.length||1)},{tier:"Best",avg:S.reduce((D,fe)=>D+(fe.best_price||0),0)/(S.length||1)}],M=[{name:"Passed",value:de.filter(D=>D.severity==="success").length,color:"#10b981"},{name:"Warnings",value:de.filter(D=>D.severity==="warning").length,color:"#f59e0b"},{name:"Errors",value:de.filter(D=>D.severity==="error").length,color:"#ef4444"}].filter(D=>D.value>0);return{top10:k,modeDistribution:w,tierDistribution:P,healthSummary:M}},[O,S,de]),Ie=p.useMemo(()=>S.filter(k=>{const w=k.item_code.toLowerCase().includes(a.toLowerCase())||k.item_name.toLowerCase().includes(a.toLowerCase()),P=s==="all"||k.source_table===s,M=l==="all"||k.mode===l||!k.mode&&l==="both",D=i==="all"||i==="active"&&k.is_active||i==="inactive"&&!k.is_active,fe=_==="all"||_==="zero"&&(k.good_price||0)===0||_==="under100"&&(k.good_price||0)>0&&(k.good_price||0)<100||_==="100-500"&&(k.good_price||0)>=100&&(k.good_price||0)<=500||_==="500-1000"&&(k.good_price||0)>500&&(k.good_price||0)<=1e3||_==="over1000"&&(k.good_price||0)>1e3;return w&&P&&M&&D&&fe}),[S,a,s,l,i,_]),Ge=()=>{const k=["Item Code","Item Name","Source Table","Mode","Entry","Good","Better","Best","Unit","Active"],w=Ie.map(ve=>{var ue,T,ce,X;return[ve.item_code,ve.item_name,ve.source_table||"N/A",ve.mode||"both",((ue=ve.entry_price)==null?void 0:ue.toFixed(2))||"0",((T=ve.good_price)==null?void 0:T.toFixed(2))||"0",((ce=ve.better_price)==null?void 0:ce.toFixed(2))||"0",((X=ve.best_price)==null?void 0:X.toFixed(2))||"0",ve.unit,ve.is_active?"Yes":"No"]}),P=[k.join(","),...w.map(ve=>ve.map(ue=>`"${ue}"`).join(","))].join(` 14`),M=new Blob([P],{type:"text/csv"}),D=URL.createObjectURL(M),fe=document.createElement("a");fe.href=D,fe.download=`v2-allowances-audit-${Vi(new Date,"yyyy-MM-dd")}.csv`,fe.click(),URL.revokeObjectURL(D),le.success("V2 allowances exported to CSV")},Oe=p.useMemo(()=>Array.from(new Set(S.map(k=>k.source_table).filter(Boolean))).sort(),[S]);return $e?e.jsx("div",{className:"flex items-center justify-center h-96",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"animate-spin rounded-full h-12 w-12 border-b-2 border-primary mx-auto mb-4"}),e.jsx("p",{className:"text-muted-foreground",children:"Loading V2 pricing data..."})]})}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between flex-wrap gap-4",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs("div",{className:"flex items-center gap-2 bg-muted/50 rounded-lg p-2",children:[e.jsx(us,{className:"h-4 w-4 text-muted-foreground"}),e.jsx(xe,{htmlFor:"scope-toggle",className:"text-sm cursor-pointer",children:c==="global"?"Global View":`Company: ${(v==null?void 0:v.company_name)||"My Company"}`}),e.jsx(ar,{id:"scope-toggle",checked:c==="company",onCheckedChange:k=>m(k?"company":"global")}),e.jsx(is,{className:"h-4 w-4 text-muted-foreground"})]}),e.jsxs(ie,{variant:"outline",className:"gap-1",children:[e.jsx(zl,{className:"h-3 w-3"}),"Super Admin"]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(H,{onClick:G,disabled:h,variant:"outline",className:"gap-2",children:[e.jsx(Ga,{className:`h-4 w-4 ${h?"animate-spin":""}`}),h?"Syncing...":"Sync Fresh"]}),e.jsxs(H,{onClick:Ge,variant:"outline",className:"gap-2",children:[e.jsx(Wa,{className:"h-4 w-4"}),"Export CSV"]})]})]}),e.jsxs("div",{className:"grid gap-4 md:grid-cols-6",children:[e.jsxs(ye,{children:[e.jsxs(ke,{className:"flex flex-row items-center justify-between space-y-0 pb-2",children:[e.jsx(Ce,{className:"text-sm font-medium",children:"Active Items"}),e.jsx(Pr,{className:"h-4 w-4 text-muted-foreground"})]}),e.jsxs(je,{children:[e.jsx("div",{className:"text-2xl font-bold",children:A.activeItems}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[A.inactiveItems," inactive"]})]})]}),e.jsxs(ye,{children:[e.jsxs(ke,{className:"flex flex-row items-center justify-between space-y-0 pb-2",children:[e.jsx(Ce,{className:"text-sm font-medium",children:"Source Tables"}),e.jsx(Hs,{className:"h-4 w-4 text-muted-foreground"})]}),e.jsxs(je,{children:[e.jsx("div",{className:"text-2xl font-bold",children:A.sourceTables}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"V2 global tables"})]})]}),e.jsxs(ye,{children:[e.jsxs(ke,{className:"flex flex-row items-center justify-between space-y-0 pb-2",children:[e.jsx(Ce,{className:"text-sm font-medium",children:"Total Items"}),e.jsx(en,{className:"h-4 w-4 text-muted-foreground"})]}),e.jsxs(je,{children:[e.jsx("div",{className:"text-2xl font-bold",children:A.total}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["In the ",A.sourceTables," allowance tables"]})]})]}),e.jsxs(ye,{children:[e.jsxs(ke,{className:"flex flex-row items-center justify-between space-y-0 pb-2",children:[e.jsx(Ce,{className:"text-sm font-medium",children:"Median Allowance"}),e.jsx(er,{className:"h-4 w-4 text-muted-foreground"})]}),e.jsxs(je,{children:[e.jsxs("div",{className:"text-2xl font-bold",children:["$",A.medianPrice.toFixed(0)]}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Good tier, ",A.allowancePriced," allowance-priced rows"]})]})]}),e.jsxs(ye,{children:[e.jsxs(ke,{className:"flex flex-row items-center justify-between space-y-0 pb-2",children:[e.jsx(Ce,{className:"text-sm font-medium",children:"No Money At All"}),e.jsx(wt,{className:`h-4 w-4 ${A.noMoney>0?"text-destructive":"text-muted-foreground"}`})]}),e.jsxs(je,{children:[e.jsx("div",{className:`text-2xl font-bold ${A.noMoney>0?"text-destructive":""}`,children:A.noMoney}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[A.baseRatePriced," priced from base rates (normal)"]})]})]}),e.jsxs(ye,{children:[e.jsxs(ke,{className:"flex flex-row items-center justify-between space-y-0 pb-2",children:[e.jsx(Ce,{className:"text-sm font-medium",children:"Data Source"}),e.jsx(ba,{className:"h-4 w-4 text-green-500"})]}),e.jsxs(je,{children:[e.jsx("div",{className:"text-2xl font-bold",children:"V2"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:c==="global"?"Global":"Company"})]})]})]}),e.jsxs(os,{value:ee,onValueChange:U,children:[e.jsxs(cs,{className:"grid w-full grid-cols-5",children:[e.jsxs(ia,{value:"overview",className:"gap-1",children:[e.jsx(xi,{className:"h-4 w-4"}),"Health"]}),e.jsxs(ia,{value:"charts",className:"gap-1",children:[e.jsx(gi,{className:"h-4 w-4"}),"Analytics"]}),e.jsxs(ia,{value:"tables",className:"gap-1",children:[e.jsx(Hs,{className:"h-4 w-4"}),"Source Tables"]}),e.jsxs(ia,{value:"items",className:"gap-1",children:[e.jsx(Pr,{className:"h-4 w-4"}),"All Items"]}),e.jsxs(ia,{value:"missing",className:"gap-1",children:[e.jsx(wt,{className:"h-4 w-4"}),"Missing"]})]}),e.jsxs(oa,{value:"overview",children:[e.jsxs(ye,{children:[e.jsxs(ke,{children:[e.jsx(Ce,{children:"V2 Pricing Health Checks"}),e.jsx(Ye,{children:"Automated validation of V2 pricing data integrity"})]}),e.jsx(je,{children:e.jsx("div",{className:"space-y-3",children:de.map((k,w)=>e.jsxs("div",{className:"flex items-center justify-between p-3 border rounded-lg",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[k.severity==="success"&&e.jsx(ba,{className:"h-5 w-5 text-green-500"}),k.severity==="warning"&&e.jsx(wt,{className:"h-5 w-5 text-yellow-500"}),k.severity==="error"&&e.jsx(wt,{className:"h-5 w-5 text-red-500"}),e.jsxs("div",{children:[e.jsx("p",{className:"font-medium",children:k.name}),k.count>0&&k.items&&e.jsxs("p",{className:"text-xs text-muted-foreground",children:[k.items.slice(0,3).join(", "),k.items.length>3&&` +${k.items.length-3} more`]})]})]}),e.jsx(ie,{variant:k.severity==="success"?"default":"destructive",children:k.count})]},w))})})]}),e.jsxs(ye,{className:"mt-4",children:[e.jsx(ke,{children:e.jsx(Ce,{children:"Health Summary"})}),e.jsx(je,{children:e.jsx("div",{className:"h-64",children:e.jsx(pt,{width:"100%",height:"100%",children:e.jsxs(Br,{children:[e.jsx(Vr,{data:he.healthSummary,cx:"50%",cy:"50%",outerRadius:80,dataKey:"value",label:({name:k,value:w})=>`${k}: ${w}`,children:he.healthSummary.map((k,w)=>e.jsx(zr,{fill:k.color},w))}),e.jsx(xt,{}),e.jsx(Ur,{})]})})})})]})]}),e.jsx(oa,{value:"charts",className:"space-y-4",children:e.jsxs("div",{className:"grid gap-4 md:grid-cols-2",children:[e.jsxs(ye,{children:[e.jsx(ke,{children:e.jsx(Ce,{className:"text-base",children:"Items by Source Table (Top 10)"})}),e.jsx(je,{children:e.jsx("div",{className:"h-72",children:e.jsx(pt,{width:"100%",height:"100%",children:e.jsxs(vs,{data:he.top10,layout:"vertical",children:[e.jsx(Ns,{strokeDasharray:"3 3"}),e.jsx(ks,{type:"number"}),e.jsx(Cs,{dataKey:"name",type:"category",width:100,tick:{fontSize:11}}),e.jsx(xt,{}),e.jsx(Ft,{dataKey:"items",fill:"hsl(var(--primary))",radius:[0,4,4,0]})]})})})})]}),e.jsxs(ye,{children:[e.jsx(ke,{children:e.jsx(Ce,{className:"text-base",children:"Mode Distribution"})}),e.jsx(je,{children:e.jsx("div",{className:"h-72",children:e.jsx(pt,{width:"100%",height:"100%",children:e.jsxs(Br,{children:[e.jsx(Vr,{data:he.modeDistribution,cx:"50%",cy:"50%",outerRadius:90,dataKey:"value",label:({name:k,percent:w})=>`${k} ${(w*100).toFixed(0)}%`,children:he.modeDistribution.map((k,w)=>e.jsx(zr,{fill:Dl[w%Dl.length]},w))}),e.jsx(xt,{}),e.jsx(Ur,{})]})})})})]}),e.jsxs(ye,{children:[e.jsx(ke,{children:e.jsx(Ce,{className:"text-base",children:"Average Price by Finish Tier"})}),e.jsx(je,{children:e.jsx("div",{className:"h-72",children:e.jsx(pt,{width:"100%",height:"100%",children:e.jsxs(vs,{data:he.tierDistribution,children:[e.jsx(Ns,{strokeDasharray:"3 3"}),e.jsx(ks,{dataKey:"tier"}),e.jsx(Cs,{}),e.jsx(xt,{formatter:k=>`$${k.toFixed(2)}`}),e.jsx(Ft,{dataKey:"avg",fill:"hsl(var(--primary))",radius:[4,4,0,0]})]})})})})]}),e.jsxs(ye,{children:[e.jsx(ke,{children:e.jsx(Ce,{className:"text-base",children:"Avg Price by Source (Top 10)"})}),e.jsx(je,{children:e.jsx("div",{className:"h-72",children:e.jsx(pt,{width:"100%",height:"100%",children:e.jsxs(vs,{data:he.top10,children:[e.jsx(Ns,{strokeDasharray:"3 3"}),e.jsx(ks,{dataKey:"name",tick:{fontSize:10},angle:-30,textAnchor:"end",height:60}),e.jsx(Cs,{}),e.jsx(xt,{formatter:k=>`$${k}`}
14),e.jsx(Ft,{dataKey:"avgPrice",fill:"#6366f1",name:"Avg",radius:[4,4,0,0]}),e.jsx(Ft,{dataKey:"maxPrice",fill:"#f59e0b",name:"Max",radius:[4,4,0,0]})]})})})})]})]})}),e.jsx(oa,{value:"tables",children:e.jsxs(ye,{children:[e.jsxs(ke,{children:[e.jsx(Ce,{children:"Source Table Analysis"}),e.jsx(Ye,{children:"V2 pricing breakdown by source table"})]}),e.jsx(je,{children:e.jsx("div",{className:"overflow-x-auto",children:e.jsxs(Ze,{children:[e.jsx(ea,{children:e.jsxs(Le,{children:[e.jsx(Z,{children:"Source Table"}),e.jsx(Z,{className:"text-right",children:"Total"}),e.jsx(Z,{className:"text-right",children:"Active"}),e.jsx(Z,{className:"text-right",children:"Avg Price"}),e.jsx(Z,{className:"text-right",children:"Min Price"}),e.jsx(Z,{className:"text-right",children:"Max Price"})]})}),e.jsx(aa,{children:O.map(k=>e.jsxs(Le,{className:"cursor-pointer hover:bg-muted/50",onClick:()=>{r(k.category),U("items")},children:[e.jsx(Q,{className:"font-medium font-mono text-xs",children:k.category}),e.jsx(Q,{className:"text-right",children:k.count}),e.jsx(Q,{className:"text-right",children:k.activeCount}),e.jsxs(Q,{className:"text-right",children:["$",k.avgPrice.toFixed(2)]}),e.jsxs(Q,{className:"text-right",children:["$",k.minPrice===1/0?0:k.minPrice.toFixed(2)]}),e.jsxs(Q,{className:"text-right",children:["$",k.maxPrice.toFixed(2)]})]},k.category))})]})})})]})}),e.jsx(oa,{value:"items",children:e.jsxs(ye,{children:[e.jsxs(ke,{children:[e.jsx(Ce,{children:"V2 Pricing Data"}),e.jsxs(Ye,{children:[Ie.length," of ",S.length," items",c==="company"&&v&&` â ${v.company_name}`]})]}),e.jsxs(je,{children:[e.jsxs("div",{className:"grid gap-3 md:grid-cols-5 mb-4",children:[e.jsxs("div",{className:"relative",children:[e.jsx(Va,{className:"absolute left-3 top-3 h-4 w-4 text-muted-foreground"}),e.jsx(Pe,{placeholder:"Search code or name...",value:a,onChange:k=>t(k.target.value),className:"pl-9"})]}),e.jsxs(Be,{value:s,onValueChange:r,children:[e.jsx(Ve,{children:e.jsx(ze,{placeholder:"Source Table"})}),e.jsxs(Ue,{children:[e.jsx(me,{value:"all",children:"All Tables"}),Oe.map(k=>e.jsx(me,{value:k,children:k},k))]})]}),e.jsxs(Be,{value:l,onValueChange:o,children:[e.jsx(Ve,{children:e.jsx(ze,{placeholder:"Mode"})}),e.jsxs(Ue,{children:[e.jsx(me,{value:"all",children:"All Modes"}),e.jsx(me,{value:"addition",children:"Addition"}),e.jsx(me,{value:"remodel",children:"Remodel"}),e.jsx(me,{value:"both",children:"Both"})]})]}),e.jsxs(Be,{value:i,onValueChange:d,children:[e.jsx(Ve,{children:e.jsx(ze,{placeholder:"Status"})}),e.jsxs(Ue,{children:[e.jsx(me,{value:"all",children:"All Status"}),e.jsx(me,{value:"active",children:"Active Only"}),e.jsx(me,{value:"inactive",children:"Inactive Only"})]})]}),e.jsxs(Be,{value:_,onValueChange:n,children:[e.jsx(Ve,{children:e.jsx(ze,{placeholder:"Price Range"})}),e.jsxs(Ue,{children:[e.jsx(me,{value:"all",children:"All Prices"}),e.jsx(me,{value:"zero",children:"$0 (Missing)"}),e.jsx(me,{value:"under100",children:"Under $100"}),e.jsx(me,{value:"100-500",children:"$100 - $500"}),e.jsx(me,{value:"500-1000",children:"$500 - $1,000"}),e.jsx(me,{value:"over1000",children:"Over $1,000"})]})]})]}),e.jsxs("div",{className:"overflow-x-auto",children:[e.jsxs(Ze,{children:[e.jsx(ea,{children:e.jsxs(Le,{children:[e.jsx(Z,{children:"Item Code"}),e.jsx(Z,{children:"Item Name"}),e.jsx(Z,{children:"Source"}),e.jsx(Z,{children:"Mode"}),e.jsx(Z,{className:"text-right",children:"Entry"}),e.jsx(Z,{className:"text-right",children:"Good"}),e.jsx(Z,{className:"text-right",children:"Better"}),e.jsx(Z,{className:"text-right",children:"Best"}),e.jsx(Z,{children:"Unit"}),e.jsx(Z,{children:"Status"}),e.jsx(Z,{className:"whitespace-nowrap",children:e.jsxs("span",{className:"inline-flex items-center gap-1",children:["Wiring ",e.jsx(xs,{className:"px-1"})]})}),e.jsx(Z,{children:"Edit"})]})}),e.jsx(aa,{children:Ie.slice(0,100).map(k=>{var w,P,M,D;return e.jsxs(Le,{children:[e.jsx(Q,{className:"font-mono text-xs",children:k.item_code}),e.jsx(Q,{className:"max-w-[200px] truncate",children:k.item_name}),e.jsx(Q,{className:"font-mono text-xs",children:k.source_table}),e.jsx(Q,{children:e.jsx(ie,{variant:"outline",children:k.mode||"both"})}),e.jsxs(Q,{className:"text-right",children:["$",((w=k.entry_price)==null?void 0:w.toFixed(2))||"0"]}),e.jsxs(Q,{className:"text-right",children:["$",((P=k.good_price)==null?void 0:P.toFixed(2))||"0"]}),e.jsxs(Q,{className:"text-right",children:["$",((M=k.better_price)==null?void 0:M.toFixed(2))||"0"]}),e.jsxs(Q,{className:"text-right",children:["$",((D=k.best_price)==null?void 0:D.toFixed(2))||"0"]}),e.jsx(Q,{children:k.unit}),e.jsx(Q,{children:e.jsx(ie,{variant:k.is_active?"default":"secondary",children:k.is_active?"Active":"Inactive"})}
14),e.jsx(Q,{children:e.jsx(_s,{itemCode:k.item_code,preloaded:(z==null?void 0:z.get(k.item_code))??null,preloadedReady:Se})}),e.jsx(Q,{children:e.jsx(H,{variant:"ghost",size:"icon",onClick:()=>te(k),children:e.jsx(bi,{className:"h-4 w-4"})})})]},k.id)})})]}),Ie.length>100&&e.jsxs("p",{className:"text-sm text-muted-foreground mt-4 text-center",children:["Showing 100 of ",Ie.length," items. Use filters to narrow results."]})]})]})]})}),e.jsx(oa,{value:"missing",children:e.jsxs(ye,{children:[e.jsxs(ke,{children:[e.jsx(Ce,{children:"Missing Pricing Items"}),e.jsx(Ye,{children:"Items referenced in calculations but not found in V2 tables"})]}),e.jsx(je,{children:R.length===0?e.jsxs("div",{className:"text-center py-8 text-muted-foreground",children:[e.jsx(ba,{className:"h-12 w-12 mx-auto mb-2 text-green-500"}),e.jsx("p",{children:"No missing pricing items found!"})]}):e.jsxs(Ze,{children:[e.jsx(ea,{children:e.jsxs(Le,{children:[e.jsx(Z,{children:"Item Code"}),e.jsx(Z,{className:"text-right",children:"References"}),e.jsx(Z,{children:"Status"})]})}),e.jsx(aa,{children:R.map(k=>e.jsxs(Le,{children:[e.jsx(Q,{className:"font-mono text-xs",children:k.item_code}),e.jsx(Q,{className:"text-right",children:k.reference_count}),e.jsx(Q,{children:e.jsx(ie,{variant:"destructive",children:k.status})})]},k.id))})]})})]})})]}),e.jsx(Ha,{open:!!b,onOpenChange:()=>x(null),children:e.jsxs(Qa,{className:"max-w-2xl",children:[e.jsx(Ja,{children:e.jsxs(Ya,{children:["Edit finish allowances â ",b==null?void 0:b.item_name]})}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("p",{className:"text-sm text-muted-foreground font-mono",children:[b==null?void 0:b.item_code," ⢠",b==null?void 0:b.source_table]}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Labor and material are entered separately per tier â never one blended total. The change is written by the audited pricing service, applies to future estimates, and existing projects keep their totals and are flagged stale. Scope: ",c==="global"?"global baseline":"my company","."]}),e.jsx("div",{className:"grid gap-3 sm:grid-cols-2",children:ts.map(k=>e.jsxs("div",{className:"rounded-lg border border-primary/15 p-3 space-y-2",children:[e.jsxs("p",{className:"text-xs font-semibold capitalize text-foreground",children:[k," tier"]}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs("div",{children:[e.jsx(xe,{className:"text-xs",children:"Labor"}),e.jsx(Pe,{type:"number",min:"0",step:"0.01",value:u[`${k}_allowance_labor`]??"0",onChange:w=>N(P=>({...P,[`${k}_allowance_labor`]:w.target.value}))})]}),e.jsxs("div",{children:[e.jsx(xe,{className:"text-xs",children:"Material"}),e.jsx(Pe,{type:"number",min:"0",step:"0.01",value:u[`${k}_allowance_material`]??"0",onChange:w=>N(P=>({...P,[`${k}_allowance_material`]:w.target.value}))})]})]})]},k))}),e.jsxs("div",{children:[e.jsx(xe,{className:"text-xs",children:"Reason (recorded in history)"}),e.jsx(Pe,{value:y,onChange:k=>L(k.target.value),placeholder:"Why this price moved"})]}),(E==null?void 0:E.verdict)&&e.jsx(Ua,{verdict:E.verdict,aiNotes:E.aiNotes,reviewerNote:E.reviewerNote,reverted:E.reverted,defaultOpen:E.verdict.state!=="pass",rechecking:be,onRecheck:async()=>{if(!b)return;F(!0);const k=await qa({item_code:b.item_code,source_table:b.source_table,scope:c,company_id:c==="company"?(V==null?void 0:V.company_id)??null:null});k.verdict&&J({...E,verdict:k.verdict,aiNotes:k.ai_notes,reviewerNote:k.reviewer_note}),se.invalidateQueries({queryKey:["pricing-wiring-verdicts","latest"]}),F(!1)}})]}),e.jsxs(Xa,{children:[e.jsx(H,{variant:"outline",onClick:()=>x(null),children:"Cancel"}),e.jsx(H,{onClick:oe,disabled:I,children:I?"Savingâ¦":"Save Changes"})]})]})})]})};function qd(a,t="good"){const s=new Map,r=new Map,l=new Map,o=new Map;let i=0,d=0,_=0,n=0;const c=(m,h,j,b)=>{const x=m.get(h)||{count:0,priced:0,total:0};x.count+=1,j&&(x.priced+=1,x.total+=b),m.set(h,x)};return a.forEach(m=>{const h=Io(m,t),j=h.total>0;j?(i+=1,n+=h.total):d+=1,m.usage_basis!=="none"&&(_+=1),c(s,m.trade,j,h.total),c(r,m.card_label||m.card_code||"â",j,h.total),(m.provenance.length?m.provenance:["seeded"]).forEac
14h(x=>l.set(x,(l.get(x)||0)+1));const b=Fo(m);o.set(b,(o.get(b)||0)+1)}),{total:a.length,priced:i,empty:d,inUse:_,avg:i?n/i:0,byTrade:[...s.entries()].sort((m,h)=>h[1].count-m[1].count),byCard:[...r.entries()].sort((m,h)=>h[1].count-m[1].count),byProvenance:[...l.entries()].sort((m,h)=>h[1]-m[1]),shapes:[...o.entries()].sort((m,h)=>h[1]-m[1])}}const pa=a=>a.toLocaleString(),qs=a=>`$${a.toLocaleString(void 0,{maximumFractionDigits:2})}`;function Kd(){const[a,t]=p.useState("good"),[s]=p.useState("global"),{data:r}=Ke({queryKey:["catalog-my-company"],queryFn:async()=>{const{data:n}=await ge.auth.getUser();if(!(n!=null&&n.user))return null;const{data:c}=await ge.rpc("get_company_id",{uid:n.user.id});return c||null}}),{universe:l,isLoading:o}=$n(s,r??null,{}),i=p.useMemo(()=>qd(l,a),[l,a]),{data:d}=Rt(!0),_=p.useMemo(()=>{const n={verified:0,caution:0,failed:0,reverted:0,unverified:0};for(const c of l)n[Yt((d==null?void 0:d.get(c.item_code))??null)]+=1;return n},[l,d]);return o?e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground py-10 justify-center",children:[e.jsx(Fe,{className:"h-4 w-4 animate-spin"})," Loading the full catalogâ¦"]}):e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-end justify-between gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(xe,{className:"text-xs",children:"Finish tier"}),e.jsxs(Be,{value:a,onValueChange:n=>t(n),children:[e.jsx(Ve,{className:"w-[160px]",children:e.jsx(ze,{})}),e.jsx(Ue,{children:qe.map(n=>e.jsx(me,{value:n,className:"capitalize",children:n},n))})]})]}),e.jsx(Tt,{view:"Insights",scope:s,filterSummary:`tier ${a} · ${l.length} catalog item(s)`,filenameBase:`pricing-insights-${a}`,canImport:!1,buildSheets:()=>[Un("Insights",l.map(n=>({item_code:n.item_code,item_name:n.item_name??"",source_table:n.source_table??"",card:n.card_code??"",wiring_state:Yt((d==null?void 0:d.get(n.item_code))??null)})),["item_code","item_name","source_table","card","wiring_state"])],liveRows:()=>new Map}),e.jsx("p",{className:"text-xs text-muted-foreground pb-2",children:"Same paged catalog as the Catalog tab â these counts and the grid always agree."})]}),e.jsx("div",{className:"grid gap-3 sm:grid-cols-2 lg:grid-cols-4",children:[{label:"Catalog items",value:pa(i.total),hint:"across every card table"},{label:"Priced at this tier",value:pa(i.priced),hint:`${pa(i.empty)} with no money`},{label:"Used by a project",value:pa(i.inUse),hint:"appears in a frozen snapshot"},{label:"Average item value",value:qs(i.avg),hint:"base + allowance, L + M"}].map(n=>e.jsxs(ye,{children:[e.jsxs(ke,{className:"pb-1",children:[e.jsx(Ye,{className:"text-xs",children:n.label}),e.jsx(Ce,{className:"text-2xl",children:n.value})]}),e.jsx(je,{className:"text-xs text-muted-foreground",children:n.hint})]},n.label))}),e.jsxs(ye,{children:[e.jsxs(ke,{className:"pb-2",children:[e.jsxs(Ce,{className:"text-base flex items-center gap-2",children:["Wiring health ",e.jsx(xs,{})]}),e.jsx(Ye,{className:"text-xs",children:"Latest final-wiring-check verdict per item. Anything other than Verified means the last price move on that item was not proven to reach every surface."})]}),e.jsxs(je,{children:[e.jsx("div",{className:"flex flex-wrap gap-2",children:wn.map(n=>{const c=hs(n);return e.jsxs("div",{className:`rounded-md border px-3 py-2 ${c.chipClass}`,title:c.hint,children:[e.jsx("div",{className:"text-lg font-semibold tabular-nums",children:pa(_[n])}),e.jsx("div",{className:"text-[11px]",children:c.label})]},n)})}),_.unverified>0&&e.jsx("p",{className:"text-xs text-muted-foreground mt-2",children:"Unverified rows are not failures â they simply have not been through the checker since it was introduced. Editing or re-checking an item produces a verdict."})]})]}),e.jsxs("div",{className:"grid gap-4 lg:grid-cols-2",children:[e.jsxs(ye,{children:[e.jsxs(ke,{className:"pb-2",children:[e.jsx(Ce,{className:"text-base",children:"By trade"}),e.jsx(Ye,{children:"Items, how many carry money at this tier, and their combined value."})]}),e.jsx(je,{children:e.jsx(Ma,{className:"h-[320px]",children:e.jsxs(Ze,{children:[e.jsx(ea,{children:e.jsxs(Le,{children:[e.jsx(Z,{children:"Trade"}),e.jsx(Z,{className:"text-right",children:"Items"}),e.jsx(Z,{className:"text-right",children:"Priced"}),e.jsx(Z,{className:"text-right",children:"Total"})]})}),e.jsx(aa,{children:i.byTrade.map(([n,c])=>e.jsxs(Le,{children:[e.jsx(Q,{className:"text-xs capitalize",children:n}),e.jsx(Q,{className:"text-right text-xs",children:pa(c.count)}),e.jsxs(Q,{className:"text-right text-xs",children:[pa(c.priced),c.priced<c.count&&e.jsxs(ie,{variant:"outline",className:"ml-2 text-[10px]",children:[pa(c.count-c.priced)," empty"]})]}),e.jsx(Q,{className:"text-right text-xs",children:qs(c.total)})]},n))})]})})})]}),e.jsxs(ye,{children:[e.jsxs(ke,{className:"pb-2",children:[e.jsx(Ce,{className:"text-base",children:"By card"}),e.jsx(Ye,{children:"Every calculator card that owns priced rows."})]}),e.jsx(je,{children:e.jsx(Ma,{className:"h-[320px]",children:e.jsxs(Ze,{children:[e.jsx(ea,{children:e.jsxs(Le,{children:[e.jsx(Z,{children:"Card"}),e.jsx(Z,{className:"text-right",children:"Items"}),e.jsx(Z,{className:"text-right",children:"Priced"}),e.jsx(Z,{className:"text-right",children:"Total"})]})}),e.jsx(aa,{children:i.byCard.map(([n,c])=>e.jsxs(Le,{children:[e.jsx(Q,{className:"text-xs",children:n}),e.jsx(Q,{className:"text-right text-xs",children:pa(c.count)}),e.jsx(Q,{className:"text-right text-xs",children:pa(c.priced)}),e.jsx(Q,{className:"text-right text-xs",children:qs(c.total)})]},n))})]})})})]})]}),e.jsxs("div",{className:"grid gap-4 lg:grid-cols-2",children:[e.jsxs(ye,{children:[e.jsxs(ke,{className:"pb-2",children:[e.jsx(Ce,{className:"text-base",children:"Where the numbers came from"}),e.jsx(Ye,{children:"Provenance stamps carried by each row."})]}),e.jsx(je,{className:"flex flex-wrap gap-2",children:i.byProvenance.map(([n,c])=>{const m=Da[n];return e.jsxs(ie,{variant:"outline",className:"text-xs",children:[(m==null?void 0:m.label)??n,": ",pa(c)]},n)})})]}),e.jsxs(ye,{children:[e.jsxs(ke,{className:"pb-2",children:[e.jsx(Ce,{className:"text-base",children:"Money shape"}),e.jsx(Ye,{children:"Base only, allowance only or both is fine. Rows with
14nothing at all are worth a look."})]}),e.jsx(je,{className:"flex flex-wrap gap-2",children:i.shapes.map(([n,c])=>e.jsxs(ie,{variant:n==="empty"?"destructive":"outline",className:"text-xs",children:[n.replace(/_/g," "),": ",pa(c)]},n))})]})]})]})}function Wd(){const[a,t]=p.useState(null),[s,r]=p.useState(!1),[l,o]=p.useState(null),i=p.useCallback(async(d={})=>{r(!0),o(null);try{const{data:_,error:n}=await ge.functions.invoke("sweep-pricing-wiring",{body:{tables:d.tables}});if(n)throw n;if(!(_!=null&&_.success))throw new Error((_==null?void 0:_.error)||"Sweep failed");return t(_),_}catch(_){return o((_==null?void 0:_.message)||"Sweep failed"),null}finally{r(!1)}},[]);return{report:a,running:s,error:l,run:i}}const Gd={pass:"bg-emerald-500/10 text-emerald-700 dark:text-emerald-400 border-emerald-500/30",warn:"bg-amber-500/10 text-amber-700 dark:text-amber-400 border-amber-500/30",fail:"bg-destructive/10 text-destructive border-destructive/30"},dr=a=>a.replace(/_line_items_global(_remodel)?$/,(t,s)=>s?" (remodel)":"").replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase());function Hd({item:a}){return e.jsxs("div",{className:"rounded-md border border-border p-2 text-xs space-y-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(ie,{variant:"outline",className:Gd[a.state],children:a.state==="fail"?"not wired":"worth a look"}),e.jsx("span",{className:"font-medium text-foreground",children:a.item_name||a.item_code}),e.jsx("span",{className:"font-mono text-muted-foreground",children:a.item_code}),e.jsxs("span",{className:"text-muted-foreground",children:["· ",dr(a.table)]}),a.card_code&&e.jsxs("span",{className:"text-muted-foreground",children:["· ",a.card_code]})]}),e.jsx("ul",{className:"space-y-0.5 pl-1",children:a.issues.map((t,s)=>e.jsxs("li",{className:"text-muted-foreground",children:[e.jsx("span",{className:"font-medium text-foreground",children:t.label})," â ",t.detail," ",e.jsxs("span",{className:"opacity-70",children:["(",t.surface,")"]})]},`${t.id}-${s}`))})]})}function Qd(){const{report:a,running:t,error:s,run:r}=Wd(),[l,o]=p.useState(""),[i,d]=p.useState(!1),_=p.useMemo(()=>{const n=(a==null?void 0:a.items)??[],c=l.trim().toLowerCase();return n.filter(m=>(!i||m.state==="fail")&&(!c||m.item_code.toLowerCase().includes(c)||(m.item_name||"").toLowerCase().includes(c)||m.table.toLowerCase().includes(c)||(m.card_code||"").toLowerCase().includes(c)))},[a,l,i]);return e.jsxs(ye,{children:[e.jsx(ke,{className:"pb-3",children:e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-2",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx(Ce,{className:"text-base",children:"Wiring sweep"}),e.jsx(Ye,{children:"Checks every catalog item against the card that has to price it: a live reader serves the table, the card is registered in the category map, the scope-resolved catalog read still returns the item, the tier ladder is complete and cheapest-first, and at least one money column can carry a price. Read-only."})]}),e.jsxs(H,{onClick:()=>r(),disabled:t,size:"sm",className:"shrink-0",children:[t?e.jsx(Fe,{className:"h-4 w-4 mr-1 animate-spin"}):e.jsx(zi,{className:"h-4 w-4 mr-1"}),t?"Sweepingâ¦":"Run sweep"]})]})}),e.jsxs(je,{className:"space-y-4",children:[s&&e.jsxs("p",{className:"text-xs text-destructive flex items-center gap-1",children:[e.jsx(wt,{className:"h-3.5 w-3.5"})," ",s]}),!a&&!t&&e.jsx("p",{className:"text-xs text-muted-foreground",children:"Run the sweep to get a per-card verdict across the whole catalog."}),a&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-4 gap-2",children:[{label:"Items swept",value:a.summary.items},{label:"Fully wired",value:a.summary.wired},{label:"Worth a look",value:a.summary.warned},{label:"Not wired",value:a.summary.failing}].map(n=>e.jsxs("div",{className:"rounded-md border border-border p-2",children:[e.jsx("p",{className:"text-[11px] text-muted-foreground",children:n.label}),e.jsx("p",{className:"text-lg font-semibold tabular-nums text-foreground",children:n.value})]},n.label))}),e.jsxs("p",{className:"text-[11px] text-muted-foreground",children:[a.summary.tables," catalog tables · swept in ",(a.duration_ms/1e3).toFixed(1),"s ·"," ",a.scope==="company"?"company overlay":"global baseline"," scope"]}),a.errors.length>0&&e.jsx("div",{className:"rounded-md border border-destructive/30 bg-destructive/5 p-2 text-xs space-y-1",children:a.errors.map(n=>e.jsxs("p",{className:"text-destructive",children:[dr(n.table),": ",n.message]},n.table))}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-xs",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-left text-muted-foreground",children:[e.jsx("th",{className:"py-1 pr-2 font-medium",children:"Card catalog"}),e.jsx("th",{className:"py-1 pr-2 font-medium",children:"Reader"}),e.jsx("th",{className:"py-1 pr-2 font-medium text-right",children:"Items"}),e.jsx("th",{className:"py-1 pr-2 font-medium text-right",children:"Wired"}),e.jsx("th",{className:"py-1 pr-2 font-medium text-right",children:"Look"}),e.jsx("th",{className:"py-1 pr-2 font-medium text-right",children:"Not wired"})]})}),e.jsx("tbody",{children:a.tables.map(n=>e.jsxs("tr",{className:"border-t border-border even:bg-muted/30",children:[e.jsx("td",{className:"py-1 pr-2 text-foreground",children:dr(n.table)}),e.jsx("td",{className:"py-1 pr-2 font-mono text-muted-foreground",children:n.reader??"â"}),e.jsx("td",{className:"py-1 pr-2 text-right tabular-nums",children:n.items}),e.jsx("td",{className:"py-1 pr-2 text-right tabular-nums text-emerald-700 dark:text-emerald-400",children:n.wired}),e.jsx("td",{className:"py-1 pr-2 text-right tabular-nums text-amber-700 dark:text-amber-400",children:n.warned}
14),e.jsx("td",{className:"py-1 pr-2 text-right tabular-nums text-destructive",children:n.failing})]},n.table))})]})}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(Pe,{value:l,onChange:n=>o(n.target.value),placeholder:"Filter flagged items by name, code, card or table",className:"h-8 max-w-sm text-xs"}),e.jsxs(H,{variant:i?"default":"outline",size:"sm",onClick:()=>d(n=>!n),children:[e.jsx(Xe,{className:"h-3.5 w-3.5 mr-1"})," Only not wired"]})]}),_.length===0?e.jsxs("p",{className:"text-xs text-emerald-700 dark:text-emerald-400 flex items-center gap-1",children:[e.jsx(ba,{className:"h-3.5 w-3.5"})," Nothing flagged for the current filter."]}):e.jsxs("div",{className:"space-y-2 max-h-[28rem] overflow-y-auto pr-1",children:[_.map(n=>e.jsx(Hd,{item:n},`${n.table}::${n.item_code}`)),a.items_truncated&&e.jsx("p",{className:"text-[11px] text-muted-foreground",children:"More flagged items exist than were returned â resolve these and re-run."})]})]})]})]})}const Jt={searchText:"",categories:[],costType:"both",priceRange:[0,1e4],modifiedWithinDays:null,hasLaborOnly:!1,hasMaterialOnly:!1,sort:"name_asc"};function Jd({filters:a,onChange:t,availableCategories:s,visibleCount:r,totalCount:l,priceMaxBound:o}){var j;const[i,d]=p.useState(a.searchText);p.useEffect(()=>{const b=setTimeout(()=>{i!==a.searchText&&t({...a,searchText:i})},200);return()=>clearTimeout(b)},[i]);const _=Math.max(o,100);p.useEffect(()=>{a.priceRange[1]===Jt.priceRange[1]&&_!==Jt.priceRange[1]&&t({...a,priceRange:[a.priceRange[0],_]})},[_]);const n=b=>{const x=new Set(a.categories);x.has(b)?x.delete(b):x.add(b),t({...a,categories:Array.from(x)})},c=(a.searchText?1:0)+(a.categories.length?1:0)+(a.costType!=="both"?1:0)+(a.priceRange[0]>0||a.priceRange[1]<_?1:0)+(a.modifiedWithinDays?1:0)+(a.hasLaborOnly?1:0)+(a.hasMaterialOnly?1:0),m=()=>{d(""),t({...Jt,priceRange:[0,_]})},h=a.categories.length?`${a.categories.length} selected`:"All categories";return e.jsx("div",{className:"sticky top-0 z-20 bg-background/95 backdrop-blur border-b py-3 -mx-6 px-6 mb-4",children:e.jsxs("div",{className:"flex flex-wrap items-end gap-3",children:[e.jsxs("div",{className:"flex-1 min-w-[260px]",children:[e.jsx(xe,{className:"text-xs text-muted-foreground",children:"Search"}),e.jsxs("div",{className:"relative",children:[e.jsx(Va,{className:"absolute left-2 top-2.5 h-4 w-4 text-muted-foreground"}),e.jsx(Pe,{value:i,onChange:b=>d(b.target.value),placeholder:"Item code or nameâ¦",className:"pl-8"})]})]}),e.jsxs("div",{children:[e.jsx(xe,{className:"text-xs text-muted-foreground",children:"Categories"}),e.jsxs(ss,{children:[e.jsx(rs,{asChild:!0,children:e.jsxs(H,{variant:"outline",className:"min-w-[180px] justify-between",children:[e.jsx("span",{className:"truncate",children:h}),e.jsx(ha,{className:"h-4 w-4 ml-2 opacity-50"})]})}),e.jsxs(ls,{className:"w-[320px] p-0",align:"start",children:[e.jsxs("div",{className:"p-2 border-b flex justify-between items-center",children:[e.jsxs("span",{className:"text-xs font-medium",children:[s.length," sources"]}),a.categories.length>0&&e.jsx(H,{size:"sm",variant:"ghost",className:"h-6 text-xs",onClick:()=>t({...a,categories:[]}),children:"Clear"})]}),e.jsx("div",{className:"max-h-[320px] overflow-y-auto p-2 space-y-1",children:s.map(b=>{const x=a.categories.includes(b.label);return e.jsxs("label",{className:"flex items-center justify-between gap-2 px-2 py-1.5 rounded hover:bg-muted cursor-pointer",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"checkbox",checked:x,onChange:()=>n(b.label)}),e.jsx("span",{className:"text-sm",children:b.label})]}),e.jsx(ie,{variant:"secondary",className:"text-xs",children:b.count})]},b.label)})})]})]})]}),e.jsxs("div",{children:[e.jsx(xe,{className:"text-xs text-muted-foreground",children:"Cost type"}),e.jsxs(Be,{value:a.costType,onValueChange:b=>t({...a,costType:b}),children:[e.jsx(Ve,{className:"w-[140px]",children:e.jsx(ze,{})}),e.jsxs(Ue,{children:[e.jsx(me,{value:"both",children:"Both"}),e.jsx(me,{value:"labor",children:"Labor only"}),e.jsx(me,{value:"material",children:"Material only"})]})]})]}),e.jsxs("div",{children:[e.jsx(xe,{className:"text-xs text-muted-foreground",children:"Modified within"}),e.jsxs(Be,{value:((j=a.modifiedWithinDays)==null?void 0:j.toString())||"any",onValueChange:b=>t({...a,modifiedWithinDays:b==="any"?null:Number(b)}
14),children:[e.jsx(Ve,{className:"w-[140px]",children:e.jsx(ze,{})}),e.jsxs(Ue,{children:[e.jsx(me,{value:"any",children:"Any time"}),e.jsx(me,{value:"7",children:"Last 7 days"}),e.jsx(me,{value:"30",children:"Last 30 days"}),e.jsx(me,{value:"90",children:"Last 90 days"})]})]})]}),e.jsxs("div",{children:[e.jsx(xe,{className:"text-xs text-muted-foreground",children:"Sort"}),e.jsxs(Be,{value:a.sort,onValueChange:b=>t({...a,sort:b}),children:[e.jsx(Ve,{className:"w-[180px]",children:e.jsx(ze,{})}),e.jsxs(Ue,{children:[e.jsx(me,{value:"name_asc",children:"Name (AâZ)"}),e.jsx(me,{value:"code_asc",children:"Code (AâZ)"}),e.jsx(me,{value:"labor_desc",children:"Labor (highâlow)"}),e.jsx(me,{value:"labor_asc",children:"Labor (lowâhigh)"}),e.jsx(me,{value:"material_desc",children:"Material (highâlow)"}),e.jsx(me,{value:"material_asc",children:"Material (lowâhigh)"}),e.jsx(me,{value:"total_desc",children:"Total (highâlow)"}),e.jsx(me,{value:"total_asc",children:"Total (lowâhigh)"}),e.jsx(me,{value:"modified_desc",children:"Recently modified"})]})]})]}),e.jsxs("div",{className:"min-w-[260px]",children:[e.jsxs(xe,{className:"text-xs text-muted-foreground",children:["Price range: $",a.priceRange[0]," â $",a.priceRange[1]]}),e.jsx(Ct,{min:0,max:_,step:Math.max(1,Math.round(_/200)),value:a.priceRange,onValueChange:b=>t({...a,priceRange:[b[0],b[1]]}),className:"mt-2"})]}),e.jsxs("div",{className:"flex items-center gap-4 self-center",children:[e.jsxs("label",{className:"flex items-center gap-2 text-xs",children:[e.jsx(ar,{checked:a.hasLaborOnly,onCheckedChange:b=>t({...a,hasLaborOnly:b})}),"Has labor > 0"]}),e.jsxs("label",{className:"flex items-center gap-2 text-xs",children:[e.jsx(ar,{checked:a.hasMaterialOnly,onCheckedChange:b=>t({...a,hasMaterialOnly:b})}),"Has material > 0"]})]}),e.jsxs("div",{className:"flex items-center gap-2 ml-auto",children:[e.jsxs(ie,{variant:"outline",className:"font-mono",children:[e.jsx(an,{className:"h-3 w-3 mr-1"}),r.toLocaleString()," of ",l.toLocaleString()]}),c>0&&e.jsxs(H,{size:"sm",variant:"ghost",onClick:m,children:[e.jsx(Et,{className:"h-3 w-3 mr-1"})," Clear (",c,")"]})]})]})})}const Yd=a=>a==="addition"?"default":a==="remodel"?"secondary":"outline";function Xd({items:a,stateCode:t,laborRatio:s,materialRatio:r}){const l=p.useMemo(()=>Ti(a,s,r),[a,s,r]),[o,i]=p.useState(new Set),d=l.length,_=l.reduce((c,m)=>c+m.itemCount,0),n=c=>{i(m=>{const h=new Set(m);return h.has(c)?h.delete(c):h.add(c),h})};return e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("p",{className:"text-sm text-muted-foreground",children:["Showing ",e.jsx("strong",{children:d})," cards aggregated from ",e.jsx("strong",{children:_.toLocaleString()})," line items."]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(H,{size:"sm",variant:"outline",onClick:()=>i(new Set(l.flatMap(c=>c.buckets.map(m=>`${c.card}::${m.scope}`)))),children:"Expand all"}),e.jsx(H,{size:"sm",variant:"outline",onClick:()=>i(new Set),children:"Collapse all"})]})]}),e.jsx("div",{className:"border rounded-lg max-h-[600px] overflow-auto",children:e.jsxs(Ze,{children:[e.jsx(ea,{className:"sticky top-0 bg-background z-10",children:e.jsxs(Le,{children:[e.jsx(Z,{className:"w-8"}),e.jsx(Z,{children:"Card"}),e.jsx(Z,{children:"Scope"}),e.jsx(Z,{className:"text-right",children:"Items"}),e.jsx(Z,{className:"text-right",children:"NJ Labor"}),e.jsx(Z,{className:"text-right",children:"NJ Material"}),e.jsxs(Z,{className:"text-right",children:[t," Labor"]}),e.jsxs(Z,{className:"text-right",children:[t," Material"]}),e.jsx(Z,{className:"text-right",children:"NJ Total"}),e.jsxs(Z,{className:"text-right",children:[t," Total"]}),e.jsx(Z,{className:"text-right",children:"Î %"})]})}),e.jsxs(aa,{children:[l.map(c=>e.jsx(p.Fragment,{children:c.buckets.map(m=>{const h=`${c.card}::${m.scope}`,j=o.has(h),b=m.deltaPct>.5?"text-orange-600 dark:text-orange-400":m.deltaPct<-.5?"text-emerald-600 dark:text-emerald-400":"text-muted-foreground";return e.jsxs(p.Fragment,{children:[e.jsxs(Le,{className:"cursor-pointer hover:bg-muted/40",onClick:()=>n(h),children:[e.jsx(Q,{className:"p-2",children:j?e.jsx(ha,{className:"h-4 w-4"}):e.jsx(fa,{className:"h-4 w-4"})}),e.jsx(Q,{className:"font-medium",children:c.card}),e.jsx(Q,{children:e.jsx(ie,{variant:Yd(m.scope),children:Li(m.scope)})}),e.jsx(Q,{className:"text-right font-mono text-xs",children:m.items.length}),e.jsxs(Q,{className:"text-right font-mono",children:["$",m.njLabor.toFixed(0)]}),e.jsxs(Q,{className:"text-right font-mono",children:["$",m.njMaterial.toFixed(0)]}),e.jsxs(Q,{className:"text-right font-mono",children:["$",m.stateLabor.toFixed(0)]}),e.jsxs(Q,{className:"text-right font-mono",children:["$",m.stateMaterial.toFixed(0)]}),e.jsxs(Q,{className:"text-right font-mono font-semibold",children:["$",m.njTotal.toFixed(0)]}),e.jsxs(Q,{className:"text-right font-mono font-semibold",children:["$",m.stateTotal.toFixed(0)]}),e.jsxs(Q,{className:`text-right font-mono ${b}`,children:[m.deltaPct>0?"+":"",m.deltaPct.toFixed(1),"%"]})]}),j&&e.jsx(Le,{className:"bg-muted/20",children:e.jsx(Q,{colSpan:11,className:"p-0",children:e.jsx("div",{className:"p-3",children:e.jsxs(Ze,{children:[e.jsx(ea,{children:e.jsxs(Le,{children:[e.jsx(Z,{className:"text-xs",children:"Code"}),e.jsx(Z,{className:"text-xs",children:"Name"}),e.jsx(Z,{className:"text-xs text-right",children:"NJ Labor"}),e.jsx(Z,{className:"text-xs text-right",children:"NJ Material"}),e.jsxs(Z,{className:"text-xs text-right",children:[t," Labor"]}),e.jsxs(Z,{className:"text-xs text-right",children:[t," Material"]}),e.jsxs(Z,{className:"text-xs text-right",children:[t," Total"]})]})}),e.jsx(aa,{children:m.items.map(x=>{const u=x.labor_rate*s,N=x.material_rate*r;return e.jsxs(Le,{children:[e.jsx(Q,{className:"font-mono text-xs",children:x.item_code}),e.jsx(Q,{className:"text-xs",children:x.item_name}),e.jsxs(Q,{className:"text-right font-mono text-xs",children:["$",x.labor_rate.toFixed(2)]}),e.jsxs(Q,{className:"text-right font-mono text-xs",children:["$",x.material_rate.toFixed(2)]}),e.jsxs(Q,{className:"text-right font-mono text-xs",children:["$",u.toFixed(2)]}),e.jsxs(Q,{className:"text-right font-mono text-xs",children:["$",N.toFixed(2)]}),e.jsxs(Q,{className:"text-right font-mono text-xs font-semibold",children:["$",(u+N).toFixed(2)]})]},`${x.source_table}-${x.id}`)})})]})})})})]},h)})},c.card)),l.length===0&&e.jsx(Le,{children:e.jsx(Q,{colSpan:11,className:"text-center text-muted-foreground py-8",children:"No cards match the current filters."})})]})]})})]})}function Zd(a){if(typeof a!="string"||!a.length)throw new Error("PDF content was not returned");const t=atob(a);if(!t.startsWith("%PDF-"))throw new Error("The export did not return a valid PDF file");return Uint8Array.from(t,s=>s.charCodeAt(0))}const em=["NJ","NY","PA","CT","MA","CA","TX","FL","IL","OH","GA","NC","MI","VA","WA","AZ","TN","IN","MO","MD","WI","CO","MN","SC","AL","LA","KY","OR","OK","UT","IA","NV","AR","MS","KS","NM","NE","WV","ID","HI","NH","ME","MT","RI","DE","SD","ND","AK","VT","WY","DC"],Gt=[{key:"interior",label:"Interior",sources:["Kitchen","Bar","Full Bath","Half Bath","Primary Bath","Interior Building","Millwork","Hardwood","Basement Flooring","Fireplaces","Mudrooms","Laundry","Built-Ins"]},{key:"exterior",label:"Exterior",sources:["Decks","Driveways","Paver Patios","Fences","Exterior Stairs","Siding","Roofing","Windows","Window Wells","Patio Doors","Skylights"]},{key:"mechanical",label:"Mechanical / Systems",sources:["Structural","HVAC Extension","Seepage Pits"]}
14,{key:"finishes",label:"Finishes & Allowances",sources:["Finish Allowances","Base Pricing (Legacy)"]}];function am(){const{toast:a}=pr(),{showStatePricingReport:t,showStatePricingExport:s}=ds(),r=!1,[l,o]=p.useState("NJ"),[i,d]=p.useState(null),[_,n]=p.useState(null),[c,m]=p.useState(""),[h,j]=p.useState(Jt),[b,x]=p.useState("interior"),[u,N]=p.useState(null),[y,L]=p.useState("line_items"),{data:I}=Ke({queryKey:["state-ratios-split",l],queryFn:async()=>{if(l==="NJ")return{ratio:1,labor_ratio:1,material_ratio:1};const{data:R}=await ge.from("state_pricing_ratios").select("ratio, labor_ratio, material_ratio").eq("state_code",l).eq("is_active",!0).maybeSingle();return{ratio:Number(R==null?void 0:R.ratio)||1,labor_ratio:Number(R==null?void 0:R.labor_ratio)||Number(R==null?void 0:R.ratio)||1,material_ratio:Number(R==null?void 0:R.material_ratio)||Number(R==null?void 0:R.ratio)||1}}}),$=(I==null?void 0:I.ratio)??1,ee=(I==null?void 0:I.labor_ratio)??$,U=(I==null?void 0:I.material_ratio)??$,{data:E=[],isLoading:J,refetch:be}=cr({priceRange:[0,Number.POSITIVE_INFINITY]}),F=p.useMemo(()=>{const R=new Map;return E.forEach(v=>R.set(v.source_label,(R.get(v.source_label)||0)+1)),Array.from(R.entries()).sort((v,G)=>v[0].localeCompare(G[0])).map(([v,G])=>({label:v,count:G}))},[E]),se=p.useMemo(()=>{const R=E.reduce((v,G)=>Math.max(v,G.labor_rate*ee,G.material_rate*U),0);return Math.max(100,Math.ceil(R/100)*100)},[E,ee,U]),V=p.useMemo(()=>{const R=h.searchText.trim().toLowerCase(),v=h.categories.length?new Set(h.categories):null,G=h.modifiedWithinDays?Date.now()-h.modifiedWithinDays*864e5:null,[te,oe]=h.priceRange,A=E.filter(O=>{if(R&&!`${O.item_code} ${O.item_name}`.toLowerCase().includes(R)||v&&!v.has(O.source_label)||G&&O.updated_at&&new Date(O.updated_at).getTime()<G||h.hasLaborOnly&&O.labor_rate<=0||h.hasMaterialOnly&&O.material_rate<=0)return!1;const he=O.labor_rate*ee,Ie=O.material_rate*U,Ge=Oe=>Oe>=te&&Oe<=oe;return!(h.costType==="labor"&&!Ge(he)||h.costType==="material"&&!Ge(Ie)||h.costType==="both"&&!(Ge(he)||Ge(Ie)))}),de={name_asc:(O,he)=>O.item_name.localeCompare(he.item_name),code_asc:(O,he)=>O.item_code.localeCompare(he.item_code),labor_asc:(O,he)=>O.labor_rate*ee-he.labor_rate*ee,labor_desc:(O,he)=>he.labor_rate*ee-O.labor_rate*ee,material_asc:(O,he)=>O.material_rate*U-he.material_rate*U,material_desc:(O,he)=>he.material_rate*U-O.material_rate*U,total_asc:(O,he)=>O.labor_rate*ee+O.material_rate*U-(he.labor_rate*ee+he.material_rate*U),total_desc:(O,he)=>he.labor_rate*ee+he.material_rate*U-(O.labor_rate*ee+O.material_rate*U),modified_desc:(O,he)=>new Date(he.updated_at||0).getTime()-new Date(O.updated_at||0).getTime()};return A.sort(de[h.sort]||de.name_asc),A},[E,h,ee,U]),z=p.useMemo(()=>{const R={};return Gt.forEach(v=>{R[v.key]={},v.sources.forEach(G=>{R[v.key][G]=[]})}),V.forEach(v=>{const G=Gt.find(oe=>oe.sources.includes(v.source_label)),te=(G==null?void 0:G.key)||"mechanical";R[te][v.source_label]||(R[te][v.source_label]=[]),R[te][v.source_label].push(v)}),R},[V]),Se=p.useMemo(()=>{const R=z[b]||{};return u?R[u]||[]:Object.values(R).flat()},[z,b,u]),re=p.useMemo(()=>{const R=V.reduce((G,te)=>G+te.labor_rate*ee,0),v=V.reduce((G,te)=>G+te.material_rate*U,0);return{itemCount:V.length,totalLabor:R,totalMaterial:v,grandTotal:R+v}},[V,ee,U]),$e=async R=>{n(null),a({title:"Editing moved",description:"Prices are edited in the Pricing Control Center so every change is audited and existing projects stay frozen."})},g=async R=>{d(R);try{const{data:v,error:G}=await ge.functions.invoke("generate-state-pricing-report",{body:{state_code:l,format:R,view:y,filters:{search:h.searchText,categories:h.categories,costType:h.costType,priceRange:h.priceRange,modifiedWithinDays:h.modifiedWithinDays,hasLaborOnly:h.hasLaborOnly,hasMaterialOnly:h.hasMaterialOnly}}});if(G)throw G;if(R==="pdf"){const te=new Blob([Zd(v==null?void 0:v.pdf_base64)],{type:"application/pdf"}),oe=URL.createObjectURL(te),A=document.createElement("a");A.href=oe,A.download=v.filename||`pricing-${l}.pdf`,A.click(),setTimeout(()=>
14URL.revokeObjectURL(oe),3e4),a({title:"PDF exported",description:"Server-priced catalog rows included."})}else if(v!=null&&v.url)window.open(v.url,"_blank"),a({title:"Report Ready",description:`Downloaded as ${R.toUpperCase()}`});else if(v!=null&&v.csv){const te=new Blob([v.csv],{type:"text/csv"}),oe=URL.createObjectURL(te),A=document.createElement("a");A.href=oe,A.download=v.filename||`pricing-${y==="card_wise"?"cardwise-":""}${l}-${Date.now()}.csv`,A.click(),URL.revokeObjectURL(oe)}}catch(v){a({title:"Export Failed",description:v.message,variant:"destructive"})}finally{d(null)}},S=(R,v)=>{const G=(_==null?void 0:_.id)===R.id&&(_==null?void 0:_.field)===v,te=v==="labor_rate"?ee:U,oe=R[v],A=oe*te;return G?e.jsxs("div",{className:"flex gap-1",children:[e.jsx(Pe,{type:"number",value:c,onChange:de=>m(de.target.value),className:"w-24 h-8",autoFocus:!0,onKeyDown:de=>{de.key==="Enter"&&$e(),de.key==="Escape"&&n(null)}}),e.jsx(H,{size:"sm",onClick:()=>$e(),className:"h-8",children:"â"})]}):e.jsxs("div",{className:"px-2 py-1 rounded font-mono text-right",onClick:()=>r,title:"Inline editing not included in your plan",children:["$",A.toFixed(2),l!=="NJ"&&e.jsxs("div",{className:"text-xs text-muted-foreground",children:["(NJ: $",oe.toFixed(2),")"]})]})};return t?e.jsx(mr,{children:e.jsxs("div",{className:"container mx-auto py-8 space-y-6",children:[e.jsxs("div",{className:"flex justify-between items-start",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-3xl font-bold text-foreground flex items-center gap-2",children:[e.jsx(fi,{className:"h-7 w-7"})," State Pricing Report"]}),e.jsxs("p",{className:"text-muted-foreground",children:["Detailed labor & material breakdown for every line item across all ",rn.length," pricing tables, per state."]})]}),s&&e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(H,{variant:"outline",onClick:()=>g("csv"),disabled:i==="csv",children:[i==="csv"?e.jsx(Fe,{className:"h-4 w-4 animate-spin mr-2"}):e.jsx(Wa,{className:"h-4 w-4 mr-2"}),"CSV"]}),e.jsxs(H,{variant:"outline",onClick:()=>g("xlsx"),disabled:i==="xlsx",children:[i==="xlsx"?e.jsx(Fe,{className:"h-4 w-4 animate-spin mr-2"}):e.jsx(Ys,{className:"h-4 w-4 mr-2"}),"Excel"]}),e.jsxs(H,{onClick:()=>g("pdf"),disabled:i==="pdf",children:[i==="pdf"?e.jsx(Fe,{className:"h-4 w-4 animate-spin mr-2"}):e.jsx(wi,{className:"h-4 w-4 mr-2"}),"PDF Report"]})]})]}),e.jsxs("div",{className:"grid gap-4 md:grid-cols-5",children:[e.jsxs(ye,{className:"md:col-span-2",children:[e.jsxs(ke,{className:"pb-3",children:[e.jsx(Ce,{className:"text-sm",children:"State Selection"}),e.jsx(Ye,{children:"NJ is the baseline (ratio 1.0)"})]}),e.jsxs(je,{children:[e.jsxs(Be,{value:l,onValueChange:o,children:[e.jsx(Ve,{children:e.jsx(ze,{})}),e.jsx(Ue,{className:"max-h-[300px]",children:em.map(R=>e.jsxs(me,{value:R,children:[R," ",R==="NJ"&&"(Baseline)"]},R))})]}),e.jsxs("div",{className:"mt-3 flex flex-wrap gap-2 text-xs",children:[e.jsxs(Na,{children:[e.jsx(ka,{asChild:!0,children:e.jsxs(ie,{variant:"secondary",className:"font-mono cursor-help",children:["Overall ",$.toFixed(3),"x ",e.jsx(Ba,{className:"h-3 w-3 ml-1"})]})}),e.jsx(Ca,{children:"Blended ratio (legacy display)"})]}),e.jsxs(Na,{children:[e.jsx(ka,{asChild:!0,children:e.jsxs(ie,{variant:"outline",className:"font-mono cursor-help",children:["Labor ",ee.toFixed(3),"x"]})}),e.jsx(Ca,{children:"RSMeans CCI labor cost ratio vs. NJ"})]}),e.jsxs(Na,{children:[e.jsx(ka,{asChild:!0,children:e.jsxs(ie,{variant:"outline",className:"font-mono cursor-help",children:["Material ",U.toFixed(3),"x"]})}),e.jsx(Ca,{children:"RSMeans CCI material cost ratio vs. NJ"})]})]})]})]}),e.jsxs(ye,{children:[e.jsx(ke,{className:"pb-3",children:e.jsx(Ce,{className:"text-sm",children:"Items (filtered)"})}),e.jsx(je,{children:e.jsx("div",{className:"text-2xl font-bold",children:re.itemCount.toLocaleString()})})]}),e.jsxs(ye,{children:[e.jsx(ke,{className:"pb-3",children:e.jsx(Ce,{className:"text-sm",children:"Total Labor"})}),e.jsx(je,{children:e.jsxs("div",{className:"text-xl sm:text-2xl font-bold font-mono tabular-nums break-all",children:["$",re.totalLabor.toFixed(0)]})})]}),e.jsxs(ye,{children:[e.jsx(ke,{className:"pb-3",children:e.jsx(Ce,{className:"text-sm",children:"Total Material"})}),e.jsx(je,{children:e.jsxs("div",{className:"text-xl sm:text-2xl font-bold font-mono tabular-nums break-all",children:["$",re.totalMaterial.toFixed(0)]})})]})]}),e.jsxs(ye,{children:[e.jsx(ke,{children:e.jsxs("div",{className:"flex items-start justify-between gap-4 flex-wrap",children:[e.jsxs("div",{children:[e.jsxs(Ce,{children:["Detailed Pricing â ",l]}),e.jsx(Ye,{children:y==="card_wise"?"Card totals split by Addition / Remodel / Standalone with state ratios applied.":"Read-only view."})]}),e.jsxs("div",{className:"inline-flex rounded-md border bg-background p-1",children:[e.jsxs(H,{size:"sm",variant:y==="line_items"?"default":"ghost",onClick:()=>L("line_items"),className:"h-8",children:[e.jsx(yi,{className:"h-4 w-4 mr-1.5"})," Line Items"]}),e.jsxs(H,{size:"sm",variant:y==="card_wise"?"default":"ghost",onClick:()=>L("card_wise"),className:"h-8",children:[e.jsx(ji,{className:"h-4 w-4 mr-1.5"})," Card-Wise (Add / Remodel)"]})]})]})}),e.jsx(je,{children:J?e.jsx("div",{className:"flex justify-center p-8",children:e.jsx(Fe,{className:"h-6 w-6 animate-spin"})}):e.jsxs(e.Fragment,{children:[e.jsx(Jd,{filters:h,onChange:j,availableCategories:F,visibleCount:V.length,totalCount:E.length,priceMaxBound:se}),y==="card_wise"?e.jsx("div",{className:"mt-4",children:e.jsx(Xd,{items:V,stateCode:l,laborRatio:ee,materialRatio:U})}):e.jsxs(os,{value:b,onValueChange:R=>{x(R),N(null)},children:[e.jsx(cs,{className:"flex-wrap h-auto",children:Gt.map(R=>{const v=Object.values(z[R.key]||{}).reduce((G,te)=>G+te.length,0);return e.jsxs(ia,{value:R.key,children:[R.label," ",e.jsx(ie,{variant:"secondary",className:"ml-2",children:v})]},R.key)})}),Gt.map(R=>e.jsxs(oa,{value:R.key,className:"mt-4 space-y-3",children:[e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsxs(H,{size:"sm",variant:u===null?"default":"outline",onClick:()=>N(null),children:["All (",Object.values(z[R.key]||{}).reduce((v,G)=>
14v+G.length,0),")"]}),R.sources.map(v=>{var te,oe;const G=((oe=(te=z[R.key])==null?void 0:te[v])==null?void 0:oe.length)||0;return G===0?null:e.jsxs(H,{size:"sm",variant:u===v?"default":"outline",onClick:()=>N(v),children:[v," ",e.jsx(ie,{variant:"secondary",className:"ml-2",children:G})]},v)})]}),e.jsx("div",{className:"border rounded-lg max-h-[600px] overflow-y-auto overflow-x-hidden",children:e.jsxs(Ze,{className:"w-full table-fixed",children:[e.jsx(ea,{className:"sticky top-0 bg-background z-10",children:e.jsxs(Le,{children:[e.jsx(Z,{className:"w-[16%]",children:"Code"}),e.jsx(Z,{className:"w-[14%]",children:"Source"}),e.jsx(Z,{children:"Name"}),e.jsxs(Z,{className:"w-[13%] text-right",children:["Labor (",l,")"]}),e.jsxs(Z,{className:"w-[13%] text-right",children:["Material (",l,")"]}),e.jsx(Z,{className:"w-[12%] text-right",children:"Total"}),e.jsx(Z,{className:"w-[10%] text-xs",children:"Modified"})]})}),e.jsxs(aa,{children:[Se.map(v=>e.jsxs(Le,{children:[e.jsx(Q,{className:"font-mono text-xs truncate",title:v.item_code,children:v.item_code}),e.jsx(Q,{className:"text-xs min-w-0",children:e.jsx("span",{className:`inline-flex max-w-full items-center rounded-full border px-2 py-0.5 text-[10px] font-medium ${Nr(v.source_label)}`,title:v.source_label,children:e.jsx("span",{className:"truncate",children:v.source_label})})}),e.jsx(Q,{className:"text-sm truncate",title:v.item_name,children:v.item_name}),e.jsx(Q,{children:S(v,"labor_rate")}),e.jsx(Q,{children:S(v,"material_rate")}),e.jsxs(Q,{className:"text-right font-mono font-semibold",children:["$",(v.labor_rate*ee+v.material_rate*U).toFixed(2)]}),e.jsx(Q,{className:"text-xs text-muted-foreground truncate",children:v.updated_at?new Date(v.updated_at).toLocaleDateString():"-"})]},`${v.source_table}-${v.id}`)),Se.length===0&&e.jsx(Le,{children:e.jsx(Q,{colSpan:7,className:"text-center text-muted-foreground py-8",children:"No items match the current filters."})})]})]})})]},R.key))]})]})})]})]})}):e.jsx("div",{className:"container mx-auto py-16 max-w-2xl text-center",children:e.jsxs(ye,{children:[e.jsxs(ke,{children:[e.jsxs(Ce,{className:"flex items-center justify-center gap-2",children:[e.jsx(tn,{className:"h-6 w-6 text-amber-500"}),"State Pricing Report not included"]}),e.jsx(Ye,{children:"The detailed per-state pricing report is available on plans that include Multi-State Pricing."})]}),e.jsxs(je,{className:"space-y-4",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Upgrade to a GC, Realtor, or Architect Professional plan (or higher) to unlock per-state labor & material breakdowns, exports, and inline editing."}),e.jsx(H,{asChild:!0,children:e.jsx(ni,{to:"/pricing",children:"View pricing plans"})})]})]})})}const tm=30,ei=.75,ai=1.5;function Bl(a,t){if(!t)return"pending";const s=Number(t.ratio??0);if(s<ei||s>ai)return"oob";const r=new Date(a.last_updated??t.last_updated??0).getTime();return(Date.now()-r)/(1e3*60*60*24)>tm?"stale":"fresh"}function sm(){const a=$a(),{showMultiStatePricing:t}=ds(),[s,r]=p.useState(null),[l,o]=p.useState({location:"",labor:"",material:""}),[i,d]=p.useState(""),[_,n]=p.useState("all"),[c,m]=p.useState("state"),[h,j]=p.useState("asc"),[b,x]=p.useState(new Set),[u,N]=p.useState(!1),[y,L]=p.useState(""),[I,$]=p.useState(null),[ee,U]=p.useState(!1),{data:E,isSuccess:J}=Rt(!0),be=async w=>{var ue;const P=y.trim();if(P.length<3)throw new Error("Enter a reason before saving state pricing");const{data:M,error:D}=await ge.functions.invoke("apply-catalog-price-update",{body:{kind:"state_ratio",scope:"global",notes:P,...w}}),fe=await wa(M,D);if(fe.verdict&&$(fe),((M==null?void 0:M.code)??null)==="no_changes_applied")return{fields:0,stale:0,noop:!0};if(D)throw D;if(M!=null&&M.error&&!(M!=null&&M.success)){const T=M.error;throw new Error(typeof T=="string"?T:"State pricing update rejected")}return(ue=M==null?void 0:M.errors)!=null&&ue.length&&le.warning("Some state values were skipped",{description:M.errors[0]}),{fields:(M==null?void 0:M.fields_changed)??0,stale:(M==null?void 0:M.analyses_marked_stale)??0,noop:!1}},F=()=>{a.invalidateQueries({queryKey:["state-cost-indices"]}),a.invalidateQueries({queryKey:["state-pricing-ratios"]}),a.invalidateQueries({queryKey:["state-ratio-audit"]}),a.invalidateQueries({queryKey:["pricing-wiring-verdicts","latest"]})},{data:se=[]}=Ke({queryKey:["state-cost-indices"],queryFn:async()=>{const{data:w,error:P}=await ge.from("state_cost_indices").select("*").order("state_code");if(P)throw P;return w??[]}}),{data:V=[]}=Ke({queryKey:["state-pricing-ratios"],queryFn:async()=>{const{data:w,error:P}=await ge.from("state_pricing_ratios").select("*").order("state_code");if(P)throw P;return w??[]}}),{data:z={}}=Ke({queryKey:["state-pricing-counts"],queryFn:async()=>{const{data:w,error:P}=await ge.from("state_pricing").select("state_code");if(P)throw P;const M={};
14return(w??[]).forEach(D=>{M[D.state_code]=(M[D.state_code]??0)+1}),M}}),{data:Se=[]}=Ke({queryKey:["state-ratio-audit"],queryFn:async()=>{const{data:w,error:P}=await ge.from("state_ratio_audit").select("*").order("created_at",{ascending:!1}).limit(100);if(P)throw P;return w??[]}}),re=Ta({mutationFn:async w=>{const P=w!=null&&w.all?{all:!0}:{},{data:M,error:D}=await ge.functions.invoke("fetch-rsmeans-indices",{body:P});if(D)throw D;if(M!=null&&M.error)throw new Error(M.error);return M},onSuccess:w=>{var P,M;le.success(`RS Means sync complete (${w.mode}). Updated: ${((P=w.updated_states)==null?void 0:P.length)??0} states`),(M=w.warnings)!=null&&M.length&&w.warnings.slice(0,5).forEach(D=>le.warning(D)),a.invalidateQueries({queryKey:["state-pricing-ratios"]}),a.invalidateQueries({queryKey:["state-cost-indices"]}),a.invalidateQueries({queryKey:["state-ratio-audit"]})},onError:w=>le.error(`Refresh failed: ${w.message}`)}),$e=Ta({mutationFn:async w=>{const{data:P,error:M}=await ge.functions.invoke("generate-state-pricing",{body:{state_code:w}});if(M)throw M;if(P!=null&&P.error)throw new Error(P.error);return P},onSuccess:(w,P)=>{le.success(`Regenerated ${P}: ${w.generated} rows`),a.invalidateQueries({queryKey:["state-pricing-counts"]})},onError:w=>le.error(`Regenerate failed: ${w.message}`)}),g=Ta({mutationFn:async w=>{const P={location_index:w.location_index};return w.labor_index!=null&&(P.labor_index=w.labor_index),w.material_index!=null&&(P.material_index=w.material_index),be({state_changes:[{target_table:"state_cost_indices",state_code:w.state_code,state_name:_t[w.state_code]??w.state_code,values:P}]})},onSuccess:w=>{w.noop?le.info("No change â the stored index already matches"):(le.success(`Index saved â ${w.fields} value(s) verified`,{description:`New indices apply to future estimates. ${w.stale} existing project(s) marked stale.`}),r(null)),F()},onError:w=>le.error(`Save failed: ${w.message}`)}),S=Ta({mutationFn:async()=>be({recompute_ratios_from_indices:!0}),onSuccess:w=>{w.noop?le.info("Ratios already match the stored indices"):le.success(`Recomputed ratios â ${w.fields} value(s) verified`,{description:`${w.stale} existing project(s) marked stale.`}),F()},onError:w=>le.error(`Recompute failed: ${w.message}`)});async function R(){if(u)return;N(!0);const w=se.filter(D=>D.state_code!=="NJ").map(D=>D.state_code);let P=0,M=0;for(const D of w)try{await $e.mutateAsync(D),P++}catch{M++}N(!1),le.success(`Bulk regenerate complete: ${P} ok, ${M} failed`),a.invalidateQueries({queryKey:["state-pricing-counts"]})}function v(){const w=new Map(V.map(ue=>[ue.state_code,ue])),P="state_code,state_name,region,location_index,labor_index,material_index,ratio,labor_ratio,material_ratio,last_updated",M=se.map(ue=>{const T=w.get(ue.state_code);return[ue.state_code,_t[ue.state_code]??ue.state_code,It[ue.state_code]??"",ue.location_index,ue.labor_index??"",ue.material_index??"",(T==null?void 0:T.ratio)??"",(T==null?void 0:T.labor_ratio)??"",(T==null?void 0:T.material_ratio)??"",ue.last_updated??""].join(",")}),D=new Blob([P+` 15`+M.join(` 16`)],{type:"text/csv"}),fe=URL.createObjectURL(D),ve=document.createElement("a");ve.href=fe,ve.download=`state-pricing-${new Date().toISOString().slice(0,10)}.csv`,ve.click(),URL.revokeObjectURL(fe),le.success(`Exported ${M.length} states to CSV`)}function G(w){const P=new FileReader;P.onload=async()=>{var M,D,fe;try{const ue=String(P.result??"").split(/\r?\n/).filter(pe=>pe.trim());if(ue.length<2)throw new Error("CSV is empty");const T=ue[0].split(",").map(pe=>pe.trim().toLowerCase()),ce=pe=>T.indexOf(pe),X=ce("state_code"),B=ce("location_index"),f=ce("labor_index"),q=ce("material_index");if(X<0||B<0)throw new Error("Required: state_code, location_index");const K=[];for(let pe=1;pe<ue.length;pe++){const W=ue[pe].split(","),we=(M=W[X])==null?void 0:M.trim().toUpperCase(),Ee=parseFloat(W[B]);if(!we||!isFinite(Ee))continue;const ne={location_index:Ee};f>=0&&((D=W[f])!=null&&D.trim())&&(ne.labor_index=parseFloat(W[f])),q>=0&&((fe=W[q])!=null&&fe.trim())&&(ne.material_index=parseFloat(W[q])),K.push({target_table:"state_cost_indices",state_code:we,state_name:_t[we]??we,values:ne})}if(!K.length)throw new Error("No valid rows found");const _e=await be({state_changes:K});le.success(`Imported ${K.length} states â ${_e.fields} value(s) verified. Recomputing ratiosâ¦`),F(),await S.mutateAsync()}catch(ve){le.error(`Import failed: ${ve.message}`)}},P.readAsText(w)}const te=se.find(w=>w.state_code==="NJ"),oe=new Map(V.map(w=>[w.state_code,w])),A=p.useMemo(()=>{let w=0,P=0,M=0,D=0,fe=0;return se.forEach(ve=>{const ue=oe.get(ve.state_code);ue!=null&&ue.is_active&&w++,z[ve.state_code]>0&&P++;const T=Bl(ve,ue);T==="stale"&&M++,T==="oob"&&D++;const ce=new Date((ue==null?void 0:ue.last_updated)??ve.last_updated??0).getTime();ce>fe&&(fe=ce)}
16),{total:se.length,activeRatios:w,withPricing:P,stale:M,oob:D,lastRefresh:fe?new Date(fe):null}},[se,oe,z]),de=p.useMemo(()=>{const w={};return V.forEach(P=>{const M=It[P.state_code];M&&(w[M]??(w[M]={sum:0,n:0}),w[M].sum+=Number(P.ratio),w[M].n+=1)}),js.map(P=>({region:P,avg:w[P]?w[P].sum/w[P].n:0}))},[V]),O=p.useMemo(()=>{const w=i.trim().toUpperCase();let P=se.filter(M=>{if(w){const D=(_t[M.state_code]??"").toUpperCase();if(!M.state_code.includes(w)&&!D.includes(w))return!1}return!(_!=="all"&&It[M.state_code]!==_)});return P=[...P].sort((M,D)=>{var ve,ue;let fe=0;if(c==="state")fe=M.state_code.localeCompare(D.state_code);else if(c==="ratio"){const T=Number(((ve=oe.get(M.state_code))==null?void 0:ve.ratio)??0),ce=Number(((ue=oe.get(D.state_code))==null?void 0:ue.ratio)??0);fe=T-ce}else c==="updated"&&(fe=new Date(M.last_updated??0).getTime()-new Date(D.last_updated??0).getTime());return h==="asc"?fe:-fe}),P},[se,i,_,c,h,oe]),he=p.useMemo(()=>{const w={};return O.forEach(P=>{const M=It[P.state_code]??"Other";w[M]??(w[M]=[]),w[M].push(P)}),w},[O]),Ie=w=>{r(w.state_code),o({location:String(w.location_index??""),labor:w.labor_index!=null?String(w.labor_index):"",material:w.material_index!=null?String(w.material_index):""})},Ge=w=>{const P=parseFloat(l.location);if(!isFinite(P)||P<=0)return le.error("Location index must be > 0");g.mutate({state_code:w,location_index:P,labor_index:l.labor?parseFloat(l.labor):null,material_index:l.material?parseFloat(l.material):null})},Oe=w=>{x(P=>{const M=new Set(P);return M.has(w)?M.delete(w):M.add(w),M})},k=(()=>{if(!s||!te)return null;const w=parseFloat(l.location);if(!isFinite(w)||w<=0)return null;const P=w/Number(te.location_index);return Math.max(ei,Math.min(ai,P))})();return t?e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"grid gap-3 md:grid-cols-5",children:[e.jsxs(ye,{children:[e.jsx(ke,{className:"pb-2",children:e.jsx(Ce,{className:"text-xs text-muted-foreground",children:"Total States"})}),e.jsx(je,{children:e.jsx("div",{className:"text-2xl font-bold",children:A.total})})]}),e.jsxs(ye,{children:[e.jsx(ke,{className:"pb-2",children:e.jsx(Ce,{className:"text-xs text-muted-foreground",children:"Active Ratios"})}),e.jsx(je,{children:e.jsx("div",{className:"text-2xl font-bold text-primary",children:A.activeRatios})})]}),e.jsxs(ye,{children:[e.jsx(ke,{className:"pb-2",children:e.jsx(Ce,{className:"text-xs text-muted-foreground",children:"Pricing Generated"})}),e.jsxs(je,{children:[e.jsx("div",{className:"text-2xl font-bold",children:A.withPricing}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["of ",A.total," states"]})]})]}),e.jsxs(ye,{children:[e.jsx(ke,{className:"pb-2",children:e.jsx(Ce,{className:"text-xs text-muted-foreground",children:"Stale (>30d)"})}),e.jsx(je,{children:e.jsx("div",{className:`text-2xl font-bold ${A.stale>0?"text-destructive":""}`,children:A.stale})})]}),e.jsxs(ye,{children:[e.jsx(ke,{className:"pb-2",children:e.jsx(Ce,{className:"text-xs text-muted-foreground",children:"Last Refresh"})}),e.jsx(je,{children:e.jsxs("div",{className:"text-sm font-medium flex items-center gap-1",children:[e.jsx(_r,{className:"h-3 w-3"}),A.lastRefresh?A.lastRefresh.toLocaleDateString():"â"]})})]})]}),e.jsxs("div",{className:"grid gap-4 md:grid-cols-2",children:[e.jsxs(ye,{children:[e.jsx(ke,{className:"pb-2",children:e.jsx(Ce,{className:"text-sm font-medium text-muted-foreground",children:"NJ Baseline Index"})}),e.jsxs(je,{children:[e.jsx("div",{className:"text-3xl font-bold text-primary",children:te?Number(te.location_index).toFixed(2):"â"}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-1",children:["All ratios derived from this baseline · Source: ",(te==null?void 0:te.source)??"n/a"]})]})]}),e.jsxs(ye,{children:[e.jsx(ke,{className:"pb-2",children:e.jsx(Ce,{className:"text-sm font-medium text-muted-foreground",children:"Region Average Ratios (vs NJ)"})}),e.jsx(je,{className:"space-y-1",children:de.map(w=>e.jsxs("div",{className:"flex items-center gap-2 text-xs",children:[e.jsx("span",{className:"w-20 text-muted-foreground",children:w.region}),e.jsx("div",{className:"flex-1 bg-muted h-2 rounded overflow-hidden",children:e.jsx("div",{className:"h-full bg-primary",style:{width:`${Math.min(100,w.avg/1.5*100)}%`}})}),e.jsxs("span",{className:"w-12 text-right font-mono",children:[w.avg.toFixed(3),"Ã"]})]},w.region))})]})]}),e.jsx(ye,{children:e.jsxs(je,{className:"pt-6 space-y-3",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("div",{className:"relative flex-1 min-w-[200px]",children:[e.jsx(Va,{className:"h-4 w-4 absolute left-2 top-2.5 text-muted-foreground"}),e.jsx(Pe,{placeholder:"Search state code or nameâ¦",value:i,onChange:w=>d(w.target.value),className:"pl-8"})]}),e.jsxs(Be,{value:_,onValueChange:w=>n(w),children:[e.jsx(Ve,{className:"w-44",children:e.jsx(ze,{placeholder:"All regions"})}),e.jsxs(Ue,{children:[e.jsx(me,{value:"all",children:"All regions"}),js.map(w=>e.jsx(me,{value:w,children:w}
16,w))]})]}),e.jsxs(Be,{value:`${c}:${h}`,onValueChange:w=>{const[P,M]=w.split(":");m(P),j(M)},children:[e.jsx(Ve,{className:"w-44",children:e.jsx(ze,{})}),e.jsxs(Ue,{children:[e.jsx(me,{value:"state:asc",children:"State AâZ"}),e.jsx(me,{value:"state:desc",children:"State ZâA"}),e.jsx(me,{value:"ratio:desc",children:"Ratio (highâlow)"}),e.jsx(me,{value:"ratio:asc",children:"Ratio (lowâhigh)"}),e.jsx(me,{value:"updated:desc",children:"Recently updated"}),e.jsx(me,{value:"updated:asc",children:"Oldest updated"})]})]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(Pe,{value:y,onChange:w=>L(w.target.value),placeholder:"Reason for this state pricing change (required)",className:"h-8 max-w-md text-xs"}),e.jsx(xs,{})]}),(I==null?void 0:I.verdict)&&e.jsx(Ua,{verdict:I.verdict,aiNotes:I.aiNotes,reviewerNote:I.reviewerNote,reverted:I.reverted,rechecking:ee,onRecheck:async()=>{if(I.runId){U(!0);try{const w=await qa({run_id:I.runId});w&&$({...I,verdict:w.verdict??I.verdict,aiNotes:w.ai_notes??I.aiNotes}),F()}catch(w){le.error(`Re-check failed: ${(w==null?void 0:w.message)??"unknown error"}`)}finally{U(!1)}}}}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsxs(H,{onClick:()=>re.mutate({all:!0}),disabled:re.isPending,size:"sm",children:[re.isPending?e.jsx(Fe,{className:"mr-2 h-4 w-4 animate-spin"}):e.jsx(Ga,{className:"mr-2 h-4 w-4"}),"Sync RS Means (All 50 States)"]}),e.jsxs(H,{onClick:()=>re.mutate({}),disabled:re.isPending,size:"sm",variant:"outline",children:[re.isPending?e.jsx(Fe,{className:"mr-2 h-4 w-4 animate-spin"}):e.jsx(Ga,{className:"mr-2 h-4 w-4"}),"Refresh Stored Indices"]}),e.jsxs(H,{onClick:()=>S.mutate(),disabled:S.isPending,size:"sm",variant:"outline",children:[S.isPending?e.jsx(Fe,{className:"mr-2 h-4 w-4 animate-spin"}):e.jsx(Fr,{className:"mr-2 h-4 w-4"}),"Recompute Ratios from Indices"]}),e.jsxs(H,{onClick:R,disabled:u,size:"sm",variant:"outline",children:[u?e.jsx(Fe,{className:"mr-2 h-4 w-4 animate-spin"}):e.jsx(Fr,{className:"mr-2 h-4 w-4"}),"Bulk Regenerate All States"]}),e.jsxs(H,{onClick:v,size:"sm",variant:"outline",children:[e.jsx(Wa,{className:"mr-2 h-4 w-4"})," Export CSV"]}),e.jsx("label",{className:"inline-flex",children:e.jsx(H,{asChild:!0,size:"sm",variant:"outline",children:e.jsxs("span",{children:[e.jsx(nn,{className:"mr-2 h-4 w-4"})," Import CSV",e.jsx("input",{type:"file",accept:".csv",className:"hidden",onChange:w=>{var M;const P=(M=w.target.files)==null?void 0:M[0];P&&G(P),w.target.value=""}})]})})})]})]})}),js.filter(w=>{var P;return(P=he[w])==null?void 0:P.length}).map(w=>{const P=b.has(w),M=he[w];return e.jsxs(ye,{children:[e.jsx(ke,{className:"cursor-pointer pb-3",onClick:()=>Oe(w),children:e.jsxs(Ce,{className:"text-base flex items-center gap-2",children:[P?e.jsx(fa,{className:"h-4 w-4"}):e.jsx(ha,{className:"h-4 w-4"}),w,e.jsx(ie,{variant:"secondary",children:M.length})]})}),!P&&e.jsx(je,{children:e.jsxs(Ze,{children:[e.jsx(ea,{children:e.jsxs(Le,{children:[e.jsx(Z,{children:"State"}),e.jsx(Z,{children:"Location Idx"}),e.jsx(Z,{children:"Labor Idx"}),e.jsx(Z,{children:"Material Idx"}),e.jsx(Z,{children:"Ratio vs NJ"}),e.jsx(Z,{children:"Pricing Rows"}),e.jsx(Z,{children:"Status"}),e.jsx(Z,{children:"Wiring"}),e.jsx(Z,{children:"Updated"}),e.jsx(Z,{children:"Actions"})]})}),e.jsx(aa,{children:M.map(D=>{const fe=oe.get(D.state_code),ve=s===D.state_code,ue=D.state_code==="NJ",T=Bl(D,fe),ce=z[D.state_code]??0;return e.jsxs(Le,{children:[e.jsxs(Q,{className:"font-medium",children:[e.jsx("div",{children:D.state_code}),e.jsx("div",{className:"text-xs text-muted-foreground",children:_t[D.state_code]}),ue&&e.jsx(ie,{variant:"secondary",className:"mt-1",children:"Baseline"})]}),e.jsx(Q,{children:ve?e.jsx(Pe,{type:"number",step:"0.01",className:"h-8 w-24",value:l.location,onChange:X=>o({...l,location:X.target.value})}):Number(D.location_index).toFixed(2)}),e.jsx(Q,{children:ve?e.jsx(Pe,{type:"number",step:"0.01",className:"h-8 w-24",value:l.labor,onChange:X=>o({...l,labor:X.target.value})}):D.labor_index!=null?Number(D.labor_index).toFixed(2):"â"}),e.jsx(Q,{children:ve?e.jsx(Pe,{type:"number",step:"0.01",className:"h-8 w-24",value:l.material,onChange:X=>o({...l,material:X.target.value})}):D.material_index!=null?Number(D.material_index).toFixed(2):"â"}),e.jsx(Q,{children:ve&&k!=null?e.jsxs(ie,{variant:"outline",className:"border-primary text-primary",children:[k.toFixed(3),"Ã preview"]}):fe?e.jsxs(ie,{variant:ue?"secondary":"outline",children:[Number(fe.ratio).toFixed(3),"Ã"]}):"â"}),e.jsx(Q,{className:"text-xs",children:ce>0?e.jsx("span",{className:"text-primary font-medium",children:ce}):e.jsx("span",{className:"text-muted-foreground",children:"0"})}),e.jsxs(Q,{children:[T==="fresh"&&e.jsx(ie,{variant:"secondary",className:"bg-primary/10 text-primary",children:"Up to date"}),T==="stale"&&e.jsx(ie,{variant:"outline",className:"border-destructive text-destructive",children:"Stale"}),T==="pending"&&e.jsx(ie,{variant:"outline",children:"Pending"}),T==="oob"&&e.jsx(ie,{variant:"destructive",children:"Out of bounds"})]}
16),e.jsx(Q,{children:e.jsx(_s,{itemCode:`state:${D.state_code}`,preloaded:E==null?void 0:E.get(`state:${D.state_code}`),preloadedReady:J})}),e.jsx(Q,{className:"text-xs text-muted-foreground",children:D.last_updated?new Date(D.last_updated).toLocaleDateString():"â"}),e.jsx(Q,{children:e.jsx("div",{className:"flex gap-1",children:ve?e.jsxs(e.Fragment,{children:[e.jsx(H,{size:"sm",onClick:()=>Ge(D.state_code),disabled:g.isPending,children:"Save"}),e.jsx(H,{size:"sm",variant:"ghost",onClick:()=>r(null),children:"Cancel"})]}):e.jsxs(e.Fragment,{children:[e.jsx(H,{size:"sm",variant:"outline",onClick:()=>Ie(D),children:"Edit"}),!ue&&e.jsx(H,{size:"sm",variant:"outline",onClick:()=>$e.mutate(D.state_code),disabled:$e.isPending,children:"Regen"})]})})})]},D.state_code)})})]})})]},w)}),e.jsxs(ye,{children:[e.jsx(ke,{children:e.jsx(Ce,{children:"Recent Ratio Audit"})}),e.jsx(je,{children:Se!=null&&Se.length?e.jsxs(Ze,{children:[e.jsx(ea,{children:e.jsxs(Le,{children:[e.jsx(Z,{children:"When"}),e.jsx(Z,{children:"State"}),e.jsx(Z,{children:"Old â New Ratio"}),e.jsx(Z,{children:"Î %"}),e.jsx(Z,{children:"Source"})]})}),e.jsx(aa,{children:Se.slice(0,30).map(w=>{const P=Number(w.percent_change??0),M=Math.abs(P)>=2;return e.jsxs(Le,{children:[e.jsx(Q,{className:"text-xs",children:new Date(w.created_at).toLocaleString()}),e.jsx(Q,{className:"font-medium",children:w.state_code}),e.jsxs(Q,{children:[w.old_ratio!=null?Number(w.old_ratio).toFixed(3):"â"," â ",Number(w.new_ratio).toFixed(3)]}),e.jsx(Q,{children:e.jsxs("span",{className:M?"text-destructive flex items-center gap-1":"flex items-center gap-1",children:[M?e.jsx(Xe,{className:"h-3 w-3"}):e.jsx(ba,{className:"h-3 w-3"}),P.toFixed(2),"%"]})}),e.jsx(Q,{className:"text-xs text-muted-foreground",children:w.triggered_by})]},w.id)})})]}):e.jsx("p",{className:"text-sm text-muted-foreground",children:"No audit entries yet."})})]})]}):e.jsxs(ye,{children:[e.jsx(ke,{children:e.jsxs(Ce,{className:"flex items-center gap-2",children:[e.jsx(Xe,{className:"h-5 w-5 text-amber-500"}),"Multi-State Pricing not included"]})}),e.jsx(je,{children:e.jsx("p",{className:"text-sm text-muted-foreground",children:"Your current plan does not include Multi-State Pricing. Upgrade to a plan that includes regional cost indices, the per-state pricing report, and the bulk price editor."})})]})}const rm=["catalog","bulk","insights","analytics","history"],lm={attention:"attention",legacy:"legacy",bands:"bands"};function Vm(){const{isSuperAdmin:a,isLoading:t}=ns(),[s,r]=Vl(),l=s.get("tab")||"",o=rm.includes(l)?l:"catalog",i=vi(l,s.get("view"));p.useEffect(()=>{const _=lm[l];if(!_||!a&&i)return;const n=new URLSearchParams(s);n.set("tab","catalog"),n.set("view",_),r(n,{replace:!0})},[l,s,r,a,i]),p.useEffect(()=>{document.title="Pricing Control Center | Home Estimator"},[]);const d=_=>{const n=new URLSearchParams(s);n.set("tab",_),r(n,{replace:!0})};return t?e.jsx("div",{role:"status",children:"Checking pricing accessâ¦"}):!a&&i?e.jsx(ii,{to:"/admin/pricing?tab=catalog",replace:!0}):e.jsx("div",{className:"w-full max-w-none px-4 py-4 space-y-4",children:e.jsxs(os,{value:o,onValueChange:d,className:"space-y-4",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-x-3 gap-y-2 border-b border-primary/15 pb-2 min-w-0",children:[e.jsx("h1",{className:"text-lg font-bold text-foreground whitespace-nowrap shrink-0",children:"Pricing Control Center"}),e.jsxs(cs,{className:"flex-wrap h-auto gap-1 bg-primary/[0.07] p-1",children:[e.jsx(ia,{value:"catalog",className:"whitespace-nowrap",children:"Catalog"}),e.jsx(ia,{value:"bulk",className:"whitespace-nowrap",children:"Bulk / State"}),a&&e.jsx(ia,{value:"insights",className:"whitespace-nowrap",children:"Insights"}),a&&e.jsx(ia,{value:"analytics",className:"whitespace-nowrap",children:"Coverage"}),a&&e.jsx(ia,{value:"history",className:"whitespace-nowrap",children:"History"})]}),e.jsxs(ss,{children:[e.jsx(rs,{asChild:!0,children:e.jsxs(H,{variant:"ghost",size:"sm",className:"text-xs text-primary ml-auto shrink-0 whitespace-nowrap",children:[e.jsx(Ba,{className:"h-3.5 w-3.5 mr-1"})," How edits behave"]})}),e.jsxs(ls,{align:"end",className:"w-96 text-xs leading-relaxed",children:[e.jsx("p",{className:"font-semibold text-sm mb-1",children:"One audited edit path"}),e.jsx("p",{className:"text-muted-foreground",children:"Every price change is written by the audited pricing service: company rows are cloned from global before editing, the whole tier set moves together, and allowance labor and material stay
16separate."}),e.jsx("p",{className:"text-muted-foreground mt-2",children:"Changes apply to future projects. Existing projects keep their frozen totals and are flagged so the estimate can be regenerated deliberately â nothing re-prices behind a client's back."})]})]})]}),e.jsx(oa,{value:"catalog",children:e.jsx(Ad,{catalogOnly:!0})}),e.jsxs(oa,{value:"bulk",className:"space-y-4",children:[e.jsxs(ye,{children:[e.jsxs(ke,{className:"pb-3",children:[e.jsx(Ce,{className:"text-base",children:"Bulk adjustments and state pricing"}),e.jsx(Ye,{children:"Percentage or absolute moves across many rows at once, applied through the audited bulk pricing service. State pricing is derived from the NJ baseline through state ratios â edit the baseline here and every state follows."})]}),e.jsx(je,{children:e.jsx(Bd,{})})]}),a&&e.jsxs(ye,{children:[e.jsxs(ke,{className:"pb-0",children:[e.jsx(Ce,{className:"text-base",children:"State cost indices and NJ ratios"}),e.jsx(Ye,{children:"Every index and ratio edit goes through the audited pricing writer: it records the run, verifies the stored value, marks existing projects stale (never repricing them silently) and reports a wiring verdict per state."})]}),e.jsx(je,{className:"pt-0",children:e.jsx(sm,{})})]}),a&&e.jsxs(ye,{children:[e.jsxs(ke,{className:"pb-0",children:[e.jsx(Ce,{className:"text-base",children:"Per-state pricing report"}),e.jsx(Ye,{children:"Read-only view of every rate scaled to a state, with CSV / Excel / PDF export. Edit the underlying numbers in the Catalog tab so the change is audited."})]}),e.jsx(je,{className:"pt-0",children:e.jsx(am,{})})]})]}),a&&e.jsx(oa,{value:"insights",children:e.jsx(Kd,{})}),a&&e.jsxs(oa,{value:"analytics",className:"space-y-4",children:[e.jsx(Qd,{}),e.jsx(Ud,{})]}),a&&e.jsx(oa,{value:"history",children:e.jsx(Yn,{})})]})})}export{Vm 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.