diff --git a/B07_DesignDetail/B07_DesignDetail_UI_Panels.ts b/B07_DesignDetail/B07_DesignDetail_UI_Panels.ts index 59bfc6f72..3f49b784d 100644 --- a/B07_DesignDetail/B07_DesignDetail_UI_Panels.ts +++ b/B07_DesignDetail/B07_DesignDetail_UI_Panels.ts @@ -29,14 +29,12 @@ export const DRAWING_GROUPS: readonly { idPrefix?: string; }[] = [ { label: "표지", kind: "cover" }, - // 종류(지형 · 노선배치도 · 대피소 · 라이다 · 사용자 추가)를 한 묶음으로 — PLAN 60장. - { label: "계획평면도", kind: "plan" }, - { label: "종단면도", kind: "longitudinal" }, - { label: "표준 횡단면도", kind: "cross_standard" }, - { label: "횡단면도", kind: "cross" }, + // 종류(지형 · 노선배치도 · 대피소 · 라이다 · 용지도 · 사용자 추가) + 배수유역도를 한 묶음으로. + { label: "평면도", kind: "plan" }, + { label: "종단도", kind: "longitudinal" }, + // 표준 횡단면도는 횡단도 묶음 맨 위 한 줄(93-5). + { label: "횡단도", kind: "cross" }, { label: "토적도(유토곡선)", kind: "mass_haul" }, - { label: "유역도(배수 유역도)", kind: "watershed" }, - { label: "용지도", idPrefix: "landuse" }, ]; /** B06 확정 산출물 기반 도면 목록 패널. */ @@ -91,7 +89,7 @@ export function buildDrawingSidePanel( for (const group of DRAWING_GROUPS) { if (group.kind === "plan") { // 종류를 다 지워도 묶음은 남긴다 — 그 안에서 다시 더한다. - const plans = drawings.filter((item) => item.kind === "plan"); + const plans = drawings.filter((item) => item.kind === "plan" || item.kind === "watershed"); panel.append(buildPlanSection(plans, drawingButton, plan)); continue; } @@ -102,8 +100,9 @@ export function buildDrawingSidePanel( (item) => item.id === group.idPrefix || item.id.startsWith(`${group.idPrefix}_`), ) : drawings.filter((item) => item.id === group.blankId); - // 한 장짜리(와 아직 내용이 없는 도면)는 컨테이너 없이 버튼 하나로 둔다. - if (items.length <= 1) { + const cross = group.kind === "cross"; + // 한 장짜리(와 아직 내용이 없는 도면)는 컨테이너 없이 버튼 하나로 둔다 — 횡단도는 늘 묶음. + if (items.length <= 1 && !cross) { const [drawing] = items; // 서버가 빈 도각을 내주지 못한 경우에만 회색 버튼으로 남는다. if (!drawing) { @@ -135,6 +134,11 @@ export function buildDrawingSidePanel( sectionTitle.className = "ui-collapsible__title"; sectionTitle.textContent = `${group.label} ${items.length}`; section.append(sectionTitle); + if (cross) { + // 표준 횡단면도 = 맨 위 한 줄(전체 폭) · 개수는 횡단 장만. + for (const standard of drawings.filter((item) => item.kind === "cross_standard")) + section.append(drawingButton(standard, standard.label)); + } for (const drawing of items) { // 횡단면도는 장 단위(여러 측점)라 서버가 준 "N장 (구간)" 라벨을 그대로 쓴다. section.append(drawingButton(drawing, drawing.label)); diff --git a/B07_DesignDetail/B07_DesignDetail_UI_PlanKinds.ts b/B07_DesignDetail/B07_DesignDetail_UI_PlanKinds.ts index 7ec37a5f6..d1dd90109 100644 --- a/B07_DesignDetail/B07_DesignDetail_UI_PlanKinds.ts +++ b/B07_DesignDetail/B07_DesignDetail_UI_PlanKinds.ts @@ -1,6 +1,6 @@ /* ============================================================================= * B07_DesignDetail_UI_PlanKinds.ts - * 좌측 도면 목록의 「계획평면도」 한 묶음 — 종류(지형 · 노선배치도 · 대피소 · 라이다 · + * 좌측 도면 목록의 「평면도」 한 묶음 — 종류(지형 · 노선배치도 · 대피소 · 라이다 · * 사용자 추가)별 도면 단추, 종류 지우기 · 추가 · 업데이트, 대피소 · 사토장 자리 (PLAN 60 · 67장). * * 종류 = 정보 조각 고르기 목록이다. 고치면 서버 파일이 바뀌고 `onChanged` 로 화면을 다시 세운다. @@ -47,7 +47,7 @@ async function run(action: () => Promise, controls: PlanKindsControls): await action(); controls.onChanged(); } catch (error) { - showToast(error instanceof Error ? error.message : "계획평면도를 고치지 못했습니다.", "error"); + showToast(error instanceof Error ? error.message : "평면도를 고치지 못했습니다.", "error"); } } @@ -148,7 +148,7 @@ function marksForm(state: PlanKindsState, controls: PlanKindsControls): HTMLElem return form; } -/** 「계획평면도」 묶음 — 종류마다 이름 줄(× 지우기) + 장 단추, 아래에 종류 · 대피소 자리. */ +/** 「평면도」 묶음 — 종류마다 이름 줄(× 지우기) + 장 단추, 아래에 종류 · 대피소 자리. */ export function buildPlanSection( items: DesignDrawingItem[], makeButton: (drawing: DesignDrawingItem, label: string) => HTMLButtonElement, @@ -156,7 +156,7 @@ export function buildPlanSection( ): HTMLElement { const section = el("section", "b07-drawing-group b07-plan ui-collapsible ui-sidebar-section"); section.dataset.kind = "plan"; - section.append(el("h3", "ui-collapsible__title", `계획평면도 ${items.length}`)); + section.append(el("h3", "ui-collapsible__title", `평면도 ${items.length}`)); const kinds = new Map(); for (const item of items) { @@ -173,7 +173,8 @@ export function buildPlanSection( makeButton(drawing, sheets.length > 1 ? `${name} ${index + 1}장` : name), ); head.append(sheets.length > 1 ? el("span", "b07-plan-kind__name", name) : buttons[0]); - if (controls) { + // × 는 종류만 — 배수유역도는 묶음 안 고정 항목(지우면 서버가 404). + if (controls && sheets[0].kind === "plan") { const remove = el("button", "b07-plan-tools__remove", "×"); remove.type = "button"; remove.title = `「${name}」 종류 지우기`; @@ -192,7 +193,7 @@ export function buildPlanSection( // 종류 · 대피소 자리는 펼칠 때 서버에서 지금 상태를 받는다. const tools = el("details", "b07-plan-tools"); tools.append(el("summary", "", "종류 추가 · 업데이트 · 대피소 자리")); - tools.addEventListener("toggle", () => { + const load = (): void => { if (!tools.open || tools.dataset.loaded) return; tools.dataset.loaded = "true"; void fetchPlanKinds(controls.projectId) @@ -204,7 +205,11 @@ export function buildPlanSection( "error", ); }); - }); + }; + tools.addEventListener("toggle", load); + // 기본 펼침 — 종류마다 얹을 정보(사용자 지정)가 바로 보이게(93-6). + tools.open = true; + load(); section.append(tools); } return section; diff --git a/B07_DesignDetail/B07_DesignDetail_UI_Style.css b/B07_DesignDetail/B07_DesignDetail_UI_Style.css index 20dd06b03..fcc59ec17 100644 --- a/B07_DesignDetail/B07_DesignDetail_UI_Style.css +++ b/B07_DesignDetail/B07_DesignDetail_UI_Style.css @@ -80,8 +80,9 @@ cursor: not-allowed; } -/* 그리드 제목은 두 열을 가로지른다 */ -.b07-drawing-group[data-kind="cross"] h3 { +/* 그리드 제목 · 표준 횡단면도는 두 열을 가로지른다 */ +.b07-drawing-group[data-kind="cross"] h3, +.b07-drawing-group[data-kind="cross"] [data-drawing-id="cross_standard"] { grid-column: 1 / -1; }