/* ============================================================================= * b_page_scaffold.ts * B 그룹 페이지 공통 스캐폴드 — "헤더 + 준비 중 안내" 및 워크플로우 셸 래퍼 * * B03~B06 등 본문 미구현 페이지에서 헤더/푸터(공통 셸)를 제외한 콘텐츠 영역을 * 일관된 형태로 채우기 위한 헬퍼. 실제 본문은 0_old 참고하여 추후 구체화. * * 제약 준수 (frontend.md): * - 문구는 호출측에서 locale 참조 후 문자열로 전달 (§3). * - 공통 워크플로우 셸(createWorkflowShell) 재사용 (§2 3단 레이아웃). * - 색상/간격은 theme.css 변수만 사용 (§1). * ========================================================================== */ import { ui_locales, currentLanguageIndex } from "@ui/ui_template_locale"; import { createWorkflowShell } from "@ui/ui_template_elements"; /** locale 헬퍼 */ function L(key: keyof typeof ui_locales): string { return ui_locales[key][currentLanguageIndex]; } const SCAFFOLD_STYLE_ID = "b-page-scaffold-style"; /** "준비 중" 안내 블록 생성 (B_Content_Pending 문구 표시) */ function buildPendingBlock(): HTMLDivElement { const block = document.createElement("div"); block.className = "b-pending"; const icon = document.createElement("div"); icon.className = "b-pending__icon"; icon.textContent = "🚧"; const msg = document.createElement("p"); msg.className = "b-pending__msg"; msg.textContent = L("B_Content_Pending"); block.append(icon, msg); return block; } /* ----------------------------------------------------------------------------- * 1. 단순 헤더 + 준비 중 안내 (비(非)워크플로우 페이지: B03 등) * -------------------------------------------------------------------------- */ export interface PendingContentOptions { /** 페이지 루트 클래스 (예: "b03-file") */ pageClass: string; title: string; subtitle: string; } export function renderPendingContent(root: HTMLElement, opts: PendingContentOptions): void { injectScaffoldStyles(); const page = document.createElement("div"); page.className = `b-scaffold ${opts.pageClass}`; const header = document.createElement("div"); header.className = "b-scaffold__header"; const title = document.createElement("h1"); title.className = "b-scaffold__title"; title.textContent = opts.title; const subtitle = document.createElement("p"); subtitle.className = "b-scaffold__subtitle"; subtitle.textContent = opts.subtitle; header.append(title, subtitle); page.append(header, buildPendingBlock()); root.append(page); } /* ----------------------------------------------------------------------------- * 2. 워크플로우 셸(3단 레이아웃) + 준비 중 안내 (B04~B06 등) * 좌측 패널·우측 뷰어 모두 준비 중 상태로 채운다. * -------------------------------------------------------------------------- */ export interface PendingWorkflowOptions { /** 상단 페이지 타이틀 (i18n 결과) */ title: string; /** 진행 단계 라벨 배열 (i18n 결과) */ steps: string[]; /** 현재 활성 단계 인덱스 */ activeStep: number; } export function renderPendingWorkflow(root: HTMLElement, opts: PendingWorkflowOptions): void { injectScaffoldStyles(); const shell = createWorkflowShell({ title: opts.title, steps: opts.steps, activeStep: opts.activeStep, }); shell.root.classList.add("b-scaffold-wf"); // 좌측/우측 모두 준비 중 안내로 채움 (본문은 추후 구체화) shell.leftPanel.append(buildPendingBlock()); shell.rightArea.append(buildPendingBlock()); root.append(shell.root); } /** 워크플로우 스텝 라벨 7종 (locale 결과) — B03~B09 공용. * 파일 입력(B03)부터 견적/문서(B09)까지 대시보드 워크플로우와 동일한 순서. * 기존 WF_Step_* / B03_File_Title 키를 재사용 (중복 등록 방지, frontend.md §3). */ export function workflowSteps(): string[] { return [ L("B03_File_Title"), L("WF_Step_Surface"), L("WF_Step_Route"), L("WF_Step_ProfileCross"), L("WF_Step_DesignDetail"), L("WF_Step_Quantity"), L("WF_Step_Estimation"), ]; } /* ----------------------------------------------------------------------------- * 스타일 주입 (theme.css 변수만 사용) * -------------------------------------------------------------------------- */ const SCAFFOLD_CSS = ` .b-scaffold { max-width: 960px; margin: 0 auto; padding: var(--spacing-40) var(--spacing-24); display: flex; flex-direction: column; gap: var(--spacing-24); } .b-scaffold__header { display: flex; flex-direction: column; gap: var(--spacing-8); } .b-scaffold__title { font-family: var(--font-display); font-size: var(--text-heading); color: var(--color-plum-velvet); } .b-scaffold__subtitle { font-size: var(--text-body-sm); color: var(--color-text-muted); } .b-scaffold-wf { height: calc(100vh - 64px - 56px); } .b-pending { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--spacing-16); min-height: 240px; padding: var(--spacing-40); border: 1px dashed var(--color-border); border-radius: var(--radius-cards); background-color: var(--color-surface); color: var(--color-text-muted); } .b-pending__icon { font-size: 40px; line-height: 1; } .b-pending__msg { font-size: var(--text-body-sm); text-align: center; } `; function injectScaffoldStyles(): void { if (document.getElementById(SCAFFOLD_STYLE_ID)) return; const style = document.createElement("style"); style.id = SCAFFOLD_STYLE_ID; style.textContent = SCAFFOLD_CSS; document.head.append(style); }