Files
Aislo/B07_DesignDetail/B07_DesignDetail_UI_Settings.ts
T
eomsangdonandClaude Opus 5.5 659baa7751 feat(484 B07 설정): 좌측 ⚙ 설정 모달 · [현재 도면 확정] · [수정] 지움 · 저장 후 이동(481-3) · 탭 줄 겹판 자리
- 공용 createPanelCard 곁값 onSettings — 캐럿 왼쪽 ⚙ · 누름이 접힘 안 일으킴(B08 · B09 그대로)
- 평면도 ⚙ = 평면도 관리 모달([평면도 관리] 단추 지움) · 횡단도 ⚙ = 배치 칸 · 표 배율 · 안내선(카드 밑 칸 지움) · 구조물 ⚙ = 「M02 그림 — 축척 없음」 · 종단 1장 · 토적 = 단추 안 ⚙ · 표지 없음
- ⚙ 머리 [원본에서 다시 그리기] — 그 묶음 도면을 연 때만 · 저장본이면 invalidate
- 잠금 없음(요구 281) — 읽기 전용 안 묶음 · 자동 B08 이동 · 「모든 횡단 확정」 잠금 지움
- onStepClick 한 길 = 고친 탭(●) + 지금 탭 저장 → B08 · B09 면 단계 4 완료(새 POST design-drawings-complete) → 이동 · 실패 = 머묾
- 저장 · 원본 묶음 = 새 B07_DesignDetail_UI_Save.ts · 모달 = 새 B07_DesignDetail_UI_Settings.ts(UI_Page 633 → 543줄)
- 탭 줄 = .cad-host 의 --cad-tab-slot-left/right(px · CSS left · right 꼴) 있으면 리본 빈 자리에 겹침 · 없으면 지금 자리
- 시험: 새 test_280_5_b07_settings · 130 · 153-1 · 180-3 · 212-3 · 269 · 311 고쳐 씀

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 22:13:04 +09:00

125 lines
4.9 KiB
TypeScript

/* =============================================================================
* B07_DesignDetail_UI_Settings.ts
* 좌측 도면 묶음 ⚙ 설정 모달(요구 280-5) — 공용 `openModal` · 머리 [원본에서 다시 그리기](281).
*
* 평면도 = 평면도 관리 모달 그대로(`openPlanManager`)
* 횡단도 = 장 배치(열 · 행 · [이 장] · [모든 장]) · 표 배율 · [안내선 숨기기] — 좌측 카드 밑에서 옮김
* 구조물 도면 = 「M02 그림 — 축척 없음」 한 줄 · 종단 · 토적 · 전개도 = 몸 비움(축척 칸은 485-2)
* [원본에서 다시 그리기] = 지금 연 도면이 그 묶음일 때만 켬
* ========================================================================== */
import { createButton } from "@ui/ui_template_elements";
import { openModal } from "@ui/ui_template_modal";
import type { CrossLayout, DesignDrawingItem } from "./B07_DesignDetail_Api_Fetch";
import {
buildCrossLayoutControls,
DRAWING_GROUPS,
isCrossSheet,
} from "./B07_DesignDetail_UI_Panels";
import { openPlanManager, type PlanManageControls } from "./B07_DesignDetail_UI_PlanManage";
type Kind = DesignDrawingItem["kind"];
export interface DrawingSettingsDeps {
drawings: DesignDrawingItem[];
current: () => DesignDrawingItem | undefined;
/** 지금 도면에 버릴 것(저장본 · 고친 것)이 있나 */
canRedraw: () => boolean;
/** 원본에서 다시 그리기 — 해냈으면 참(모달 닫음) */
redraw: () => Promise<boolean>;
plan?: PlanManageControls;
cross: {
layout: () => Promise<CrossLayout>;
/** 배치 저장 — 모달은 닫힌 뒤 · `sheet` = 지금 장 번호(장 아니면 0) */
save: (next: CrossLayout, sheet: number) => void;
guideToggle: HTMLButtonElement;
};
}
/** ⚙ 묶음에 드는 도면 종류 — 횡단도 카드엔 표준 횡단면도 줄이 같이 있음. */
const memberOf = (kind: Kind): Kind[] => (kind === "cross" ? ["cross", "cross_standard"] : [kind]);
const note = (text: string): HTMLElement => {
const line = document.createElement("p");
line.className = "b07-settings__note";
line.textContent = text;
return line;
};
/** 묶음 `kind` 의 ⚙ 모달을 엶. */
export function openDrawingSettings(kind: Kind, deps: DrawingSettingsDeps): void {
const current = deps.current();
const mine = !!current && memberOf(kind).includes(current.kind);
let closeModal = (): void => undefined;
const redraw = createButton({
label: "원본에서 다시 그리기",
variant: "ghost",
disabled: !(mine && deps.canRedraw()),
onClick: () => {
void deps.redraw().then((done) => done && closeModal());
},
});
redraw.title = !mine
? "이 묶음 도면을 연 뒤 쓸 수 있음"
: redraw.disabled
? "이미 원본 그대로"
: "저장본 · 고친 것을 버리고 B06 원본에서 새로 그림";
redraw.classList.add("b07-settings__redraw");
if (kind === "plan" && deps.plan) {
const manager = openPlanManager({ ...deps.plan, actions: [redraw] });
closeModal = manager.close;
return;
}
const label = DRAWING_GROUPS.find((group) => group.kind === kind)?.label ?? "도면";
openModal({
title: `${label} 설정`,
closeLabel: "닫기",
dialogClass: "b07-settings",
actions: [redraw],
mount: (body, close) => {
closeModal = close;
if (mine) body.append(note(`지금 도면: ${current?.label}`));
if (kind === "structure") body.append(note("M02 그림 — 축척 없음"));
if (kind === "cross") mountCross(body, deps, close);
},
});
}
/** 횡단 모달 몸 — 배치 칸은 받은 뒤 · 안내선 단추는 먼저(배치를 못 받아도 남음). */
function mountCross(body: HTMLElement, deps: DrawingSettingsDeps, close: () => void): void {
const current = deps.current();
const sheet =
current && isCrossSheet(current)
? deps.drawings.filter(isCrossSheet).findIndex((item) => item.id === current.id) + 1
: 0;
const holder = document.createElement("div");
holder.className = "b07-cross-layout";
holder.append(deps.cross.guideToggle);
body.append(holder);
void deps.cross
.layout()
.then((layout) => {
const apply = (next: CrossLayout): void => {
close();
deps.cross.save(next, sheet);
};
const controls = buildCrossLayoutControls(
(sheet && layout.sheets[String(sheet)]) || layout.default,
sheet
? (grid) => apply({ ...layout, sheets: { ...layout.sheets, [String(sheet)]: grid } })
: null,
(grid) => apply({ ...layout, default: grid, sheets: {} }),
{
scale: {
value: layout.table_scale ?? 1,
onApply: (scale) => apply({ ...layout, table_scale: scale }),
},
},
);
controls.append(deps.cross.guideToggle);
holder.replaceWith(controls);
})
.catch(() => holder.prepend(note("배치를 받지 못했습니다.")));
}