wip feat(M01): 기계 구분·상세구분 2단 거름 · 소요량/계수 용도 표시·대상 거름
기계.json 머리 구분 딕셔너리 추가(세부분류 유지) · UI_Side 기계 2단 필터 Store/Router/Api_Fetch usage 쿼리 추가 · UI_Tables 용도 표시 + 대상 드롭다운 locale 문구 추가 · 관련 시험 수정·추가
This commit is contained in:
@@ -4,9 +4,15 @@
|
||||
* → 표 하나(조건 칸 + 값 칸의 긴 줄) · 눌러 고침(노랑) · 줄 더하기·지우기
|
||||
* ========================================================================== */
|
||||
|
||||
import { createButton, el, showToast } from "@ui/ui_template_elements";
|
||||
import { createButton, createSelectField, el, showToast } from "@ui/ui_template_elements";
|
||||
import { t as L } from "@ui/ui_template_locale";
|
||||
import { fetchTable, fetchTables, type Row, type TableHead } from "./M01_MasterData_Api_Fetch";
|
||||
import {
|
||||
fetchTable,
|
||||
fetchTables,
|
||||
type Row,
|
||||
type TableHead,
|
||||
type TableUsage,
|
||||
} from "./M01_MasterData_Api_Fetch";
|
||||
import { saveView, type Pick } from "./M01_MasterData_UI_Side";
|
||||
import {
|
||||
onDraftChange,
|
||||
@@ -27,16 +33,31 @@ import {
|
||||
|
||||
const LIST_SIZE = 30;
|
||||
const LIST_COLS = ["키", "원문번호", "구분", "상세구분", "이름", "기준", "출처", "비고"] as const;
|
||||
/** 용도 대상 거름 드롭다운 후보 — PLAN 1-1 셋째 줄 그대로. */
|
||||
const USAGE_TARGETS = ["인력", "기계", "재료", "할증", "환산", "작업량 조건"];
|
||||
|
||||
/** 돌려받은 함수 = 이 화면을 걷을 때 부를 해제. */
|
||||
export function renderTables(host: HTMLElement, pick: Pick, q: string): () => void {
|
||||
let stop = (): void => {};
|
||||
let usage = pick.view?.usage ?? "";
|
||||
const list = (page = pick.view?.page ?? 1): void => {
|
||||
stop();
|
||||
stop = (): void => {};
|
||||
void showList(host, pick, q, page, (file, key) => {
|
||||
stop = openTable(host, file, key, () => list(page));
|
||||
});
|
||||
void showList(
|
||||
host,
|
||||
pick,
|
||||
q,
|
||||
usage,
|
||||
page,
|
||||
(file, key) => {
|
||||
stop = openTable(host, file, key, () => list(page));
|
||||
},
|
||||
(next) => {
|
||||
usage = next;
|
||||
saveView(pick.group, { usage, page: 1 });
|
||||
list(1);
|
||||
},
|
||||
);
|
||||
};
|
||||
list();
|
||||
const off = onDraftChange(() => host.querySelector(".m01-master__tables") && markChanged(host));
|
||||
@@ -58,17 +79,19 @@ async function showList(
|
||||
host: HTMLElement,
|
||||
pick: Pick,
|
||||
q: string,
|
||||
usage: string,
|
||||
page: number,
|
||||
open: (file: string, key: string) => void,
|
||||
onUsageChange: (usage: string) => void,
|
||||
): Promise<void> {
|
||||
let got: { total: number; tables: TableHead[] };
|
||||
try {
|
||||
got = await fetchTables(pick.group, pick.sub, pick.detail, q, page, LIST_SIZE);
|
||||
got = await fetchTables(pick.group, pick.sub, pick.detail, q, page, LIST_SIZE, usage);
|
||||
} catch (error) {
|
||||
showToast(error instanceof Error ? error.message : L("M01_LoadFailed"), "error");
|
||||
return;
|
||||
}
|
||||
saveView(pick.group, { page });
|
||||
saveView(pick.group, { page, usage });
|
||||
const rows = got.tables.map((t) => {
|
||||
const tr = el("tr", {
|
||||
className: "m01-master__table-row",
|
||||
@@ -81,8 +104,24 @@ async function showList(
|
||||
tr.addEventListener("click", () => open(t.file, t.키));
|
||||
return tr;
|
||||
});
|
||||
const usageField = createSelectField({
|
||||
options: [
|
||||
{ value: "", text: L("M01_All") },
|
||||
...USAGE_TARGETS.map((v) => ({ value: v, text: v })),
|
||||
],
|
||||
value: usage,
|
||||
compact: true,
|
||||
label: L("M01_UsageTarget"),
|
||||
});
|
||||
usageField.select.addEventListener("change", () => onUsageChange(usageField.select.value));
|
||||
host.replaceChildren(
|
||||
buildPager(got.total, LIST_SIZE, page, (p) => void showList(host, pick, q, p, open)),
|
||||
el("div", { className: "m01-master__filter", children: [usageField.root] }),
|
||||
buildPager(
|
||||
got.total,
|
||||
LIST_SIZE,
|
||||
page,
|
||||
(p) => void showList(host, pick, q, usage, p, open, onUsageChange),
|
||||
),
|
||||
el("div", {
|
||||
className: "m01-master__grid-wrap m01-master__tables",
|
||||
children: [
|
||||
@@ -169,6 +208,7 @@ function openTable(host: HTMLElement, file: string, key: string, back: () => voi
|
||||
const notes = ((table.주 ?? []) as string[]).map((n) =>
|
||||
el("p", { className: "m01-master__muted", text: n }),
|
||||
);
|
||||
const usage = table.용도 as TableUsage | undefined;
|
||||
host.replaceChildren(
|
||||
el("div", {
|
||||
className: "m01-master__bar",
|
||||
@@ -179,6 +219,17 @@ function openTable(host: HTMLElement, file: string, key: string, back: () => voi
|
||||
className: "m01-master__muted",
|
||||
text: `${key} · ${table.기준 || "—"} · ${table.출처 || ""}`,
|
||||
}),
|
||||
...(usage
|
||||
? [
|
||||
el("span", {
|
||||
className: "m01-master__muted",
|
||||
attrs: { title: usage.로직키.join(", ") },
|
||||
text: `${L("M01_TableUsage")}: ${usage.공종} · ${usage.대상.join(", ")} · ${L(
|
||||
"M01_TableUsageLogicCount",
|
||||
).replace("{value}", String(usage.로직키.length))}`,
|
||||
}),
|
||||
]
|
||||
: []),
|
||||
add,
|
||||
],
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user