feat(b08): 면고르기 성토면 회색 제안 + [제안값 넣기] — 서버 fill_suggested 그대로 · 누른 때만 칸에 들어가고 비워 두면 「안 정함」 · 메인 976e5fd9

화면: 칸 빈 값 · 회색 「제안(비우면 안 정함): 성토면 · 기계 · 무한궤도 — 영월 실무…」 · 단추 누르면 칸만 바뀌고 저장값은 그대로 빈 값(저장 안 함)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
This commit is contained in:
2026-09-14 16:53:25 +09:00
co-authored by Claude Opus 5
parent 9d59a32898
commit b95ad5e838
3 changed files with 45 additions and 4 deletions
@@ -5,11 +5,13 @@
*
* 페이지 본문(`B08_Quantity_UI_Page.ts`)이 700줄을 넘어 새 칸을 이 파일로 뺌(CLAUDE.md 4장).
* ⚠ 선택지는 **서버가 내려준 목록 그대로**(`face_dressing_choices`) — 화면에 다시 적지 않음(두 벌 금지).
* ⚠ 제안값 없음(판정 Ⓒ) — 첫 보기가 「안 정함」이고 비면 내역 줄이 입력 사유로 섬.
* ⚠ 스스로 안 고름(판정 Ⓒ) — 첫 보기가 「안 정함」이고 비면 내역 줄이 입력 사유로 섬. 성토면 제안은
* 회색 근거 + [제안값 넣기]를 **누른 때만**(메인 976e5fd9 `fill_suggested`).
* ⚠ 면적은 화면이 셈하지 않음 — 비우면 서버가 파종 면적(초류종자살포 × 반영률)을 씀.
* ========================================================================== */
import { ui_locales, currentLanguageIndex } from "@ui/ui_template_locale";
import { createButton } from "@ui/ui_template_elements";
import type { SideFieldHelpers } from "./B08_Quantity_UI_Side_TreeWaste";
function L(key: keyof typeof ui_locales): string {
@@ -29,6 +31,8 @@ export interface FaceDressingDraft {
export interface FaceDressingChoices {
cut: string[];
fill: string[];
/** 성토면 제안(서버 한 곳 · 실무 관측) — 회색으로 보이고 [제안값 넣기]를 **누른 때만** 들어감. */
fill_suggested?: { value: string; basis: string };
}
export function appendFaceDressingFields(
@@ -76,11 +80,36 @@ export function appendFaceDressingFields(
draft.face_dressing_cut_class = v;
}),
);
panel.append(
pick("B08_Quantity_FaceDressing_Fill", draft.face_dressing_fill_class, choices.fill, (v) => {
const fillRow = pick(
"B08_Quantity_FaceDressing_Fill",
draft.face_dressing_fill_class,
choices.fill,
(v) => {
draft.face_dressing_fill_class = v;
},
);
panel.append(fillRow);
// 성토면 제안 — 칸은 비워 둔 채 회색 근거 + 단추(층따기와 같은 모양). 비우면 「안 정함」 그대로.
const suggested = choices.fill_suggested;
if (suggested?.value) {
panel.append(
h.hintRow(
`${L("B08_Quantity_FaceDressing_Suggest")} ${suggested.value}${suggested.basis}`,
),
);
panel.append(
createButton({
label: L("B08_Quantity_FaceDressing_FillSuggested"),
variant: "ghost",
onClick: () => {
const select = fillRow.querySelector("select");
if (select) select.value = suggested.value;
draft.face_dressing_fill_class = suggested.value;
draft.dirty = true;
},
}),
);
}
panel.append(
area("B08_Quantity_FaceDressing_FillArea", draft.face_dressing_fill_area_m2, (v) => {
draft.face_dressing_fill_area_m2 = v;
@@ -24,6 +24,16 @@ def test_저장에_네_키를_싣고_불러온다() -> None:
assert f"{key}: (stored.{key}" in PAGE, f"불러오기에 {key} 없음"
def test_성토면_제안은_회색_근거와_단추로만_넣는다() -> None:
"""메인 976e5fd9 — `fill_suggested` {value, basis}. 비워 두면 「안 정함」 그대로(스스로 안 고름)."""
side = SIDE.read_text(encoding="utf-8")
assert "choices.fill_suggested" in side and "suggested.basis" in side
button = side.split("createButton(")[1]
assert "draft.face_dressing_fill_class = suggested.value" in button # 누른 때만 넣음
assert side.count("= suggested.value") == 2 # 단추 안의 칸·초안 둘뿐
assert "BenchCut" not in side # 층따기 문구(「KDS 토사 0.5 m」)를 빌려 쓰지 않음
def test_선택지는_서버_목록_그대로() -> None:
side = SIDE.read_text(encoding="utf-8")
assert "appendFaceDressingFields(" in PAGE and "face_dressing_choices" in PAGE
+2
View File
@@ -753,6 +753,8 @@ export const ui_locales_b2 = {
B08_Quantity_FaceDressing_FillArea: ["성토면 면적(㎡)", "Fill face area (㎡)"],
B08_Quantity_FaceDressing_CutArea: ["절토면 면적(㎡)", "Cut face area (㎡)"],
B08_Quantity_FaceDressing_Area_Placeholder: ["파종 면적 그대로", "Same as seeding area"],
B08_Quantity_FaceDressing_Suggest: ["제안(비우면 안 정함):", "Suggested (blank = not set):"],
B08_Quantity_FaceDressing_FillSuggested: ["제안값 넣기", "Fill suggested"],
B08_Quantity_Side_FaceDressing_Hint: [
"품셈 9-19-1 원문 표 두 벌(절토면 토질 6 · 성토면 시공·토질) — 제안값 없음, 안 고르면 내역 줄이 입력 사유로 섭니다. 면적은 비우면 초류종자살포 면적(× 반영률) 그대로 · 넣으면 그 값으로 덮어씀",
"Standard estimate 9-19-1 tables (cut face soil · fill face method/soil) — no suggested value; unset leaves the bill row with an input reason. Area left blank uses the seeding area (× ratio); a value overrides it",