/* ============================================================================= * M02_MasterTemplete_Labor_LogicMats.ts * 자재목록 표의 로직 자재 줄(103-1) — 담은 로직 맨 위 층 재료 줄(서버 calc `줄[].재료`) · 사용자 자재 줄과 같은 칸 * (코드 · 이름 · 규격 · 수량 · 단위 · 가격 다섯 · 단가 / 금액) · 사용자 자재 앞. * · 삭제 없음 · [바꾸기] = M01 자재품목 표에서 고름(문서 `담은로직[].고름` · 엔진 `choosing`) · 바꾼 줄만 [기본](고름 풂) * · 금액은 로직 단가 안이라 합에 다시 안 더함(보기만) · 수량은 로직 것(누름 · 알약 없음) * · 하위 로직 안 재료는 안 보임(엔진이 맨 위 층만 고름) * ========================================================================== */ import { createButton, el } from "@ui/ui_template_elements"; import { formatMoney } from "../M01_MasterData/M01_MasterData_UI_Logic_Money"; import { openPickTable } from "../M01_MasterData/M01_MasterData_UI_Logic_PickTable"; import { headWord } from "../M01_MasterData/M01_MasterData_UI_LogicLab_Modal"; import type { LaborCalc, LaborRow } from "./M02_MasterTemplete_Labor_Api"; import { lineId } from "./M02_MasterTemplete_Labor_Calc"; import { moneyCell, PRICE_SLOTS } from "./M02_MasterTemplete_Labor_Rows"; import { tc } from "./M02_MasterTemplete_Labor_Text"; import type { LogicMat } from "./M02_Labor_LogicMats_Model"; export interface LogicMatHandlers { /** [바꾸기]로 고른 품목 키 — `row` = 담은 로직 차례 · `at` = 호표 차례 */ swap: (row: number, at: number, key: string) => void; /** [기본] — 그 줄 고름 풂 */ reset: (row: number, at: number) => void; } const num = (v: number | null): string => v === null ? "—" : Number(v.toPrecision(12)).toLocaleString("ko-KR", { maximumFractionDigits: 6 }); /** 담은 로직 차례대로 그 줄 로직 자재 — calc 답이 없으면 빈 것(답이 오면 다시 그림) */ export function logicMatRows( rows: LaborRow[], calc: LaborCalc | null, wait: boolean, on?: LogicMatHandlers, ): HTMLElement[] { return rows.flatMap((row, r) => { const line = row.참조 ? undefined : calc?.줄.find((l) => lineId(l) === lineId(row)); return (line?.재료 ?? []).map((mat) => matRow(row, r, mat, wait, on)); }); } function matRow( row: LaborRow, r: number, mat: LogicMat, wait: boolean, on?: LogicMatHandlers, ): HTMLElement { const item = mat.품목; const name = item?.이름 ?? mat.이름; const owner = `${row.별칭 ?? row.로직} · ${mat.이름}`; const priceCell = (slot: (typeof PRICE_SLOTS)[number]): HTMLElement => { const base = !!item?.값칸 && item.값칸 === slot; const v = mat.가격?.[slot]; return el("td", { className: `m02-labrow__num m02-labrow__price${base ? " is-base-price" : ""}`, text: wait ? "…" : v === null || v === undefined ? "—" : formatMoney(v), attrs: { "data-label": slot, "data-price-slot": slot }, }); }; const money = moneyCell(mat.단가, mat.금액, wait, tc("Labor_AppliedSum")); money.title = tc("LogicMat_Inside"); const tools = on ? [ el("td", { className: "m02-labrow__move", children: [ el("div", { className: "ui-btn-group", children: [ createButton({ label: tc("LogicMat_Swap"), variant: "ghost", onClick: (e) => { e.stopPropagation(); openPickTable({ kind: "재료", title: `${tc("LogicMat_PickTitle")} · ${mat.이름}`, seed: headWord(name), alt: [headWord(mat.이름)], isCurrent: (x) => String(x["키"]) === item?.키, onPick: (x) => on.swap(r, mat.차례, String(x["키"])), }); }, }), ...(mat.고름 ? [ createButton({ label: tc("LogicMat_Reset"), variant: "ghost", onClick: (e) => { e.stopPropagation(); on.reset(r, mat.차례); }, }), ] : []), ], }), ], }), ] : []; return el("tr", { className: `m02-labrow__row m02-labrow__logic-mat${mat.고름 ? " is-picked-mat" : ""}`, attrs: { "data-labor-logic-mat": `${row.로직}|${mat.차례}` }, children: [ el("td", { className: "m02-labrow__code", text: item?.키 ?? "—" }), el("td", { className: "m02-labrow__name", children: [ el("strong", { text: name, attrs: { title: name } }), el("small", { className: "m02-labrow__key", text: mat.고름 ? `${owner} · ${tc("LogicMat_Picked")}` : owner, attrs: { title: owner }, }), ...(mat.까닭 ? [el("small", { className: "m02-labrow__empty", text: mat.까닭 })] : []), ], }), el("td", { className: "m02-labrow__spec", text: item?.규격 ?? "", attrs: { title: item?.규격 ?? "" }, }), el("td", { className: "m02-labrow__qty", text: wait ? "…" : num(mat.수량), attrs: { "data-label": tc("Labor_QtyCol") }, }), el("td", { className: "m02-labrow__unit", text: mat.단위, attrs: { "data-label": tc("Labor_Unit") }, }), ...PRICE_SLOTS.map(priceCell), money, ...tools, ], }); }