feat(M02): 면적산출 상세 오른쪽 = 일위대가 패널 AreaPanel — 담은 로직 · 자재목록(기준 · 반영) · 줄 누름 칸 지정 · 칸 값 바뀌면 바로 곱함 · 조합 줄 · [조합 고치기] 지움 (PLAN 39-4 D2 · D6)

- AreaLink 칸 값 글(수 · 글 · 참 · 오류) 고침

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W4uKaV4ZBhsJN4GHG7yRj4
This commit is contained in:
2026-10-04 19:06:21 +09:00
co-authored by Claude Opus 5.5
parent f0b8882a84
commit 611f5413f3
5 changed files with 267 additions and 20 deletions
@@ -28,7 +28,7 @@ import {
} from "./M02_MasterTemplete_Structure";
import { inputPills } from "./M02_MasterTemplete_Inputs";
import { askSettle } from "./M02_MasterTemplete_TreePanel_Dialogs";
import { buildComboBar } from "./M02_MasterTemplete_Combo";
import { buildAreaPanel, type AreaPanel } from "./M02_MasterTemplete_AreaPanel";
import { buildComboPanel, type ComboPanel } from "./M02_MasterTemplete_ComboPanel";
import {
buildMaterialPanel,
@@ -193,7 +193,9 @@ export function createMain(
let sheetHandle: SpreadsheetHandle | null = null;
let matPanel: MaterialPanel | null = null;
let matState: MaterialState | null = null;
let cpanel: ComboPanel | null = null; // 면적산출 · 재료산출 오른쪽 조합 패널(프로젝트 층 아님)
let cpanel: ComboPanel | null = null; // 재료산출 오른쪽 조합 패널(프로젝트 층 아님)
let apanel: AreaPanel | null = null; // 면적산출 오른쪽 일위대가 패널(프로젝트 층 아님 · 39-4)
let picked = "A1"; // 면적산출 시트에서 지금 고른 칸 — 칸 지정 모달 [지금 고른 칸으로]
let seq = 0;
let dirty = false;
/** 저장 안 한 고침 — 이 화면 + 카드(도면 31-4 · 면적산출 · 재료산출 31-3) */
@@ -242,6 +244,8 @@ export function createMain(
matState = null;
cpanel?.destroy();
cpanel = null;
apanel?.destroy();
apanel = null;
panel?.destroy();
panel = null;
extra.replaceChildren();
@@ -264,8 +268,8 @@ export function createMain(
return made;
}
/** 면적산출 · 재료산출 스프레드시트 — 위 알약 막대(sub7 `links`) · 면적 = 그 열 일위대가 입력값 ·
* 재료 = 자재DB 찾기(`pillsFor`) · 시스템 층은 면적 = 조합 줄 + [조합 고치기] ·
/** 면적산출 · 재료산출 스프레드시트 — 아래 알약 막대 · 면적 = 그 열 일위대가 알약(`pillsFor`) ·
* 재료 = 자재DB 찾기 · 프로젝트 층 아니면 면적 = 오른쪽 일위대가 패널(담은 로직 · 자재목록 · 칸 지정) ·
* 재료 = 그 열 자재 조합 담은 자재(알약 항목 = 옆 판 표 = 같은 목록) + 옆 판
* (`pillItems` = 옆 판에서 고친 목록으로 알약 막대만 다시 만들 때) */
async function mountSheet(
@@ -305,13 +309,29 @@ export function createMain(
onChange: () => {
dirty = !readOnly;
matPanel?.refresh(); // 알약을 이음 · 풂 — 옆 판 「이은 칸」 바로 갱신
apanel?.refresh(); // 칸 값 · 연결이 바뀜 — 반영 금액을 바로 다시 곱함
},
onSelect: (s) => (picked = s.칸),
links,
},
);
editor = handle;
sheetHandle = handle;
if (at.layer === "project") return;
if (kind === "area") {
// 오른쪽 일위대가 패널 — 담은 로직 + 자재목록(기준 · 반영) · 줄 누름 = 칸 지정 모달
apanel?.destroy();
apanel = buildAreaPanel({
layer: at.layer,
column: at.name,
sheet: () => sheetHandle,
picked: () => picked,
pills: () => links.항목,
readOnly,
});
host.append(apanel.root);
return;
}
// 오른쪽 조합 패널 — 한 번 만들고 시트를 다시 붙여도 그대로(늘 시트 뒤)
cpanel ??= buildComboPanel({
kind,
@@ -320,20 +340,6 @@ export function createMain(
onUsed: () => remount(kind, at, readOnly, true),
});
host.append(cpanel.root);
if (kind === "area") {
const bar = await buildComboBar({
column: at.name,
label: at.label ?? at.name,
isAdmin,
beforeEdit: async () => true,
onApplied: async () => {
await remount(kind, at, readOnly, false);
await cpanel?.refresh();
},
});
if (mine === seq) cpanel?.setMine(bar);
return;
}
if (matPanel || !matState) return;
matPanel = buildMaterialPanel({
column: at.name,