feat(b09): 원가계산 화면 새 틀 — 설계내역서·일위대가·단가산출근거 탭(실무 서식 · 내역 → 호표 → 산근 들어가기)
- 틀 B09_Estimation_UI_Shell: 탭 줄과 등록만 · 탭마다 파일 하나(계약 _Shell_Types) - 설계내역서: 실무 열(합계/노무/재료/경비 단가·금액) · 머리글 접기·레벨 고르개 · 줄 누르면 제 N 호표 · 단산 N 단추 · 미확정 빨간 테두리 - 일위대가·단가산출근거: 목록표(내역에 처음 쓰인 차례) + 본표 · 줄 누르면 하위 호표·산근·중기로 · 자취 눌러 되돌아감 · Q 식 글자 그대로 - 옛 탭 여섯(원가계산서·중기·관급사급·기초자료·설계서 구성·산출기초)은 옛 코드 그대로 이어 붙임 — 새 탭 파일이 서면 등록 한 줄씩 바꿈 - 본표 합계 줄 = 호표 성분 소계 원 미만 절사 값 · 비율 줄 금액도 0.1원 절사 표시 - 사전 ui_template_locale_b3 새 벌(b2 700줄 넘음) - 검증: ORCA 검증 프로젝트 — 본체 122,848,989 · 지장목제거 865·15,460,837 · 제 9 호표 합계 1,708 = 산근 8호표 합계 1,708 · 옛 탭 여섯 다 뜸 · 접기 53→51·레벨1 11줄 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
/* =============================================================================
|
||||
* 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 { legacyTab } from "./B09_Estimation_UI_Tab_Legacy";
|
||||
import { billTab } from "./B09_Estimation_UI_Tab_Bill";
|
||||
import { unitPriceTab } from "./B09_Estimation_UI_Tab_UnitPrice";
|
||||
import { priceBasisTab } from "./B09_Estimation_UI_Tab_PriceBasis";
|
||||
|
||||
/** 탭 등록 — 한 줄에 탭 하나. 옛 탭(`legacyTab`)은 새 탭 파일이 서면 그 줄만 바꿈. */
|
||||
const TABS: B09Tab[] = [
|
||||
legacyTab("cost_sheet", "B09_Estimation_Tab_CostSheet"), // → 랩탑_메인 원가계산서 탭
|
||||
billTab,
|
||||
unitPriceTab,
|
||||
priceBasisTab,
|
||||
legacyTab("machine", "B09_Estimation_Tab_Machine"),
|
||||
legacyTab("supply", "B09_Estimation_Tab_Supply"),
|
||||
legacyTab("base_data", "B09_Estimation_Tab_BaseData"),
|
||||
legacyTab("design_doc", "B09_Estimation_Tab_DesignDoc"),
|
||||
legacyTab("basis_sheet", "B09_Estimation_Tab_BasisSheet"),
|
||||
];
|
||||
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user