import { useState, type FormEvent } from "react"; import type { PacketRead, Weld, WeldBody } from "../api/types"; import { Sheet } from "../components/Sheet"; import { bpos } from "../lib/geometry"; import { fmtTime } from "../lib/format"; import { DEFAULT_SIZE, DEFAULT_TYPE, PROCESSES, WELD_TYPES, lastProcess, weldId, woChoices, } from "../lib/weldDefaults"; /** The new weld's spot, from the tap on the drawing. */ export interface NewWeldAt { page: number; fx: number; fy: number; } interface Draft { wo_base: string; piece: number; type: string; size: string; process: string; stamp: string; items: number[]; } /** * The weld sheet: work order, piece, type, size, process, stamp and the BOM items the weld joins (at least one). * A new weld sends its point and the default label position; an existing one sends only what changed. */ export function WeldSheet({ p, weld, at, editable, myStamp, sub, onSave, onRemove, onClose, }: { p: PacketRead; /** The weld to edit, or null for a new one. */ weld: Weld | null; at: NewWeldAt | null; editable: boolean; /** The signed-in user's welder stamp, when known. */ myStamp: string | null; sub: string; onSave: (body: WeldBody) => void; onRemove: () => void; onClose: () => void; }) { const wos = woChoices(p); const [d, setD] = useState(() => weld ? { wo_base: weld.wo_base ?? wos[0]?.base ?? "", piece: weld.piece ?? 1, type: weld.type ?? DEFAULT_TYPE, size: weld.size ?? DEFAULT_SIZE, process: weld.process ?? lastProcess(p), stamp: weld.stamp ?? "", items: [...weld.items], } : { wo_base: wos[0]?.base ?? "", piece: 1, type: DEFAULT_TYPE, size: DEFAULT_SIZE, process: lastProcess(p), stamp: myStamp || p.welder?.stamp || "", items: [], }, ); const [error, setError] = useState(null); const qty = wos.find((w) => w.base === d.wo_base)?.qty ?? 1; const title = weld ? `Weld ${weldId(weld)}` : "New weld"; const dis = !editable; const toggle = (item: number) => setD((o) => ({ ...o, items: o.items.includes(item) ? o.items.filter((x) => x !== item) : [...o.items, item].sort((a, b) => a - b), })); const heats = d.items .map((i) => { const b = p.bom.find((x) => x.item === i); return b ? `${i}: ${b.heat || (b.na ? "N/A" : "-")}` : ""; }) .filter(Boolean) .join(" · "); const submit = (e: FormEvent) => { e.preventDefault(); if (!editable) return; if (!d.items.length) { setError("Pick at least one BOM item this weld joins."); return; } const size = d.size.trim() || DEFAULT_SIZE; const stamp = d.stamp.trim() || null; if (!weld) { if (!at) return; const b = bpos({ fx: at.fx, fy: at.fy }); onSave({ page: at.page, fx: at.fx, fy: at.fy, bfx: b.bfx, bfy: b.bfy, ...(d.wo_base ? { wo_base: d.wo_base } : {}), piece: d.piece, items: d.items, type: d.type, size, process: d.process, ...(stamp ? { stamp } : {}), }); return; } const body: WeldBody = {}; if ((weld.wo_base ?? "") !== d.wo_base && d.wo_base) body.wo_base = d.wo_base; if ((weld.piece ?? 1) !== d.piece) body.piece = d.piece; if ((weld.type ?? "") !== d.type) body.type = d.type; if ((weld.size ?? "") !== size) body.size = size; if ((weld.process ?? "") !== d.process) body.process = d.process; if ((weld.stamp ?? null) !== stamp) body.stamp = stamp; if ([...weld.items].sort((a, b) => a - b).join(",") !== d.items.join(",")) body.items = d.items; if (!Object.keys(body).length) { onClose(); return; } onSave(body); }; return ( {weld?.carried ? (
Logged in an earlier department. Shown for the record.
) : null}
Mating BOM items
{p.bom.map((b) => ( ))}
{d.items.length ? `Selected: item ${d.items.join(" + ")}${heats ? ` · heats ${heats}` : ""}` : "Tap each BOM item number this weld joins."}
{error ? (
{error}
) : null}
{editable ? ( ) : null} {editable && weld ? ( <> ) : null}
); }