/* ============================================================================= * B05_Profile_UI_Structure_Pick_Session.ts * 3D에서 고른 구조물을 **좌측 「구조물 배치」 패널로 넘기고**, 그 선택을 세션 한 칸에 * 남겨 **B06 진입 때 같은 측점 카드가 열리게** 한다(2026-09-04 사용자 확정). * * B05·B06은 라우터가 따로 띄우는 화면이라 실시간 양방향이 아니다 — 조작 상태는 캐시 * 몫이라는 데이터 3층 규칙대로 sessionStorage 한 칸에 남긴다. 값은 **지우지 않고 남긴다** * (2026-09-04 사용자: 두 화면이 한 페이지처럼 움직여야 함) — B06에서 고른 것도 같은 칸에 * 적혀, 어느 쪽으로 오가든 마지막 선택이 그대로 살아 있다. * ========================================================================== */ import { readState, writeState } from "../A00_Common/b_page_state"; import type { StructurePick, StructurePickControls } from "./B05_Profile_UI_Viewer_Structure_Pick"; import type { StructuresSection } from "./B05_Profile_UI_Structures_Panel_Types"; import type { StructureInstance } from "./B05_Profile_Api_Structures"; /** B06으로 넘기는 선택 — B06이 쓰는 `{ 측점, 부재키 }` 한 쌍과 같은 모양이다. */ export interface StructurePickHandoff { at: number; key?: string; } /* 넘김값도 ② 설계 초안이다 — 별도 임시 키를 두지 않고 등록표(`b_page_state`)를 쓴다 (2026-09-06 캐시·세션 일원화). */ /** 세션에 남긴다(선택 해제면 지운다). */ export function rememberStructurePick(projectId: string | null, pick: StructurePick | null): void { if (!projectId) return; if (!pick) return writeState("structure-pick", null, projectId); const handoff: StructurePickHandoff = { at: pick.chainageM, key: pick.key }; writeState("structure-pick", handoff, projectId); } /** 화면에서 고른 것을 세션에 적는다 — B06 쪽 창구(측점만 고르면 부재키는 비운다). */ export function writeStructurePick( projectId: string | null, at: number | null, key?: string, ): void { if (!projectId) return; if (at === null) return writeState("structure-pick", null, projectId); // 부재키 없이 **측점만** 오는 길(사이드 목록·선택 동기화)이 3D 로 고른 부재키를 지웠다 // (2026-09-05 진단). 같은 측점이면 이미 적힌 부재키를 지킨다 — 3D 로 고른 직후 선택 // 동기화가 이 길을 타도 조정창이 그대로 열린다. const kept = key ?? readStructurePick(projectId)?.key; writeState("structure-pick", { at, key: kept }, projectId); } /** 세션에 남은 선택을 읽는다(지우지 않는다). 없으면 null. */ export function readStructurePick(projectId: string | null): StructurePickHandoff | null { if (!projectId) return null; try { const value = readState>("structure-pick", projectId); if (!value) return null; if (typeof value.at !== "number" || !Number.isFinite(value.at)) return null; return { at: value.at, key: typeof value.key === "string" ? value.key : undefined }; } catch { return null; } } /** 구간형 구조물이 그 누가거리를 덮는가(기준점형은 ±0.51m 안). */ function covers(entry: StructureInstance, chainageM: number): boolean { const start = entry.start_m ?? entry.chainage_m; const end = entry.end_m ?? entry.chainage_m; if (start == null || end == null) return false; return chainageM >= Math.min(start, end) - 0.51 && chainageM <= Math.max(start, end) + 0.51; } /** * 3D 클릭 결과를 화면 전체에 적용한다. * * 배수관 세트(기슭막이·집수정·배관)는 `selectStation`(=기존 선택 동기화)이 좌측 폼·종단 * 그래프·3D 마커·유역도를 한 줄로 맞춘다. 그 줄에서 아무것도 안 잡히면 옛 정본 구조물로 * 보고 구조물 id로 연다. */ export function wireStructurePick( controls: StructurePickControls, projectId: string | null, structures: StructuresSection, /** 기존 선택 동기화(`selectStationOfPipe`) — 누가거리 하나로 전 화면을 맞춘다. */ selectStation: (chainageM: number | null) => void, ): void { controls.onPick = (pick: StructurePick | null): void => { rememberStructurePick(projectId, pick); if (!pick) { selectStation(null); return; } selectStation(pick.chainageM); if (structures.hasSelection()) return; const hit = structures.getStructures().find((entry) => covers(entry, pick.chainageM)); structures.selectById(hit?.structure_id ?? null); }; } /** * 화면에 들어올 때 세션에 남은 선택을 되살린다 — B06에서 고른 것도 그대로 이어 받는다 * (2026-09-04 사용자: 두 화면이 한 페이지처럼). 3D 강조는 코리도가 뜬 뒤 자동으로 다시 * 칠해지므로 여기서는 선택만 세워 둔다. * * **되살렸으면 true.** 관 목록이 아직 안 실렸으면 폼이 그 시설을 못 찾으므로 false를 * 돌려준다 — 부르는 쪽은 목록이 실릴 때마다 다시 부르면 된다. */ export function restoreStructurePick( controls: StructurePickControls, projectId: string | null, structures: StructuresSection, selectStation: (chainageM: number | null) => void, ): boolean { const handoff = readStructurePick(projectId); if (!handoff) return true; // 되살릴 것이 없으면 끝난 것으로 본다. controls.select({ chainageM: handoff.at, kind: "", key: handoff.key }); selectStation(handoff.at); return structures.hasSelection(); }