feat(M02): 면적산출 · 재료산출 오른쪽 조합 패널 — 조합 목록 · 이 열에 쓰기 · 조합 고치기
- 오른쪽 안쪽 패널: 공용 사이드바 카드 · 접기(attachCollapsible) · 공용 폭 손잡이(createPanelResizer · 폭 기억 · 최소 280 · 최대 60%) · 공용 접기 손잡이(createWorkflowPanelHandle)
- 「이 열의 조합」 칸: 면적 = 일위대가 조합 줄 + [조합 고치기] · 재료 = 담은 자재 표(옆 판 aside 없앰)
- 조합 목록: 면적 = 일위대가(UA) · 재료 = 자재 조합(UM) · 키 · 이름 · 수 · 본뜬키 · 찾기 · 이 열 조합 강조
- [이 열에 쓰기]: 서버 POST /api/m02/structures/{column}/use-combo(집계표 판 검사 · 그 열 키만 바꿈 · 조합은 그대로) → 알약 다시 받음
- 상태 등록표에 m02-combo-panel-width · collapsed · 시험 더함
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Kyw9qnkJ94pC1A4PfpDtA
This commit is contained in:
@@ -24,6 +24,7 @@ import {
|
||||
type StructurePanelHandle,
|
||||
} from "./M02_MasterTemplete_Structure";
|
||||
import { buildComboBar } from "./M02_MasterTemplete_Combo";
|
||||
import { buildComboPanel, type ComboPanel } from "./M02_MasterTemplete_ComboPanel";
|
||||
import {
|
||||
buildMaterialPanel,
|
||||
loadMaterialState,
|
||||
@@ -109,7 +110,6 @@ export function createMain(
|
||||
const back = createButton({ label: L("M02_Back"), variant: "ghost", size: "sm" });
|
||||
const slot = el("div", { className: "m02-main__slot" }); // 도면 양식의 작도 영역 칸이 들어옴
|
||||
const notice = el("div", { className: "m02-main__notice", attrs: { hidden: "" } });
|
||||
const comboSlot = el("div", { className: "m02-main__combo" }); // 면적산출 — 알약 막대 위 조합 줄
|
||||
const host = el("div", { className: "m02-main__host" });
|
||||
const extra = el("div", { className: "m02-main__extra" }); // 표 밖 형제 자리 — 구조물 설계 컨테이너
|
||||
const root = el("div", {
|
||||
@@ -117,7 +117,6 @@ export function createMain(
|
||||
children: [
|
||||
el("div", { className: "m02-main__head", children: [title, back, slot, reload, save] }),
|
||||
notice,
|
||||
comboSlot,
|
||||
host,
|
||||
extra,
|
||||
],
|
||||
@@ -132,6 +131,7 @@ export function createMain(
|
||||
let sheetHandle: SpreadsheetHandle | null = null;
|
||||
let matPanel: MaterialPanel | null = null;
|
||||
let matState: MaterialState | null = null;
|
||||
let cpanel: ComboPanel | null = null; // 면적산출 · 재료산출 오른쪽 조합 패널(시스템 층)
|
||||
let seq = 0;
|
||||
let dirty = false;
|
||||
|
||||
@@ -176,11 +176,12 @@ export function createMain(
|
||||
sheetHandle = null;
|
||||
matPanel = null;
|
||||
matState = null;
|
||||
cpanel?.destroy();
|
||||
cpanel = null;
|
||||
panel?.destroy();
|
||||
panel = null;
|
||||
extra.replaceChildren();
|
||||
slot.replaceChildren();
|
||||
comboSlot.replaceChildren();
|
||||
};
|
||||
|
||||
/** 구조물집계표 아래 설계 컨테이너 — 고른 열의 도면 정보 · 면적산출 · 재료산출 카드 */
|
||||
@@ -244,23 +245,26 @@ export function createMain(
|
||||
editor = handle;
|
||||
sheetHandle = handle;
|
||||
if (at.layer !== "system") return;
|
||||
// 오른쪽 조합 패널 — 한 번 만들고 시트를 다시 붙여도 그대로(늘 시트 뒤)
|
||||
cpanel ??= buildComboPanel({
|
||||
kind,
|
||||
column: at.name,
|
||||
isAdmin,
|
||||
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 () => {
|
||||
if (mine !== seq) return;
|
||||
const kept = handle.getDoc();
|
||||
editor?.destroy();
|
||||
editor = null;
|
||||
host.replaceChildren();
|
||||
await mountSheet(kept, kind, at, readOnly);
|
||||
await remount(kind, at, readOnly, false);
|
||||
await cpanel?.refresh();
|
||||
},
|
||||
});
|
||||
if (mine === seq) comboSlot.replaceChildren(...(bar ? [bar] : []));
|
||||
if (mine === seq) cpanel?.setMine(bar);
|
||||
return;
|
||||
}
|
||||
if (matPanel || !matState) return;
|
||||
@@ -269,6 +273,7 @@ export function createMain(
|
||||
label: at.label ?? at.name,
|
||||
isAdmin,
|
||||
state: matState,
|
||||
onApplied: () => void cpanel?.refresh(),
|
||||
links: () => sheetHandle?.getDoc().시트.flatMap((s) => s.연결 ?? []) ?? [],
|
||||
// 옆 판 표에서 고침 — 알약 막대만 이 목록으로 다시 만듦(저장 안 한 시트 고침은 그대로)
|
||||
onChange: (items) => {
|
||||
@@ -294,12 +299,31 @@ export function createMain(
|
||||
dirty = !readOnly;
|
||||
},
|
||||
});
|
||||
host.append(matPanel.root);
|
||||
cpanel.setMine(matPanel.root);
|
||||
} catch {
|
||||
empty(L("M02_NoSpreadsheet"));
|
||||
}
|
||||
}
|
||||
|
||||
/** 시트만 다시 붙임(알약을 새로 받음) — 저장 안 한 시트 고침은 그대로 옮김 ·
|
||||
* `fresh` = 이 열 조합이 바뀜(재료는 자재 조합 · 담은 자재 표를 새로 받음) */
|
||||
async function remount(
|
||||
kind: "area" | "material",
|
||||
at: Selection,
|
||||
readOnly: boolean,
|
||||
fresh: boolean,
|
||||
): Promise<void> {
|
||||
const kept = sheetHandle?.getDoc();
|
||||
if (sel !== at || !kept) return;
|
||||
editor?.destroy();
|
||||
editor = null;
|
||||
if (fresh && kind === "material") {
|
||||
matPanel = null;
|
||||
matState = null;
|
||||
}
|
||||
await mountSheet(kept, kind, at, readOnly);
|
||||
}
|
||||
|
||||
async function mount(doc: unknown, at: Selection): Promise<void> {
|
||||
const readOnly = !canEdit(at.layer, isAdmin);
|
||||
host.replaceChildren();
|
||||
|
||||
Reference in New Issue
Block a user