import { useState } from "react"; import { ApiError } from "../api/client"; import { packetsApi } from "../api/packets"; import type { PacketRead, Weld, WeldBody } from "../api/types"; import type { ReasonOptions } from "../components/ReasonSheet"; import { errorText } from "../lib/format"; import { voidText } from "../lib/voidStamp"; import { weldId, weldSummary } from "../lib/weldDefaults"; import type { Write, WriteResult } from "../warehouse/PullTable"; import { MapViewer } from "./MapViewer"; import { openPrint } from "./closeUtil"; import { WeldMark, type MarkMove } from "./marks"; import { landingPage, pageLabel, usePeople, viewPages } from "./shopUtil"; import { useSerial } from "./useSerial"; import { WeldRecord } from "./WeldRecord"; import { WeldSheet, type NewWeldAt } from "./WeldSheet"; import type { Mutate } from "./tabs"; const rv = (cur: PacketRead, no: number, fallback: number) => cur.welds.find((w) => w.weld_no === no)?.row_version ?? fallback; function WeldRow({ w, onOpen }: { w: Weld; onOpen: (w: Weld) => void }) { return ( ); } /** * The weld map: the drawing with the welds of the open sheet as pink leader marks. "Mark a weld" turns on * marking; a tap on the joint opens the weld sheet. Bubbles and arrows drag when the user may edit welds. */ export function WeldMapTab({ p, write, mutate, reload, askReason, sub, myId, onError, }: { p: PacketRead; write: Write; mutate: Mutate; reload: () => Promise; askReason: (o: ReasonOptions) => Promise; sub: string; myId: string | null; onError: (text: string) => void; }) { const pages = viewPages(p.pages); const [picked, setPicked] = useState<{ n: number; onPurpose: boolean } | null>(null); const page = landingPage(pages, picked?.n ?? null, picked?.onPurpose ?? false); const [marking, setMarking] = useState(false); const [sheet, setSheet] = useState<{ weldNo: number | null; at: NewWeldAt | null } | null>(null); const serial = useSerial(p, write); const { people } = usePeople(p.dept.code); const myStamp = people.find((x) => x.id === myId)?.stamp ?? null; if (!page) return
No drawing pages in this packet.
; const isVoid = !!page.void; const canEdit = p.can.includes("edit_welds"); const editable = canEdit && !isVoid; const onSheet = p.welds.filter((w) => w.page === page.n); const current = onSheet.filter((w) => !w.carried); const carried = onSheet.filter((w) => w.carried); const vText = isVoid ? voidText(page, p.pages) : ""; const open = sheet ? (sheet.weldNo !== null ? (p.welds.find((w) => w.weld_no === sheet.weldNo) ?? null) : null) : null; const done = async (r: WriteResult): Promise => { if (r.ok) return true; if (r.err !== undefined) { if (r.err instanceof ApiError && (r.err.status === 409 || r.err.status === 412)) await reload(); onError(errorText(r.err)); } return false; }; const add = async (body: WeldBody) => { if (await done(await serial((cur, g) => packetsApi.addWeld(cur.id, body, g)))) { setSheet(null); setMarking(false); } }; const save = async (w: Weld, body: WeldBody) => { if (await done(await serial((cur, g) => packetsApi.patchWeld(cur.id, w.weld_no, rv(cur, w.weld_no, w.row_version), body, g)))) setSheet(null); }; const remove = async (w: Weld) => { const reason = await askReason({ title: `Remove weld ${weldId(w)}`, sub, note: "The weld leaves the weld map. It stays in the record with your reason.", min: 3, danger: true, submitLabel: "Remove weld", }); if (reason === null) return; if (await done(await serial((cur, g) => packetsApi.removeWeld(cur.id, w.weld_no, rv(cur, w.weld_no, w.row_version), { reason, ...g })))) setSheet(null); }; const move = (w: Weld, m: MarkMove) => serial((cur, g) => packetsApi.patchWeld( cur.id, w.weld_no, rv(cur, w.weld_no, w.row_version), m.bubble ? { bfx: m.bfx, bfy: m.bfy } : { fx: m.fx, fy: m.fy, bfx: m.bfx, bfy: m.bfy }, g, ), ).then(done); const markBtn = editable ? ( ) : null; return (
{isVoid ? (
VOID copy, not for fabrication. {vText}. Kept for the record with its weld marks.{" "} {page.void?.new_n ? ( ) : null}
) : null}
{pages.length > 1 ? (
{pages.map((x) => ( ))}
) : ( {pageLabel(page)} )} {markBtn} {marking ? Tap the weld location on the drawing. : null} {!canEdit ? ( {p.welds.length} weld{p.welds.length === 1 ? "" : "s"} recorded ) : null} {!p.removed ? ( ) : null}
{ if (marking && editable) setSheet({ weldNo: null, at: { page: page.n, fx, fy } }); }} fsBar={ <> {pageLabel(page)} {markBtn} } > {onSheet.map((w) => ( setSheet({ weldNo: x.weld_no, at: null })} onMove={move} /> ))}

Welds on this sheet ({current.length}) {current.length !== p.welds.filter((w) => !w.carried).length ? of {p.welds.filter((w) => !w.carried).length} : null}

{editable && current.length ?
Drag a bubble to move it off the linework. Drag the arrow to fix the weld location.
: null}
{current.length ? ( current.map((w) => setSheet({ weldNo: x.weld_no, at: null })} />) ) : (
{editable ? "Tap Mark a weld, then tap the joint on the drawing." : "No welds recorded yet."}
)}
{carried.length ? (

Carried from an earlier department

{carried.map((w) => ( setSheet({ weldNo: x.weld_no, at: null })} /> ))}
) : null}
{sheet && (sheet.weldNo === null || open) ? ( x.n === open.page)?.void : isVoid) && !open?.carried} myStamp={myStamp} sub={sub} onSave={(body) => void (open ? save(open, body) : add(body))} onRemove={() => { if (open) void remove(open); }} onClose={() => setSheet(null)} /> ) : null}
); }