- 카드 차례 도면 · 일위대가 · 면적산출 — 새 ui_template_item_picker_labor.ts(담은 로직 수 · 자재 수 · 기준 합 · 반영 합 · 빠진 입력 · 멈춘 로직) - 자료 laborOf: 복사본이면 복사본 일위대가 + calc · 아니면 원본 층 labor calc(저장 안 함) · 일위대가 없으면 「일위대가 없음」 - 넣을 값 카드 · 편집 = M02_Labor_Values 바로 · 목록 = 담은 로직 입력 전부(logic-lib/inputs) · 값은 복사본 입력값 - ProjectCalc 에 기준합 · 반영합 계 · 시험 test_item_picker_detail 손봄 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UoSr2sqvYtBf1dtQdus88s
61 lines
2.8 KiB
TypeScript
61 lines
2.8 KiB
TypeScript
/* =============================================================================
|
|
* 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")] : []),
|
|
);
|
|
},
|
|
};
|
|
}
|