/* ============================================================================= * B09_Estimation_UI_Tab_Lists.ts * B09 목록표 탭 — 일곱 목록표를 한 자리에 (실무 `…목록표` 시트 · PLAN 12장) * * 일위대가 · 단가산출근거 · 중기 호표 · 명칭 · 규격 · 단위 · 합계 · 노무비 · 재료비 · 경비 · 비고 * 재료비 · 노무비 · 경비 · 일식견적 호표 · 명칭 · 규격 · 단위 · 단가 · 비고 * * - ⚠ 목록표는 **색인**일 뿐 — 계산 쌍이 없음. 서버가 실은 번호·코드·단가를 그대로 늘어놓음. * 번호는 내역에 처음 쓰인 차례(서버가 낼 때마다 매김). * - 일위대가·산근·중기 줄을 누르면 그 호표로 들어감. * ========================================================================== */ import type { B09Tab, B09TabContext } from "./B09_Estimation_UI_Shell_Types"; import { L, el, hint, numberCell, plainTable, segmented, won } from "./B09_Estimation_UI_Sheet"; import { loadBill, type BillDto, type ResourceGroup } from "./B09_Estimation_UI_Store"; type ListKey = "unit_price" | "price_basis" | ResourceGroup; let active: ListKey = "unit_price"; const LISTS: Array<[ListKey, Parameters[0]]> = [ ["unit_price", "B09_Sheet_UnitPriceList"], ["price_basis", "B09_Sheet_BasisList"], ["machine", "B09_Sheet_MachineList"], ["material", "B09_Sheet_List_Material"], ["labor", "B09_Sheet_List_Labor"], ["expense", "B09_Sheet_List_Expense"], ["lumpsum", "B09_Sheet_List_Lumpsum"], ]; interface ListRow { label: string; name: string; spec: string; unit: string; money: string[]; note: string; open?: [string, string]; } function rowsOf(bill: BillDto, key: ListKey): ListRow[] { if (key === "unit_price") { return bill.unit_price_sheet.entries.map((entry) => ({ label: entry.label, name: entry.name, spec: entry.spec, unit: entry.unit, money: [entry.total_krw ?? "", entry.labor_krw, entry.material_krw, entry.expense_krw], note: entry.unconfirmed ? `${L("B09_Sheet_Unconfirmed")} ${entry.unconfirmed}` : "", open: ["unit_price", entry.code], })); } if (key === "price_basis") { return bill.price_basis.entries.map((entry) => ({ label: `${L("B09_Sheet_Basis_Long")} ${entry.number}${L("B09_Sheet_Basis_Suffix")}`, name: entry.name, spec: entry.spec, unit: entry.unit, money: [entry.unit_price_krw ?? "", entry.labor_krw, entry.material_krw, entry.expense_krw], note: "", open: ["price_basis", entry.code], })); } return bill.lists[key].map((row) => ({ label: String(row.number), name: row.name, spec: row.spec, unit: row.unit, money: key === "machine" ? [ row.unit_price_krw ?? "", row.unit_labor_krw ?? "", row.unit_material_krw ?? "", row.unit_expense_krw ?? "", ] : [row.unit_price_krw ?? ""], note: row.note, open: key === "machine" ? ["machine", row.code] : undefined, })); } function draw(ctx: B09TabContext, bill: BillDto): void { ctx.body.append( segmented( LISTS.map(([key, label]) => [key, L(label)]), active, (key) => { active = key as ListKey; ctx.body.replaceChildren(); draw(ctx, bill); }, ), ); const fourWay = active === "unit_price" || active === "price_basis" || active === "machine"; const money = fourWay ? [ L("B09_Sheet_Col_Total"), L("B09_Sheet_Col_Labor"), L("B09_Sheet_Col_Material"), L("B09_Sheet_Col_Expense"), ] : [L("B09_Sheet_Col_UnitPrice")]; const { wrap, tbody } = plainTable([ L("B09_Sheet_Col_Sheet"), L("B09_Sheet_Col_Name"), L("B09_Sheet_Col_Spec"), L("B09_Sheet_Col_Unit"), ...money, L("B09_Sheet_Col_Note"), ]); const rows = rowsOf(bill, active); for (const row of rows) { const tr = el("tr"); tr.append( el("td", "", row.label), el("td", "", row.name), el("td", "", row.spec), el("td", "", row.unit), ); for (const value of row.money) tr.append(numberCell(won(value))); tr.append(el("td", "b09s-note", row.note)); if (row.open) { const [tab, code] = row.open; tr.classList.add("is-clickable"); tr.title = L("B09_Sheet_Drill"); tr.addEventListener("click", () => ctx.open(tab, code)); } tbody.append(tr); } ctx.body.append(wrap); if (rows.length === 0) ctx.body.append(hint(L("B09_Sheet_EmptyGroup"))); } export const listsTab: B09Tab = { key: "lists", label: () => L("B09_Sheet_Tab_Lists"), render(ctx) { if (!ctx.projectId) { ctx.body.append(hint(L("B09_Sheet_NoProject"))); return; } ctx.body.append(hint(L("B09_Sheet_Loading"))); loadBill(ctx.projectId) .then((bill) => { ctx.body.replaceChildren(); draw(ctx, bill); }) .catch((error: Error) => { ctx.body.replaceChildren(hint(`${L("B09_Sheet_LoadFailed")} ${error.message}`, true)); }); }, };