/* ============================================================================= * ui_template_item_picker_labor.ts * 항목 고르기 모달 「일위대가」 카드(계획서 39-1c) — 담은 로직 수 · 자재 수 · 기준 합 · 반영 합 글. * 보기만 · 고치기는 원본 층 일위대가 상세. 일위대가 보기 부품(39-3 C)이 오면 몸을 그것으로 바꿈. * 자료 = `ui_template_item_picker_project.laborOf`(복사본이면 복사본 계산 · 아니면 원본 층 계산). * 상세(`ui_template_item_picker_detail.ts`)가 카드를 받을 때 함께 `import()`. * ========================================================================== */ import { el } from "./ui_template_elements"; import { cardNote, cardShell } from "../M02_MasterTemplete/M02_MasterTemplete_CardShell"; import type { LaborSummary } from "./ui_template_item_picker_project"; const TEXT = { title: "일위대가", none: "일위대가 없음", failed: "일위대가를 못 읽음 — {value}", logics: "단가산출 로직 {value}개", materials: "자재 {value}개", base: "기준 합 {value}원", reflected: "반영 합 {value}원", gaps: "빠진 입력 {value}개", stuck: "멈춘 로직 {value}개", }; const fill = (text: string, value: string | number): string => text.replace("{value}", String(value)); const won = (value: number | null): string => value === null ? "—" : Math.round(value).toLocaleString(); export interface LaborCardHandle { root: HTMLElement; loading: () => () => void; /** `null` = 일위대가 없음 · `note` 가 있으면 못 읽은 까닭 */ set: (summary: LaborSummary | null, note?: string, retry?: () => void) => void; } export function createLaborCard(): LaborCardHandle { const number = el("span", { className: "m02-struct__no" }); const body = el("div", { className: "m02-struct__sheet ui-item-picker__labor" }); const shell = cardShell({ title: TEXT.title, sub: [number], body }); const line = (text: string, className = ""): HTMLElement => el("p", { className: `ui-item-picker__labor-line ${className}`.trim(), text }); return { root: shell.root, loading: () => shell.loading(), set: (summary, note, retry) => { number.textContent = summary?.번호 ?? ""; if (note && retry) return shell.fail(fill(TEXT.failed, note), retry); if (!summary) return void body.replaceChildren(cardNote(TEXT.none)); body.replaceChildren( line(`${fill(TEXT.logics, summary.로직.length)} · ${fill(TEXT.materials, summary.자재)}`), line(fill(TEXT.base, won(summary.base))), line(fill(TEXT.reflected, won(summary.reflected)), "is-strong"), ...(summary.gaps ? [line(fill(TEXT.gaps, summary.gaps), "is-warn")] : []), ...(summary.stuck ? [line(fill(TEXT.stuck, summary.stuck), "is-warn")] : []), ); }, }; }