"use client"; /* One stock line: a garment in one size. On hand against par, where it lives, what is coming, and the three things done about it: print a label, count its shelf, put it on the draft order. */ import { useCallback, useState } from "react"; import { useParams } from "next/navigation"; import { useDerived, useSnap } from "@/lib/client"; import { bcBound, key, label, locMap, locTrail, money, onOrderText, onhand, reorderAt } from "@/lib/compute"; import { INK, MBody, MButton, MEmpty, MKick, MONO, MPill, MRow, MRule, MTop, useToast } from "@/components/m"; import PrintSheet from "@/components/m/stock/PrintSheet"; import { heldByStaff, lastCountedText } from "@/components/m/stock/stockdata"; const dt: React.CSSProperties = { margin: 0, padding: "11px 14px 11px 0", borderBottom: "1px solid var(--color-divider)", fontSize: 12, fontWeight: 800, letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--color-neutral-600)" }; const dd: React.CSSProperties = { margin: 0, padding: "11px 0", borderBottom: "1px solid var(--color-divider)", textAlign: "right", fontWeight: 700 }; export default function MLinePage() { const params = useParams<{ itemId: string; si: string }>(); const { s, isAdmin, mutate, busy } = useSnap(); const { L } = useDerived(); const toast = useToast(); const [printing, setPrinting] = useState(false); // Stable, because MSheet re-runs its focus handling whenever onClose changes. const closePrint = useCallback(() => setPrinting(false), []); const itemId = decodeURIComponent(String(params.itemId || "")); const si = /^\d+$/.test(String(params.si || "")) ? Number(params.si) : -1; const it = s.catalog.find((x) => x.id === itemId); if (!it || it.archived || si < 0 || si >= it.sizes.length) { return ( <> ); } const k = key(it.id, si); const size = String(it.sizes[si]); const oh = onhand(s, L, k), par = reorderAt(s, k); const code = bcBound(s, it, si); const locs = locMap(s); const placedId = s.placed[k]; const placed = placedId ? locs[placedId] : undefined; const shelf = placed ? (locTrail(locs, placed.id, 0) || placed.name) : ""; const onOrder = onOrderText(s, it.id, si); const short = Math.max(0, par - oh); const addToDraft = async () => { const r = await mutate<{ added: number; qty: number }>("stock.orderLine", { itemId: it.id, si }); if (!r.ok) { toast(r.error); return; } toast(r.result.added > 0 ? `Added ${r.result.added} to the draft order` : "Already on the draft order"); }; return ( <> {code || (it.sku ? `SKU ${it.sku}` : "No barcode")}

{label(it)} · {size}

{oh} / {par} par
{short > 0 ? {short} short : At par}
Shelf
{shelf || "Not on a shelf"}
On order
{onOrder || "None"}
Last counted
{lastCountedText(s, it.id, si)}
Held by staff
{heldByStaff(s, it.id, si)}
Unit cost
{money(it.cost)}
setPrinting(true)} /> {!code &&
No barcode bound
} {!code && isAdmin && } {placed && }
{isAdmin && (
)}
{code && } ); }