refactor(M02): 자재 고르기 창 따로 — M02_Material_Pick.ts(pickMaterial · MaterialItem) · 일위대가 자재목록이 다시 씀
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NPJGtfXo6GMbcpiboQC4uK
This commit is contained in:
@@ -5,15 +5,7 @@
|
||||
* (서버 `branchMaterialCombo`) · 원래 조합은 그대로. 빼는 자재가 칸에 이어져 있으면 확인 후 연결도 풂.
|
||||
* ========================================================================== */
|
||||
|
||||
import {
|
||||
createButton,
|
||||
createInputField,
|
||||
el,
|
||||
showConfirmDialog,
|
||||
showToast,
|
||||
} from "@ui/ui_template_elements";
|
||||
import { openModal } from "@ui/ui_template_modal";
|
||||
import { searchMaterials } from "../M01_MasterData/M01_MasterData_Api_Fetch";
|
||||
import { createButton, el, showConfirmDialog, showToast } from "@ui/ui_template_elements";
|
||||
import type { LinkItem } from "../A00_Common/spreadsheet/spreadsheet_links";
|
||||
import type { CellLink } from "../A00_Common/spreadsheet/spreadsheet_types";
|
||||
import {
|
||||
@@ -22,6 +14,7 @@ import {
|
||||
type MaterialCombo,
|
||||
type MaterialItem,
|
||||
} from "./M02_MasterTemplete_Api_Fetch";
|
||||
import { pickMaterial } from "./M02_Material_Pick";
|
||||
import { askBranch, branchName, branchToast } from "./M02_MasterTemplete_Combo";
|
||||
import { readColumnBase, reasonOf } from "./M02_MasterTemplete_Combo_Api";
|
||||
|
||||
@@ -51,12 +44,6 @@ const TEXT = {
|
||||
askAlone:
|
||||
"이 자재 조합은 모든 프로젝트가 같이 씀 — 고친 내용으로 새 자재 조합을 만들고 이 열만 새 조합을 가리킴 · 같은 내용이면 있는 조합을 씀",
|
||||
failed: "자재 조합을 못 고침 — {value}",
|
||||
pickTitle: "자재 추가",
|
||||
pickClose: "닫기",
|
||||
search: "자재 이름 · 규격 · 코드",
|
||||
searching: "찾는 중…",
|
||||
noMatch: "맞는 자재 없음",
|
||||
searchFailed: "자재 목록을 못 받음",
|
||||
};
|
||||
|
||||
const fill = (text: string, values: Record<string, string | number>): string =>
|
||||
@@ -122,57 +109,6 @@ export interface MaterialPanelOptions {
|
||||
onApplied?: () => void;
|
||||
}
|
||||
|
||||
/** 자재 고르기 창 — 이름 · 규격 · 코드 낱말로 찾아 하나 고름(좌측 자재 조합 상세도 씀) */
|
||||
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();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** 옆 판 — 이 열에 자재 조합이 없어도 판은 뜸(더하면 새로 만듦) */
|
||||
export function buildMaterialPanel(opts: MaterialPanelOptions): MaterialPanel {
|
||||
let key = opts.state.key;
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
StaleError,
|
||||
type MaterialCombo,
|
||||
} from "./M02_MasterTemplete_Api_Fetch";
|
||||
import { pickMaterial } from "./M02_MasterTemplete_Materials";
|
||||
import { pickMaterial } from "./M02_Material_Pick";
|
||||
import { tm } from "./M02_MasterTemplete_Matset_Text";
|
||||
|
||||
export interface MatsetSectionOptions {
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/* =============================================================================
|
||||
* 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();
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user