- 계산 묶음 drainage 단계(pipelineStage · 붙이기 = 묶음 쪽) — 노선 초안 · 관이 바뀌면 낡음 · 자동 = 3 s 조용한 뒤 「지금 노선으로 셈」 · 수동 = 칸만 흐림 + 가운데 [업데이트] · 구석 「계산 중」 · 다시 조작하면 요청 끊고 처음으로 · 덮개 없음 - ⚙ 설정 창(배수유역 칸 머리 · openModal) 수동(기본) / 자동 · 계정 화면 설정 drainage-mode(b_page_state 등록표 한 줄 · build:corridor 다시 지음) - 늦은 답 버림 = 차례 번호 · 서버 superseded · 세부유역 요청 감싸기와 같은 차례(B05_Profile_UI_Drainage_Run 으로 나눔) - 제안 = 관경(Ø→Ø) · 시설(BOX암거 · 세월교) · 관 자리 후보(지도 점선 원) · [적용] 한 번에 관 초안 · 자동 바꿈 없음 - [확정] savePipes(confirm) = PUT ?recompute=true · [저장] = 낡음 달고 저장 · 패널 691줄 - 순수 규칙 logic/B05_Profile_Drainage_Live · _Suggest · 시험 test_347_2_drainage_live_ui · typecheck 통과 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XWh5wNNycMkbwMpACz1rte
88 lines
3.2 KiB
TypeScript
88 lines
3.2 KiB
TypeScript
/* =============================================================================
|
|
* B05_Profile_UI_Drainage_Suggest.ts
|
|
* 배수유역 칸 제안 목록(347-3) — 관경 · 시설 종류 · 관 자리 후보를 보여 주고 [적용] 한 번에 관 초안으로.
|
|
* 모으기 · 얹기 규칙은 `logic/B05_Profile_Drainage_Suggest.ts` · 자동 바꿈 없음.
|
|
* 관 자리 후보는 배수유역도에도 점선 원으로 그림(`candidates()` → 그리기 판).
|
|
* ========================================================================== */
|
|
|
|
import type {
|
|
DetailBasinResponse,
|
|
DetailPipeInput,
|
|
} from "../B04_PreProcess/B04_PreProcess_Api_Fetch";
|
|
import {
|
|
applySuggestions,
|
|
collectSuggestions,
|
|
type Suggestion,
|
|
} from "./logic/B05_Profile_Drainage_Suggest";
|
|
|
|
const FACILITY_NAME: Record<string, string> = {
|
|
pipe: "배관",
|
|
box_culvert: "BOX암거",
|
|
ford_bridge: "세월교",
|
|
};
|
|
|
|
const facilityName = (id: string): string => FACILITY_NAME[id] ?? id;
|
|
|
|
/** 제안 한 줄 글. */
|
|
export function suggestionText(item: Suggestion): string {
|
|
const at = `측점 ${Math.round(item.chainageM)} m`;
|
|
if (item.kind === "position") return `${at} — 관 자리 후보(흐름이 모이는 오목 자리)`;
|
|
if (item.kind === "facility")
|
|
return `${at} — ${facilityName(item.from)} → ${facilityName(item.to)} 검토`;
|
|
return `${at} — 관경 ${item.from === null ? "미정" : `Ø${item.from}`} → Ø${item.to}`;
|
|
}
|
|
|
|
export interface DrainageSuggest {
|
|
root: HTMLElement;
|
|
update(response: DetailBasinResponse): void;
|
|
/** 관 자리 후보 누가거리 — 배수유역도 점선 원. */
|
|
candidates(): number[];
|
|
}
|
|
|
|
export function createDrainageSuggest(
|
|
pipeRequest: () => DetailPipeInput[],
|
|
applyPoints: (points: DetailPipeInput[]) => void,
|
|
): DrainageSuggest {
|
|
const root = document.createElement("div");
|
|
root.className = "b05-drainage__suggest";
|
|
root.hidden = true;
|
|
const head = document.createElement("div");
|
|
head.className = "b05-drainage__suggest-head";
|
|
const title = document.createElement("span");
|
|
const apply = document.createElement("button");
|
|
apply.type = "button";
|
|
apply.className = "b05-drainage__analyze";
|
|
apply.textContent = "적용";
|
|
apply.title =
|
|
"제안을 관 초안에 한 번에 얹습니다(관 더함 · 관경 · 시설 바꿈) — [저장] 때 남습니다.";
|
|
head.append(title, apply);
|
|
const list = document.createElement("ul");
|
|
list.className = "b05-drainage__suggest-list";
|
|
root.append(head, list);
|
|
let suggestions: Suggestion[] = [];
|
|
|
|
apply.addEventListener("click", () => {
|
|
if (suggestions.length) applyPoints(applySuggestions(pipeRequest(), suggestions));
|
|
});
|
|
|
|
return {
|
|
root,
|
|
update(response) {
|
|
suggestions = response.stale
|
|
? []
|
|
: collectSuggestions(response.pipe_points, response.basins, response.pipe_candidates ?? []);
|
|
root.hidden = suggestions.length === 0;
|
|
title.textContent = `제안 ${suggestions.length}건`;
|
|
list.replaceChildren(
|
|
...suggestions.map((item) => {
|
|
const row = document.createElement("li");
|
|
row.textContent = suggestionText(item);
|
|
return row;
|
|
}),
|
|
);
|
|
},
|
|
candidates: () =>
|
|
suggestions.filter((item) => item.kind === "position").map((item) => item.chainageM),
|
|
};
|
|
}
|