feat(M01): PLAN 7-1 — 「로직 개선 시험」을 「단가산출 로직」 하나로 합침

소요량·계수의 쓰는 로직 · 조합 화면 로직 이름 · 패널 제목 세 자리를 모두
새 컨테이너(UI_LogicLab)로 돌림 · 옛 컨테이너(UI_Logic_Page)는 old_code/M01_MasterData/
로 옮김(지우지 않음 · import 경로만 고침 · 통째 복사 아님) · 정본 GC·GF 를 화면에서
바로 고쳐 저장 · 정본 파일에 빈 줄 더하기 두 길은 사용자 확정으로 버림.
분석 = resources/master_data/ref/_분석_로직컨테이너_통합.md.

typecheck 통과 · M01 시험 107 통과 · ORCA — 패널에 「단가산출 로직」 하나만
· 소요량 표 쓰는 로직 키(GF000002 · GF000051) 클릭 각각 그 로직이 새 컨테이너에서 열림
· 조합 화면 로직 이름도 같은 컨테이너로 이어짐.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WRFJmmhPi4exAzHgPZHMT
This commit is contained in:
2026-09-22 12:08:54 +09:00
co-authored by Claude Sonnet 5
parent 727d110db4
commit 0eebf357fa
8 changed files with 42 additions and 57 deletions
+4 -16
View File
@@ -59,7 +59,7 @@ export function takePendingLogicKey(): string | null {
}
}
/** 「로직 개선 시험」 알약 → 마스터 화면 — 표(키) 또는 요소(그룹 · 키 · 파일) */
/** 「단가산출 로직」 알약 → 마스터 화면 — 표(키) 또는 요소(그룹 · 키 · 파일) */
export type MasterJump =
{ kind: "table"; key: string } | { kind: "element"; group: string; ref: string; file?: string };
@@ -88,8 +88,6 @@ export interface SideHandle {
logicHost: HTMLElement;
/** 일위대가 조합 컨테이너 안(구분 · 상세구분 거름이 들어갈 자리) */
comboHost: HTMLElement;
/** 「로직 개선 시험」 컨테이너 안 */
labHost: HTMLElement;
/** 그룹의 파일 판본을 다시 받음(저장 뒤) — 돌려받는 것 = 새 목록 */
refresh: (group: string) => Promise<FileInfo[]>;
/** 그룹의 파일 목록(이미 받은 것) */
@@ -147,13 +145,11 @@ const LEAF: Group[] = ["환율", "요율"];
/** 거름이 있는 컨테이너 — 펼치면 「전체」(또는 닫기 전 거름) 이 바로 열림 */
const FILTERED: Group[] = ["인력", "기계", "소요량", "계수"];
const LOGIC_ID = "로직|";
const LAB_ID = "로직시험|";
const COMBO_ID = "조합|";
export function buildSide(
onOpen: (pick: Pick) => void,
onLogic: () => void,
onLab: () => void,
onCombo: () => void = () => {},
): SideHandle {
const lists = new Map<Group, FileInfo[]>();
@@ -447,7 +443,7 @@ ${first.file}`
});
const logicHost = el("div", { className: "m01-side__items" });
const logic = section(L("M01_GroupLogic"), logicHost);
const logic = section(tx("Lab_Title"), logicHost);
logic.querySelector(".ui-collapsible__title")?.addEventListener("click", () => {
if (!logic.classList.contains("is-collapsed")) return; // 닫을 때는 그대로 둠
setActive(buttons.has(LOGIC_ID) ? LOGIC_ID : null);
@@ -462,15 +458,7 @@ ${first.file}`
onCombo();
});
const labHost = el("div", { className: "m01-side__items" });
const lab = section(tx("Lab_Title"), labHost);
lab.querySelector(".ui-collapsible__title")?.addEventListener("click", () => {
if (!lab.classList.contains("is-collapsed")) return;
setActive(buttons.has(LAB_ID) ? LAB_ID : null);
onLab();
});
const root = el("div", { className: "m01-side", children: [...groups, logic, combo, lab] });
const root = el("div", { className: "m01-side", children: [...groups, logic, combo] });
attachCollapsible(root);
void Promise.all(GROUPS.map(refresh)).catch((error) =>
showToast(error instanceof Error ? error.message : L("M01_LoadFailed"), "error"),
@@ -479,5 +467,5 @@ ${first.file}`
onPicked = fn;
};
const files = (group: string): FileInfo[] => lists.get(group as Group) ?? [];
return { root, logicHost, comboHost, labHost, refresh, files, setActive, setOnPicked, filter };
return { root, logicHost, comboHost, refresh, files, setActive, setOnPicked, filter };
}