/* ============================================================================= * B08_Quantity_UI_Drawing.ts * 2탭 구조물도(PLAN 61-2) — 집계표 열(저장된 구조물 조합)마다 보조 탭 · 한 장 = 그 조합의 * M02 도면(도각 포함 · 보기 전용 CAD) + 면적산출 — M02 항목 카드(`M02_MasterTemplete_ItemCards`) 그대로. * * 조합 목록 · 차례 = 집계표와 같음(`B08_Quantity_Summary_Data`) * 읽기만 — 조합 원본 층(`readTemplate`)을 읽고 카드는 [저장] · [수정] 없음 · B05/B06 자료도 읽기만 * 카드 · CAD · 스프레드시트는 이 탭을 열 때만 `import()` * ========================================================================== */ import "./B08_Quantity_UI_Drawing.css"; import { ui_locales, currentLanguageIndex } from "@ui/ui_template_locale"; import { createButton } from "@ui/ui_template_elements"; import { loadRows as loadPickerRows } from "@ui/ui_template_item_picker"; import { layerOf, pathOf, rowId, type PickerRow } from "@ui/ui_template_item_picker_data"; import { readTemplate } from "../M02_MasterTemplete/M02_MasterTemplete_Api_Fetch"; import type { ItemSource } from "../M02_MasterTemplete/M02_MasterTemplete_ItemSource"; import { fetchStructures } from "../B05_Profile/B05_Profile_Api_Structures"; import { fetchDetailPipePoints } from "../B04_PreProcess/B04_PreProcess_Api_Fetch"; import { summaryTooltip } from "../common_util/common_util_summary_item"; import { comboId, summaryColumns, type ComboColumn, type ComboLabel, } from "./B08_Quantity_Summary_Data"; function L(key: keyof typeof ui_locales): string { return ui_locales[key][currentLanguageIndex]; } function note(text: string): HTMLElement { const node = document.createElement("p"); node.className = "ui-general-block__empty"; node.textContent = text; return node; } /** 집계표와 같은 열 + 열마다 M02 줄(없으면 M02 에 없는 조합). */ async function loadColumns( projectId: string, ): Promise<{ columns: ComboColumn[]; rows: Map }> { const [structures, pickerRows, pipes] = await Promise.all([ fetchStructures(projectId), loadPickerRows(), // 배수 분석 전이면 관이 없음 — 구조물만으로 fetchDetailPipePoints(projectId).then( (response) => response.pipe_points, () => [], ), ]); const rows = new Map(pickerRows.map((row) => [rowId(row), row])); const describe = (item: Parameters[0]): ComboLabel | null => { const row = rows.get(comboId(item)); if (!row) return null; const [group = "", ...rest] = pathOf(row); return { group, name: rest.join(" ") || group || row.key }; }; return { columns: summaryColumns([...structures.structures, ...pipes], describe), rows }; } /** 탭 몸통을 그림 — 불러오는 동안 한 줄 · 실패하면 까닭 한 줄. */ export async function renderStructureSheets(host: HTMLElement, projectId: string): Promise { host.replaceChildren(note(L("B08_Quantity_Drawing_Loading"))); try { const [{ columns, rows }, { createItemCards }] = await Promise.all([ loadColumns(projectId), import("../M02_MasterTemplete/M02_MasterTemplete_ItemCards"), ]); if (!host.isConnected) return; // 그새 다른 탭으로 옮김 if (!columns.length) return void host.replaceChildren(note(L("B08_Quantity_Summary_NoCombo"))); let row: PickerRow | null = null; const source = (): ItemSource => { const layer = row ? layerOf(row) : "system"; return { layer, projectId: null, read: (part, column) => readTemplate(layer, part, column, null), }; }; const cards = createItemCards({ source, editable: () => false, onEdit: () => undefined, warnOnFail: () => false, // 못 읽으면 카드에 「없음」 }); const tabs = document.createElement("div"); tabs.className = "b08-quantity__tabs b08-drawing__tabs"; tabs.setAttribute("role", "tablist"); const notice = document.createElement("div"); const sheet = document.createElement("div"); sheet.className = "b08-drawing__cards"; sheet.append(cards.root); const select = (picked: ComboColumn): void => { tabs.replaceChildren( ...columns.map((column) => { const button = createButton({ label: column.group ? `${column.group} ${column.name}` : column.name, variant: column === picked ? "filled" : "ghost", size: "sm", onClick: () => column !== picked && select(column), }); button.setAttribute("role", "tab"); button.setAttribute("aria-selected", String(column === picked)); button.dataset.b08Combo = column.id; button.title = summaryTooltip(column.item); if (column.missing) button.classList.add("is-missing"); return button; }), ); row = rows.get(picked.id) ?? null; if (!row?.열) { notice.replaceChildren(note(L("B08_Quantity_Drawing_Missing"))); return void cards.load(null); } notice.replaceChildren(...(row.도번 ? [] : [note(L("B08_Quantity_Drawing_NoDrawing"))])); void cards.load({ id: row.열, label: picked.name }); }; host.replaceChildren(tabs, notice, sheet); select(columns[0]); } catch (error) { const reason = error instanceof Error ? error.message : String(error); host.replaceChildren(note(`${L("B08_Quantity_Drawing_Failed")} — ${reason}`)); } }