"use client"; /* Receive a delivery: tick each line as it is unpacked, step a line down when less came. Receiving closes the order; anything short goes onto a back order raised by order.receive. */ import { useMemo, useState } from "react"; import { useParams } from "next/navigation"; import { useDerived, useSnap } from "@/lib/client"; import { key, staffName } from "@/lib/compute"; import { plural } from "@/lib/today"; import { DoneScreen, useShowDone, type DoneProps } from "@/components/SignFlow"; import { MBar, MBody, MButton, MEmpty, MError, MField, MKick, MPickRow, MRule, MSection, MStepper, MTop, inputStyle } from "@/components/m"; import { RECEIVABLE, garmentSize, locMap, orderWhen, outstandingLines, segment, shelfOf, type OutLine } from "@/components/m/work/util"; export default function ReceiveOrder() { const id = segment(useParams<{ id: string }>().id); const { s, mutate } = useSnap(); const { byId, staffById } = useDerived(); const order = s.orders.find((o) => o.id === id); const lines = useMemo(() => (order && RECEIVABLE.includes(order.status) ? outstandingLines(order, byId) : []), [order, byId]); const locs = useMemo(() => locMap(s), [s]); const [tick, setTick] = useState>({}); const [qty, setQty] = useState>({}); const [invoice, setInvoice] = useState(() => order?.invoice || ""); const [err, setErr] = useState(""); const [saving, setSaving] = useState(false); const [done, setDone] = useState(null); const showDone = useShowDone(); if (done) return ; const q = (l: OutLine) => qty[l.id] ?? l.outstanding; const ticked = lines.filter((l) => tick[l.id]); const n = ticked.reduce((t, l) => t + q(l), 0); const all = lines.length > 0 && ticked.length === lines.length; const receive = async () => { if (!order || saving) return; setSaving(true); setErr(""); const r = await mutate("order.receive", { id: order.id, invoice: invoice.trim(), lines: lines.map((l) => ({ lineId: l.id, itemId: l.itemId, size: l.size, arrived: q(l), dest: order.staffId ? "pickup" : "shelf" })), }); setSaving(false); if (!r.ok) { setErr(r.error); return; } const short = lines.some((l) => q(l) < l.outstanding); const d: DoneProps = { head: `${plural(n, "item")} received`, sub: `${order.code} · ${order.supplier || "Supplier"} · order closed${short ? " · back order raised" : ""}`, shelfKeys: order.staffId ? [] : lines.filter((l) => q(l) > 0 && l.si >= 0).map((l) => key(l.itemId, l.si)), next: "work", }; setDone(d); showDone(d); }; const forName = order?.staffId ? staffName(staffById[order.staffId]) : ""; return ( <> setErr("")} /> {!order || !lines.length ? ( <> ) : ( <> {`${order.supplier || "Supplier"} · ${orderWhen(s, order)}`} {lines.map((l) => { const name = garmentSize(byId[l.itemId], "Garment", l.size); const sub = forName ? `for ${forName}` : l.si >= 0 ? shelfOf(s, locs, l.itemId, l.si) : ""; return ( setTick((x) => ({ ...x, [l.id]: !x[l.id] }))} title={name} sub={sub || undefined} tickLabel={`Came in ${name}`}> setQty((x) => ({ ...x, [l.id]: v }))} /> ); })} setTick(Object.fromEntries(lines.map((l) => [l.id, true])))} /> setInvoice(e.target.value)} autoComplete="off" maxLength={80} style={inputStyle} /> )} {order && lines.length > 0 && ( )} ); }