- 판정 = 저장 노선 대 초안이 그릴 선 정점 1 mm(`routeShapeChanged` · 파이썬 `route_shape_changed` 짝) · 스냅 · 간격 · 지형만 = 아님 - 띠 = 평면(노선 편집) 위 한 줄 · B06 평면 패널로 같이 옮겨짐 · 저장 노선 = 페이지 자료 줄 `pageRoutePlan`(조작마다 안 물음) - [저장] 확인 창 = 잠금 막 · 서버 요청 앞 · 구조물 · 관 · 추가 측점 · 종단 편집 수 · [취소] = 요청 0 · 추천 [적용] 같은 글 · 수 - 저장 뒤 = 응답 `steps.route.route_reset` 지운 수 한 줄 · 초기화면 세션 초안 통째 비움 → 서버 정본으로 다시 세움 · 옛 서버(칸 없음) = 알림 건너뜀 - 시험: 새 test_283_route_reset_confirm(띠 · 확인 창 수 · [취소] · 스냅만 · 거울) · 저장 헬퍼 셋 확인 창 가짜 · 476-2 확인 글 기대 고침 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
102 lines
4.4 KiB
TypeScript
102 lines
4.4 KiB
TypeScript
/* =============================================================================
|
|
* B05_Profile_UI_RouteReset.ts
|
|
* 노선 모양 바뀐 [저장] = 초기화(요구 283 · 284 · 285 · 492-2) — 화면 몫.
|
|
*
|
|
* · 띠 — 평면(노선 편집) 위 한 줄 · 노선 초안이 저장 노선 모양을 바꾸면 보임(B06 평면 패널로 옮겨져도 같이 감).
|
|
* · 확인 창 — [저장](`design_save`) · 추천 [적용](476-2) 앞 · 지워질 수 = 지금 캐시의 사용자 구조물 · 관 ·
|
|
* 추가 측점 · 종단 편집 · [취소] = 요청 0.
|
|
* · 저장 뒤 알림 — 서버 응답 `route_reset`(정본 판정) · 없으면(옛 서버) 건너뜀.
|
|
* 셈 · 글 = `logic/B05_Profile_Route_Reset` · 저장 노선 = 페이지 자료 줄(`pageRoutePlan` · 조작마다 안 물음).
|
|
* ========================================================================== */
|
|
|
|
import { showConfirmDialog } from "@ui/ui_template_elements";
|
|
import type { RouteDraft } from "../A00_Common/design/logic/design_pipeline_types";
|
|
import { useDesignStore } from "../A00_Common/design/design_store";
|
|
import {
|
|
pagePipes,
|
|
pageRouteId,
|
|
pageRoutePlan,
|
|
pageStructures,
|
|
} from "../A00_Common/design/design_page_data";
|
|
import { plusStationsOf } from "./B05_Profile_Api_PlusStations";
|
|
import { pendingAlignment, routeAlignment } from "./B05_Profile_UI_Profile_Edit";
|
|
import {
|
|
askRouteReset,
|
|
draftShapeChanged,
|
|
ROUTE_RESET_BAND,
|
|
routeResetConfirmText,
|
|
type RouteResetCounts,
|
|
} from "./logic/B05_Profile_Route_Reset";
|
|
|
|
/** 노선 초안 동안의 계획고 초안 칸 — `design_pipeline_page` 의 `DRAFT_ROUTE_ID` 와 같은 값. */
|
|
const DRAFT_ROUTE_ID = 0;
|
|
|
|
/** 초안이 저장 노선 모양을 바꾸나(저장 노선을 못 받으면 바뀜으로 봄). */
|
|
export async function draftResets(projectId: string, draft: RouteDraft | null): Promise<boolean> {
|
|
if (!draft) return false;
|
|
const plan = await pageRoutePlan(projectId).catch(() => null);
|
|
return draftShapeChanged(plan?.planned ?? null, draft, plan?.min_radius_m ?? 0);
|
|
}
|
|
|
|
/** 지금 캐시(초안 ?? 저장분)에서 지워질 수. */
|
|
export async function routeResetCounts(projectId: string): Promise<RouteResetCounts> {
|
|
const store = useDesignStore(projectId, null);
|
|
const [structures, pipes] = await Promise.all([
|
|
store.get("structures") ??
|
|
pageStructures(projectId).then(
|
|
(list) => list.structures,
|
|
() => [],
|
|
),
|
|
store.get("pipes") ??
|
|
pagePipes(projectId).then(
|
|
(list) => list.pipe_points,
|
|
() => [],
|
|
),
|
|
]);
|
|
const routeId = pageRouteId(projectId);
|
|
const edits =
|
|
pendingAlignment(DRAFT_ROUTE_ID) ?? (routeId === null ? null : routeAlignment(routeId));
|
|
return {
|
|
structures: structures?.length ?? 0,
|
|
pipes: pipes?.length ?? 0,
|
|
plusStations: plusStationsOf(projectId).length,
|
|
profileEdits:
|
|
Object.keys(edits?.station_offsets ?? {}).length +
|
|
Object.keys(edits?.curve_radii ?? {}).length,
|
|
};
|
|
}
|
|
|
|
/** [저장] 앞 — 모양 바뀐 초안이면 확인 창 · [취소] = false(요청 0) · 안 바뀜 = 묻지 않고 true. */
|
|
export async function confirmRouteReset(projectId: string, draft: RouteDraft): Promise<boolean> {
|
|
return askRouteReset(
|
|
await draftResets(projectId, draft),
|
|
() => routeResetCounts(projectId),
|
|
(text) => showConfirmDialog(text, "저장"),
|
|
);
|
|
}
|
|
|
|
/** 추천 [적용] 확인 창 글 — [저장]과 같은 글 · 수. */
|
|
export async function applyResetText(projectId: string): Promise<string> {
|
|
return routeResetConfirmText(await routeResetCounts(projectId), "적용");
|
|
}
|
|
|
|
/** 평면 위 띠를 세움 — 노선 초안이 바뀔 때마다 맞춤 · 돌려준 함수 = 떠날 때 풂. */
|
|
export function mountRouteResetBand(parent: HTMLElement, projectId: string): () => void {
|
|
const band = document.createElement("div");
|
|
band.className = "b05-routeedit__reset-band";
|
|
band.setAttribute("role", "status");
|
|
band.textContent = ROUTE_RESET_BAND;
|
|
band.hidden = true;
|
|
parent.append(band);
|
|
const store = useDesignStore(projectId, null);
|
|
let turn = 0;
|
|
const sync = async (draft: RouteDraft | null): Promise<void> => {
|
|
const mine = ++turn; // 늦게 온 옛 판정이 새 판정을 덮지 않게
|
|
const changed = await draftResets(projectId, draft);
|
|
if (mine === turn) band.hidden = !changed;
|
|
};
|
|
void sync(store.get("routeDraft"));
|
|
const stop = store.subscribe("routeDraft", (draft) => void sync(draft));
|
|
return () => (stop(), band.remove());
|
|
}
|