1import{j as e}from"./vendor-motion-CAS9Mrr8.js";import{a as c}from"./vendor-charts-CCcpKWTT.js";import{a9 as pe,Y as oe,ab as le,d as q,_ as w,$ as b,I,L as ce,aa as he,B as u,i as J,J as P,O as F,Q as g,K as A,N as D,P as h,a0 as G,T as xe}from"./index-CxC89PRg.js";import{u as ve,L as je,o as ye}from"./location-scope-G9hYAwbU.js";import{B as ge}from"./badge-DXnfPCD0.js";import{S as X,a as Z,b as ee,c as te,d as N}from"./select-CaKL9gM6.js";import{U as fe}from"./upgrade-gate-mCiqKCUt.js";import{L as Ne,I as p,S as ae}from"./lamplit-sheet-DBfx0skq.js";import{P as we}from"./printer-ClqLiZZ6.js";import{D as W}from"./download-BNGtOizC.js";import{B as be}from"./boxes-fSSpVakS.js";import{T as ne}from"./trash-2-DAItjZQU.js";import"./vendor-pdf-C9TCjkzL.js";import"./map-pin-BxtxPAf8.js";import"./index-BdQq_4o_.js";import"./Combination-Bymh1jIy.js";import"./use-tier-access-DycmD0Wc.js";function ie(n){const i=new Map;for(const d of n){const m=(d.station??"").trim()||"Unassigned",x=i.get(m);x?x.push(d):i.set(m,[d])}return[...i.entries()].sort(([d],[m])=>d==="Unassigned"?1:m==="Unassigned"?-1:d.localeCompare(m))}const S=n=>n.toLocaleString("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2}),V=n=>String(Number(n.toFixed(3))),re=()=>{const n=new Date;return`${n.getFullYear()}-${String(n.getMonth()+1).padStart(2,"0")}-${String(n.getDate()).padStart(2,"0")}`},Se={uncounted:"not counted",unlinked:"not linked",no_price:"no invoice price",unit_mismatch:"unit mismatch",no_recipe_cost:"recipe cost unavailable",removed:"item removed"};function We(){const n=pe(),i=n.id?parseInt(n.id):null;return e.jsx(fe,{domain:"inventory",children:i&&Number.isFinite(i)?e.jsx(ke,{countId:i}):e.jsx(Ce,{})})}function Ce(){const{toast:n}=oe(),i=le(),[d,m]=c.useState(""),[x,r]=c.useState(""),[B,T]=c.useState(""),[E,R]=c.useState(""),[L,C]=c.useState(null),[U,$]=c.useState(re()),[v,k]=c.useState(""),[j,O]=c.useState(""),[s,o]=c.useState({name:"",quantity:"",unit:"",reason:"spoilage"}),a=ve(),{data:K=[]}=q({queryKey:["/api/inventory/items",a.value],queryFn:()=>fetch(`/api/inventory/items${a.query}`,{credentials:"include"}).then(t=>t.json())}),{data:y=[]}=q({queryKey:["/api/inventory/suggestions"]}),{data:f=[]}=q({queryKey:["/api/inventory/counts",a.value],queryFn:()=>fetch(`/api/inventory/counts${a.query}`,{credentials:"include"}).then(t=>t.json())}),{data:Q}=q({queryKey:["/api/inventory/waste",a.value],queryFn:()=>fetch(`/api/inventory/waste${a.query}`,{credentials:"include"}).then(t=>t.json())}),{data:l}=q({queryKey:["/api/inventory/variance",v,j],enabled:!!(v&&j&&v!==j)}),z=w({mutationFn:async()=>(await b("POST","/api/inventory/items",{name:d.trim(),unit:x.trim(),parLevel:B.trim()||null,station:E.trim()||null,locationId:a.locationId,producedFromRecipeId:L})).json(),onSuccess:()=>{m(""),r(""),T(""),C(null),i.invalidateQueries({queryKey:["/api/inventory/suggestions"]}),i.invalidateQueries({queryKey:["/api/inventory/items"]})},onError:()=>n({title:"Couldn't add that item",variant:"destructive"})}),_=w({mutationFn:async t=>await(await b("POST","/api/inventory/items/bulk",{items:t.map(Y=>({name:Y.name,unit:Y.unit,producedFromRecipeId:Y.producedFromRecipeId??null}))})).json(),onSuccess:t=>{i.invalidateQueries({queryKey:["/api/inventory/items"]}),i.invalidateQueries({queryKey:["/api/inventory/suggestions"]}),n({title:`Added ${t.created} item${t.created===1?"":"s"}`,description:t.skipped.length?`${t.skipped.length} skipped â see the list`:void 0})},onError:()=>n({title:"Couldn't add those items",variant:"destructive"})}),de=w({mutationFn:async t=>{await b("DELETE",`/api/inventory/items/${t}`)},onSuccess:()=>i.invalidateQueries({queryKey:["/api/inventory/items"]})}),M=w({mutationFn:async()=>(await b("POST","/api/inventory/waste",{ingredientName:s.name.trim(),quantity:Number(s.quantity),unit:s.unit.trim(),reason:s.reason,occurredOn:re(),locationId:a.locationId})).json(),onSuccess:()=>{o({...s,name:"",quantity:""}),i.invalidateQueries({queryKey:["/api/inventory/waste"]}),i.invalidateQueries({queryKey:["/api/inventory/variance"]})},onError:()=>n({title:"Couldn't log that",variant:"destructive"})}),ue=w({mutationFn:async t=>{await b("DELETE",`/api/inventory/waste/${t}`)},onSuccess:()=>{i.invalidateQueries({queryKey:["/api/inventory/waste"]}),i.invalidateQueries({queryKey:["/api/inventory/variance"]})}}),H=w({mutationFn:async()=>await(await b("POST","/api/inventory/counts",{countedOn:U,locationId:a.locationId})).json(),onSuccess:()=>i.invalidateQueries({queryKey:["/api/inventory/counts"]}),onError:()=>
1n({title:"Couldn't start that count",variant:"destructive"})}),me=!!(v&&j&&v!==j);return e.jsxs("div",{className:"max-w-4xl mx-auto p-4 space-y-6",style:{paddingTop:"calc(1rem + env(safe-area-inset-top, 0px))"},children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-2xl font-semibold flex items-center gap-2",children:[e.jsx(be,{className:"h-6 w-6"})," Inventory"]}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:"Count the shelf, value it off your own invoices, and see where usage doesn't match what the prep sheets called for."}),e.jsx("div",{className:"mt-3",children:e.jsx(je,{value:a.value,onChange:a.setValue})})]}),e.jsxs(P,{children:[e.jsx(A,{className:"pb-3",children:e.jsx(D,{className:"text-base",children:"Items"})}),e.jsxs(F,{className:"space-y-3",children:[e.jsxs("div",{className:"flex flex-wrap gap-2 items-end",children:[e.jsxs("div",{className:"flex-1 min-w-[10rem]",children:[e.jsx(h,{htmlFor:"item-name",children:"Name"}),e.jsx(g,{id:"item-name",value:d,onChange:t=>{m(t.target.value),C(null)},placeholder:"tomatoes","data-testid":"input-item-name"})]}),e.jsxs("div",{children:[e.jsx(h,{htmlFor:"item-unit",children:"Count in"}),e.jsx(g,{id:"item-unit",value:x,onChange:t=>r(t.target.value),placeholder:"lb",className:"w-24","data-testid":"input-item-unit"})]}),e.jsxs("div",{children:[e.jsx(h,{htmlFor:"item-par",children:"Par"}),e.jsx(g,{id:"item-par",value:B,onChange:t=>T(t.target.value),placeholder:"20",className:"w-20",inputMode:"decimal","data-testid":"input-item-par"})]}),e.jsxs("div",{children:[e.jsx(h,{htmlFor:"item-station",children:"Area"}),e.jsx(g,{id:"item-station",value:E,onChange:t=>R(t.target.value),placeholder:"walk-in",className:"w-28","data-testid":"input-item-station"})]}),e.jsx(u,{onClick:()=>z.mutate(),disabled:!d.trim()||!x.trim()||z.isPending,"data-testid":"button-add-item",children:z.isPending?e.jsx(I,{className:"h-4 w-4 animate-spin"}):e.jsx(G,{className:"h-4 w-4"})})]}),e.jsx("p",{className:"text-[14px] text-muted-foreground",children:"Use the same name the recipe uses â that's how one vendor link prices the recipe, the invoice, and this shelf at once."}),y.length>0&&e.jsxs("div",{className:"border p-3 space-y-2","data-testid":"inventory-suggestions",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("p",{className:"text-sm font-medium",children:[y.length," ingredient",y.length===1?"":"s"," in your recipes aren't on the item list"]}),e.jsxs(u,{size:"sm",variant:"outline",onClick:()=>_.mutate(y.filter(t=>t.unit)),disabled:_.isPending||!y.some(t=>t.unit),"data-testid":"button-seed-items",children:[_.isPending?e.jsx(I,{className:"h-4 w-4 animate-spin mr-1"}):null,"Add ",y.filter(t=>t.unit).length||"all"]})]}),e.jsx("div",{className:"max-h-40 overflow-y-auto divide-y",children:y.slice(0,40).map(t=>e.jsxs("div",{className:"flex items-center gap-2 py-1 text-sm",children:[e.jsx("span",{className:"flex-1 truncate",children:t.name}),e.jsx("span",{className:`text-xs ${t.unitSource==="unclear"?"text-amber-500/80":"text-muted-foreground"}`,title:t.unitSource==="vendor"?`Bought as ${t.vendorItemName}`:t.unitSource==="unclear"?`Recipes only measure this in ${t.recipeUnit||"no unit at all"}, which is no way to count a shelf`:"From your recipes",children:t.unitSource==="vendor"?`${t.unit} (bought)`:t.unitSource==="batch"?t.unit?`${t.unit} (made)`:"set a batch yield on the recipe":t.unit||`pick a unit${t.recipeUnit?` (recipes use ${t.recipeUnit})`:""}`}),e.jsxs("span",{className:"text-[14px] text-muted-foreground w-16 text-right",children:[t.recipeCount," recipe",t.recipeCount===1?"":"s"]}),e.jsx(u,{size:"sm",variant:"ghost",className:"h-7 px-2 text-xs",onClick:()=>{m(t.name),r(t.unit),C(t.producedFromRecipeId??null)},children:"edit"})]},t.name))}),e.jsx("p",{className:"text-[14px] text-muted-foreground",children:`The unit comes from how you BUY the item when it's linked to a vendor invoice, since that is the unit a count values in with no conversion. Otherwise it comes from your recipes, and when the recipes only measure it in pinches or teaspoons nothing is offered, because a wrong unit is worse than a blank one. "Add all" skips those. Hit edit to give one a unit.`})]}),K.length===0?e.jsx("p",{className:"text-xs text-muted-foreground text-center py-3 border border-dashed",children:"No items yet."}):e.jsx("div",{className:"divide-y",children:K.map(t=>e.jsxs("div",{className:"flex items-center gap-3 py-2 text-sm","data-testid":`item-${t.id}`,children:[e.jsx("span",{className:"flex-1 truncate",children:t.name}),e.jsxs("span",{className:"text-muted-foreground text-xs",children:[t.unit,t.producedFromRecipeId?" · made":"",t.parLevel?` · par ${t.parLevel}`:"",t.station?` · ${t.station}`:""]}),e.jsx(u,{size:"sm",variant:"ghost",className:"h-8 w-8 p-0",onClick:()=>de.mutate(t.id),"aria-label":"Remove item",children:e.jsx(ne,{className:"h-3.5 w-3.5"})})]},t.id))})]})]}),e.jsxs(P,{children:[e.jsx(A,{className:"pb-3",children:e.jsx(D,{className:"text-base",children:"Counts"})}),e.jsxs(F,{className:"space-y-3",children:[e.jsxs("div",{className:"flex gap-2 items-end",children:[e.jsxs("div",{children:[e.jsx(h,{htmlFor:"count-date",children:"Date"}),e.jsx(g,{id:"count-date",type:"date",value:U,onChange:t=>$(t.target.value),className:"w-44","data-testid":"input-count-date"})]}),e.jsxs(u,{onClick:()=>H.mutate(),disabled:K.length===0||H.isPending,"data-testid":"button-start-count",children:[H.isPending?e.jsx(I,{className:"h-4 w-4 animate-spin"}):e.jsx(G,{className:"h-4 w-4 mr-1"}),"Start count"]})]}),f.length===0?e.jsx("p",{className:"text-xs text-muted-foreground text-center py-3 border border-dashed",children:"No counts yet."}):e.jsx("div",{className:"divide-y",children:f.map(t=>e.jsx(ce,{href:`/inventory/counts/${t.id}`,children:e.jsxs("a",{className:"flex items-center gap-3 py-2 text-sm hover:text-primary","data-testid":`count-${t.id}`,children:[e.jsx("span",{className:"flex-1 truncate",children:t.name||t.countedOn}),e.jsx("span",{className:"text-xs text-muted-foreground",children:t.countedOn}),e.jsx(ge,{variant:t.status==="closed"?"secondary":"outline",className:"text-[13px]",children:t.status})]})},t.id))})]})]}),e.jsxs(P,{children:[e.jsx(A,{className:"pb-3",children:e.jsx(D,{className:"text-base",children:"Waste"})}),e.jsxs(F,{className:"space-y-3",children:[e.jsxs("div",{className:"flex flex-wrap gap-2 items-end",children:[e.jsxs("div",{className:"flex-1 min-w-[10rem]",children:[e.jsx(h,{htmlFor:"waste-name",children:"What"}),e.jsx(g,{id:"waste-name",value:s.name,onChange:t=>o({...s,name:t.target.value}),placeholder:"tomatoes","data-testid":"input-waste-name"})]}),e.jsxs("div",{children:[e.jsx(h,{htmlFor:"waste-qty",children:"How much"}),e.jsx(g,{id:"waste-qty",value:s.quantity,onChange:t=>o({...s,quantity:t.target.value}),placeholder:"4",inputMode:"decimal",className:"w-20","data-testid":"input-waste-qty"})]}),e.jsxs("div",{children:[e.jsx(h,{htmlFor:"waste-unit",children:"Unit"}),e.jsx(g,{id:"waste-unit",value:s.unit,onChange:t=>o({...s,unit:t.target.value}),placeholder:"lb",className:"w-20","data-testid":"input-waste-unit"})]}),e.jsxs("div",{children:[e.jsx(h,{children:"Why"}),e.jsxs(X,{value:s.reason,onValueChange:t=>o({...s,reason:t}),children:[e.jsx(Z,{className:"w-36","data-testid":"select-waste-reason",children:e.jsx(ee,{})}),e.jsxs(te,{children:[e.jsx(N,{value:"spoilage",children:"spoilage"}),e.jsx(N,{value:"over_prep",children:"over-prep"}),e.jsx(N,{value:"burned",children:"burned"}),e.jsx(N,{value:"dropped",children:"dropped"}),e.jsx(N,{value:"comp",children:"comped"}),e.jsx(N,{value:"other",children:"other"})]})]})]}),e.jsx(u,{onClick:()=>M.mutate(),disabled:!s.name.trim()||!s.quantity.trim()||!s.unit.trim()||M.isPending,"data-testid":"button-log-waste",children:M.isPending?e.jsx(I,{className:"h-4 w-4 animate-spin"}):e.jsx(G,{className:"h-4 w-4"})})]}),e.jsx("p",{className:"text-[14px] text-muted-foreground",children:"Logging waste doesn't just record
1it. Usage variance subtracts it, so the number left over is the part nobody has accounted for."}),Q&&Q.entries.length>0&&e.jsxs("div",{className:"divide-y",children:[e.jsxs("p",{className:"text-sm pb-1",children:[e.jsx("span",{className:"font-semibold",children:S(Q.totalValue)})," ",e.jsxs("span",{className:"text-muted-foreground",children:["logged, last ",Q.entries.length]})]}),Q.entries.slice(0,12).map(t=>e.jsxs("div",{className:"flex items-center gap-3 py-1.5 text-sm","data-testid":`waste-${t.id}`,children:[e.jsx("span",{className:"flex-1 truncate",children:t.ingredientName}),e.jsxs("span",{className:"text-xs text-muted-foreground",children:[t.quantity," ",t.unit," · ",t.reason.replace("_","-")," · ",t.occurredOn]}),e.jsx("span",{className:"w-16 text-right font-mono text-xs",children:t.value!=null?S(t.value):"â"}),e.jsx(u,{size:"sm",variant:"ghost",className:"h-8 w-8 p-0",onClick:()=>ue.mutate(t.id),"aria-label":"Remove waste entry",children:e.jsx(ne,{className:"h-3.5 w-3.5"})})]},t.id))]})]})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsxs(P,{children:[e.jsx(A,{className:"pb-3",children:e.jsx(D,{className:"text-base",children:"Usage variance"})}),e.jsx(F,{children:e.jsxs("div",{className:"flex flex-wrap gap-2 items-end",children:[e.jsxs("div",{children:[e.jsx(h,{children:"Opening count"}),e.jsxs(X,{value:v,onValueChange:k,children:[e.jsx(Z,{className:"w-44","data-testid":"select-variance-from",children:e.jsx(ee,{placeholder:"Pick a count"})}),e.jsx(te,{children:f.map(t=>e.jsxs(N,{value:String(t.id),children:[t.countedOn," ",t.name?`â ${t.name}`:""]},t.id))})]})]}),e.jsxs("div",{children:[e.jsx(h,{children:"Closing count"}),e.jsxs(X,{value:j,onValueChange:O,children:[e.jsx(Z,{className:"w-44","data-testid":"select-variance-to",children:e.jsx(ee,{placeholder:"Pick a count"})}),e.jsx(te,{children:f.map(t=>e.jsxs(N,{value:String(t.id),children:[t.countedOn," ",t.name?`â ${t.name}`:""]},t.id))})]})]})]})})]}),e.jsx(Ne,{title:"Usage variance",meta:l?`${l.opening.countedOn} â ${l.closing.countedOn}`:void 0,folio:l?e.jsxs(e.Fragment,{children:[e.jsx("span",{children:"THE RESTAURANT CONSULTANT"}),e.jsx("span",{children:"WASTE ALREADY SUBTRACTED"})]}):void 0,testid:"variance-sheet",children:me?l?e.jsxs(e.Fragment,{children:[e.jsx(ae,{emphasis:!0,label:"Unexplained",sub:`Measured against ${l.planCount} prep sheet${l.planCount===1?"":"s"}.`+(l.totalWasteValue>0?` The gap was ${S(l.totalVarianceValue)}, and ${S(l.totalWasteValue)} of it is logged waste.`:""),value:S(l.totalUnexplainedValue),valueInk:l.totalUnexplainedValue>0?p.bad:l.totalUnexplainedValue<0?p.good:p.full,testid:"variance-total"}),l.skipped.length>0&&e.jsx("div",{className:"paper-entry py-2.5 space-y-1","data-testid":"variance-skipped",children:l.skipped.map((t,se)=>e.jsxs("p",{className:"text-[13px] flex gap-2",style:{color:p.mid},children:[e.jsx(xe,{className:"h-3.5 w-3.5 flex-shrink-0 mt-0.5",style:{color:p.warn}}),t]},se))}),l.lines.length===0?e.jsx("p",{className:"text-[13px] py-2.5",style:{color:p.faint},children:"Nothing to reconcile between these two counts."}):l.lines.map(t=>e.jsx(ae,{testid:`variance-${t.itemId}`,label:t.name,sub:t.note?t.note:`used ${V(t.actualUsage??0)} ${t.unit}, recipes called for ${V(t.theoreticalQty)} ${t.unit}`+(t.producedQty?`, ${V(t.producedQty)} ${t.unit} made`:"")+(t.wasteQty?`, ${V(t.wasteQty)} ${t.unit} logged as waste`:""),value:t.unexplainedValue!=null?S(t.unexplainedValue):"â",valueInk:t.unexplainedValue==null?p.faint:t.unexplainedValue>0?p.bad:t.unexplainedValue<0?p.good:p.full,valueSub:!t.note&&t.variancePct!=null?`${t.variancePct>0?"+":""}${t.variancePct}%`:void 0},t.itemId))]}):e.jsx("p",{className:"text-[13px]",style:{color:p.mid},children:"Working the two counts."}):e.jsx("p",{className:"text-[13px]",style:{color:p.mid},children:f.length<2?"A variance needs two counts â one at the open of the period, one at the close. Start them above and this page fills itself in.":v&&j?"That's the same count twice. Pick a different open and close.":"Pick an opening and a closing count. Everything bought, made and wasted in between gets weighed against what the prep sheets called for."})})]})]})}function ke({countId:n}
1){const{toast:i}=oe();async function d(s){try{await ye(s)}catch(o){i({title:"Couldn't open that",description:o?.message,variant:"destructive"})}}const m=le(),x=["/api/inventory/counts",n],{data:r,isLoading:B}=q({queryKey:x}),[T,E]=c.useState({}),[R,L]=c.useState(!1),[C,U]=c.useState(()=>typeof navigator>"u"?!0:navigator.onLine),$=`trc-count-draft-${n}`;c.useEffect(()=>{if(!r)return;let s=null;try{const o=localStorage.getItem($);o&&(s=JSON.parse(o))}catch{}E(s??Object.fromEntries(r.lines.map(o=>[o.itemId,o.quantity??""]))),L(!!s)},[r,$]),c.useEffect(()=>{const s=()=>U(!0),o=()=>U(!1);return window.addEventListener("online",s),window.addEventListener("offline",o),()=>{window.removeEventListener("online",s),window.removeEventListener("offline",o)}},[]);function v(s){try{localStorage.setItem($,JSON.stringify(s)),L(!0)}catch{}}const k=w({mutationFn:async()=>{await b("PUT",`/api/inventory/counts/${n}/lines`,{lines:Object.entries(T).map(([s,o])=>({itemId:Number(s),quantity:o}))})},onSuccess:()=>{try{localStorage.removeItem($)}catch{}
1L(!1),m.invalidateQueries({queryKey:x}),i({title:"Count saved"})},onError:()=>i({title:"Saved on this device",description:"No connection. The count is kept here and will go up when you're back online."})});c.useEffect(()=>{const s=r?.count.status==="closed";C&&R&&!k.isPending&&!s&&k.mutate()},[C]);const j=w({mutationFn:async()=>(await b("PATCH",`/api/inventory/counts/${n}`,{status:r?.count.status==="closed"?"open":"closed"})).json(),onSuccess:()=>{m.invalidateQueries({queryKey:x}),m.invalidateQueries({queryKey:["/api/inventory/counts"]})}});if(B||!r)return e.jsx("div",{className:"flex justify-center py-16",children:e.jsx(I,{className:"h-5 w-5 animate-spin text-muted-foreground"})});const O=r.count.status==="closed";return e.jsxs("div",{className:"max-w-3xl mx-auto p-4 space-y-5",children:[e.jsx("style",{children:` 2 @media print { 3 .no-print { display: none !important; } 4 body { background: #fff !important; } 5 .print-box { display: inline-block !important; } 6 .count-row { break-inside: avoid; } 7 } 8 .print-box { display: none; } 9 `}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(ce,{href:"/inventory",children:e.jsx("a",{className:"text-muted-foreground hover:text-foreground","aria-label":"Back to inventory",children:e.jsx(he,{className:"h-5 w-5"})})}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("h1",{className:"text-xl font-semibold truncate",children:r.count.name||"Count"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:r.count.countedOn})]}),e.jsxs("div",{className:"ml-auto text-right",children:[e.jsx("p",{className:"text-lg font-semibold",children:S(r.total)}),e.jsx("p",{className:"text-[14px] text-muted-foreground",children:r.unpricedCount>0?`${r.unpricedCount} unpriced â floor`:"on hand"}),R&&e.jsx("p",{className:"text-[14px] text-amber-500","data-testid":"count-pending",children:C?"unsaved on this device":"offline â kept on this device"})]}),e.jsxs("div",{className:"flex gap-1 no-print",children:[e.jsx(u,{size:"sm",variant:"outline",onClick:()=>J()?d(`/api/inventory/counts/${n}/sheet`):window.print(),title:"Print a blank sheet for the walk-in","data-testid":"button-print-count",children:e.jsx(we,{className:"h-4 w-4"})}),J()?e.jsx(u,{size:"sm",variant:"outline",onClick:()=>d(`/api/inventory/counts/${n}/export`),title:"Open this count as CSV","data-testid":"link-export-count",children:e.jsx(W,{className:"h-4 w-4"})}):e.jsx("a",{href:`/api/inventory/counts/${n}/export`,"data-testid":"link-export-count",children:e.jsx(u,{size:"sm",variant:"outline",title:"Download this count as CSV",children:e.jsx(W,{className:"h-4 w-4"})})})]})]}),r.belowPar.length>0&&e.jsx(P,{className:"border-warning/50",children:e.jsxs(F,{className:"p-4",children:[e.jsx("p",{className:"text-sm font-medium mb-1.5 text-warning",children:"Below par"}),r.belowPar.map(s=>e.jsxs("p",{className:"text-sm","data-testid":`below-par-${s.itemId}`,children:[e.jsx("span",{className:"text-muted-foreground",children:s.name}),e.jsx("span",{className:"text-muted-foreground",children:" â short "}),e.jsxs("span",{className:"text-warning font-medium",children:[V(s.shortBy??0)," ",s.unit]})]},s.itemId))]})}),e.jsx(P,{children:e.jsx(F,{className:"p-4 space-y-1",children:ie(r.lines).map(([s,o])=>e.jsxs("div",{className:"pt-2 first:pt-0",children:[ie(r.lines).length>1&&e.jsx("p",{className:"text-[12px] uppercase tracking-wide text-muted-foreground border-b pb-1 mb-1",children:s}),o.map(a=>e.jsxs("div",{className:"count-row flex items-center gap-3 py-1.5","data-testid":`count-line-${a.itemId}`,children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"text-sm truncate",children:a.name}),e.jsxs("p",{className:"text-[14px] text-muted-foreground",children:[a.status==="valued"&&a.costPerUnit!=null?`$${a.costPerUnit.toFixed(3)}/${a.unit}
9`:Se[a.status]??String(a.status).replace(/_/g," "),a.costSource==="recipe"?" · made":"",a.parLevel?` · par ${a.parLevel}`:""]})]}),e.jsx(g,{value:T[a.itemId]??"",onChange:K=>E(y=>{const f={...y,[a.itemId]:K.target.value};return v(f),f}),disabled:O,placeholder:"â",inputMode:"decimal",className:"w-24 text-right no-print","data-testid":`input-count-${a.itemId}`}),e.jsx("span",{className:"print-box w-24 h-6 border-b border-black","aria-hidden":"true"}),e.jsx("span",{className:"w-10 text-xs text-muted-foreground",children:a.unit}),e.jsx("span",{className:"w-20 text-right text-sm font-mono",children:a.value!=null?S(a.value):"â"})]},a.itemId))]},s))})}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(u,{onClick:()=>k.mutate(),disabled:O||k.isPending,"data-testid":"button-save-count",children:[k.isPending?e.jsx(I,{className:"h-4 w-4 animate-spin mr-1"}):null,"Save count"]}),e.jsx(u,{variant:"outline",onClick:()=>j.mutate(),"data-testid":"button-close-count",children:O?"Reopen":"Close count"}),J()?e.jsxs(u,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>d(`/api/inventory/counts/${n}/export/blank`),"data-testid":"link-blank-sheet",children:[e.jsx(W,{className:"h-4 w-4 mr-1"})," Blank sheet"]}):e.jsx("a",{href:`/api/inventory/counts/${n}/export/blank`,className:"ml-auto","data-testid":"link-blank-sheet",children:e.jsxs(u,{variant:"ghost",size:"sm",children:[e.jsx(W,{className:"h-4 w-4 mr-1"})," Blank sheet"]})})]})]})}export{We 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.