1import{a as m,d as A,j as e}from"./vendor-query-B-_nDQQY.js";import{B as E,L as re,Z as de,C as x,a as q,c as P,d as h,f as oe,I as D,h as me,i as xe,j as he,k as ue,l as p,g as K,e as T,q as H,R as pe,t as _,b as j}from"./index-D8ww6b7J.js";import{C as ge}from"./checkbox-DYv8y0li.js";import{L as be}from"./layers-De-P0_bF.js";import{T as je}from"./trending-down-BIipizug.js";import"./vendor-three-1K-S22da.js";import"./vendor-charts-i-522T5A.js";import"./vendor-react-BUIlT3ms.js";import"./vendor-pdf-Bwkk3Ew0.js";import"./vendor-radix-X0WMATEu.js";function $e(){const[f,Q]=m.useState(""),[N,V]=m.useState("all"),[o,$]=m.useState([]),[v,Z]=m.useState(120),[y,G]=m.useState(65),[z,B]=m.useState(!1),[l,S]=m.useState(null),{data:w=[]}=A({queryKey:["batch-nesting-jobs"],queryFn:()=>j.entities.Job.list("-created_date",200),initialData:[]}),{data:Y=[]}=A({queryKey:["batch-nesting-pieces"],queryFn:()=>j.entities.ProductionPiece.list(),initialData:[]}),{data:X=[]}=A({queryKey:["batch-nesting-prices"],queryFn:()=>j.entities.MaterialPriceList.list(),initialData:[]}),C=m.useMemo(()=>{let s=w.filter(t=>t.status!=="cancelled"&&t.status!=="completed");if(N!=="all"&&(s=s.filter(t=>t.status===N)),f){const t=f.toLowerCase();s=s.filter(a=>{var i,u,c;return((i=a.customer_name)==null?void 0:i.toLowerCase().includes(t))||((u=a.job_number)==null?void 0:u.toLowerCase().includes(t))||((c=a.material_type)==null?void 0:c.toLowerCase().includes(t))})}return s},[w,f,N]),b=m.useMemo(()=>{const s={};return Y.forEach(t=>{s[t.job_id]||(s[t.job_id]=[]),s[t.job_id].push(t)}),s},[Y]),ee=s=>{$(t=>t.includes(s)?t.filter(a=>a!==s):[...t,s]),S(null)},se=()=>{const s=C.filter(t=>{var a;return(a=b[t.id])==null?void 0:a.length}).map(t=>t.id);o.length===s.length?$([]):$(s),S(null)},te=(s,t)=>{const a=X.find(i=>i.material_name===s||i.material_type===t);return(a==null?void 0:a.cost_per_sqft)||25},J=(s,t)=>s.filter(a=>a.length>0&&a.width>0).map(a=>{var i;return{id:a.id,name:`${a.piece_name||a.piece_number} (${((i=t.customer_name)==null?void 0:i.split(" ")[0])||""})`,width:a.width,height:a.length,jobRef:t.id,sqft:a.width*a.length/144}}),ae=async()=>{var s,t;if(o.length<2){_.error("Select at least 2 jobs to batch");return}B(!0),S(null);try{const a=w.filter(n=>o.includes(n.id)),i=[];for(const n of a){const r=b[n.id]||[];
1if(r.length===0)continue;const U=J(r,n),g=await j.functions.invoke("optimizeBatchNesting",{pieces:U,slabWidth:v,slabLength:y,allowRotation:!0,multiSlab:!0});(s=g==null?void 0:g.data)!=null&&s.success&&i.push({jobId:n.id,jobNumber:n.job_number||`#${n.id.slice(-4)}`,customerName:n.customer_name,materialType:n.material_type,pieceCount:r.length,totalSqft:U.reduce((ne,ce)=>ne+ce.sqft,0),slabsUsed:g.data.summary.totalSlabs,yieldPct:g.data.summary.overallYieldPct,slabs:g.data.slabs})}const u=[];for(const n of a){const r=b[n.id]||[];u.push(...J(r,n))}const c=await j.functions.invoke("optimizeBatchNesting",{pieces:u,slabWidth:v,slabLength:y,allowRotation:!0,multiSlab:!0});if(!((t=c==null?void 0:c.data)!=null&&t.success)){_.error("Batch optimization failed"),B(!1);return}const d=c.data,R=i.reduce((n,r)=>n+r.slabsUsed,0),k=d.summary.totalSlabs,F=R-k,le=v*y/144,M=F*le;let I=0,W=0;for(const n of i){const r=te(n.materialType,n.materialType);W+=r*n.totalSqft,I+=n.totalSqft}const O=I>0?W/I:25,L=M*O,ie=L*1;S({individual:i,batch:{totalSlabs:k,totalPieces:d.summary.totalPieces,totalPlaced:d.summary.totalPlaced,yieldPct:d.summary.overallYieldPct,totalAreaSqft:d.summary.totalAreaSqft,slabs:d.slabs},comparison:{individualSlabs:R,batchSlabs:k,slabsSaved:F,sqftSaved:M.toFixed(1),materialSavings:L.toFixed(2),profitImpact:ie.toFixed(2),avgCostPerSqft:O.toFixed(2),individualYieldAvg:i.length>0?(i.reduce((n,r)=>n+r.yieldPct,0)/i.length).toFixed(1):0,batchYield:d.summary.overallYieldPct}}),_.success(`Batch saves ${F} slab(s) â $${L.toFixed(0)} in material`)}catch{_.error("Optimization failed")}B(!1)};return w.filter(s=>o.includes(s.id)),e.jsx("div",{className:"min-h-screen bg-background p-4 sm:p-6",children:e.jsxs("div",{className:"max-w-7xl mx-auto space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between flex-wrap gap-3",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-2xl sm:text-3xl font-bold flex items-center gap-2",children:[e.jsx(be,{className:"w-7 h-7 text-primary"}),"Batch Nesting"]}),e.jsx("p",{className:"text-muted-foreground text-sm mt-1",children:"Combine multiple jobs on shared slabs to reduce waste"})]}),e.jsx(E,{onClick:ae,disabled:z||o.length<2,size:"lg",children:z?e.jsxs(e.Fragment,{children:[e.jsx(re,{className:"w-4 h-4 animate-spin mr-2"})," Optimizing..."]}):e.jsxs(e.Fragment,{children:[e.jsx(de,{className:"w-4 h-4 mr-2"})," Run Batch (",o.length," jobs)"]})})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-3 gap-6",children:[e.jsxs("div",{className:"lg:col-span-1 space-y-4",children:[e.jsxs(x,{children:[e.jsx(q,{className:"pb-2",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(P,{className:"text-sm font-semibold",children:"Select Jobs"}),e.jsx(E,{variant:"ghost",size:"sm",onClick:se,className:"text-xs h-7",children:o.length===C.filter(s=>{var t;return(t=b[s.id])==null?void 0:t.length}).length?"Deselect All":"Select All"})]})}),e.jsxs(h,{className:"space-y-3",children:[e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("div",{className:"relative flex-1",children:[e.jsx(oe,{className:"absolute left-2 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground"}),e.jsx(D,{value:f,onChange:s=>Q(s.target.value),placeholder:"Search jobs...",className:"pl-7 h-8 text-xs"})]}),e.jsxs(me,{value:N,onValueChange:V,children:[e.jsx(xe,{className:"h-8 w-28 text-xs",children:e.jsx(he,{})}),e.jsxs(ue,{children:[e.jsx(p,{value:"all",children:"All Status"}),e.jsx(p,{value:"quote",children:"Quote"}),e.jsx(p,{value:"template",children:"Template"}),e.jsx(p,{value:"cnc_programming",children:"CNC"}),e.jsx(p,{value:"cutting",children:"Cutting"}),e.jsx(p,{value:"polishing",children:"Polishing"}),e.jsx(p,{value:"installation",children:"Installation"})]})]})]}),e.jsx(K,{className:"h-[320px]",children:e.jsxs("div",{className:"space-y-1 pr-2",children:[C.map(s=>{var a,i;const t=((a=b[s.id])==null?void 0:a.length)||0;return e.jsxs("label",{className:`flex items-center gap-3 p-2.5 rounded-lg cursor-pointer transition-colors border ${o.includes(s.id)?"bg-primary/5 border-primary/30":"hover:bg-muted border-transparent"} ${t===0?"opacity-50":""}
1`,children:[e.jsx(ge,{checked:o.includes(s.id),onCheckedChange:()=>ee(s.id),disabled:t===0}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"text-sm font-medium truncate",children:s.customer_name||s.job_number||"Unnamed"}),e.jsxs("p",{className:"text-[10px] text-muted-foreground truncate",children:[s.material_type||"N/A"," · ",(i=s.status)==null?void 0:i.replace("_"," ")]})]}),e.jsxs(T,{variant:"outline",className:"text-[10px] shrink-0",children:[t," pcs"]})]},s.id)}),C.length===0&&e.jsx("p",{className:"text-center text-muted-foreground text-sm py-8",children:"No jobs found"})]})})]})]}),e.jsxs(x,{children:[e.jsx(q,{className:"pb-2",children:e.jsx(P,{className:"text-sm font-semibold",children:"Slab Dimensions"})}),e.jsx(h,{children:e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx(H,{className:"text-xs",children:"Width (in)"}),e.jsx(D,{type:"number",value:v,onChange:s=>Z(Number(s.target.value)||120),className:"h-8 text-sm"})]}),e.jsxs("div",{children:[e.jsx(H,{className:"text-xs",children:"Length (in)"}),e.jsx(D,{type:"number",value:y,onChange:s=>G(Number(s.target.value)||65),className:"h-8 text-sm"})]})]})})]})]}),e.jsxs("div",{className:"lg:col-span-2 space-y-4",children:[!l&&e.jsx(x,{className:"border-dashed border-2 border-muted h-full flex items-center justify-center min-h-[300px]",children:e.jsxs(h,{className:"text-center py-12",children:[e.jsx(pe,{className:"w-12 h-12 text-muted-foreground mx-auto mb-4 opacity-30"}),e.jsx("p",{className:"text-muted-foreground font-medium",children:"Select 2+ jobs and run the optimizer"}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"See how batch nesting reduces slab usage vs individual cutting"})]})}),l&&e.jsxs(e.Fragment,{children:[e.jsx(x,{className:"border-green-300 bg-green-50 dark:bg-green-900/20",children:e.jsx(h,{className:"py-4",children:e.jsxs("div",{className:"flex items-center gap-4 flex-wrap",children:[e.jsx(je,{className:"w-8 h-8 text-green-600"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"text-lg font-bold text-green-800 dark:text-green-300",children:l.comparison.slabsSaved>0?`Batch saves ${l.comparison.slabsSaved} slab(s)`:"No slab savings from batching"}),e.jsx("p",{className:"text-sm text-green-700 dark:text-green-400",children:l.comparison.slabsSaved>0?`${l.comparison.sqftSaved} sqft saved · $${l.comparison.materialSavings} material cost`:"Individual nesting was already optimal"})]}),e.jsxs("div",{className:"text-right",children:[e.jsx("p",{className:"text-[10px] text-green-600 uppercase",children:"Profit Impact"}),e.jsxs("p",{className:"text-2xl font-bold text-green-700 dark:text-green-300",children:["+$",l.comparison.profitImpact]})]})]})})}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-3",children:[e.jsx(x,{children:e.jsxs(h,{className:"py-3 text-center",children:[e.jsx("p",{className:"text-[10px] text-muted-foreground uppercase",children:"Individual Avg Yield"}),e.jsxs("p",{className:"text-xl font-bold text-amber-600",children:[l.comparison.individualYieldAvg,"%"]}),e.jsxs("p",{className:"text-[10px] text-muted-foreground",children:[l.comparison.individualSlabs," slabs"]})]})}),e.jsx(x,{children:e.jsxs(h,{className:"py-3 text-center",children:[e.jsx("p",{className:"text-[10px] text-muted-foreground uppercase",children:"Batch Yield"}),e.jsxs("p",{className:"text-xl font-bold text-green-600",children:[l.comparison.batchYield,"%"]}),e.jsxs("p",{className:"text-[10px] text-muted-foreground",children:[l.comparison.batchSlabs," slabs"]})]})}),e.jsx(x,{className:l.comparison.slabsSaved>0?"bg-green-50 dark:bg-green-900/20":"",children:e.jsxs(h,{className:"py-3 text-center",children:[e.jsx("p",{className:"text-[10px] text-muted-foreground uppercase",children:"Material Cost Saved"}),e.jsxs("p",{className:"text-xl font-bold text-green-600",children:["$",l.comparison.materialSavings]}),e.jsxs("p",{className:"text-[10px] text-muted-foreground",children:["@ $",l.comparison.avgCostPerSqft,"/sqft"]})]})})]}),e.jsxs(x,{children:[e.jsx(q,{className:"pb-2",children:e.jsx(P,{className:"text-sm font-semibold",children:"Individual vs Batch Breakdown"})}),e.jsx(h,{children:e.jsxs("div",{className:"border rounded-lg overflow-hidden",children:[e.jsxs("div",{className:"grid grid-cols-6 gap-2 px-4 py-2 bg-muted text-[10px] font-semibold uppercase text-muted-foreground",children:[e.jsx("span",{className:"col-span-2",children:"Job"}),e.jsx("span",{className:"text-center",children:"Pieces"}),e.jsx("span",{className:"text-center",children:"Sqft"}),e.jsx("span",{className:"text-center",children:"Individual"}),e.jsx("span",{className:"text-center",children:"Batch"})]}),e.jsx("div",{className:"divide-y",children:l.individual.map(s=>e.jsxs("div",{className:"grid grid-cols-6 gap-2 px-4 py-2.5 text-xs items-center",children:[e.jsxs("div",{className:"col-span-2 min-w-0",children:[e.jsx("p",{className:"font-medium truncate",children:s.customerName}),e.jsx("p",{className:"text-[10px] text-muted-foreground",children:s.materialType||"N/A"})]}),e.jsx("span",{className:"text-center",children:s.pieceCount}),e.jsx("span",{className:"text-center",children:s.totalSqft.toFixed(1)}),e.jsxs("div",{className:"text-center",children:[e.jsxs(T,{variant:"outline",className:"text-[10px]",children:[s.yieldPct,"%"]}),e.jsxs("span",{className:"ml-1 text-[10px] text-muted-foreground",children:[s.slabsUsed,"s"]})]}),e.jsxs("div",{className:"text-center",children:[e.jsxs("span",{className:"text-green-600 font-medium",children:[l.comparison.batchYield,"%"]}),e.jsx("span",{className:"ml-1 text-[10px] text-muted-foreground",children:"shared"})]})]},s.jobId))}),e.jsxs("div",{className:"grid grid-cols-6 gap-2 px-4 py-2.5 bg-green-50 dark:bg-green-900/20 text-xs font-semibold",children:[e.jsx("div",{className:"col-span-2",children:"Batch Total"}),e.jsx("span",{className:"text-center",children:l.batch.totalPieces}),e.jsx("span",{className:"text-center",children:l.individual.reduce((s,t)=>s+t.totalSqft,0).toFixed(1)}),e.jsxs("span",{className:"text-center text-amber-600",children:[l.comparison.individualSlabs," slabs"]}),e.jsxs("span",{className:"text-center text-green-600",children:[l.comparison.batchSlabs," slabs"]})]})]})})]}),e.jsxs(x,{children:[e.jsx(q,{className:"pb-2",children:e.jsxs(P,{className:"text-sm font-semibold",children:["Batch Slab Layout (",l.batch.totalSlabs," slab",l.batch.totalSlabs!==1?"s":"",")"]})}),e.jsx(h,{children:e.jsx(K,{className:"max-h-[400px]",children:e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:l.batch.slabs.map(s=>e.jsxs("div",{className:"border rounded-lg p-3 bg-muted/30",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"font-semibold text-xs",children:s.slabLabel}),e.jsxs(T,{variant:s.stats.yieldPct>=80?"default":"secondary",className:"text-[10px]",children:[s.stats.yieldPct,"% yield"]})]}),e.jsx("div",{className:"relative bg-slate-800 rounded overflow-hidden",style:{paddingBottom:`${s.slabDimensions.length/s.slabDimensions.width*100}%`},children:e.jsx("div",{className:"absolute inset-0",children:s.placed.map((t,a)=>{var i,u,c,d;return e.jsx("div",{className:"absolute border border-opacity-60 flex items-center justify-center text-[7px] text-white",style:{left:`${t.x/s.slabDimensions.width*100}%`,top:`${t.y/s.slabDimensions.length*100}%`,width:`${t.placedWidth/s.slabDimensions.width*100}%`,height:`${t.placedHeight/s.slabDimensions.length*100}%`,backgroundColor:`hsl(${(a*55+((u=(i=t.jobRef)==null?void 0:i.charCodeAt)==null?void 0:u.call(i,
10))||0)%360}, 55%, 50%, 0.45)`,borderColor:`hsl(${(a*55+((d=(c=t.jobRef)==null?void 0:c.charCodeAt)==null?void 0:d.call(c,0))||0)%360}, 55%, 50%)`},children:e.jsx("span",{className:"truncate px-0.5",children:t.name})},a)})})})]},s.slabIndex))})})})]})]})]})]})]})})}export{$e 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.