Files
Aislo/M02_MasterTemplete/M02_MasterTemplete_Hopyo_ToItem.ts
T
eomsangdonandClaude Opus 5.5 f9ffd5fc77 feat(M02 사전조합 → 구조물 조합 한 단계): 실무자료 확인 창 [구조물 조합으로] · 규격 묶음 제안 (PLAN 704-4 뒷부분)
- 확인 창 몸 그대로(체크 = 품셈 줄 · 나머지 = 고정 줄)로 구조물 조합 항목(SU)을 바로 만듦 — 사전조합 SC 문서 안 씀 · 옛 [사전조합 생성] 길 그대로
- 규격 묶음 제안 — 같은 이름 · 단위 · 줄 구성 · 규격만 다른 호표 → 한 항목의 규격 열(H=1.5 → 이름 H · 열 1.5) · 열마다 같은 몸으로 만든 줄 수량 · 기본 열 = 연 호표
- 서버 M02_Hopyo_Item · /hopyo/{키}/{번}/siblings · /hopyo-item(이 층 쓰기 · 「실무자료」 폴더) · Builder.build(save=False)
- 규격 열 줄 id 가 고정 줄을 못 알아보던 흠 — line_key = fixed_id(TS lineId 와 같음)
- 만든 뒤 나무 · 옆 목록 다시
- 시험: 울진 대흥 돌기슭막이 H 1.5 / 2.0 / 2.5 = 한 항목 열 셋 · 열마다 = 그 호표 엑셀 합계 · 줄 구성 다른 호표 400 · 남의 층 403 · 사전조합 0 · 마스터 그대로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 16:14:59 +09:00

113 lines
4.1 KiB
TypeScript

/* =============================================================================
* M02_MasterTemplete_Hopyo_ToItem.ts
* [구조물 조합으로](PLAN 704-4 뒷부분) — 실무자료 확인 창 몸 그대로 구조물 조합 항목(SU)을 바로 만듦(사전조합 안 거침).
* 창 = 항목 이름(기본 = 호표 이름 · 규격) · 규격 묶음 제안(같은 이름 · 줄 구성 · 규격만 다른 호표 → 한 항목의 규격 열 ·
* 기본 켬 · 끄면 이 호표 하나) · [만들기] → 서버 `/hopyo-item`(이 층 쓰기 · 「실무자료」 폴더) → 나무 다시
* 숫자는 서버가 파일에서 — 화면은 체크 · 고름만
* ========================================================================== */
import {
createButton,
el,
hideLoadingOverlay,
showLoadingOverlay,
showToast,
} from "@ui/ui_template_elements";
import { createCheckbox } from "@ui/ui_template_checkbox";
import { createInputField } from "@ui/ui_template_input";
import { openModal } from "@ui/ui_template_modal";
import { createText } from "@ui/ui_template_text";
import {
buildHopyoItem,
hopyoSiblings,
type BuildLine,
type BuildTarget,
type HopyoOne,
type HopyoScope,
} from "./M02_MasterTemplete_Hopyo_Api";
/** 항목을 만들었음(document 알림) — 구조물 조합 나무 · 옆 목록 다시 */
export const ITEM_BUILT = "m02-hopyo-item-built";
export interface ToItemOptions {
scope: HopyoScope;
target: HopyoScope;
key: string;
no: number;
hopyo: HopyoOne["호표"];
lines: BuildLine[];
whole: { 대상: BuildTarget[] } | null;
}
export async function toItem(o: ToItemOptions): Promise<void> {
let sib: Awaited<ReturnType<typeof hopyoSiblings>>;
try {
sib = await hopyoSiblings(o.scope, o.key, o.no);
} catch (error) {
showToast(
`묶음 제안 실패 — ${error instanceof Error ? error.message : String(error)}`,
"error",
);
return;
}
const h = o.hopyo;
const one = [h.이름, h.규격].filter(Boolean).join(" ");
const bundle = sib.묶음.length > 1;
const name = createInputField({ label: "구조물 조합 이름", value: bundle ? h.이름 : one });
const pack = bundle
? createCheckbox(
`규격 열로 묶음 — ${sib.이름}: ${sib.묶음.map((r) => `${r.열}(제${r.번}호표)`).join(" · ")}`,
{
checked: true,
onChange: (on) => (name.input.value = on ? h.이름 : one),
},
)
: null;
openModal({
title: `구조물 조합으로 — 제${o.no}호표`,
closeLabel: "취소",
width: "40rem",
mount: (body, close, actions) => {
const go = createButton({
label: "만들기",
onClick: async () => {
const label = name.input.value.trim();
if (!label) return name.setError("이름이 빔");
const from = { 층: o.scope.layer, 주인: o.scope.owner, 키: o.key, 번: o.no };
const with_ = pack?.input.checked
? sib.묶음.map((r) => r.번).filter((n) => n !== o.no)
: [];
showLoadingOverlay();
try {
const got = await buildHopyoItem(o.target, from, o.lines, o.whole, with_, label);
close();
document.dispatchEvent(new Event(ITEM_BUILT));
showToast(
`구조물 조합 「${got.이름}」 만듦 — 「실무자료」 폴더 · 줄 ${got.줄수}` +
(got.열수 > 1 ? ` · 규격 열 ${got.열수}` : ""),
"success",
6000,
);
} catch (error) {
showToast(
`못 만듦 — ${error instanceof Error ? error.message : String(error)}`,
"error",
);
} finally {
hideLoadingOverlay();
}
},
});
actions.append(go);
body.append(
createText(
"체크한 줄 = 품셈 줄 · 나머지 = 고정 줄(엑셀 숫자 그대로) — 사전조합을 거치지 않고 구조물 조합 항목을 바로 만듦",
"muted",
),
name.root,
...(pack ? [el("div", { children: [pack.root] })] : []),
);
},
});
}