Files
Aislo/old_code/B08_Quantity/B08_Quantity_UI_Side_TreeWaste.ts
T
eomsangdonandClaude Opus 5 8472fc9f40 refactor(B08,B09): 폴더째 old_code 로 옮기고 빈 화면 둘만 남김 (PLAN 7-3)
B08_Quantity 86 · B09_Estimation 111 파일을 old_code/ 로 옮김(지우지 않음).
화면은 메뉴·주소·단계 막대만 남은 빈 틀 둘 — main.py 라우터 13 개는 끊음.
B07 이 빌려 쓰던 비탈 길이·면적은 필요한 함수만 B07_DesignDetail_Engine_SlopeGeometry
로 옮겨 적음(면적 적분·노면 면적·측점 묶음은 안 옮김) · 시험 하나를 새로 둠.
B07 구조물도 조립(Cad_StandardSheet)은 2026-09-13 에 이미 도면 목록에서 빠져
부르는 곳이 없어 old_code 로 같이 보냄 — 구조물 그림은 되살리지 않음.
B06 구조물 몫 조회는 빈 값으로 두어 화면이 그대로 서게 함.
B08·B09 를 부르던 시험 25 개도 old_code/resources/tester 로 옮김.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PAdA5ThqmtVSsbzjusk1cJ
2026-09-22 12:27:45 +09:00

132 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* =============================================================================
* B08_Quantity_UI_Side_TreeWaste.ts
* 산출 조건 「임목폐기물」 구획 — 현장 조사값 넷 · 수동 처리단가 · 분리발주(2026-09-14 판정).
*
* 페이지 본문(`B08_Quantity_UI_Page.ts`)이 700줄을 넘어 새 칸을 이 파일로 뺌(CLAUDE.md 4장).
* ⚠ 톤은 서버가 셈 — 여기는 값만 캐시에 쌓고 [저장]에서 정본으로 감(5장).
* ========================================================================== */
import { ui_locales, currentLanguageIndex } from "@ui/ui_template_locale";
function L(key: keyof typeof ui_locales): string {
return ui_locales[key][currentLanguageIndex];
}
export interface TreeWasteDraft {
tree_waste: Record<string, number | null>;
tree_waste_unit_price_krw_per_ton: number | null;
waste_separate_order: boolean;
/** 뿌리 산정법 — `""` 분배비 15/85(기본) · "root_ball" 뿌리분 체적 × 1,300. */
tree_waste_root_method: string;
dirty: boolean;
}
/** 페이지의 칸 만들기 도우미 — 같은 모양을 쓰려고 받아 씀. */
export interface SideFieldHelpers {
field(label: string, value: string): HTMLElement;
optionalNumberField(
label: string,
value: number | null,
step: string,
onInput: (value: number | null) => void,
): HTMLElement;
selectField(
label: string,
value: string,
options: { value: string; label: string }[],
onChange: (value: string) => void,
): HTMLElement;
hintRow(text: string): HTMLElement;
}
/** 조사값 칸 — 서버 `TREE_WASTE_INPUTS` 와 같은 키. */
const INPUTS: [string, keyof typeof ui_locales, string][] = [
["stems_per_1000m2", "B08_Quantity_TreeWaste_Stems", "1"],
["dbh_cm", "B08_Quantity_TreeWaste_Dbh", "0.1"],
["height_m", "B08_Quantity_TreeWaste_Height", "0.1"],
["unit_weight_kg_m3", "B08_Quantity_TreeWaste_UnitWeight", "10"],
];
/** 수동 단가 칸 — 값이 있으면 빨간 테두리(미확정). */
function markManual(row: HTMLElement, value: number | null): void {
const input = row.querySelector("input");
if (input) input.style.outline = value ? "2px solid var(--color-danger, #d9534f)" : "";
}
export function appendTreeWasteFields(
panel: HTMLElement,
draft: TreeWasteDraft,
h: SideFieldHelpers,
): void {
panel.append(h.field(L("B08_Quantity_Side_TreeWaste"), ""));
for (const [key, label, step] of INPUTS) {
panel.append(
h.optionalNumberField(L(label), draft.tree_waste[key] ?? null, step, (value) => {
draft.tree_waste[key] = value;
draft.dirty = true;
}),
);
}
panel.append(h.hintRow(L("B08_Quantity_Side_TreeWaste_Hint")));
// 뿌리 — 지침 부록1 이 두 방법을 둠. 뿌리분 직경은 흉고직경과 갈라 따로 받음(지침 표기가 모호).
panel.append(
h.selectField(
L("B08_Quantity_TreeWaste_RootMethod"),
draft.tree_waste_root_method,
[
{ value: "", label: L("B08_Quantity_TreeWaste_RootRatio") },
{ value: "root_ball", label: L("B08_Quantity_TreeWaste_RootBall") },
],
(value) => {
draft.tree_waste_root_method = value;
draft.dirty = true;
},
),
);
panel.append(
h.optionalNumberField(
L("B08_Quantity_TreeWaste_RootBallDiameter"),
draft.tree_waste["root_ball_diameter_m"] ?? null,
"0.01",
(value) => {
draft.tree_waste["root_ball_diameter_m"] = value;
draft.dirty = true;
},
),
);
panel.append(h.hintRow(L("B08_Quantity_TreeWaste_Root_Hint")));
const price = h.optionalNumberField(
L("B08_Quantity_TreeWaste_Price"),
draft.tree_waste_unit_price_krw_per_ton,
"1000",
(value) => {
draft.tree_waste_unit_price_krw_per_ton = value;
draft.dirty = true;
markManual(price, value);
},
);
markManual(price, draft.tree_waste_unit_price_krw_per_ton);
panel.append(price);
const priceHint = h.hintRow(L("B08_Quantity_TreeWaste_Price_Hint"));
priceHint.classList.add("b08-quantity__hint--warn");
panel.append(priceHint);
panel.append(
h.selectField(
L("B08_Quantity_TreeWaste_Separate"),
draft.waste_separate_order ? "on" : "",
[
{ value: "", label: L("B08_Quantity_TreeWaste_Separate_Off") },
{ value: "on", label: L("B08_Quantity_TreeWaste_Separate_On") },
],
(value) => {
draft.waste_separate_order = value === "on";
draft.dirty = true;
},
),
);
panel.append(h.hintRow(L("B08_Quantity_TreeWaste_Separate_Hint")));
}