- 종단 도구 · [창 분할] = 단추 유리 · 보조 단 18 · ▲▼ = 아이콘 단추 선 18 · 배율 + − ⤢ = 아이콘 단추 22 - 배수 머리 단추 = 단추 22 · 층 단추 = 켜기 칩 20(색 점 = 층 색) · 유역 줄 = 목록 줄 32 - [추가] · [삭제] · [리셋] · [해제] · 확폭 = 단추 주 · 위험 고스트 · 보조 · [-][+] = 아이콘 단추 24 - 지도 도구줄 · 3D 보기 줄 = 단 32(34 에서) · 접기 ▾ = 아이콘 단추 18 · 잰 값 닫기 = 아이콘 단추 24 - 페이지 CSS 의 단추 꼴(테두리 · 바탕 · 글 · 둥글기) 지움 · 날 색 대체값(#d98a00 · #5b8def · #3a3f4a) 지움 - 시험 선택자 · 가짜 DOM(setAttribute) 같이 고침 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
100 lines
3.7 KiB
TypeScript
100 lines
3.7 KiB
TypeScript
/* =============================================================================
|
|
* B05_Profile_UI_Drainage_Suggest.ts
|
|
* 배수유역 칸 제안 목록(347-3) — 관경 · 시설 종류를 보여 주고 [적용] 한 번에 관 초안으로.
|
|
* 모으기 · 얹기 규칙은 `logic/B05_Profile_Drainage_Suggest.ts` · 자동 바꿈 없음.
|
|
* 관 자리 후보 = [자동 제안] 목록(510 · `B05_Profile_UI_Drainage_Propose`) — 여기 안 올림(두 목록 겹침).
|
|
* ========================================================================== */
|
|
|
|
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; // 모으지 않음(510 · [자동 제안] 목록)
|
|
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;
|
|
}
|
|
|
|
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 = "ui-btn ui-btn--filled b05-drainage__analyze";
|
|
apply.setAttribute("data-size", "22");
|
|
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.length === 0;
|
|
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, []);
|
|
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();
|
|
},
|
|
};
|
|
}
|