Files
Aislo/B07_DesignDetail/B07_DesignDetail_UI_Settings.ts
T

128 lines
5.1 KiB
TypeScript

/* =============================================================================
* B07_DesignDetail_UI_Settings.ts
* 좌측 도면 묶음 ⚙ 설정 모달(요구 280-5) — 공용 `openModal` · 머리 [원본에서 다시 그리기](281).
*
* 평면도 = 평면도 관리 모달 그대로(`openPlanManager`)
* 횡단도 = 장 배치(열 · 행 · [이 장] · [모든 장]) · 표 배율 · [안내선 숨기기] — 좌측 카드 밑에서 옮김
* 구조물 도면 = 「M02 그림 — 축척 없음」 한 줄 · 종단 · 횡단 · 토적 · 전개도 = X · Y 축척 칸(`_UI_Settings_Scale`)
* [원본에서 다시 그리기] = 지금 연 도면이 그 묶음일 때만 켬
* ========================================================================== */
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";
import { mountDrawingScale } from "./B07_DesignDetail_UI_Settings_Scale";
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 그림 — 축척 없음"));
mountDrawingScale(body, kind, deps, close);
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;
body.classList.add("ui-panel-form"); // 칸 · 단추 꼴 = 좌측 패널 때와 같음(269)
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("배치를 받지 못했습니다.")));
}