/* ============================================================================= * B05_Profile_Api_PlusStations.ts * 추가 측점(368-2 · 요구 240-21) — 종단 원지반선에서 넣은 일반 측점(정수 m · 이름 없음). * * 초안 = 설계 가게 `plusStations`(세션 · 되돌리기 사진첩에 듦) · 저장분 = 서버 `plus_stations.json` * (`GET/PUT /section/plus-stations`) · [저장] 차례 = 구조물 뒤 · 계획고 앞(`design_save`). * 측점 계획(`planStations`)이 읽는 곳 = 초안 ?? 저장분(`setPlusStations` · 부를 때마다 읽음). * ========================================================================== */ import { API_BASE_URL, API_TIMEOUT_MS } from "../config/config_frontend"; import { draftProjectId, useDesignStore } from "../A00_Common/design/design_store"; import { onPageHistory } from "./B05_Profile_UI_Profile_History"; const saved = new Map(); const loaded = new Map>(); async function request(projectId: string, init: RequestInit = {}): Promise { const controller = new AbortController(); const timer = window.setTimeout(() => controller.abort(), API_TIMEOUT_MS); try { const response = await fetch(`${API_BASE_URL}/projects/${projectId}/section/plus-stations`, { credentials: "include", headers: { "Content-Type": "application/json" }, signal: controller.signal, ...init, }); const payload = await response.json().catch(() => null); if (!response.ok) throw new Error(payload?.message ?? `요청이 실패했습니다 (${response.status}).`); return Array.isArray(payload?.chainages) ? payload.chainages.map(Number) : []; } finally { window.clearTimeout(timer); } } export const readPlusDraft = (projectId: string): number[] | null => useDesignStore(projectId, null).get("plusStations"); /** 지금 추가 측점 — 초안이 있으면 초안(빈 목록 = 다 지움) · 없으면 저장분. */ export const plusStationsOf = (projectId: string): number[] => readPlusDraft(projectId) ?? saved.get(projectId) ?? []; /** 초안을 씀(정렬 · 같은 m 하나) — 바뀜 신호로 B05 종단 · B06 목록이 다시 맞춤. */ export function writePlusDraft(projectId: string, next: number[] | null): void { const list = next && [...new Set(next.map(Math.round))].sort((a, b) => a - b); useDesignStore(projectId, null).set("plusStations", list); } /** 저장분이 바뀜 — 듣는 쪽을 부름(초안 칸 값 그대로 다시 씀). */ function notify(projectId: string): void { useDesignStore(projectId, null).set("plusStations", readPlusDraft(projectId)); } // 되돌리기 · 다시하기는 세션을 바로 되씀 — 바뀜 신호를 다시 냄(종단 측점선 · B06 목록) · 다른 되살림이 // 측점 목록을 다시 세운 뒤(같은 차례 안에서 덮이지 않게) onPageHistory({ restore: () => void setTimeout(() => notify(draftProjectId()), 0) }); /** 저장분을 한 번 받음(못 받으면 빈 목록) — 읽는 곳 두기(`setPlusStations`)는 횡단 상세 가게 몫. */ export function loadSavedPlusStations(projectId: string): Promise { if (!loaded.has(projectId)) loaded.set( projectId, request(projectId) .then((list) => { saved.set(projectId, list); if (list.length) notify(projectId); }) .catch(() => undefined), ); return loaded.get(projectId)!; } /** [저장] 차례 — 초안이 있으면 정본에 씀 · 없으면 저장분만 다시 받음(노선 저장이 좌표로 옮겼을 수 있음). */ export async function flushPlusStations(projectId: string): Promise { const draft = readPlusDraft(projectId); const list = draft ? await request(projectId, { method: "PUT", body: JSON.stringify({ chainages: draft }) }) : await request(projectId); saved.set(projectId, list); loaded.set(projectId, Promise.resolve()); if (draft) useDesignStore(projectId, null).set("plusStations", null); else notify(projectId); }