Files
Aislo/B09_Estimation/B09_Estimation_UI_Shell.ts

107 lines
4.3 KiB
TypeScript

/* =============================================================================
* B09_Estimation_UI_Shell.ts
* 로그인 후 09: 6차 워크플로우 (원가계산) — 화면 **틀** (PLAN 12장 · 2026-09-14 브레인 판정)
*
* - 틀은 탭 줄과 등록만. 탭마다 파일 하나(`B09_Estimation_UI_Tab_<이름>.ts`) — 계약은 `_Shell_Types`.
* - ⚠ 등록 권한 = 랩탑_서브. 다른 창은 탭 파일을 만들고 이름을 알려 등록을 부탁함.
* - 탭을 고를 때마다 본문·좌측 칸을 비우고 `render(ctx, arg)`. `ctx.open(key, arg)` = 다른 탭으로 들어가기.
* ========================================================================== */
import { createWorkflowLayout } from "@ui/ui_template_workflow_layout";
import { CURRENT_PROJECT_ID_KEY } from "@config/config_frontend";
import { workflowSteps } from "../A00_Common/b_page_scaffold";
import { goToWorkflowStage, WORKFLOW_STEP_ROUTES } from "../A00_Common/b_workflow_nav";
import type { B09Tab, B09TabContext } from "./B09_Estimation_UI_Shell_Types";
import { L, el, injectSheetStyles } from "./B09_Estimation_UI_Sheet";
import { costSheetTab } from "./B09_Estimation_UI_Tab_CostSheet";
import { rateTableTab } from "./B09_Estimation_UI_Tab_RateTable";
import { billTab } from "./B09_Estimation_UI_Tab_Bill";
import { unitPriceTab } from "./B09_Estimation_UI_Tab_UnitPrice";
import { priceBasisTab } from "./B09_Estimation_UI_Tab_PriceBasis";
import { machineTab } from "./B09_Estimation_UI_Tab_Machine";
import { priceCompareTab } from "./B09_Estimation_UI_Tab_PriceCompare";
import { materialPricesTab } from "./B09_Estimation_UI_Tab_MaterialPrices";
import { summaryTab } from "./B09_Estimation_UI_Tab_Summary";
import { listsTab } from "./B09_Estimation_UI_Tab_Lists";
import { designDocTab } from "./B09_Estimation_UI_Tab_DesignDoc";
import { basisSheetTab } from "./B09_Estimation_UI_Tab_BasisSheet";
import { supplyTab } from "./B09_Estimation_UI_Tab_Supply";
import { baseDataTab } from "./B09_Estimation_UI_Tab_BaseData";
import { contractTab } from "./B09_Estimation_UI_Tab_Contract";
import { executionTab } from "./B09_Estimation_UI_Tab_Execution";
import { progressTab } from "./B09_Estimation_UI_Tab_Progress";
import { completionTab } from "./B09_Estimation_UI_Tab_Completion";
/** 탭 등록 — 한 줄에 탭 하나. */
const TABS: B09Tab[] = [
costSheetTab, // 랩탑_메인
rateTableTab, // 랩탑_메인
billTab,
unitPriceTab,
priceBasisTab,
machineTab,
priceCompareTab,
materialPricesTab, // 랩탑_메인 — 자재단가대비표 옆(자재 수동 단가)
summaryTab,
listsTab,
supplyTab,
baseDataTab,
designDocTab,
basisSheetTab,
contractTab, // 랩탑_메인 — 설계 뒤 계약 단계라 맨 끝
executionTab, // 랩탑_메인 — 계약 뒤 실행 단계
progressTab, // 랩탑_메인 — 실행 뒤 기성 단계
completionTab, // 랩탑_메인 — 기성 뒤 준공 단계
];
export async function renderB09Estimation(root: HTMLElement): Promise<void> {
injectSheetStyles();
const projectId = localStorage.getItem(CURRENT_PROJECT_ID_KEY);
const page = el("div", "b09s-page");
const bar = el("div", "b09s-tabs");
const body = el("div", "b09s-body");
const panel = el("div");
page.append(bar, body);
let active = TABS[0].key;
const open = (key: string, arg?: string): void => {
const tab = TABS.find((item) => item.key === key);
if (!tab) return;
active = key;
drawBar();
body.replaceChildren();
panel.replaceChildren();
const ctx: B09TabContext = { projectId, body, panel, root, open };
tab.render(ctx, arg);
};
const drawBar = (): void => {
bar.replaceChildren(
...TABS.map((tab) => {
const button = el(
"button",
`b09s-tab${tab.key === active ? " is-active" : ""}`,
tab.label(),
);
button.type = "button";
button.dataset.tab = tab.key;
button.addEventListener("click", () => open(tab.key));
return button;
}),
);
};
const layout = createWorkflowLayout({
title: L("B09_Estimation_Title"),
steps: workflowSteps(),
activeStep: 6,
leftPanel: panel,
mainContent: page,
routes: WORKFLOW_STEP_ROUTES,
onStepClick: (stepIndex) => {
if (projectId) goToWorkflowStage(projectId, WORKFLOW_STEP_ROUTES[stepIndex]);
},
});
root.append(layout.root);
open(active);
}