Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018jonfdxn1Xit9bdkNJpE4G
145 lines
6.6 KiB
TypeScript
145 lines
6.6 KiB
TypeScript
/* =============================================================================
|
|
* B06_Section_UI_Cross_View_Panels.ts
|
|
* 횡단 카드 ↔ **배수관 · 흙막이 조정창 두 벌**(카드 안 · 좌측 [횡단 조정] 사본) 배선 —
|
|
* 카드 렌더러(`_UI_Cross_View.ts`)가 700줄을 넘어 떼었다(137-1). 그리기 · 기하는 하지 않는다.
|
|
* ========================================================================== */
|
|
|
|
import type { CrossSection } from "./B06_Section_Api_Fetch";
|
|
import type { RevetKey, RevetPick } from "./B06_Section_UI_Cross_Culvert";
|
|
import { REVET_FORM_DEFAULT } from "./B06_Section_UI_Cross_Culvert_Const";
|
|
import type { WallAdjust } from "./B06_Section_UI_Cross_Culvert_Types";
|
|
import type {
|
|
CulvertLink,
|
|
ExtraWallControl,
|
|
InletStructureControl,
|
|
RevetLinkControl,
|
|
RevetOffsetControl,
|
|
StructureSpanControl,
|
|
} from "./B06_Section_UI_Cross_Culvert_Wire";
|
|
import { buildStructurePanel } from "./B06_Section_UI_Cross_Structure_Panel";
|
|
import { adoptAdjustPanel, releaseAdjustPanel } from "./B06_Section_UI_Adjust_Dock";
|
|
import { structurePanelDeps } from "./B06_Section_UI_Cross_View_Structure";
|
|
|
|
/** 조정창이 읽는 카드 상태 — 마지막 계산 결과(그릴 때마다 바뀜). */
|
|
export interface CardCulvertState {
|
|
/** 유입이 집수정인가 — 조정창 표시 · 제목 분기. */
|
|
inletIsBasin: boolean;
|
|
/** 기준벽이 **독립 기슭막이**인가(관 없는 숨김 세트) — 걸음 0.1 m(2026-08-29 사용자). */
|
|
hiddenPipe: boolean;
|
|
/** 드롭다운 선택지 가용성(2026-08-22) — 기하 판정을 조정창에 전달. */
|
|
inletOptions: { revetAllowed: boolean; basinLUAllowed: boolean };
|
|
/** 추가 기슭막이 상태(2026-08-22) — 끝 성토부 5m 이상(canAdd) · 세워진 개수. */
|
|
extraState: { canAdd: boolean; count: number };
|
|
/** 집수정 계류측 다단 상태(2026-08-22) — 조정창의 집수정 단 수 행이 쓴다. */
|
|
basinExtraState: { canAdd: boolean; count: number };
|
|
/** 마지막 계산의 벽 제원(높이 · 재질) — 배관 벽은 순수 높이(2026-08-23 사용자). */
|
|
wallSpecs: Map<RevetKey, { height: number; form: string }>;
|
|
/** 마지막 계산의 실제 적용 d(상하) — d 미지정(자동) 벽의 ▲▼ 시작값. */
|
|
appliedD: Map<RevetKey, number>;
|
|
}
|
|
|
|
export const emptyCardCulvertState = (): CardCulvertState => ({
|
|
inletIsBasin: false,
|
|
hiddenPipe: false,
|
|
inletOptions: { revetAllowed: true, basinLUAllowed: true },
|
|
extraState: { canAdd: false, count: 0 },
|
|
basinExtraState: { canAdd: false, count: 0 },
|
|
wallSpecs: new Map(),
|
|
appliedD: new Map(),
|
|
});
|
|
|
|
export interface CardPanelsInput {
|
|
section: CrossSection;
|
|
culvertLink?: CulvertLink;
|
|
isLinkedCulvert: boolean;
|
|
revetOffset?: RevetOffsetControl;
|
|
inletStructure?: InletStructureControl;
|
|
extraWalls?: ExtraWallControl;
|
|
structureSpan?: StructureSpanControl;
|
|
revetLink?: RevetLinkControl;
|
|
state: CardCulvertState;
|
|
activeRevet: () => RevetPick | null;
|
|
setActiveRevet: (key: RevetPick | null) => void;
|
|
toggleRevet: (key: RevetPick) => void;
|
|
}
|
|
|
|
/** 카드 안 조정창 + 좌측 사본을 만든다. `show` = 고른 벽(없으면 null)으로 두 창을 맞춤. */
|
|
export function buildCardPanels(input: CardPanelsInput): {
|
|
root: HTMLElement;
|
|
show: (key: RevetPick | null) => void;
|
|
} {
|
|
const { section, culvertLink, isLinkedCulvert, revetOffset, revetLink, state } = input;
|
|
// 구조물 조정은 도면 안 오버레이 창(2026-08-21). 화면 좌(◀) = offset 증가 —
|
|
// 벽 기준 이동량(outward 부호)으로 환산해 넘긴다.
|
|
// 유입측 벽 — 기준벽과 유입측 다단(bextra). 빼먹으면 그 벽만 좌우가 뒤집힌다.
|
|
const inletSideRole = (role: RevetKey): boolean => role === "inlet" || role.startsWith("bextra");
|
|
const outwardOf = (role: RevetKey): number =>
|
|
// 독립 기슭막이는 배관 유입/유출과 무관 — 정본 설치 측(좌 = +offset)으로 부호를 잡는다.
|
|
role === "own"
|
|
? section.revetment?.side === "우"
|
|
? -1
|
|
: 1
|
|
: ((section.uphill_side ?? "left") === "left") === inletSideRole(role)
|
|
? 1
|
|
: -1;
|
|
const heightOfWall = (key: RevetKey): number => state.wallSpecs.get(key)?.height ?? 0;
|
|
const formOfWall = (key: RevetKey): string =>
|
|
state.wallSpecs.get(key)?.form ?? REVET_FORM_DEFAULT;
|
|
// 연동 중인 링크 카드의 조작은 **소유 측점**에 실린다(2026-08-24) — 풀면 자기 값.
|
|
const adjustTarget = (): CrossSection =>
|
|
isLinkedCulvert && culvertLink && (revetLink?.linkedFor(section) ?? true)
|
|
? culvertLink.source
|
|
: section;
|
|
// 연동을 푼 측점에서 **아직 손대지 않은** 벽은 소유 측점 값을 보여 준다 — 창이
|
|
// 0(자동)을 보여 주면 첫 ◀ 한 번에 벽이 원위치로 튄다(2026-08-30).
|
|
const adjustOf = (key: RevetKey): WallAdjust => {
|
|
const stored = revetOffset?.storedAdjustFor(adjustTarget(), key);
|
|
if (stored) return stored;
|
|
const source = isLinkedCulvert && culvertLink ? culvertLink.source : section;
|
|
return revetOffset?.adjustFor(source, key) ?? { x: 0, d: null, h: null, m: null };
|
|
};
|
|
const panelContext = {
|
|
section,
|
|
scrollKey: section.station_id,
|
|
adjustChainage: () => adjustTarget().chainage_m,
|
|
isLinked: isLinkedCulvert,
|
|
revetOffset,
|
|
inletStructure: input.inletStructure,
|
|
extraWalls: input.extraWalls,
|
|
structureSpan: input.structureSpan,
|
|
revetLink,
|
|
adjustOf,
|
|
outwardOf,
|
|
heightOfWall,
|
|
drawnWallKeys: () => [...state.wallSpecs.keys()],
|
|
formOfWall,
|
|
appliedD: () => state.appliedD,
|
|
inletIsBasin: () => state.inletIsBasin,
|
|
hiddenPipe: () => state.hiddenPipe,
|
|
bodyGuard: () => !!(section.culvert ?? culvertLink?.source.culvert)?.body,
|
|
fordGuard: () => (section.culvert ?? culvertLink?.source.culvert)?.body === "ford",
|
|
inletOptions: () => state.inletOptions,
|
|
extraState: () => state.extraState,
|
|
basinExtraState: () => state.basinExtraState,
|
|
activeRevet: input.activeRevet,
|
|
setActiveRevet: input.setActiveRevet,
|
|
toggleRevet: input.toggleRevet,
|
|
};
|
|
const panel = buildStructurePanel(structurePanelDeps(panelContext));
|
|
// 좌측 [횡단 조정] 사본 — 같은 deps라 어느 쪽 조작이든 카드 재렌더에서 두 창이
|
|
// 함께 새 값으로 그려진다(2026-08-29 일원화). 스크롤 기억 키만 분리한다.
|
|
const dockPanel = buildStructurePanel(
|
|
structurePanelDeps({ ...panelContext, scrollKey: `dock:${section.station_id}` }),
|
|
{ dock: true },
|
|
);
|
|
return {
|
|
root: panel.root,
|
|
show: (key) => {
|
|
panel.show(key);
|
|
dockPanel.show(key);
|
|
if (key) adoptAdjustPanel(dockPanel.root);
|
|
else releaseAdjustPanel(dockPanel.root);
|
|
},
|
|
};
|
|
}
|