/* ============================================================================= * M01_MasterData_UI_Combo_Pick.ts * [로직 더하기] 창 — 구분 → 상세구분 → 찾기로 사용자가 로직을 하나씩 고름(자동 추천 없음) * ========================================================================== */ import { createButton, createInputField, createSelectField, el, showToast, } from "@ui/ui_template_elements"; import { t as L } from "@ui/ui_template_locale"; import { fetchLogics, fetchLogicSubs, type LogicSummary, type SubBrief, } from "./M01_MasterData_UI_Logic_Api"; import { tc } from "./M01_MasterData_UI_Combo_Text"; const opts = (values: string[]): { value: string; text: string }[] => [L("M01_All"), ...values].map((v, i) => ({ value: i ? v : "", text: v })); export function openLogicPicker(done: (logic: LogicSummary) => void): void { const subs: SubBrief[] = []; let all: LogicSummary[] = []; const sub = createSelectField({ options: opts([]), compact: true, label: tc("Sub") }); const detail = createSelectField({ options: opts([]), compact: true, label: tc("Detail") }); detail.select.disabled = true; const searchField = createInputField({ type: "search", placeholder: tc("Pick_Search") }); const list = el("div", { className: "m01-logic__pick-list" }); const hint = el("p", { className: "m01-logic__muted", text: tc("Pick_Hint") }); const close = (): void => backdrop.remove(); const find = (): void => { const q = searchField.input.value.trim().toLowerCase(); const found = all.filter( (x) => (!sub.select.value || x.구분 === sub.select.value) && (!detail.select.value || x.상세구분 === detail.select.value) && (!q || `${x.키} ${x.이름}`.toLowerCase().includes(q)), ); hint.textContent = found.length ? `${found.length} / ${all.length}` : tc("Pick_None"); list.replaceChildren( ...found.slice(0, 100).map((x) => { const row = el("button", { className: "m01-logic__pick-row m01-logic__pick-row--button", attrs: { type: "button", "data-pick": x.키 }, children: [ el("div", { className: "m01-logic__stack", children: [ el("strong", { text: x.이름 }), el("span", { className: "m01-logic__muted", text: `${x.키} · ${x.구분} ${x.상세구분}`.trim(), }), ], }), el("span", { text: `${x.결과단위}${x.blocked ? ` · ${tc("Pick_Blocked")}` : ""}` }), ], }); row.addEventListener("click", () => { close(); done(x); }); return row; }), ); }; sub.select.addEventListener("change", () => { const d = subs.find((s) => s.name === sub.select.value)?.details ?? []; detail.setOptions(opts(d), ""); detail.select.disabled = d.length === 0; }); const dialog = el("div", { className: "m01-logic__pick", attrs: { role: "dialog", "aria-label": tc("Pick_Title") }, children: [ el("div", { className: "m01-logic__section-head", children: [ el("h3", { text: tc("Pick_Title") }), createButton({ label: tc("Pick_Close"), variant: "ghost", onClick: close }), ], }), el("div", { className: "m01-logic__filters", children: [ sub.root, detail.root, searchField.root, createButton({ label: tc("Pick_Find"), variant: "filled", onClick: find }), ], }), hint, list, ], }); const backdrop = el("div", { className: "m01-logic__backdrop", children: [dialog] }); backdrop.addEventListener("click", (ev) => ev.target === backdrop && close()); backdrop.addEventListener("keydown", (ev) => ev.key === "Escape" && close()); document.body.append(backdrop); void Promise.all([fetchLogicSubs(), fetchLogics()]) .then(([s, l]) => { subs.push(...s); all = l; sub.setOptions(opts(s.map((x) => x.name)), ""); }) .catch((error) => showToast(error instanceof Error ? error.message : tc("Load_Failed"), "error"), ); }