feat(M01): 옛 일위대가 로직 컨테이너는 호표 표 그대로 · 아래에 「로직 쉽게 보기·만들기」 컨테이너를 더해 방식 C + 새로 만들기 모달을 담음

- 일위대가 로직 컨테이너 = 로직을 누르면 옛 호표 표 + 시험 계산 칸이 바로 열림 · 보기 전환 단추와 보기 캐시 값 없앰 · 「새로 만들기」 는 옛 초안 방식
- 새 컨테이너 = 같은 목록·API 를 쓰되 거름 기억과 저장 안 한 것 캐시를 따로 둠 · 로직을 고르면 흐름 그림 · 새로 만들기 모달 · 본떠 만들기 · 상자 고치기

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WRFJmmhPi4exAzHgPZHMT
This commit is contained in:
2026-09-21 12:12:16 +09:00
co-authored by Claude Sonnet 5
parent 5bef49df88
commit 83752f8698
4 changed files with 91 additions and 38 deletions
+19 -3
View File
@@ -9,6 +9,7 @@ import { createSelectField, el, showToast } from "@ui/ui_template_elements";
import { attachCollapsible } from "@ui/ui_template_collapsible";
import { t as L } from "@ui/ui_template_locale";
import { fetchFiles, fetchSubsAll, type FileInfo, type SubInfo } from "./M01_MasterData_Api_Fetch";
import { tx } from "./M01_MasterData_UI_Logic_Text";
import { renderTree, type MakeRow } from "./M01_MasterData_UI_Tree";
/** 컨테이너마다 기억하는 화면 상태 — 찾기 글 · 쪽 · 소요량·계수 표의 용도 대상 거름 (거름은 `m01.filter.*`) */
@@ -74,6 +75,8 @@ export interface SideHandle {
root: HTMLElement;
/** 일위대가 로직 컨테이너 안(로직 목록이 들어갈 자리) */
logicHost: HTMLElement;
/** 「로직 쉽게 보기·만들기」 컨테이너 안(같은 로직 목록이 들어갈 자리) */
easyHost: HTMLElement;
/** 그룹의 파일 판본을 다시 받음(저장 뒤) — 돌려받는 것 = 새 목록 */
refresh: (group: string) => Promise<FileInfo[]>;
setActive: (id: string | null) => void;
@@ -127,8 +130,13 @@ const LEAF: Group[] = ["환율", "요율"];
/** 거름이 있는 컨테이너 — 펼치면 「전체」(또는 닫기 전 거름) 이 바로 열림 */
const FILTERED: Group[] = ["인력", "기계", "소요량", "계수"];
const LOGIC_ID = "로직|";
const EASY_ID = "쉬움|";
export function buildSide(onOpen: (pick: Pick) => void, onLogic: () => void): SideHandle {
export function buildSide(
onOpen: (pick: Pick) => void,
onLogic: () => void,
onEasy: () => void,
): SideHandle {
const lists = new Map<Group, FileInfo[]>();
const bodies = new Map<Group, HTMLElement>();
const buttons = new Map<string, HTMLElement>();
@@ -403,10 +411,18 @@ export function buildSide(onOpen: (pick: Pick) => void, onLogic: () => void): Si
onLogic();
});
const root = el("div", { className: "m01-side", children: [...groups, logic] });
const easyHost = el("div", { className: "m01-side__items" });
const easy = section(tx("Easy_Title"), easyHost);
easy.querySelector(".ui-collapsible__title")?.addEventListener("click", () => {
if (!easy.classList.contains("is-collapsed")) return;
setActive(buttons.has(EASY_ID) ? EASY_ID : null);
onEasy();
});
const root = el("div", { className: "m01-side", children: [...groups, logic, easy] });
attachCollapsible(root);
void Promise.all(GROUPS.map(refresh)).catch((error) =>
showToast(error instanceof Error ? error.message : L("M01_LoadFailed"), "error"),
);
return { root, logicHost, refresh, setActive, filter };
return { root, logicHost, easyHost, refresh, setActive, filter };
}