PageSourceSearch

https://willowcommerce.com/assets/UnifiedInventoryPage-CQLlNHks.js

js willowcommerce.com collected 2026-10-04 03:01:36 UTC 17,459 bytes, 9 lines download raw bytes

1import{r as g,W as H,j as e,aB as G,D as L,aG as W,C as J,aH as Z,I as X,S as P,o as D,p as M,q as T,s as o,a0 as F,a1 as K,a2 as f,a3 as l,a5 as $,a6 as c,aI as Y,am as z,w as _,aJ as ee,aK as te,aL as se,aM as ae,B as re,t as ne}from"./index-Cz3wH2jj.js";function ie(){const[r,A]=g.useState(""),[x,j]=g.useState("all"),[y,V]=g.useState("all"),[I,v]=g.useState("all"),[C,p]=g.useState("name-asc"),[n,u]=g.useState(null),{data:k=[]}=H({queryKey:["inv-warehouses"],queryFn:async()=>{const{data:s}=await _.from("warehouses").select("id,name").order("name");return s??[]}}),{data:O=[]}=H({queryKey:["inv-locations"],queryFn:async()=>{const{data:s}=await _.from("warehouse_locations").select("id,location_code,name");return s??[]}}),{data:b=[],isLoading:w}=H({queryKey:["inv-lots"],queryFn:async()=>{const{data:s,error:d}=await _.from("inventory_lots").select(`
2          id, product_id, warehouse_id, location_id, lot_number,
3          current_qty, reserved_qty, purchase_price, landed_cost,
4          product:products(id,name,sku,images)
5        `).gt("current_qty",0).limit(2e3);if(d)throw d;return s??[]}}),{data:S=[],isLoading:U}=H({queryKey:["inv-raw"],queryFn:async()=>{const{data:s,error:d}=await _.from("raw_inventory").select(`
6          id, raw_product_id, warehouse_id, location_id, lot_number,
7          qty_on_hand, qty_reserved,
8          raw_product:raw_products(id,name,sku,cost,image_url,images)
9        `).gt("qty_on_hand",0).limit(2e3);if(d)throw d;return s??[]}}),{data:m}=H({queryKey:["inv-price-recency"],queryFn:async()=>{const[{data:s},{data:d}]=await Promise.all([_.from("product_price_history").select("product_id, created_at").order("created_at",{ascending:!1}).limit(5e3),_.from("raw_product_price_history").select("raw_product_id, created_at").order("created_at",{ascending:!1}).limit(5e3)]),i=new Map;for(const a of s??[])i.has(a.product_id)||i.set(a.product_id,a.created_at);const t=new Map;for(const a of d??[])t.has(a.raw_product_id)||t.set(a.raw_product_id,a.created_at);return{product:i,raw:t}}}),h=g.useMemo(()=>{const s=new Map(k.map(t=>[t.id,t.name])),d=new Map(O.map(t=>[t.id,t.location_code||t.name])),i=[];for(const t of b){const a=t.product;i.push({key:`lot-${t.id}`,kind:"product",refId:t.product_id,name:(a==null?void 0:a.name)??"—",sku:(a==null?void 0:a.sku)??"",image:Array.isArray(a==null?void 0:a.images)?a.images[0]:null,warehouseId:t.warehouse_id,warehouseName:s.get(t.warehouse_id)??null,locationId:t.location_id,locationName:d.get(t.location_id)??null,lotNumber:t.lot_number,qtyOnHand:Number(t.current_qty||0),qtyReserved:Number(t.reserved_qty||0),unitCost:Number(t.landed_cost??t.purchase_price??0),lastPriceChangeAt:(m==null?void 0:m.product.get(t.product_id))??null})}for(const t of S){const a=t.raw_product,R=Array.isArray(a==null?void 0:a.images)?a.images:[];i.push({key:`raw-${t.id}`,kind:"raw",refId:t.raw_product_id,name:(a==null?void 0:a.name)??"—",sku:(a==null?void 0:a.sku)??"",image:R[0]||(a==null?void 0:a.image_url)||null,warehouseId:t.warehouse_id,warehouseName:s.get(t.warehouse_id)??null,locationId:t.location_id,locationName:d.get(t.location_id)??null,lotNumber:t.lot_number,qtyOnHand:Number(t.qty_on_hand||0),qtyReserved:Number(t.qty_reserved||0),unitCost:Number((a==null?void 0:a.cost)??0),lastPriceChangeAt:(m==null?void 0:m.raw.get(t.raw_product_id))??null})}return i},[b,S,k,O,m]),N=g.useMemo(()=>{const s=r.trim().toLowerCase(),d=Date.now(),t={all:null,"7d":7,"30d":30,"90d":90,never:-1}[I];return h.filter(a=>{if(x!=="all"&&a.kind!==x||y!=="all"&&a.warehouseId!==y)return!1;if(t!=null){if(t===-1){if(a.lastPriceChangeAt)return!1}else if(!a.lastPriceChangeAt||(d-new Date(a.lastPriceChangeAt).getTime())/864e5>t)return!1}return!(s&&!`${a.name} ${a.sku} ${a.lotNumber??""} ${a.warehouseName??""} ${a.locationName??""}`.toLowerCase().includes(s))})},[h,r,x,y,I]),B=g.useMemo(()=>{const s=[...N],d=i=>i?new Date(i).getTime():0;return s.sort((i,t)=>{switch(C){case"name-asc":return i.name.localeCompare(t.name);case"qty-desc":return t.qtyOnHand-i.qtyOnHand;case"qty-asc":return i.qtyOnHand-t.qtyOnHand;case"value-desc":return t.qtyOnHand*t.unitCost-i.qtyOnHand*i.unitCost;
9case"price-recent":return d(t.lastPriceChangeAt)-d(i.lastPriceChangeAt);case"price-stale":{const a=d(i.lastPriceChangeAt),R=d(t.lastPriceChangeAt);return!a&&!R?0:a?R?a-R:1:-1}default:return 0}}),s},[N,C]),Q=g.useMemo(()=>{const s=N.reduce((i,t)=>i+t.qtyOnHand,0),d=N.reduce((i,t)=>i+t.qtyOnHand*t.unitCost,0);return{totalQty:s,totalValue:d}},[N]),E=w||U;return e.jsxs("div",{className:"p-4 md:p-6 space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between flex-wrap gap-2",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-2xl font-semibold flex items-center gap-2",children:[e.jsx(G,{className:"h-6 w-6"}),"Inventory"]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Unified view of finished products and raw materials across all warehouses."})]}),e.jsxs("div",{className:"flex items-center gap-3 text-sm",children:[e.jsxs(L,{variant:"secondary",children:[N.length," rows"]}),e.jsxs(L,{variant:"secondary",children:["Qty: ",Q.totalQty.toLocaleString()]}),e.jsxs(L,{variant:"secondary",children:["Value: ",W(Q.totalValue,{decimals:2})]})]})]}),e.jsxs(J,{className:"p-4",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2 mb-4",children:[e.jsxs("div",{className:"relative flex-1 min-w-[240px]",children:[e.jsx(Z,{className:"absolute left-2 top-2.5 h-4 w-4 text-muted-foreground"}),e.jsx(X,{placeholder:"Search name, SKU, lot, warehouse, location…",value:r,onChange:s=>A(s.target.value),className:"pl-8"})]}),e.jsxs(P,{value:x,onValueChange:s=>j(s),children:[e.jsx(D,{className:"w-[160px]",children:e.jsx(M,{})}),e.jsxs(T,{children:[e.jsx(o,{value:"all",children:"All Types"}),e.jsx(o,{value:"product",children:"Products"}),e.jsx(o,{value:"raw",children:"Raw Products"})]})]}),e.jsxs(P,{value:y,onValueChange:V,children:[e.jsx(D,{className:"w-[200px]",children:e.jsx(M,{placeholder:"Warehouse"})}),e.jsxs(T,{children:[e.jsx(o,{value:"all",children:"All Warehouses"}),k.map(s=>e.jsx(o,{value:s.id,children:s.name},s.id))]})]}),e.jsxs(P,{value:I,onValueChange:s=>v(s),children:[e.jsx(D,{className:"w-[200px]",children:e.jsx(M,{placeholder:"Price change"})}),e.jsxs(T,{children:[e.jsx(o,{value:"all",children:"Any price age"}),e.jsx(o,{value:"7d",children:"Changed in last 7 days"}),e.jsx(o,{value:"30d",children:"Changed in last 30 days"}),e.jsx(o,{value:"90d",children:"Changed in last 90 days"}),e.jsx(o,{value:"never",children:"Never changed"})]})]}),e.jsxs(P,{value:C,onValueChange:s=>p(s),children:[e.jsx(D,{className:"w-[200px]",children:e.jsx(M,{placeholder:"Sort"})}),e.jsxs(T,{children:[e.jsx(o,{value:"name-asc",children:"Name (A→Z)"}),e.jsx(o,{value:"qty-desc",children:"On hand (high → low)"}),e.jsx(o,{value:"qty-asc",children:"On hand (low → high)"}),e.jsx(o,{value:"value-desc",children:"Value (high → low)"}),e.jsx(o,{value:"price-recent",children:"Price changed (most recent)"}),e.jsx(o,{value:"price-stale",children:"Price changed (oldest first)"})]})]})]}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs(F,{children:[e.jsx(K,{children:e.jsxs(f,{children:[e.jsx(l,{className:"w-12"}),e.jsx(l,{children:"Type"}),e.jsx(l,{children:"Name"}),e.jsx(l,{children:"SKU"}),e.jsx(l,{children:"Warehouse"}),e.jsx(l,{children:"Location"}),e.jsx(l,{children:"Lot"}),e.jsx(l,{className:"text-right",children:"On Hand"}),e.jsx(l,{className:"text-right",children:"Reserved"}),e.jsx(l,{className:"text-right",children:"Available"}),e.jsx(l,{className:"text-right",children:"Unit Cost"}),e.jsx(l,{className:"text-right",children:"Value"}),e.jsx(l,{children:"Last Price Change"})]})}),e.jsxs($,{children:[E&&e.jsx(f,{children:e.jsx(c,{colSpan:13,className:"text-center py-8 text-muted-foreground",children:"Loading…"})}),!E&&B.length===0&&e.jsx(f,{children:e.jsx(c,{colSpan:13,className:"text-center py-8 text-muted-foreground",children:"No inventory rows match your filters."})}),B.map(s=>e.jsxs(f,{className:"cursor-pointer",onClick:()=>u(s),children:[e.jsx(c,{children:s.image?e.jsx("img",{src:s.image,alt:"",className:"w-10 h-10 rounded object-cover"}):e.jsx("div",{className:"w-10 h-10 rounded bg-muted flex items-center justify-center",children:e.jsx(Y,{className:"h-4 w-4 text-muted-foreground"})})}),e.jsx(c,{children:s.kind==="raw"?e.jsx(L,{className:"bg-amber-500/15 text-amber-700 dark:text-amber-400 hover:bg-amber-500/20",children:"RAW"}):e.jsx(L,{variant:"secondary",children:"PRODUCT"})}),e.jsx(c,{className:"font-medium max-w-[260px] truncate",children:s.name}),e.jsx(c,{className:"font-mono text-xs",children:s.sku||"—"}),e.jsx(c,{children:s.warehouseName??"—"}),e.jsx(c,{children:s.locationName??"—"}),e.jsx(c,{className:"font-mono text-xs",children:s.lotNumber??"—"}),e.jsx(c,{className:"text-right",children:s.qtyOnHand.toLocaleStr
9ing()}),e.jsx(c,{className:"text-right text-muted-foreground",children:s.qtyReserved.toLocaleString()}),e.jsx(c,{className:"text-right",children:(s.qtyOnHand-s.qtyReserved).toLocaleString()}),e.jsx(c,{className:"text-right",children:W(s.unitCost,{decimals:2})}),e.jsx(c,{className:"text-right font-medium",children:W(s.qtyOnHand*s.unitCost,{decimals:2})}),e.jsx(c,{className:"text-xs text-muted-foreground",children:s.lastPriceChangeAt?z(new Date(s.lastPriceChangeAt),"MMM d, yyyy"):"—"})]},s.key))]})]})})]}),e.jsx(ce,{row:n,onClose:()=>u(null)})]})}function q({label:r,value:A,hint:x}){return e.jsxs("div",{className:"rounded-md border bg-muted/30 px-3 py-2",children:[e.jsx("div",{className:"text-[10px] uppercase tracking-wide text-muted-foreground",children:r}),e.jsx("div",{className:"text-sm font-semibold",children:A}),x&&e.jsx("div",{className:"text-[10px] text-muted-foreground",children:x})]})}function ce({row:r,onClose:A}){const x=!!r,j=(r==null?void 0:r.kind)==="raw",{data:y=[],isLoading:V}=H({queryKey:["inv-movements",r==null?void 0:r.kind,r==null?void 0:r.refId],enabled:x,queryFn:async()=>{if(!r)return[];if(r.kind==="raw"){const{data:u}=await _.from("raw_inventory_movements").select("id, delta, reason, unit_cost, lot_number, notes, created_at").eq("raw_product_id",r.refId).order("created_at",{ascending:!1}).limit(100);return u??[]}const{data:n}=await _.from("inventory_lots").select("id, lot_number, current_qty, initial_qty, reserved_qty, purchase_price, landed_cost, received_date, warehouse_id").eq("product_id",r.refId).order("received_date",{ascending:!1}).limit(100);return n??[]}}),{data:I=[]}=H({queryKey:["inv-price-history",r==null?void 0:r.kind,r==null?void 0:r.refId],enabled:x,queryFn:async()=>{if(!r)return[];if(r.kind==="raw"){const{data:u}=await _.from("raw_product_price_history").select("id, previous_cost, new_cost, source_reference, created_at").eq("raw_product_id",r.refId).order("created_at",{ascending:!1}).limit(20);return u??[]}const{data:n}=await _.from("product_price_history").select("id, previous_purchase_price, new_purchase_price, previous_landed_cost, new_landed_cost, source_reference, created_at").eq("product_id",r.refId).order("created_at",{ascending:!1}).limit(20);return n??[]}}),v=g.useMemo(()=>{if(!r)return{received:0,consumed:0,lastReceiptDate:null,lastReceiptCost:null};if(r.kind==="raw"){const w=y,S=w.filter(h=>Number(h.delta)>0).reduce((h,N)=>h+Number(N.delta),0),U=w.filter(h=>Number(h.delta)<0).reduce((h,N)=>h+Math.abs(Number(N.delta)),0),m=w.find(h=>Number(h.delta)>0);return{received:S,consumed:U,lastReceiptDate:(m==null?void 0:m.created_at)??null,lastReceiptCost:m?Number(m.unit_cost??0):null}}const n=y,u=n.reduce((w,S)=>w+Number(S.initial_qty||0),0),k=n.reduce((w,S)=>w+Number(S.current_qty||0),0),O=u-k,b=n[0];return{received:u,consumed:O,lastReceiptDate:(b==null?void 0:b.received_date)??null,lastReceiptCost:b?Number(b.landed_cost??b.purchase_price??0):null}},[r,y]),C=n=>n?z(new Date(n),"MMM d, yyyy"):"—",p=n=>n==null?"—":`${ne()}${Number(n).toFixed(2)}`;return e.jsx(ee,{open:x,onOpenChange:n=>!n&&A(),children:e.jsx(te,{className:"w-[640px] sm:max-w-[640px] overflow-y-auto",children:r&&e.jsxs(e.Fragment,{children:[e.jsxs(se,{children:[e.jsxs(ae,{className:"flex items-center gap-2",children:[j?e.jsx(L,{className:"bg-amber-500/15 text-amber-700 dark:text-amber-400",children:"RAW MATERIAL"}):e.jsx(L,{variant:"secondary",children:"FINISHED PRODUCT"}),e.jsx("span",{className:"truncate",children:r.name})]}),e.jsxs("div",{className:"flex items-center gap-3 text-xs text-muted-foreground",children:[e.jsx("span",{className:"font-mono",children:r.sku||"—"}),r.warehouseName&&e.jsxs("span",{children:["· ",r.warehouseName]}),r.locationName&&e.jsxs("span",{children:["· ",r.locationName]}),r.lotNumber&&e.jsxs("span",{children:["· Lot ",e.jsx("span",{className:"font-mono",children:r.lotNumber})]})]})]}),e.jsxs("div",{className:"mt-5",children:[e.jsx("h4",{className:"font-semibold text-xs uppercase tracking-wide text-muted-foreground mb-2",children:"Snapshot"}),e.jsxs("div",{className:"grid grid-cols-3 gap-2",children:[e.jsx(q,{label:"On Hand",value:r.qtyOnHand.toLocaleStr
9ing()}),e.jsx(q,{label:"Reserved",value:r.qtyReserved.toLocaleString()}),e.jsx(q,{label:"Available",value:(r.qtyOnHand-r.qtyReserved).toLocaleString()}),e.jsx(q,{label:"Unit Cost",value:p(r.unitCost),hint:j?"Latest raw cost":"Landed cost"}),e.jsx(q,{label:"Value",value:p(r.qtyOnHand*r.unitCost)}),e.jsx(q,{label:"Last Receipt",value:C(v.lastReceiptDate),hint:v.lastReceiptCost!=null?`@ ${p(v.lastReceiptCost)}`:void 0})]})]}),e.jsxs("div",{className:"mt-5",children:[e.jsx("h4",{className:"font-semibold text-xs uppercase tracking-wide text-muted-foreground mb-2",children:j?"Movement Totals":"Lot Totals"}),e.jsxs("div",{className:"grid grid-cols-3 gap-2",children:[e.jsx(q,{label:j?"Received In":"Total Received",value:`+${v.received.toLocaleString()}`}),e.jsx(q,{label:j?"Issued / Out":"Consumed",value:`-${v.consumed.toLocaleString()}`}),e.jsx(q,{label:"Net On Hand",value:(v.received-v.consumed).toLocaleString()})]})]}),e.jsxs("div",{className:"mt-6",children:[e.jsx("h4",{className:"font-semibold text-sm mb-2",children:j?"Recent Movements":"Inventory Lots"}),V?e.jsx("p",{className:"text-sm text-muted-foreground",children:"Loading…"}):y.length===0?e.jsx("p",{className:"text-sm text-muted-foreground",children:"No history yet."}):j?e.jsx("div",{className:"overflow-hidden rounded-md border",children:e.jsxs(F,{children:[e.jsx(K,{children:e.jsxs(f,{children:[e.jsx(l,{className:"h-8",children:"Date"}),e.jsx(l,{className:"h-8",children:"Reason"}),e.jsx(l,{className:"h-8",children:"Lot"}),e.jsx(l,{className:"h-8 text-right",children:"Qty"}),e.jsx(l,{className:"h-8 text-right",children:"Unit Cost"})]})}),e.jsx($,{children:y.map(n=>{const u=Number(n.delta);return e.jsxs(f,{children:[e.jsx(c,{className:"py-1.5 text-xs text-muted-foreground",children:C(n.created_at)}),e.jsx(c,{className:"py-1.5 text-xs",children:e.jsx(L,{variant:"outline",className:"capitalize",children:n.reason})}),e.jsx(c,{className:"py-1.5 font-mono text-xs",children:n.lot_number??"—"}),e.jsxs(c,{className:`py-1.5 text-right text-xs font-medium ${u>=0?"text-emerald-600":"text-rose-600"}`,children:[u>=0?"+":"",u]}),e.jsx(c,{className:"py-1.5 text-right text-xs",children:p(n.unit_cost)})]},n.id)})})]})}):e.jsx("div",{className:"overflow-hidden rounded-md border",children:e.jsxs(F,{children:[e.jsx(K,{children:e.jsxs(f,{children:[e.jsx(l,{className:"h-8",children:"Received"}),e.jsx(l,{className:"h-8",children:"Lot"}),e.jsx(l,{className:"h-8 text-right",children:"Initial"}),e.jsx(l,{className:"h-8 text-right",children:"On Hand"}),e.jsx(l,{className:"h-8 text-right",children:"Purchase"}),e.jsx(l,{className:"h-8 text-right",children:"Landed"})]})}),e.jsx($,{children:y.map(n=>e.jsxs(f,{children:[e.jsx(c,{className:"py-1.5 text-xs text-muted-foreground",children:C(n.received_date)}),e.jsx(c,{className:"py-1.5 font-mono text-xs",children:n.lot_number??"—"}),e.jsx(c,{className:"py-1.5 text-right text-xs",children:Number(n.initial_qty)}),e.jsx(c,{className:"py-1.5 text-right text-xs font-medium",children:Number(n.current_qty)}),e.jsx(c,{className:"py-1.5 text-right text-xs",children:p(n.purchase_price)}),e.jsx(c,{className:"py-1.5 text-right text-xs",children:p(n.landed_cost)})]},n.id))})]})})]}),e.jsxs("div",{className:"mt-6",children:[e.jsx("h4",{className:"font-semibold text-sm mb-2",children:"Price History"}),I.length===0?e.jsx("p",{className:"text-sm text-muted-foreground",children:"No price changes recorded."}):e.jsx("div",{className:"overflow-hidden rounded-md border",children:e.jsxs(F,{children:[e.jsx(K,{children:e.jsxs(f,{children:[e.jsx(l,{className:"h-8",children:"Date"}),e.jsx(l,{className:"h-8 text-right",children:"Previous"}),e.jsx(l,{className:"h-8 text-right",children:"New"}),e.jsx(l,{className:"h-8",children:"Source"})]})}),e.jsx($,{children:I.map(n=>{const u=j?n.previous_cost:n.previous_purchase_price,k=j?n.new_cost:n.new_purchase_price;return e.jsxs(f,{children:[e.jsx(c,{className:"py-1.5 text-xs text-muted-foreground",children:C(n.created_at)}),e.jsx(c,{className:"py-1.5 text-right text-xs",children:p(u)}),e.jsx(c,{className:"py-1.5 text-right text-xs font-medium",children:p(k)}),e.jsx(c,{className:"py-1.5 text-xs text-muted-foreground truncate max-w-[180px]",children:n.source_reference??"—"})]},n.id)})})]})})]}),e.jsx("div",{className:"mt-6 flex gap-2",children:e.jsx(re,{variant:"outline",onClick:A,children:"Close"})})]})})})}export{ie 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.