refactor(B05): 배관 편집을 구조물 배치 폼으로 단일화 — 별도 시설 폼 폐지
- 자동 배관·수동 배관은 같은 구조물(2026-08-17 사용자 지시) — 별도 편집 UI (createFacilityEditor) 폐지. 배관/BOX암거/물넘이/세월교도 일반 구조물과 같은 흐름(구조물군 → 종류 → 시작·기준·종료 측점 → 옵션 → 추가/수정/삭제) - createFacilityOptionsForm: 부속 옵션 서브폼이 구조물 폼 옵션 자리에 삽입. 시설 종류는 종류 드롭다운, 위치는 측점 칸이 담당 - loadPipeForm: 목록·그래프·3D·배수유역도 어디서 골라도 같은 폼에 로드, 버튼 [수정]. onPipeUpdate 신설(기준점 이동=관 이동, 옵션만=재계산) - 기슭막이 총/앞/뒤 → 시작·종료 측점 칸 자동 채움. onPipesChanged에 source·options 추가. 배수유역 패널은 지도·정본 보관·재계산만 담당 - 700줄 대응: 입력 조각을 B05_Profile_UI_Structures_Fields.ts로 분리 (패널 685줄). tmp/tests 98건·typecheck·build 통과
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
/* =============================================================================
|
||||
* B05_Profile_UI_Structures_Fields.ts
|
||||
* 「구조물 배치」 폼 입력 조각 — 라벨 필드·숫자칸·셀렉트·측점번호+잔여거리 두 칸.
|
||||
*
|
||||
* 패널 본체(B05_Profile_UI_Structures_Panel)가 700줄 한계에 닿아 분리했다.
|
||||
* 측점 두 칸은 구 비정규 측점 UI와 같은 입력 방식이다(2026-08-17 사용자 확정) —
|
||||
* 저장은 누가거리(m), 화면 입출력만 측점번호+잔여거리.
|
||||
* ========================================================================== */
|
||||
|
||||
import { chainageToStation } from "./B05_Profile_Util_Station";
|
||||
|
||||
export function field(labelText: string, input: HTMLElement): HTMLLabelElement {
|
||||
const wrapper = document.createElement("label");
|
||||
wrapper.className = "b05-route__field";
|
||||
const caption = document.createElement("span");
|
||||
caption.textContent = labelText;
|
||||
wrapper.append(caption, input);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
export function numberInput(step = "0.1", min = "0"): HTMLInputElement {
|
||||
const input = document.createElement("input");
|
||||
input.type = "number";
|
||||
input.step = step;
|
||||
input.min = min;
|
||||
return input;
|
||||
}
|
||||
|
||||
export function select(options: ReadonlyArray<[string, string]>): HTMLSelectElement {
|
||||
const element = document.createElement("select");
|
||||
element.replaceChildren(...options.map(([value, label]) => new Option(label, value)));
|
||||
return element;
|
||||
}
|
||||
|
||||
/** 측점번호 + 잔여거리 두 칸 묶음. */
|
||||
export interface StationFields {
|
||||
wrap: HTMLElement;
|
||||
station: HTMLInputElement;
|
||||
remainder: HTMLInputElement;
|
||||
/** 두 칸을 누가거리로 읽는다. 비었으면 null, 형식 오류면 붉히고 null. */
|
||||
read: (intervalM: number, required: boolean) => number | null;
|
||||
/** 누가거리를 두 칸에 나눠 싣는다. null이면 비운다. */
|
||||
write: (chainageM: number | null, intervalM: number) => void;
|
||||
clearInvalid: () => void;
|
||||
}
|
||||
|
||||
export function stationFields(labelText: string): StationFields {
|
||||
const station = numberInput("1", "0");
|
||||
station.placeholder = "측점";
|
||||
const remainder = numberInput("0.1", "0");
|
||||
remainder.placeholder = "+m";
|
||||
const pair = document.createElement("div");
|
||||
pair.className = "b05-structure__station-pair";
|
||||
pair.append(station, remainder);
|
||||
const wrap = field(labelText, pair);
|
||||
const markInvalid = (bad: boolean): void => {
|
||||
station.classList.toggle("is-invalid", bad);
|
||||
remainder.classList.toggle("is-invalid", bad);
|
||||
};
|
||||
return {
|
||||
wrap,
|
||||
station,
|
||||
remainder,
|
||||
read(intervalM, required) {
|
||||
const stationText = station.value.trim();
|
||||
const remainderText = remainder.value.trim();
|
||||
if (!stationText && !remainderText) {
|
||||
markInvalid(required);
|
||||
return null;
|
||||
}
|
||||
const stationNo = stationText ? Number(stationText) : 0;
|
||||
const rest = remainderText ? Number(remainderText) : 0;
|
||||
const valid =
|
||||
Number.isFinite(stationNo) && stationNo >= 0 && Number.isFinite(rest) && rest >= 0;
|
||||
markInvalid(!valid);
|
||||
return valid ? stationNo * intervalM + rest : null;
|
||||
},
|
||||
write(chainageM, intervalM) {
|
||||
if (chainageM === null) {
|
||||
station.value = "";
|
||||
remainder.value = "";
|
||||
return;
|
||||
}
|
||||
const parts = chainageToStation(chainageM, intervalM);
|
||||
station.value = String(parts.station);
|
||||
remainder.value = parts.remainder.toFixed(1);
|
||||
},
|
||||
clearInvalid: () => markInvalid(false),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user