feat(M01): 조합 미리 보기 자동값 채우기 · 견본 딱지 · 열자마자 계산 · 바꾸면 다시
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JgUhN55Z3BCYhUJTjwTNfj
This commit is contained in:
@@ -5,10 +5,11 @@
|
||||
* ========================================================================== */
|
||||
|
||||
import { createInputField, createSelectField, el } from "@ui/ui_template_elements";
|
||||
import { fetchLogic, type LogicInput } from "./M01_MasterData_UI_Logic_Api";
|
||||
import { fetchAuto, fetchLogic, type LogicInput } from "./M01_MasterData_UI_Logic_Api";
|
||||
import { previewCombo, type Combo } from "./M01_MasterData_UI_Combo_Api";
|
||||
import { tc, type ComboTextKey } from "./M01_MasterData_UI_Combo_Text";
|
||||
import { formatMoney } from "./M01_MasterData_UI_Logic_Money";
|
||||
import { tx } from "./M01_MasterData_UI_Logic_Text";
|
||||
|
||||
const COSTS = ["노무비", "재료비", "경비"] as const;
|
||||
const LABEL: Record<(typeof COSTS)[number], ComboTextKey> = {
|
||||
@@ -29,6 +30,8 @@ function inputCell(
|
||||
input: LogicInput,
|
||||
key: string,
|
||||
values: Record<string, Record<string, string>>,
|
||||
sample: Set<string>,
|
||||
onEdit: () => void,
|
||||
): HTMLElement {
|
||||
const mine = (values[key] ??= {});
|
||||
const value = mine[input.이름] ?? initial(input);
|
||||
@@ -40,8 +43,20 @@ function inputCell(
|
||||
const control = "select" in field ? field.select : field.input;
|
||||
control.value = value;
|
||||
control.setAttribute("data-input", `${key}|${input.이름}`);
|
||||
control.addEventListener("input", () => (mine[input.이름] = control.value));
|
||||
control.addEventListener("change", () => (mine[input.이름] = control.value));
|
||||
const tag = sample.has(`${key}|${input.이름}`)
|
||||
? el("span", { className: "m01-logic__tag", text: tx("Calc_Sample") })
|
||||
: undefined;
|
||||
if (tag) field.root.append(tag);
|
||||
const edit = (): void => {
|
||||
mine[input.이름] = control.value;
|
||||
sample.delete(`${key}|${input.이름}`);
|
||||
tag?.remove();
|
||||
};
|
||||
control.addEventListener("input", edit);
|
||||
control.addEventListener("change", () => {
|
||||
edit();
|
||||
onEdit(); // 바꾸면 다시 미리 보기 계산
|
||||
});
|
||||
return field.root;
|
||||
}
|
||||
|
||||
@@ -55,6 +70,9 @@ export function buildPreview(combo: () => Combo): PreviewHandle {
|
||||
const values: Record<string, Record<string, string>> = {};
|
||||
/** 서버가 받을 꼴 — 원래 숫자·고르기 값으로 되돌림 */
|
||||
const inputs = new Map<string, LogicInput[]>();
|
||||
/** 견본(자동값)으로 채운 칸 `로직|입력` — 사용자가 고치면 빠짐 · 로직마다 자동값은 한 번만 받음 */
|
||||
const sample = new Set<string>();
|
||||
const asked = new Set<string>();
|
||||
const form = el("div", { className: "m01-logic__stack" });
|
||||
const out = el("div", {
|
||||
className: "m01-master__grid-wrap",
|
||||
@@ -131,7 +149,18 @@ export function buildPreview(combo: () => Combo): PreviewHandle {
|
||||
inputs.clear();
|
||||
for (const row of combo().담은로직) {
|
||||
try {
|
||||
const one = await fetchLogic(row.로직);
|
||||
const [one, auto] = await Promise.all([
|
||||
fetchLogic(row.로직),
|
||||
asked.has(row.로직) ? Promise.resolve({}) : fetchAuto(row.로직),
|
||||
]);
|
||||
asked.add(row.로직);
|
||||
const mine = (values[row.로직] ??= {});
|
||||
for (const i of one.logic.입력) {
|
||||
const got = (auto as Record<string, unknown>)[i.이름];
|
||||
if (got === undefined || got === null || (mine[i.이름] ?? "").trim() !== "") continue;
|
||||
mine[i.이름] = String(got);
|
||||
sample.add(`${row.로직}|${i.이름}`);
|
||||
}
|
||||
inputs.set(row.로직, one.logic.입력);
|
||||
blocks.push(
|
||||
el("div", {
|
||||
@@ -141,7 +170,9 @@ export function buildPreview(combo: () => Combo): PreviewHandle {
|
||||
className: "m01lab__cell--wide",
|
||||
text: `${row.로직} ${one.logic.이름}`,
|
||||
}),
|
||||
...one.logic.입력.map((i) => inputCell(i, row.로직, values)),
|
||||
...one.logic.입력.map((i) =>
|
||||
inputCell(i, row.로직, values, sample, () => void run()),
|
||||
),
|
||||
],
|
||||
}),
|
||||
);
|
||||
@@ -150,7 +181,9 @@ export function buildPreview(combo: () => Combo): PreviewHandle {
|
||||
}
|
||||
}
|
||||
form.replaceChildren(...blocks);
|
||||
out.replaceChildren(el("p", { className: "m01-logic__muted", text: tc("Prev_Wait") }));
|
||||
if (blocks.length)
|
||||
await run(); // 열자마자 한 번 미리 보기 계산
|
||||
else out.replaceChildren(el("p", { className: "m01-logic__muted", text: tc("Prev_Wait") }));
|
||||
};
|
||||
|
||||
const root = el("section", {
|
||||
|
||||
Reference in New Issue
Block a user