Files
Aislo/B05_Profile/B05_Profile_UI_Panel_Plan.ts
T
eomsangdonandClaude Opus 5.5 dfba0e7b57 feat(755-1·755-2): B05 예정노선 수정 — 켠 동안 판만 고침 · 끌 때 한 번 추적 · 재기 · 받은 노선 색 · 설명 · 위치 칸 걷음
- 755-1 켠 동안 끊김 허용(가운데 묶음 지움) · 고칠 때마다 다시 추적 걷음 · 끌 때 끊김 = 알림하고 안 끔 · 바뀜 = 확인창 → /route/follow 한 걸음 · 켠 동안 되돌리기 = 예정노선 판 사진첩(Ctrl+Z · 도구줄 단추 · bindHistoryControls local) · [잇기] 기능 표 b05 사용
- 755-2 켠 동안 재기 = D03 재기 겹(createPlanMeasure · 선 따라 · 두 점) · 받은 노선 = 분홍 점선 + 검은 테(기존 --draw-map-route-3 · theme.css 안 고침) · 켬 설명 걷음 · 위치 칸 걷음(기능 표 site b05 숨김 · 칸 자리 그리기 하나 · 찾기 이동 · toPlan 걷음)
- 낡은 시험 고침: test_626_3(되돌리기 = 판 사진첩 · join b05 사용) · test_635_3(칸 하나 · 위치 숨김 · 끌 때 한 번 · RouteEdit 줄 한도 683 → 690) · test_635_5(찾기 이동 걷음) · 새 지킴 시험 test_755_expected_flow

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 23:11:21 +09:00

74 lines
2.8 KiB
TypeScript

/* =============================================================================
* B05_Profile_UI_Panel_Plan.ts
* 종단 보기 왼쪽 「그리기」 칸 자리(PLAN 635-3 · 755-2 · 요구 546 · 589-8 위치 칸 걷음) — 예정노선 키트(`createPlanKit` 「b05」) 칸을 앉힘.
* 칸은 페이지가 먼저 세우고 편집기는 노선을 읽은 뒤 섬 → 칸 = 빈 자리(order 1) · 편집기가 `fillPlanPanel` 로 채움.
* 늦게 온 쪽이 붙임 · 새 칸 자리(페이지 다시 세움) = 떠난 편집기 칸(문서 밖) 버림 · 비면 자리 숨김.
* 좌표 변환(635-5) = 서버(`POST /route/coords` · 사업지 좌표계 pyproj) — 속성 판 경위도 때만 부름.
* ========================================================================== */
import { registerPanelSection } from "../A00_Common/design/design_panel";
import { requestJson } from "./B05_Profile_Api_Replan";
type Vertex = [number, number];
let holder: HTMLElement | null = null;
let card: HTMLElement | null = null;
const attach = (): void => {
if (!holder) return;
holder.replaceChildren(...(card ? [card] : []));
holder.hidden = !card;
};
registerPanelSection({
id: "plan-draw",
title: "그리기",
views: ["profile"],
order: 1,
build: () => {
holder = document.createElement("div");
holder.className = "b05-route__plan-slot";
if (!card?.isConnected) card = null; // 떠난 편집기 칸
attach();
return holder;
},
});
/** 키트 칸을 앉힘(새 편집기가 갈음). */
export function fillPlanPanel(next: HTMLElement | null): void {
card = next;
attach();
}
export interface PlanCoords {
/** 사업지 → 경위도 — 받은 점이면 바로 · 처음이면 null 주고 한 번 물음(오면 `onLonLat`). */
lonLat: (x: number, y: number) => Vertex | null;
}
/** 사업지 → 경위도 서버 변환 · 같은 점은 캐시(끌기 중엔 안 부름 — 판은 고름 · 놓음 때만 그림). */
export function createPlanCoords(projectId: string, onLonLat: () => void): PlanCoords {
const ask = (to: "lonlat", point: Vertex): Promise<Vertex | null> =>
requestJson<{ points: Vertex[] }>(
`/projects/${projectId}/route/coords`,
{ method: "POST", body: JSON.stringify({ to, points: [point] }) },
15_000,
).then(
(answer) => answer.points[0] ?? null,
() => null,
);
const known = new Map<string, Vertex | null>();
return {
lonLat(x, y) {
const key = `${x},${y}`;
if (known.has(key)) return known.get(key) ?? null;
known.set(key, null); // 묻는 중
void ask("lonlat", [x, y]).then((at) => {
if (at) known.set(key, at);
else known.delete(key); // 실패 = 다음 고름 때 다시
if (at) onLonLat();
});
return null;
},
};
}