feat(M01): 로직 개선 시험 줄 모달 — 한 줄 풀이와 알약 단추(누른 자료 하나만 펼침·접힘) (PLAN 5-3)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PAdA5ThqmtVSsbzjusk1cJ
This commit is contained in:
@@ -9,13 +9,16 @@ import { createButton, el } from "@ui/ui_template_elements";
|
||||
import type { ElementBrief, NamedFormula } from "./M01_MasterData_UI_Logic_Api";
|
||||
import { formatNumber } from "./M01_MasterData_UI_Logic_Edit";
|
||||
import {
|
||||
explain,
|
||||
loadTable,
|
||||
matchRow,
|
||||
relatedFinds,
|
||||
type RelatedFind,
|
||||
type TableRow,
|
||||
} from "./M01_MasterData_UI_Logic_Note";
|
||||
import { pillBar, type Pill } from "./M01_MasterData_UI_LogicLab_Pill";
|
||||
import { tl } from "./M01_MasterData_UI_LogicLab_Text";
|
||||
import "./M01_MasterData_UI_LogicLab_Pill.css";
|
||||
|
||||
export interface ModalTarget {
|
||||
title: string;
|
||||
@@ -87,6 +90,9 @@ function tableView(
|
||||
});
|
||||
}
|
||||
|
||||
const groupOf = (ref: string): string =>
|
||||
ref.startsWith("LB") ? "인력" : ref.startsWith("M") ? "재료" : ref.startsWith("EQ") ? "기계" : "";
|
||||
|
||||
function priceView(ref: string, brief: ElementBrief): HTMLElement {
|
||||
const cols = Object.entries(brief.값칸 ?? {});
|
||||
return el("div", {
|
||||
@@ -134,38 +140,59 @@ export function openMaterialModal(target: ModalTarget): void {
|
||||
backdrop.addEventListener("click", (ev) => ev.target === backdrop && close());
|
||||
backdrop.addEventListener("keydown", (ev) => ev.key === "Escape" && close());
|
||||
|
||||
const parts: HTMLElement[] = [
|
||||
el("p", { className: "m01-logic__muted", text: tl("Modal_Qty") }),
|
||||
el("pre", { className: "m01lab__expr", text: target.expr }),
|
||||
];
|
||||
const finds = relatedFinds(target.expr, target.middles);
|
||||
const price = target.element ? target.prices[target.element] : undefined;
|
||||
if (target.element?.startsWith("로직(")) {
|
||||
parts.push(el("p", { text: `${tl("Modal_Logic")} · ${target.element}` }));
|
||||
} else if (price) {
|
||||
parts.push(
|
||||
el("p", { className: "m01-logic__muted", text: tl("Modal_Price") }),
|
||||
priceView(target.element as string, price),
|
||||
);
|
||||
const base = target.element?.split(".")[0] ?? "";
|
||||
const price = target.element ? (target.prices[target.element] ?? target.prices[base]) : undefined;
|
||||
const logicRef = target.element?.startsWith("로직(") ? target.element : "";
|
||||
const pills: Pill[] = [];
|
||||
if (price && target.element) {
|
||||
pills.push({
|
||||
label: `${groupOf(base)} ${price.이름 ?? base}`.trim(),
|
||||
view: () => priceView(target.element as string, price),
|
||||
});
|
||||
} else if (target.element && !logicRef) {
|
||||
pills.push({
|
||||
label: `${groupOf(base)} ${target.title}`.trim(),
|
||||
view: () => el("p", { text: target.element }),
|
||||
});
|
||||
}
|
||||
const tables = el("div", { className: "m01lab__tables" });
|
||||
parts.push(tables);
|
||||
if (!finds.length && !price && !target.element?.startsWith("로직(")) {
|
||||
parts.push(el("p", { className: "m01-logic__muted", text: tl("Modal_NoData") }));
|
||||
if (logicRef) {
|
||||
pills.push({
|
||||
label: `${tl("Pill_Logic")} ${logicRef.slice(3).split(",")[0].replace(/\)$/, "")}`,
|
||||
view: () => el("p", { text: `${tl("Modal_Logic")} · ${logicRef}` }),
|
||||
});
|
||||
}
|
||||
for (const f of finds) {
|
||||
pills.push({
|
||||
label: `${tl("Pill_Table")} ${f.find.table}`,
|
||||
view: async () => {
|
||||
const table = await loadTable(f.find.table);
|
||||
return table
|
||||
? tableView(f, table, target.values)
|
||||
: el("p", { className: "m01-logic__bad", text: `${f.find.table} ?` });
|
||||
},
|
||||
});
|
||||
}
|
||||
const unit = price ? `${tl("Modal_UnitPrice")} ${formatNumber(price.값)} × ` : "";
|
||||
const parts: HTMLElement[] = [
|
||||
el("p", { className: "m01-logic__muted", text: tl("Modal_Sum") }),
|
||||
el("p", {
|
||||
className: "m01lab__sum",
|
||||
text: `${target.title} = ${unit}${explain(target.expr)}`,
|
||||
}),
|
||||
...(pills.length
|
||||
? [el("p", { className: "m01-logic__muted", text: tl("Pill_Hint") }), pillBar(pills)]
|
||||
: [el("p", { className: "m01-logic__muted", text: tl("Modal_NoData") })]),
|
||||
el("details", {
|
||||
className: "m01lab__raw",
|
||||
children: [
|
||||
el("summary", { text: tl("Modal_Qty") }),
|
||||
el("pre", { className: "m01lab__expr", text: target.expr }),
|
||||
],
|
||||
}),
|
||||
];
|
||||
body.replaceChildren(...parts);
|
||||
document.body.append(backdrop);
|
||||
dialog.tabIndex = -1;
|
||||
dialog.focus();
|
||||
|
||||
void Promise.all(finds.map(async (f) => ({ f, table: await loadTable(f.find.table) }))).then(
|
||||
(got) =>
|
||||
tables.replaceChildren(
|
||||
...got.map(({ f, table }) =>
|
||||
table
|
||||
? tableView(f, table, target.values)
|
||||
: el("p", { className: "m01-logic__bad", text: `${f.find.table} ?` }),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user