feat(B 페이지): 떠남 물음 가드 · 지금 프로젝트 = 탭마다 (PLAN 572-2 · 요구 400~403)

- B04 · B07 · B08 · B09 가 공용 guardProjectLeave 에 {dirty, save, discard} 등록 — 고침 있을 때만 [취소 · 폐기 · 저장]
  - B04 = 관 지점 고침(drainageDirty) · 저장 = 관 지점 · 세부유역 영구저장
  - B07 = CAD · 탭 고침 · 저장 = saveEditedDrawings · 폐기 = 고친 도면 CAD 자동백업도 버림(discardEditedRecovery)
  - B08 = 세션 b08-* 칸 넷 · 저장 = saveShown · B09 = b09-estimation 칸 · 저장 = saveChanged
- 지금 프로젝트 직접 읽기(localStorage) → currentProjectId() · B02 새 프로젝트 = setCurrentProject — B02 · B03 · B04 · B07 · B08 · B09 · B11
- 다른 프로젝트 보관함 지우기 셋(B04 · B05 종단 · B11) 뺌 — enterProject 한 곳 · 다른 탭 보관분 안 지움
- B02 · B03 은 가드 없음 — 저장 안 한 프로젝트 값 없음(B03 올리기 끊김은 이어 올리기 배너가 받음)
- 시험 test_560_4 넓힘(B 가드 · 탭 프로젝트 · 보관함) · helper_298_2 · helper_481_2 · test_204_2 흉내를 currentProjectId 로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-28 18:07:58 +09:00
co-authored by Claude Opus 5.5
parent 92d952d8ac
commit 676b46eb9e
21 changed files with 154 additions and 47 deletions
+10 -2
View File
@@ -20,7 +20,6 @@ import {
} from "@ui/ui_template_elements";
import { askConfirm } from "@ui/ui_template_modal";
import { createWorkflowLayout } from "@ui/ui_template_workflow_layout";
import { CURRENT_PROJECT_ID_KEY } from "@config/config_frontend";
// 좌측 패널(도면 목록·설계 정보)은 파일이 700줄을 넘어 떼어냈다(2026-09-04).
import {
buildDesignInfoPanel,
@@ -70,12 +69,14 @@ import {
resetDrawings,
saveDrawingsNow,
saveEditedDrawings,
discardEditedRecovery,
} from "./B07_DesignDetail_UI_Save";
import { openDrawingSettings } from "./B07_DesignDetail_UI_Settings";
// CAD iframe 부모 흐름 · 도각 편집은 M02 와 한 벌로 공용에 둔다(PLAN 10-3).
import { createCadHost, type CadSaveResult } from "@ui/cad_host/cad_host";
import { createFrameTemplateEditor } from "@ui/cad_host/cad_host_frame_edit";
import { createCadTabs, type CadTab } from "@ui/cad_host/cad_host_tabs";
import { currentProjectId, guardProjectLeave } from "../A00_Common/b_project_switch";
/** CAD 앱 수량 패널로 넘기는 설계 컨텍스트 (openwebcad DesignMeta와 동일 형식). */
interface DesignMeta {
@@ -106,7 +107,7 @@ let reopenDrawingId: string | undefined;
let reopenCrossSheet: number | undefined;
export async function renderB07DesignDetail(root: HTMLElement): Promise<void> {
const projectId = localStorage.getItem(CURRENT_PROJECT_ID_KEY);
const projectId = currentProjectId();
// 311 다시 세우면 옛 목록 접힘 그대로 — 기다리기 전에 읽음(처음 들어오면 B07 목록이 없어 기본값)
const folded = foldedGroups(root);
let workflowState: WorkflowState | undefined;
@@ -516,6 +517,13 @@ export async function renderB07DesignDetail(root: HTMLElement): Promise<void> {
});
layout.root.classList.add("b07-design-layout");
root.replaceChildren(layout.root);
// 572-2 떠남 물음 — 고침 = CAD · 탭 · 저장 = 단계 이동과 같은 길 · 폐기 = 고친 도면 CAD 자동백업도
if (projectId)
guardProjectLeave(layout.root, {
dirty: () => cadDirty || tabs.anyDirty(),
save: () => saveEditedDrawings(store),
discard: () => discardEditedRecovery(store),
});
// 페이지 진입 시 첫 도면(표지 · 311)을 자동 선택 — 빈 CAD 화면 방지.
// CAD가 아직 준비 전이면 cad.load 가 붙들고 있다가 ready 때 보낸다.
@@ -222,3 +222,16 @@ export async function resetDrawings(store: DrawingStore): Promise<void> {
hideLoadingOverlay();
}
}
/** 떠남 [폐기](572-2) — 고친 도면(지금 CAD · 고친 탭)의 CAD 자동백업만 버림 · 다음에 들어와도 안 살아남. */
export function discardEditedRecovery(store: DrawingStore): void {
const ids = store.tabs
.tabs()
.filter((tab) => tab.dirty)
.map((tab) => tab.id);
const current = store.current();
if (current && store.cadDirty()) ids.push(current.id);
ids.forEach((id) =>
localStorage.removeItem(`${CAD_RECOVERY_KEY}__${recoveryScopeOf(store.projectId, id)}`),
);
}