Files
Aislo/M02_MasterTemplete/M02_MasterTemplete_Labor_MatTable.ts
T
eomsangdonandClaude Opus 5.5 f8338194c6 refactor(717-3): 일위대가 상세 · 줄 표 나눔 — 자재목록 표(Labor_MatTable) · 서고 구분 고르기(Labor_LibMeta) 떼어 냄 · 동작 같음
- Labor_Rows 671 → 566 줄 · Labor_Detail 700 → 650 줄(717-3 모달 단추 자리)
- 낡은 시험 셋 고침: mat_marks · precombo_class = 옮긴 파일을 읽음 · hopyo_screen 의 Detail 「꼭 700 줄」 = 「700 줄 넘지 않음」(나눔으로 줄어듦)
- 시험 158 통과 · 1 실패(test_175 B09 겹 대가 = Store_Combo._PER 없음 · 나눔 전부터 · 719-2 몫)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 16:32:32 +09:00

128 lines
4.8 KiB
TypeScript

/* =============================================================================
* M02_MasterTemplete_Labor_MatTable.ts
* 일위대가 자재목록 표(43-3 · `Labor_Rows` 에서 뗌 · 717-3) — 상세 · 보기 갈래가 같이 씀.
* 자재목록 = 코드 · 이름 · 규격 · 수량산출 · 단위 · 가격 다섯(기준 칸 강조) · 기준단가 / 반영 금액.
* 금액은 calc 답(없으면 「…」) · 줄 누름 · [삭제]는 `on` 이 있을 때만.
* ========================================================================== */
import { createButton, el } from "@ui/ui_template_elements";
import { formatMoney } from "../M01_MasterData/M01_MasterData_UI_Logic_Money";
import type {
LaborCalc,
LaborCalcLine,
LaborCalcMat,
LaborMat,
} from "./M02_MasterTemplete_Labor_Api";
import { markCells, markHeads } from "./M02_MasterTemplete_Labor_MatMarks";
import {
moneyCell,
PRICE_SLOTS,
qtyCell,
table,
titled,
type RowHandlers,
} from "./M02_MasterTemplete_Labor_Rows";
import { tc } from "./M02_MasterTemplete_Labor_Text";
export interface MatTableData {
mats: LaborMat[];
/** 로직 자재 줄(103-1 · `Labor_LogicMats`) — 사용자 자재 앞 · 같은 칸 */
lead?: HTMLElement[];
calc: LaborCalc | null;
fail?: string | null;
cells?: ReadonlyMap<string, string>;
}
/** 자재목록 표(43-3 · 로직 줄과 같은 꼴) — 코드 · 이름 · 규격 · 수량산출(위 기준 수량 1 단위 / 아래 지금
* 수량) · 단위 · 가격 다섯(빈 것 「—」 · 기준단가가 된 칸 강조) · 금액(위 기준단가 / 아래 반영 = 기준단가 × 수량) ·
* 보기 갈래는 `on` 없이 */
export function matTable(data: MatTableData, on?: Omit<RowHandlers, "move">): HTMLElement {
const wait = !data.calc && !data.fail;
const remove = on?.remove;
const show = (v: number | null | undefined): string =>
wait ? "…" : v === null || v === undefined ? "—" : formatMoney(v);
const trs = data.mats.map((mat, i) => {
const line: LaborCalcMat | undefined = data.calc?.자재.find((m) => m.코드 === mat.코드);
// 수량산출 칸은 로직 줄 칸을 그대로 씀 — 기준 수량 = 자재 단위 1
const qtyLine = { ...line, 배: 1, 분모: mat.단위 ?? "" } as LaborCalcLine;
const priceCell = (slot: (typeof PRICE_SLOTS)[number]): HTMLElement => {
const base = !!line?.기준칸 && line.기준칸 === slot;
return el("td", {
className: `m02-labrow__num m02-labrow__price${base ? " is-base-price" : ""}`,
text: show(line?.가격?.[slot]),
attrs: {
"data-label": slot,
"data-price-slot": slot,
...(base ? { title: tc("Labor_BasePrice") } : {}),
},
});
};
const tr = el("tr", {
className: on ? "m02-labrow__row is-open" : "m02-labrow__row",
attrs: { "data-labor-mat": mat.코드 },
children: [
el("td", { className: "m02-labrow__code", text: mat.코드 }),
titled(
el("td", {
className: "m02-labrow__name",
children: [
el("strong", { text: mat.이름 ?? "" }),
...(line?.까닭
? [el("small", { className: "ui-text ui-text--error", text: line.까닭 })]
: []),
],
}),
),
el("td", {
className: "m02-labrow__spec",
text: mat.규격 ?? "",
attrs: { title: mat.규격 ?? "" },
}),
qtyCell(qtyLine, data.cells, on?.qty ? () => on.qty?.(i) : null),
el("td", {
className: "m02-labrow__unit",
text: mat.단위 ?? "",
attrs: { "data-label": tc("Labor_Unit") },
}),
...markCells(mat, on?.mark ? (k, v) => on.mark?.(i, k, v) : undefined),
...PRICE_SLOTS.map(priceCell),
moneyCell(line?.기준단가, line?.반영, wait, tc("Labor_AppliedSum")),
...(remove
? [
el("td", {
className: "m02-labrow__move",
children: [
createButton({
label: tc("Remove"),
variant: "danger",
onClick: (e) => {
e.stopPropagation();
remove(i);
},
}),
],
}),
]
: []),
],
});
if (on) tr.addEventListener("click", () => on.open(i));
return tr;
});
const heads = [
tc("Labor_Code"),
tc("Col_Name"),
tc("Labor_Spec"),
tc("Labor_QtyCol"),
tc("Labor_Unit"),
...markHeads(),
...PRICE_SLOTS,
`${tc("Labor_BasePrice")} · ${tc("Labor_AppliedSum")}`,
...(remove ? [tc("Col_Move")] : []),
];
const lead = data.lead ?? [];
return data.mats.length || lead.length
? table(heads, [...lead, ...trs], [])
: el("p", { className: "ui-text ui-text--muted", text: tc("Labor_NoMat") });
}