/* ============================================================================= * M02_MasterTemplete_Hopyo_WizardSk.ts * 일위대가 불러오기 마법사 ② 단가산출 단계(PLAN 729-3 · 요구서 내역19 1장 7 · 2장 3) — * · [단가산출 만들기] = 서버 `sangeun`(산근 블록마다 매칭 → 같으면 기초 · 다르면 SK = 기초 + 엑셀 차이 · 맞는 기초 없음 = 고름 대기) * · 만든 줄 표 = 블록 · 이름 · 키 · 갈래(기초 · SK 차이 있음) · 이미 만든 블록은 「그대로」 수만 * · 고름 대기 표 = 블록마다 후보(판정 · 글) 고르기 칸 → [고른 기초로 만들기](바탕 = 고른 기초 · 엑셀 품 견줘 SK) * · 별칭 제안 = 이 층 별칭 장부에 남음 · 모두에게 쓰이려면 시스템 관리자가 M01 › 별칭 장부에서 승인(링크 · 716 길 그대로) * 계산 · 판정은 서버 — 화면은 보이기 · 고름만 · 자동 저장 없음(누를 때만 서버). * ========================================================================== */ import { ROUTES } from "@config/config_frontend"; import { createBadge } from "@ui/ui_template_badge"; import { createButton, createSelectField, el, showToast } from "@ui/ui_template_elements"; import { t as L } from "@ui/ui_template_locale"; import { createTable } from "@ui/ui_template_table"; import { createText } from "@ui/ui_template_text"; import { makeSangeun, type HopyoScope, type SangeunBuilt, type SangeunPick, } from "./M02_MasterTemplete_Hopyo_Api"; const why = (error: unknown): string => (error instanceof Error ? error.message : String(error)); /** 고름 대기 후보 글 — 「이름 [단위] · 판정 · 글」 */ export const candLabel = (c: { 이름: string; 단위: string; 판정: string; 글: string }): string => `${c.이름} [${c.단위}] · ${c.판정}${c.글 && c.글 !== c.판정 ? ` · ${c.글}` : ""}`; /** 만든 갈래 꼬리표 — 기초 = 초록 · SK = 차이 있음 */ const kindBadge = (kind: string): HTMLElement => kind === "SK" ? createBadge(L("M02_WizSkDiff"), "accent") : createBadge(L("M02_WizSkBase"), "success"); /** ② 단가산출 단계 칸 — `root` 를 마법사 본 칸에 붙임 */ export function sangeunStep(scope: HopyoScope, key: string): { root: HTMLElement } { const out = el("div", { className: "m02-hopyo", attrs: { "data-wiz-sk": "" } }); const make = createButton({ label: L("M02_WizSkMake"), variant: "filled", onClick: () => void run(), }); make.title = L("M02_WizSkMakeTip"); make.dataset.hopyoSangeunMake = ""; const root = el("div", { className: "m02-hopyo", children: [el("div", { className: "ui-toolbar", children: [make] }), out], }); async function run(picks?: SangeunPick): Promise { make.disabled = true; try { const got = await makeSangeun(scope, key, picks); draw(got); showToast(summary(got), got.고름대기.length ? "warning" : "success"); } catch (error) { showToast(why(error), "error"); } finally { make.disabled = false; } } const summary = (got: SangeunBuilt): string => L("M02_WizSkSummary") .replace("{b}", String(got.블록)) .replace("{base}", String(got.기초)) .replace("{sk}", String(got.SK)) .replace("{keep}", String(got.그대로)) .replace("{wait}", String(got.고름대기.length)); function draw(got: SangeunBuilt): void { const made = createTable( [ { label: L("M02_WizSkBlock"), width: "80px" }, { label: L("M02_SangeunColName") }, { label: L("M02_WizSkKey"), width: "110px" }, { label: L("M02_WizSkKind"), width: "120px" }, ], got.만듦.map((x) => [`단산${x.번}`, x.이름, x.키, kindBadge(x.갈래)]), { density: "data", empty: L("M02_WizSkNoneMade") }, ); const selects = new Map(); const wait = createTable( [ { label: L("M02_WizSkBlock"), width: "80px" }, { label: L("M02_SangeunColName") }, { label: L("M02_SangeunColUnit"), width: "64px" }, { label: L("M02_LeftWhy") }, { label: L("M02_LeftBase"), width: "40%" }, ], got.고름대기.map((x) => { const pick = createSelectField({ options: [{ value: "", text: L("M02_WizSkNoPick") }].concat( x.후보.map((c) => ({ value: c.로직, text: candLabel(c) })), ), compact: true, size: 24, ariaLabel: `${L("M02_LeftBase")} 단산${x.번}`, }); pick.select.dataset.wizWait = String(x.번); selects.set(x.번, pick.select); return [`단산${x.번}`, x.이름, x.단위 ?? "", x.까닭, pick.root]; }), { density: "data", empty: L("M02_WizSkNoWait") }, ); const again = createButton({ label: L("M02_WizSkRemake"), variant: "filled", size: 28, onClick: () => { const picks: SangeunPick = {}; for (const [no, s] of selects) if (s.value) picks[no] = { 로직: s.value }; if (!Object.keys(picks).length) return showToast(L("M02_WizSkPickFirst"), "warning"); void run(picks); }, }); again.dataset.wizRemake = ""; const ledger = createButton({ label: L("M02_WizSkLedger"), variant: "link", onClick: () => void window.open(`#/${ROUTES.M01_MASTER_DATA}`, "_blank"), }); out.replaceChildren( createText(summary(got), "muted", 14), made, ...(got.고름대기.length ? [ createText(L("M02_WizSkWaitHint"), "hint", 14), wait, el("div", { className: "ui-toolbar", children: [again] }), ] : []), el("div", { className: "ui-toolbar", children: [ createText(L("M02_WizSkAlias").replace("{n}", String(got.별칭 ?? 0)), "muted", 14), ledger, ], }), ); } return { root }; }