Files
Aislo/ui_template/ui_template_item_picker_labor.ts
T
eomsangdonandClaude Opus 5.5 c7a8ed7cf9 fix(M02): 이름 맞춤 — 한 줄 표 머리 「항목 · 수량산출 · 단위 · …」(사용자 글) · 남은 화면 글 「담은 로직」 → 「단가산출 로직」(40-1 끝)
- 한 줄 표(compact) 머리만 · 상세 표 머리는 그대로
- 글 줄만: 넣을 값 빈 글 · 전체 항목 · 복사 생성 「단가산출 로직 수」 · 면적산출 알약 없음 · 실무문서 locale · B05 고르기 모달 일위대가 카드 · 면적 알약 없음 · 일위대가 문서 검사 글(「단가산출 로직 n째」)
- 시험 기대값: test_m02_item_list 머리 글

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MgChuAcyBqUkhHMTXomQC7
2026-10-04 22:44:14 +09:00

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")] : []),
);
},
};
}