feat(M01): 자재 조합 화면 — 목록 · 상세 · 자재 더하기 · 지우기 알림

- 좌측 「자재 조합」 컨테이너(찾기) + 우측 목록(키 · 이름 · 자재 수 · 본뜬키 · 소유) · 상세(이름 · 비고 · 본뜬키 · 담은 자재 표 · 빼기)
- [자재 더하기] = 자재DB 낱말 찾기 → 하나씩 고름(이미 담은 자재는 잠김) · 저장 · 지우기는 M01 길 /api/m01/matset…
- 쓰는 구조물 열이 있어 지울 수 없으면 서버가 준 구조물 이름들을 알림으로 보임
- 알약 키 「이름|단위」 주석 갱신

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RoyUwuTFiDJfvCfHpvKKzp
This commit is contained in:
2026-09-28 19:14:10 +09:00
co-authored by Claude Sonnet 5
parent d35269e32a
commit 4c8ee6828f
6 changed files with 525 additions and 6 deletions
+23 -3
View File
@@ -39,6 +39,7 @@ import { tl } from "./M01_MasterData_UI_LogicLab_Text";
import { renderTables } from "./M01_MasterData_UI_Tables";
import type { LogicHandle } from "./M01_MasterData_UI_LogicLab";
import type { ComboHandle } from "./M01_MasterData_UI_Combo";
import type { MatsetHandle } from "./M01_MasterData_UI_Matset";
import "./M01_MasterData_UI_Style.css";
const TABLE_GROUPS = ["소요량", "계수"];
@@ -60,6 +61,7 @@ function buildPage(): HTMLElement {
let dispose = (): void => {};
let logicMounted = false;
let comboHandle: ComboHandle | null = null;
let matsetHandle: MatsetHandle | null = null;
/* --- 우측: 머리(제목·찾기·저장) + 알림 + 본문 --- */
const title = el("h2", { className: "m01-master__title", text: L("M01_PickFile") });
@@ -76,6 +78,7 @@ function buildPage(): HTMLElement {
});
const logicHost = el("div", { className: "m01-master__logic", attrs: { hidden: "" } });
const comboHost = el("div", { className: "m01-master__logic", attrs: { hidden: "" } });
const matsetHost = el("div", { className: "m01-master__logic", attrs: { hidden: "" } });
const elementView = el("div", {
className: "m01-master__elements",
children: [
@@ -98,9 +101,10 @@ function buildPage(): HTMLElement {
onDraftChange(refreshBar);
refreshBar();
const showMode = (mode: "elements" | "logic" | "combo"): void => {
const showMode = (mode: "elements" | "logic" | "combo" | "matset"): void => {
logicHost.hidden = mode !== "logic";
comboHost.hidden = mode !== "combo";
matsetHost.hidden = mode !== "matset";
elementView.hidden = mode !== "elements";
};
@@ -222,6 +226,22 @@ function buildPage(): HTMLElement {
});
};
/** 「자재 조합」 — 목록을 새로 받아 그림 */
const openMatsetTab = (): void => {
dispose();
dispose = (): void => {};
current = null;
showMode("matset");
if (matsetHandle) {
void matsetHandle.show();
return;
}
void import("./M01_MasterData_UI_Matset").then((m) => {
matsetHandle = m.mountM01Matset(matsetHost, side);
void matsetHandle.show();
});
};
/** 알약 → 마스터 화면 — 찾기 글을 그 키로 두고 열고, 알림줄에 「단가산출 로직으로 돌아가기」를 둠 */
const jump = async (target: MasterJump): Promise<void> => {
let group = target.kind === "element" ? target.group : "";
@@ -262,7 +282,7 @@ function buildPage(): HTMLElement {
setMasterJump((target) => void jump(target));
/* --- 좌측: 컨테이너 --- */
const side = buildSide(openFile, () => openLogicTab(), openComboTab);
const side = buildSide(openFile, () => openLogicTab(), openComboTab, openMatsetTab);
const layout = el("div", { className: "ui-workflow-layout m01-master" });
const main = el("main", {
@@ -270,7 +290,7 @@ function buildPage(): HTMLElement {
children: [
el("div", {
className: "m01-master__panel",
children: [elementView, logicHost, comboHost],
children: [elementView, logicHost, comboHost, matsetHost],
}),
],
});