feat(718-3): M01 별칭 장부 화면 — 왼쪽 칸 · 모인 후보 표(이름 · 짝 · 회사 수 · 사람 수 · 충돌) · 승인 · 반려 · 마스터 장부 보기 · 지움 · 대시보드 줄

- 새 M01_MasterData_UI_Alias — 모인 후보 / 마스터 장부 탭 · 승인 · 반려 · 지움 = 확인 창 뒤 서버(718-2 길) · 마스터 장부 = M02 별칭 장부 부품 그대로(마스터 층) + 마스터 공사 내역 맞춤
- M01 왼쪽 판 = 구조물 옵션 정의 아래 「별칭 장부」 칸(본 칸 = 옵션 정의와 같은 자리) · 주소 ?open=별칭(M01 페이지 한 줄)
- 대시보드 설계 기본값 마스터 데이터 묶음에 「별칭 장부」 줄(m_settings_nav 한 줄 · 화면 글 키 하나)
- 시험 test_b01_settings_cards · test_197_1 = 줄 하나 늘어난 자리 · 별칭 칸 대조로 고침(낡은 줄 번호)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-01 15:09:14 +09:00
co-authored by Claude Opus 5.5
parent 27dc456d73
commit c6df183983
7 changed files with 274 additions and 14 deletions
+20 -3
View File
@@ -3,6 +3,7 @@
* 왼쪽 패널 — 공용 접기 컨테이너(`ui-collapsible ui-sidebar-section`)
* 인력 · 재료 · 기계 · 소요량 · 계수 · 환율 · 요율 · 단가산출 로직(일위대가 조합은 M02 · PLAN 27-2b)
* ─ 구분선 ─ 구조물 옵션 정의(716-1 · 화면 코드는 M02 `StructOptions/` 그대로 · 입구만 여기)
* · 별칭 장부(718-3 · 누르면 본 칸에 모인 후보 · 마스터 장부 · `M01_MasterData_UI_Alias`)
* 펼치면 하위 목록(거름 · 파일) · 환율/요율은 누르면 바로 표 · 로직은 안에 로직 목록
* ========================================================================== */
@@ -14,6 +15,7 @@ import {
buildOptionsSection,
type OptionsSectionOptions,
} from "../M02_MasterTemplete/StructOptions/M02_SO_Options";
import { ALIAS_TITLE, buildAliasLedger } from "./M01_MasterData_UI_Alias";
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";
@@ -110,7 +112,7 @@ export interface SideHandle {
/** 「전체」 + 드롭다운 거름 한 벌 — 로직 컨테이너도 씀 */
filter: (args: FilterArgs) => HTMLElement;
/** 주소 `open` — 그 컨테이너를 펼치고 고름(로직 = 로직 목록 · 옵션 = 정의 화면까지) */
reveal: (target: "로직" | "옵션") => void;
reveal: (target: "로직" | "옵션" | "별칭") => void;
/** 옵션 줄 고름 표시 지움(다른 화면을 열었음) · 켬(떠나기를 취소해 머묾) */
setOptionsMark: (on: boolean) => void;
}
@@ -166,6 +168,7 @@ const LEAF: Group[] = ["환율", "요율"];
/** 거름이 있는 컨테이너 — 펼치면 「전체」(또는 닫기 전 거름) 이 바로 열림 */
const FILTERED: Group[] = ["인력", "기계", "소요량", "계수"];
const LOGIC_ID = "로직|";
const ALIAS_ID = "별칭|";
export function buildSide(
onOpen: (pick: Pick) => void,
@@ -500,9 +503,22 @@ ${first.file}`
// 구조물 옵션 정의 — 로직 칸 아래 구분선 + 칸 하나(시스템 관리자 화면이라 고침 가능)
const options = buildOptionsSection({ ...optionsOpt, isAdmin: true });
const optionsSec = section(options.title, options.body);
// 별칭 장부(718-3) — 옵션 칸 아래 칸 하나 · 누르면 본 칸(옵션 정의와 같은 자리)
const aliasSec = section(ALIAS_TITLE, null);
aliasSec.classList.add("m01-side__leaf");
buttons.set(ALIAS_ID, aliasSec);
const openAlias = async (): Promise<void> => {
if (!(await optionsOpt.confirmLeave())) return;
optionsOpt.show(ALIAS_TITLE, buildAliasLedger());
options.clear();
setActive(ALIAS_ID);
};
aliasSec
.querySelector(".ui-collapsible__title")
?.addEventListener("click", () => void openAlias());
const root = el("div", {
className: "m01-side ui-sidebar-panel",
children: [...groups, logic, createDivider(), optionsSec],
children: [...groups, logic, createDivider(), optionsSec, aliasSec],
});
attachCollapsible(root);
void Promise.all(GROUPS.filter((g) => g !== FUEL_GROUP).map(refresh)).catch((error) =>
@@ -514,7 +530,8 @@ ${first.file}`
// 재료는 유가 · 전력 파일까지 다(알약 → 마스터 화면 길이 파일로 찾음) · 유가 · 전력은 그 파일만
const files = (group: string): FileInfo[] =>
group === FUEL_GROUP ? shown(FUEL_GROUP) : (lists.get(group as Group) ?? []);
const reveal = (target: "로직" | "옵션"): void => {
const reveal = (target: "로직" | "옵션" | "별칭"): void => {
if (target === "별칭") return void openAlias();
if (target === "옵션") {
optionsSec.classList.remove("is-collapsed");
options.body.querySelector<HTMLElement>("button")?.click();