Files
Aislo/B05_Profile/B05_Profile_UI_Page_Actions.ts
T
eomsangdonandClaude Opus 5.5 9feba3de10 fix(B05·B06 한 페이지): 저장 끝 캐시 한 번 비움 · 종단 다시 읽음 · 관 길이 = 공용 캐시 · 평면 횡단 판 = 페이지 노선 · 암선 기본 config (416-1)
- M1: [저장] 끝 한 벌이 상세 캐시를 한 번 비움 · 종단 보기 done 이 새 상세 다시 읽어 종단 · 평면 판 그림 (보기마다 비우던 것 지움)
- M5: 관 길이 출처 = 페이지가 거는 공용 캐시(페이지 노선) 한 벌 · 보기마다 걸던 것 지움
- L2: peekSectionDetail(projectId, routeId) = 그 노선 상세 · 가장 큰 노선 번호 고르기 지움
- 암선 기본 = 종단 보기가 기억한 context(config) 값
- 시험 test_416_page_cache.py

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VmC34fsxxbweEG3RUjs3Mn
2026-10-18 12:22:53 +09:00

85 lines
4.6 KiB
TypeScript

/* =============================================================================
* 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<typeof createRouteViewer>;
panel: () => ReturnType<typeof createRoutePanel>;
profilePanel: () => ReturnType<typeof createRouteProfilePanel>;
bridge: () => ReturnType<typeof createStructuresBridge>;
/** 상단측(측구 방향) 사용자 변경분 — 키는 누가거리 문자열. */
uphillOverrides: Map<string, "left" | "right">;
persistUphillOverrides: () => void;
loadLatest: (forceFresh?: boolean) => Promise<RouteLatestResponse>;
renderLatest: (next: RouteLatestResponse) => void;
restoreSections: (routeId: number) => Promise<void>;
}
/** [저장] · [확정]에 종단 보기가 보태는 몫 — 차례는 저장 한 줄기(`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);
},
};
}