- 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>
74 lines
2.8 KiB
TypeScript
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;
|
|
},
|
|
};
|
|
}
|