/* ============================================================================= * B05_Profile_UI_Drainage_Suggest.ts * 배수유역 칸 제안 목록(347-3) — 관경 · 시설 종류 · 관 자리 후보를 보여 주고 [적용] 한 번에 관경 · 시설만 * 관 초안으로(관 자리 = [자동 제안] · 369). * 모으기 · 얹기 규칙은 `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 = { 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; /** 노선 · 관이 바뀌어 낡음 — [적용] 끔(옛 노선 기준 제안이 새 노선에 안 들어가게). */ setStale(stale: boolean): 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 = "적용"; const applyTitle = "관경 · 시설 제안을 관 초안에 한 번에 얹습니다 — [저장] 때 남습니다(관 자리는 [자동 제안])."; apply.title = applyTitle; head.append(title, apply); const list = document.createElement("ul"); list.className = "b05-drainage__suggest-list"; root.append(head, list); let suggestions: Suggestion[] = []; let stale = false; /** [적용] 켜짐 — 낡지 않고 관경 · 시설 제안이 있을 때(관 자리 후보만이면 할 일 없음). */ const paintApply = (): void => { apply.disabled = stale || !suggestions.some((item) => item.kind !== "position"); apply.title = stale ? "노선이 바뀌어 제안이 낡음 — 새 계산 뒤 적용" : applyTitle; }; apply.addEventListener("click", () => { if (suggestions.length && !apply.disabled) 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}건`; paintApply(); list.replaceChildren( ...suggestions.map((item) => { const row = document.createElement("li"); row.textContent = suggestionText(item); return row; }), ); }, setStale(next) { stale = next; paintApply(); }, candidates: () => suggestions.filter((item) => item.kind === "position").map((item) => item.chainageM), }; }