feat(M01): 몫 줄 단가 = 단가 x 몫 비율 · 줄 모달 윗줄 요소조각 · 로직 알약이 그 로직을 엶 (PLAN 5장)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WRFJmmhPi4exAzHgPZHMT
This commit is contained in:
@@ -19,8 +19,19 @@ import { formatNumber } from "./M01_MasterData_UI_Logic_Edit";
|
||||
import { formatMoney } from "./M01_MasterData_UI_Logic_Money";
|
||||
import { explain, loadTable, type TableRow } from "./M01_MasterData_UI_Logic_Note";
|
||||
import { jumpToMaster, type MasterJump } from "./M01_MasterData_UI_Side";
|
||||
import { fragmentRow, type Fragment } from "./M01_MasterData_UI_LogicLab_Pill";
|
||||
import { tl } from "./M01_MasterData_UI_LogicLab_Text";
|
||||
|
||||
/** 로직 알약 → 그 로직 열기 — 로직 화면이 자기 열기를 등록 · 열려 있는 모달은 다 닫음 */
|
||||
let logicOpener: (key: string) => void = () => {};
|
||||
export const setLogicOpener = (fn: (key: string) => void): void => {
|
||||
logicOpener = fn;
|
||||
};
|
||||
export function openLogic(key: string): void {
|
||||
document.querySelectorAll(".m01-logic__backdrop").forEach((b) => b.remove());
|
||||
logicOpener(key);
|
||||
}
|
||||
|
||||
/** 재료 고르기 조건(호표 줄 `요소` 가 글 대신 객체일 때) — 서버 `master_material.PICK_KEYS` 와 같은 칸 */
|
||||
export interface PickCond {
|
||||
구분?: string;
|
||||
@@ -51,6 +62,10 @@ export interface ModalTarget {
|
||||
middles: NamedFormula[];
|
||||
/** 시험 계산 칸에 넣은 값 — 걸린 줄을 맞히는 데 씀 */
|
||||
values: Record<string, string>;
|
||||
/** 서버 `요소조각` — 단가 자리(요소 · 로직 부르기)를 조각으로 · 없으면 로직 키만 알약으로 */
|
||||
unitFrag?: Fragment[];
|
||||
/** 서버 수량 조각 — 한 줄 풀이를 조각으로(알약 포함) · 없으면 식 풀이 글 */
|
||||
qtyFrag?: Fragment[];
|
||||
}
|
||||
|
||||
/** 수량 칸 표 알약 하나가 여는 자료 — 서버 조각 `참조`(키 · 행 · 열)가 곧 찾은 자리 */
|
||||
@@ -289,18 +304,31 @@ export function openMaterialModal(target: ModalTarget): void {
|
||||
? (target.prices[element] ?? target.prices[base])
|
||||
: undefined;
|
||||
const priceRef = cond ? pickedOf(cond, target.values, known?.ref ?? "") : element;
|
||||
const logicRef = element.startsWith("로직(") ? element : "";
|
||||
const logicKey = /^로직\((\w+)/.exec(element)?.[1] ?? "";
|
||||
const sum = el("p", { className: "m01lab__sum" });
|
||||
const setSum = (price: ElementBrief | null | undefined): void => {
|
||||
const unit = price ? `${tl("Modal_UnitPrice")} ${formatMoney(price.값)} × ` : "";
|
||||
sum.textContent = `${target.title} = ${unit}${explain(target.expr)}`;
|
||||
if (target.qtyFrag) {
|
||||
sum.replaceChildren(`${target.title} = ${unit}`, fragmentRow(target.qtyFrag));
|
||||
} else sum.textContent = `${target.title} = ${unit}${explain(target.expr)}`;
|
||||
};
|
||||
setSum(known);
|
||||
const rate = el("div", { className: "m01lab__modal-body" });
|
||||
if (known && priceRef) {
|
||||
rate.append(priceView(priceRef, known));
|
||||
} else if (logicRef) {
|
||||
rate.append(el("p", { text: `${tl("Modal_Logic")} · ${logicRef}` }));
|
||||
} else if (logicKey) {
|
||||
rate.append(
|
||||
el("p", {
|
||||
children: [
|
||||
`${tl("Modal_Logic")} · `,
|
||||
fragmentRow(
|
||||
target.unitFrag ?? [
|
||||
{ pill: { label: logicKey, onClick: () => openLogic(logicKey) } },
|
||||
],
|
||||
),
|
||||
],
|
||||
}),
|
||||
);
|
||||
} else if (cond && priceRef) {
|
||||
rate.append(muted("…")); // 후보 목록이 오면 그 줄로 채움 — 100건 밖이면 키로 따로 찾아 옴
|
||||
} else if (cond) {
|
||||
@@ -335,7 +363,13 @@ export function openMaterialModal(target: ModalTarget): void {
|
||||
className: "m01lab__raw",
|
||||
children: [
|
||||
el("summary", { text: tl("Modal_Qty") }),
|
||||
el("pre", { className: "m01lab__expr", text: target.expr }),
|
||||
el("pre", {
|
||||
className: "m01lab__expr",
|
||||
text: logicKey
|
||||
? `${element}
|
||||
${target.expr}`
|
||||
: target.expr,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user