/* ============================================================================= * B09_Estimation_UI_Tab_DesignDoc.ts * B09 설계서 구성 탭 — 법이 정한 목차와 우리가 내는 것을 맞대 봄(별표2 (5)(가)) * * - 옛 `B09_Estimation_UI_BaseData.ts` 의 설계서 구성표를 그대로 옮김(PLAN 12장 옛 탭 옮기기). * - ⚠ 「없음」과 「우리 몫 아님」을 갈라 보임 — 갈라야 다음에 할 일이 달라짐. * ========================================================================== */ import { API_BASE_URL } from "@config/config_frontend"; import type { B09Tab } from "./B09_Estimation_UI_Shell_Types"; import { L, hint } from "./B09_Estimation_UI_Sheet"; import { head, infoTable, note } from "./B09_Estimation_UI_Table"; interface DesignDocDto { law: string; summary: string; items: Array<{ order: number; name: string; status: string; owner: string; where: string; note: string; }>; notes: string[]; } let cached: DesignDocDto | null = null; function draw(body: HTMLElement, data: DesignDocDto): void { body.append(head(`설계서 구성 (법이 정한 ${data.items.length})`)); body.append(note(data.summary)); body.append(note(data.law)); body.append( infoTable( ["차례", "이 름", "상 태", "누가 만드나", "어디서 나오나", "비 고"], data.items.map((row) => [ String(row.order), row.name, row.status, row.owner, row.where || "—", row.note, ]), [0, 1, 2, 3, 4, 5], ), ); for (const line of data.notes) body.append(note(line)); } export const designDocTab: B09Tab = { key: "design_doc", label: () => L("B09_Estimation_Tab_DesignDoc"), render(ctx) { if (!ctx.projectId) { ctx.body.append(hint(L("B09_Sheet_NoProject"))); return; } // 프로젝트 값이 아니라 **우리가 무엇을 내는가**의 표 — 한 번 받으면 그대로 씀. if (cached) { draw(ctx.body, cached); return; } ctx.body.append(hint(L("B09_Sheet_Loading"))); fetch( `${API_BASE_URL}/projects/${encodeURIComponent(ctx.projectId)}/estimation/design-doc-index`, { credentials: "include" }, ) .then((response) => { if (!response.ok) throw new Error(String(response.status)); return response.json() as Promise; }) .then((data) => { cached = data; ctx.body.replaceChildren(); draw(ctx.body, data); }) .catch((error: Error) => { ctx.body.replaceChildren(hint(`${L("B09_Sheet_LoadFailed")} ${error.message}`, true)); }); }, };