Merge remote-tracking branch 'origin/sub_laptop_3' into main_laptop_1

This commit is contained in:
2026-10-05 20:02:22 +09:00
4 changed files with 305 additions and 70 deletions
@@ -5,13 +5,8 @@
* 프로젝트 · 카드엔 서고 줄 없음
* ========================================================================== */
import {
createButton,
createInputField,
createSelectField,
el,
showToast,
} from "@ui/ui_template_elements";
import { createButton, createSelectField, el, showToast } from "@ui/ui_template_elements";
import { createFindList } from "@ui/ui_template_find_list";
import { t as L } from "@ui/ui_template_locale";
import type { LogicSummary, SubBrief } from "../M01_MasterData/M01_MasterData_UI_Logic_Api";
import { fetchSessionUser } from "../A06_Login/A06_Login_Api_Fetch";
@@ -65,9 +60,6 @@ export function openLogicPicker(done: (logic: LogicSummary) => void, lib?: Libra
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" });
const close = (): void => backdrop.remove();
/* 한 목록 — 구분(단가산출 · 단가승격 · 일위조합) 칸 · 층 단추는 서고 줄(승격 · 조합)의 층 */
@@ -77,31 +69,15 @@ export function openLogicPicker(done: (logic: LogicSummary) => void, lib?: Libra
let libRows: { kind: "Kind_Promote" | "Kind_Combo"; row: LibraryRow }[] = [];
let loading = false;
let seq = 0;
const pickRow = (
key: string,
kind: string,
title: string,
sub2: string,
unit: string,
): HTMLElement =>
el("button", {
className: "m01-logic__pick-row m01-logic__pick-row--button",
attrs: { type: "button", "data-pick": key },
children: [
el("span", { className: "m01-logic__muted", attrs: { "data-pick-kind": "" }, text: kind }),
el("div", {
className: "m01-logic__stack",
children: [
el("strong", { text: title }),
el("span", { className: "m01-logic__muted", text: sub2 }),
],
}),
el("span", { text: unit }),
],
});
/* 공용 찾기 목록 — 구분 · 상세구분 2열 · 이름 왼쪽 맞춤 · ↑ ↓ Enter */
const finder = createFindList({
placeholder: tc("Pick_Search"),
filters: lib?.only ? [] : [sub.root, detail.root],
extra: [layerBar],
});
const find = (): void => {
const q = searchField.input.value.trim().toLowerCase();
const q = finder.search.value.trim().toLowerCase();
const found = all.filter(
(x) =>
(!sub.select.value || x.구분 === sub.select.value) &&
@@ -113,38 +89,38 @@ export function openLogicPicker(done: (logic: LogicSummary) => void, lib?: Libra
: libRows.filter((x) => !q || `${x.row.이름} ${x.row.제목 ?? ""}`.toLowerCase().includes(q));
const total = all.length + libRows.length;
const shown = found.length + libFound.length;
hint.textContent = loading ? tc("Loading") : shown ? `${shown} / ${total}` : tc("Pick_None");
list.replaceChildren(
...found.slice(0, 100).map((x) => {
const row = pickRow(
x.키,
tc("Kind_Logic"),
x.이름,
`${x.키} · ${x.구분} ${x.상세구분}`.trim(),
`${x.결과단위}${x.blocked ? ` · ${tc("Pick_Blocked")}` : ""}`,
);
row.addEventListener("click", () => {
finder.hint.textContent = loading
? tc("Loading")
: shown
? `${shown} / ${total}`
: tc("Pick_None");
finder.setRows([
...found.slice(0, 100).map((x) => ({
key: x.키,
tag: tc("Kind_Logic"),
name: x.이름,
sub: `${x.키} · ${x.구분} ${x.상세구분}`.trim(),
unit: `${x.결과단위}${x.blocked ? ` · ${tc("Pick_Blocked")}` : ""}`,
onPick: () => {
close();
done(x);
});
return row;
}),
},
})),
...libFound.map((x) => {
const at = scope as Scope;
const row = pickRow(
x.row.이름,
tc(x.kind),
x.row.제목 || x.row.이름,
x.row.이름,
x.row.단위 ?? "",
);
row.addEventListener("click", () => {
close();
lib?.pick({ ...at, 키: x.row.이름 }, x.row.제목 || x.row.이름);
});
return row;
return {
key: x.row.이름,
tag: tc(x.kind),
name: x.row.제목 || x.row.이름,
sub: x.row.이름,
unit: x.row.단위 ?? "",
onPick: () => {
close();
lib?.pick({ ...at, 키: x.row.이름 }, x.row.제목 || x.row.이름);
},
};
}),
);
]);
};
const loadLib = async (): Promise<void> => {
if (!lib || !scope) return;
@@ -191,12 +167,8 @@ export function openLogicPicker(done: (logic: LogicSummary) => void, lib?: Libra
find();
});
detail.select.addEventListener("change", find);
searchField.input.addEventListener("input", find);
finder.search.addEventListener("input", find);
const filters = el("div", {
className: "m01-logic__filters",
children: [...(lib?.only ? [] : [sub.root, detail.root]), searchField.root],
});
layerBar.style.display = "none";
if (lib)
void upper(lib.layer, lib.owner).then((got) => {
@@ -219,17 +191,14 @@ export function openLogicPicker(done: (logic: LogicSummary) => void, lib?: Libra
createButton({ label: tc("Pick_Close"), variant: "ghost", onClick: close }),
],
}),
filters,
layerBar,
hint,
list,
finder.root,
],
});
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);
searchField.input.focus();
finder.search.focus();
if (lib?.only) return;
void Promise.all([fetchLogicSubs(), fetchLogics()])