- 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>
128 lines
4.8 KiB
TypeScript
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") });
|
|
}
|