Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NPJGtfXo6GMbcpiboQC4uK
78 lines
2.9 KiB
TypeScript
78 lines
2.9 KiB
TypeScript
/* =============================================================================
|
|
* M02_Material_Pick.ts
|
|
* M01 자재 하나 고르기 창 — 이름 · 규격 · 코드 낱말로 찾아 하나 고름(일위대가 자재목록 · 자재 추가가 씀).
|
|
* 모양(`m02-pick*`)은 `M02_MasterTemplete_Structure.css`.
|
|
* ========================================================================== */
|
|
|
|
import { createInputField, el, showToast } from "@ui/ui_template_elements";
|
|
import { openModal } from "@ui/ui_template_modal";
|
|
import { searchMaterials } from "../M01_MasterData/M01_MasterData_Api_Fetch";
|
|
|
|
/** 고른 자재 한 줄 — M01 자재(키 `MT`) */
|
|
export interface MaterialItem {
|
|
코드: string;
|
|
이름: string | null;
|
|
규격: string | null;
|
|
단위: string | null;
|
|
}
|
|
|
|
const TEXT = {
|
|
pickTitle: "자재 추가",
|
|
pickClose: "닫기",
|
|
search: "자재 이름 · 규격 · 코드",
|
|
searching: "찾는 중…",
|
|
noMatch: "맞는 자재 없음",
|
|
searchFailed: "자재 목록을 못 받음",
|
|
};
|
|
|
|
/** 자재 고르기 창 — 고르면 `done` 부르고 닫음 */
|
|
export function pickMaterial(done: (item: MaterialItem) => void): void {
|
|
openModal({
|
|
title: TEXT.pickTitle,
|
|
closeLabel: TEXT.pickClose,
|
|
dialogClass: "m02-modal m02-pick",
|
|
mount: (body, close) => {
|
|
const search = createInputField({ placeholder: TEXT.search, type: "search" });
|
|
const list = el("div", { className: "m02-pick__list" });
|
|
let seq = 0;
|
|
const paint = async (): Promise<void> => {
|
|
const mine = ++seq;
|
|
list.replaceChildren(el("p", { className: "m02-struct__empty", text: TEXT.searching }));
|
|
try {
|
|
const hits = await searchMaterials(search.input.value.trim());
|
|
if (mine !== seq) return;
|
|
list.replaceChildren(
|
|
...(hits.length
|
|
? hits.map((m) => {
|
|
const row = el("button", {
|
|
className: "m02-pick__item",
|
|
attrs: { type: "button", "data-material": m.코드 },
|
|
children: [
|
|
el("span", { className: "m02-pick__key", text: m.코드 }),
|
|
`${m.이름} ${m.규격} ${m.단위}`.replace(/\s+/g, " "),
|
|
],
|
|
});
|
|
row.addEventListener("click", () => {
|
|
done(m);
|
|
close();
|
|
});
|
|
return row;
|
|
})
|
|
: [el("p", { className: "m02-struct__empty", text: TEXT.noMatch })]),
|
|
);
|
|
} catch {
|
|
if (mine === seq) showToast(TEXT.searchFailed, "error");
|
|
}
|
|
};
|
|
let timer = 0;
|
|
search.input.addEventListener("input", () => {
|
|
window.clearTimeout(timer);
|
|
timer = window.setTimeout(() => void paint(), 250);
|
|
});
|
|
body.append(search.root, list);
|
|
void paint();
|
|
search.input.focus();
|
|
},
|
|
});
|
|
}
|