/* ============================================================================= * M02_SO_Def_Parts.ts * 구조물 정의 「부품」 탭(PLAN 322-2) — 코드가 그리는 방법(부품 상자 `common_util_structure_parts.json`). * 갈래마다 부품 · 이름 · 읽는 칸 · 맞는 자리꼴 · 정본 · 쓰는 종류 · 켬/끔(정의 `부품` = 끈 것만). * 끈 부품을 쓰는 종류는 그 갈래가 없음(카드 이름은 종류 이름)으로 — 표 줄(`resolveCatalog`)이 따름. * ========================================================================== */ import { el } from "@ui/ui_template_elements"; import type { StructDef } from "./M02_SO_Def_Model"; import { OWNER_KO, PART_BOX, partsOff, PLACE_KO, setPartOn, shortName, usersOf, } from "./M02_SO_Def_Reflect"; import { checkBox, head } from "./M02_SO_Def_Ui"; import { to } from "./M02_SO_Text"; type Branch = keyof typeof PART_BOX; export function buildParts(opt: { def: StructDef; edit: boolean; changed: () => void; }): HTMLElement { const { def, edit, changed } = opt; const off = partsOff(def); /** 옵션 키 → 정의 이름(단위) — 그 부품을 쓰는 종류의 칸 이름 먼저 · 없으면 아무 종류 · 그래도 없으면 키. */ const labelOf = (key: string, users: readonly string[]): string => { const types = [ ...def.types.filter((t) => users.includes(t.type_id)), ...def.types.filter((t) => !users.includes(t.type_id)), ]; const o = types.flatMap((t) => t.options).find((x) => x.key === key); return o ? (o.unit ? `${o.label} (${o.unit})` : o.label) : key; }; const blocks = (Object.keys(PART_BOX) as Branch[]).flatMap((branch) => [ ...head(branch), el("table", { className: "m02-sod__table m02-sod__table--wrap", attrs: { "data-sod-parts": branch }, children: [ el("thead", { children: [ el("tr", { children: (["ColName", "PartRead", "PartFits", "PartUsers", "PartOn"] as const).map( (key) => el("th", { text: to(key) }), ), }), ], }), el("tbody", { children: Object.entries(PART_BOX[branch]).map(([id, part]) => { const key = `${branch}.${id}`; // 끈 부품을 쓰던 종류도 보이게 — 끈 동안은 표가 none 으로 풀므로 켠 꼴로 셈 const users = usersOf({ ...def, 부품: {} } as StructDef, branch, id); return el("tr", { attrs: { "data-sod-part": key }, className: off[key] === false ? "is-off" : "", children: [ // 영어 키는 툴팁만(322-2 다듬기) — 이름 = 짧은 이름 · 읽는 칸 = 정의 칸 이름 el("td", { text: shortName(part.이름), attrs: { title: `${id} · ${part.이름}` } }), el("td", { text: part["읽는 칸"] .map((k) => labelOf( k, users.map((row) => row.typeId), ), ) .join(" · ") || "—", }), el("td", { text: `${part.자리꼴.map((p) => PLACE_KO[p] ?? p).join(" · ")} / ${part.정본 .map((o) => OWNER_KO[o] ?? o) .join(" · ")}`, }), el("td", { text: users.map((row) => row.name).join(" · ") || "—" }), el("td", { children: [ checkBox( to("PartOn"), off[key] !== false, (on) => (setPartOn(def, key, on), changed()), { edit, attr: "data-sod-part-on" }, ), ], }), ], }); }), }), ], }), ]); return el("div", { className: "m02-sod__tablewrap", children: [el("p", { className: "m02-side__empty", text: to("PartsNote") }), ...blocks], }); }