/* ============================================================================= * B05_Profile_UI_Page_Actions.ts * 종단 보기의 **버튼 동작** — [저장]·[확정]에 보태는 종단 보기 몫. [경로 계산]은 `Old/` 로 옮김(54-24). * * 종단 보기 본체(`design_view_profile`)에서 떼어냈다(700줄 제한, 2026-09-02). 화면 조립·로딩 * 순서는 본체에 남고, 여기에는 영구저장소를 건드리는 갈래만 둔다(CLAUDE.md 5장: 세션에 쌓인 * 조작은 [저장]·[확정]에서만 정본으로 나간다). [초기화]는 한 벌(`design_reset`)이 한다. * ========================================================================== */ import { confirmRoute, type RouteLatestResponse } from "./B05_Profile_Api_Fetch"; import type { DesignViewSave } from "../A00_Common/design/design_shared"; import { pageRouteId } from "../A00_Common/design/design_page_route"; import type { createRoutePanel } from "./B05_Profile_UI_Panel"; import type { createRouteProfilePanel } from "./B05_Profile_UI_Profile_Panel"; import type { createStructuresBridge } from "./B05_Profile_UI_Page_Structures"; import type { createRouteViewer } from "./B05_Profile_UI_Viewer"; /** 버튼 동작이 페이지에서 받아 쓰는 창구 — 값은 바뀌므로 함수로 받는다. */ export interface PageActionContext { projectId: string; latest: () => RouteLatestResponse | null; /** 확정 지표면 응답 — 모델 id 는 `model_id` 다(2026-09-06 호출 정리). */ confirmedSurface: () => { model_id: number | null } | null; routeReady: () => boolean; viewer: () => ReturnType; panel: () => ReturnType; profilePanel: () => ReturnType; bridge: () => ReturnType; /** 상단측(측구 방향) 사용자 변경분 — 키는 누가거리 문자열. */ uphillOverrides: Map; persistUphillOverrides: () => void; loadLatest: (forceFresh?: boolean) => Promise; renderLatest: (next: RouteLatestResponse) => void; restoreSections: (routeId: number) => Promise; } /** [저장] · [확정]에 종단 보기가 보태는 몫 — 차례는 저장 한 줄기(`saveDesign`)가 정하고 * 한 벌(`design_shared`)이 두 보기 몫을 모아 한 번에 보낸다(계획서 24-2a · 24-3b). 관(배수유역도) · * 계획고는 한 벌 종단도가 낸다. */ export function profileSaveParts(ctx: PageActionContext): DesignViewSave { const projectId = ctx.projectId; return { routeId: () => (ctx.routeReady() ? pageRouteId(projectId) : null), // 노선 id 한 칸(386-2b) steps: { // 구조물 — 저장 뒤 서버 목록(새 식별자)으로 화면을 맞춘다. 실패는 자체 토스트로 알리고 // 세션에 남겨 두므로 저장 전체를 멈추지 않는다(2026-08-29 — CLAUDE.md 5장). structures: () => ctx.bridge().saveStructuresIfDirty(), // 상단측 + 비정규 측점 — 데이터로는 확정 저장하되, 단계 완료 전이는 하지 않는다. uphill: async () => { const latest = ctx.latest(); await confirmRoute( projectId, { filter_key: latest?.surface_params.source_filter, method: latest?.surface_params.method, smooth: latest?.surface_params.smooth, surface_model_id: ctx.confirmedSurface()?.model_id ?? undefined, irregular_stations: ctx .bridge() .irregularStations() .map((station) => ({ chainage_m: station.chainage_m, structure: station.structure, })), // 상단측(측구 방향) 사용자 변경분 — 종단 정본에 병합되어 B06이 그대로 소비한다. uphill_overrides: [...ctx.uphillOverrides.entries()].map(([chainage, side]) => ({ chainage_m: Number(chainage), side, })), }, false, ); }, }, // 횡단 본문은 늘 횡단 보기 몫 — [저장]이 숨긴 채라도 세움(386-6 · 옛 캐시 패치 길 지움) // 공유 캐시는 한 벌(`design_shared`)이 저장 끝에 한 번 비움 — 여기서는 새 자료를 다시 읽어 종단 · // 평면 오른쪽 판을 그림(416 · 노선 안 바뀐 [저장]도 · B06 다녀오지 않아도 면적 = B06) done: async () => { ctx.renderLatest(await ctx.loadLatest(true)); const routeId = pageRouteId(projectId); if (routeId !== null) await ctx.restoreSections(routeId); }, }; }