feat(m02-df): 검증 칸을 Model designInputs · Eval breaks 로 이음 · 출력 단위 고르기(UnitPick) · 단위 표준 소수자리 제안

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EauA2ATmqNRbeV48s9CcBr
This commit is contained in:
2026-10-01 19:52:25 +09:00
co-authored by Claude Sonnet 5.5
parent f759216242
commit 296255e357
3 changed files with 79 additions and 88 deletions
@@ -11,6 +11,7 @@ import { formatMoney } from "../../M01_MasterData/M01_MasterData_UI_Logic_Money"
import { evalLogic, type CfEvalResult, type CfValue } from "./M02_DF_Eval";
import { portsOut, type CfBox, type CfCost, type CfLogic, type CfRound } from "./M02_DF_Model";
import { defaultItemRound, roundText } from "./M02_DF_Round";
import { createUnitPick, suggestPlaces } from "./M02_DF_UnitPick";
import "./M02_DF_OutputPanel.css";
const TEXT = {
@@ -22,7 +23,6 @@ const TEXT = {
Expense: ["경비", "Expense"],
Plain: ["값(비용 아님)", "Value (not a cost)"],
Unit: ["단위", "Unit"],
UnitHint: ["예: 원 · ㎥ · 시간 · -", "e.g. KRW · ㎥ · h · -"],
Got: ["받은 값", "Received value"],
From: ["어디서", "From"],
Value: ["값", "Value"],
@@ -39,6 +39,8 @@ const TEXT = {
RoundDefault: ["끝수 기본", "Default rounding"],
RoundStd: ["일위대가표 금액란", "unit-price sheet amount column"],
RoundNone: ["끝수 없음(값 그대로)", "No rounding (value as is)"],
Suggest: ["단위 표준 제안", "Unit standard suggests"],
Apply: ["적용", "Apply"],
RoundReset: ["기본으로", "Back to default"],
RoundUser: ["고른 끝수", "Chosen rounding"],
PlainHint: [
@@ -165,13 +167,7 @@ export function renderOutputPanel(
})),
),
});
const unitBox = el("input", {
className: "m02-dfout__input",
attrs: { type: "text", placeholder: to("UnitHint"), "aria-label": to("Unit") },
});
unitBox.value = box.output?.unit ?? box.unit;
unitBox.addEventListener("change", () => {
const next = unitBox.value.trim() || "-";
const setUnit = (next: string): void =>
emit(() =>
withBox(lg, box.id, (b) => ({
...b,
@@ -179,7 +175,27 @@ export function renderOutputPanel(
output: { ...b.output, cost: b.output?.cost ?? "노무비", unit: next },
})),
);
const unitBox = createUnitPick({
value: box.output?.unit ?? box.unit,
ariaLabel: to("Unit"),
extra: lg.resultUnit.includes("/") ? [lg.resultUnit.split("/")[0]] : [],
onPick: setUnit,
});
/** 단위 표준의 소수자리 제안(주 ① 반올림) — 값(비용 아님)이고 끝수를 안 정했을 때 */
const suggestNote = el("span", { className: "m02-dfout__muted" });
if (cost === "값" && !box.output?.round)
void suggestPlaces(box.output?.unit ?? box.unit).then((p) => {
if (p === null) return;
suggestNote.textContent = `${to("Suggest")}: ${to("RoundPlaces")} ${p} · 반올림`;
suggestNote.append(
createButton({
label: to("Apply"),
size: "sm",
variant: "ghost",
onClick: () => setRound({ places: p, method: "반올림" }),
}),
);
});
const field = (label: string, control: HTMLElement): HTMLElement =>
el("label", {
className: "m02-dfout__field",
@@ -253,6 +269,7 @@ export function renderOutputPanel(
],
}),
roundNote,
suggestNote,
],
});