From c8b30810f61f5f44c35e9a73b6312860a6b014e5 Mon Sep 17 00:00:00 2001 From: mind-one001 Date: Thu, 1 Oct 2026 15:54:43 +0900 Subject: [PATCH] style(sn): format integrated map modules --- .../components/aged-pipe/aged-pipe-layer.ts | 41 +++- .../aged-pipe/aged-pipe-popup-page.tsx | 6 +- .../sn/app/(map-layout)/map/lib/layer-tree.ts | 7 +- .../map/lib/use-map-runtime-bridge.ts | 24 +- .../(map-layout)/map/ui/map-page-client.tsx | 206 +++++++++++++++--- .../entities/facility/lib/aged-pipe-utils.ts | 13 +- .../ui/fldng-predc-prst-popup-content.tsx | 4 +- .../lib/flow-direction-selection.ts | 3 +- 8 files changed, 249 insertions(+), 55 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/components/aged-pipe/aged-pipe-layer.ts b/apps/sn/app/(map-layout)/map/components/aged-pipe/aged-pipe-layer.ts index afdbadb9e..6f4db0d4b 100644 --- a/apps/sn/app/(map-layout)/map/components/aged-pipe/aged-pipe-layer.ts +++ b/apps/sn/app/(map-layout)/map/components/aged-pipe/aged-pipe-layer.ts @@ -1,24 +1,35 @@ /** 노후관로의 지도와 목록이 사용하는 DB 레이어 설정 계약이다. */ import { getRawJson } from "@/shared/api/sewerage-api"; -import { buildAgedPipeCqlFilters, isAgedPipeLayerNode, type AgedPipeFilters } from "@/entities/facility/lib/aged-pipe-utils"; +import { + buildAgedPipeCqlFilters, + isAgedPipeLayerNode, + type AgedPipeFilters, +} from "@/entities/facility/lib/aged-pipe-utils"; /** DB 응답을 그대로 보존하며 최초 표출 전에 필터만 해석한다. */ -export const prepareAgedPipeLayerRows = (rows: any[], filters: AgedPipeFilters): any[] => +export const prepareAgedPipeLayerRows = ( + rows: any[], + filters: AgedPipeFilters, +): any[] => rows.map((row) => { const next = { ...row }; if (isAgedPipeLayerNode(row)) { next.agedPipeFilterTemplate = row.flterSql; try { validateAgedPipeLayer(row); - next.flterSql = buildAgedPipeCqlFilters(filters, row.flterSql).join(" AND "); + next.flterSql = buildAgedPipeCqlFilters(filters, row.flterSql).join( + " AND ", + ); } catch (error) { // 노후관로 DB 미전환이 다른 시설물 레이어까지 중단시키지 않도록 이 행만 차단한다. - next.agedPipeConfigError = error instanceof Error ? error.message : "노후관로 레이어 설정 오류"; + next.agedPipeConfigError = + error instanceof Error ? error.message : "노후관로 레이어 설정 오류"; next.actlLyrYn = "N"; next.flterSql = "EXCLUDE"; } } - if (Array.isArray(row.children)) next.children = prepareAgedPipeLayerRows(row.children, filters); + if (Array.isArray(row.children)) + next.children = prepareAgedPipeLayerRows(row.children, filters); return next; }); @@ -26,7 +37,9 @@ export const prepareAgedPipeLayerRows = (rows: any[], filters: AgedPipeFilters): export const findAgedPipeLayer = (rows: any[]): any | undefined => { for (const row of rows) { if (isAgedPipeLayerNode(row)) return row; - const child = Array.isArray(row.children) ? findAgedPipeLayer(row.children) : undefined; + const child = Array.isArray(row.children) + ? findAgedPipeLayer(row.children) + : undefined; if (child) return child; } }; @@ -34,14 +47,24 @@ export const findAgedPipeLayer = (rows: any[]): any | undefined => { /** 예전 제어용 행을 실제 WFS 레이어처럼 요청하지 않도록 전환 상태를 확인한다. */ export const validateAgedPipeLayer = (row: any) => { if (row?.agedPipeConfigError) throw new Error(row.agedPipeConfigError); - if (!row || row.actlLyrYn !== "Y" || row.srvcNm !== "wfs" || !row.lyrTyNm || row.lyrTyNm === "tb_old_pipe") { - throw new Error("노후관로 DB 레이어 설정을 실제 WFS 레이어와 sql_filt 템플릿으로 갱신해 주세요."); + if ( + !row || + row.actlLyrYn !== "Y" || + row.srvcNm !== "wfs" || + !row.lyrTyNm || + row.lyrTyNm === "tb_old_pipe" + ) { + throw new Error( + "노후관로 DB 레이어 설정을 실제 WFS 레이어와 sql_filt 템플릿으로 갱신해 주세요.", + ); } }; /** 독립 목록 팝업도 부모창의 하드코딩 없이 동일 설정 API를 조회한다. */ export const fetchAgedPipeLayer = async () => { - const rows = await getRawJson("/sewerage-service/api/v1/map/lyrStngs/SN_NETWORK"); + const rows = await getRawJson( + "/sewerage-service/api/v1/map/lyrStngs/SN_NETWORK", + ); const row = findAgedPipeLayer(Array.isArray(rows) ? rows : []); validateAgedPipeLayer(row); return row; diff --git a/apps/sn/app/(map-layout)/map/components/aged-pipe/aged-pipe-popup-page.tsx b/apps/sn/app/(map-layout)/map/components/aged-pipe/aged-pipe-popup-page.tsx index b9a31efe5..5c96c0d6d 100644 --- a/apps/sn/app/(map-layout)/map/components/aged-pipe/aged-pipe-popup-page.tsx +++ b/apps/sn/app/(map-layout)/map/components/aged-pipe/aged-pipe-popup-page.tsx @@ -150,7 +150,11 @@ export default function AgedPipePopupPage() { setAppliedFilters(normalizeAgedPipeFilters(nextFilters)); } catch (error) { console.error("노후관로 목록 조회 중 오류:", error); - alert(error instanceof Error ? error.message : "노후관로 목록 조회 중 오류가 발생했습니다."); + alert( + error instanceof Error + ? error.message + : "노후관로 목록 조회 중 오류가 발생했습니다.", + ); setRows([]); setTotal(0); } finally { diff --git a/apps/sn/app/(map-layout)/map/lib/layer-tree.ts b/apps/sn/app/(map-layout)/map/lib/layer-tree.ts index d734b6c08..0ad7f2d45 100644 --- a/apps/sn/app/(map-layout)/map/lib/layer-tree.ts +++ b/apps/sn/app/(map-layout)/map/lib/layer-tree.ts @@ -1,4 +1,3 @@ - import { SINKHOLE_TREE_ICON_NAME } from "../model/map-constants"; export const normalizeTreeRowSpacing = (data: any[]) => { @@ -16,4 +15,8 @@ export const normalizeTreeRowSpacing = (data: any[]) => { }; }); }; -export { extractUsageCodesFromLayerInfo, isLayerVisibleAtZoom, extractCheckedPipeUsageStyles } from "@/features/map-layers/lib/flow-direction-selection"; +export { + extractUsageCodesFromLayerInfo, + isLayerVisibleAtZoom, + extractCheckedPipeUsageStyles, +} from "@/features/map-layers/lib/flow-direction-selection"; diff --git a/apps/sn/app/(map-layout)/map/lib/use-map-runtime-bridge.ts b/apps/sn/app/(map-layout)/map/lib/use-map-runtime-bridge.ts index 980074046..c8882a6e1 100644 --- a/apps/sn/app/(map-layout)/map/lib/use-map-runtime-bridge.ts +++ b/apps/sn/app/(map-layout)/map/lib/use-map-runtime-bridge.ts @@ -1,6 +1,11 @@ "use client"; import type { useFloodPredictionMap } from "@/features/fldng-predc-prst/lib/use-flood-prediction-map"; -import { useEffect, type MutableRefObject, type Dispatch, type SetStateAction } from "react"; +import { + useEffect, + type MutableRefObject, + type Dispatch, + type SetStateAction, +} from "react"; import GisApp from "@common/business_components/ui/map/lib/gis.core"; import { WINDOW_POPUP_MESSAGE_TYPE } from "@/features/window-popup/model/types"; @@ -8,7 +13,9 @@ type MapRuntimeBridgeOptions = { /** 공통 Gis가 생성한 지도 참조. 생성/파괴 소유권은 Gis에 유지한다. */ gisMaps: MutableRefObject; setMapReady: Dispatch>; - handleFloodPredictionPopupSelection: ReturnType["handleFloodPredictionPopupSelection"]; + handleFloodPredictionPopupSelection: ReturnType< + typeof useFloodPredictionMap + >["handleFloodPredictionPopupSelection"]; }; /** 지도 준비 감지와 정보검색/GIS 업로드 메시지 연결을 소유한다. @@ -81,10 +88,15 @@ export function useMapRuntimeBridge({ return; } - if (data?.type === WINDOW_POPUP_MESSAGE_TYPE.MAP_SEARCH_SHOW_FLOOD_GROUP) { - await handleFloodPredictionPopupSelection(data.payload, { source: event.source as Window | null, origin: event.origin }); - return; - } + if ( + data?.type === WINDOW_POPUP_MESSAGE_TYPE.MAP_SEARCH_SHOW_FLOOD_GROUP + ) { + await handleFloodPredictionPopupSelection(data.payload, { + source: event.source as Window | null, + origin: event.origin, + }); + return; + } if (data?.type === WINDOW_POPUP_MESSAGE_TYPE.GIS_UPLOAD_COMPLETED) { const rawLayerTypeNames = data.payload?.refreshLayerTypeNames; diff --git a/apps/sn/app/(map-layout)/map/ui/map-page-client.tsx b/apps/sn/app/(map-layout)/map/ui/map-page-client.tsx index 920574774..8c2c93076 100644 --- a/apps/sn/app/(map-layout)/map/ui/map-page-client.tsx +++ b/apps/sn/app/(map-layout)/map/ui/map-page-client.tsx @@ -17,8 +17,15 @@ "use client"; import { useFloodPredictionMap } from "@/features/fldng-predc-prst/lib/use-flood-prediction-map"; -import { FLOOD_DNGR_MAP_LAYER_NAME, FLOOD_DNGR_MAP_LAYER_TYPE } from "../components/flood-dngr-map/flood-dngr-map-types"; -import { findAgedPipeLayer, prepareAgedPipeLayerRows, validateAgedPipeLayer } from "../components/aged-pipe/aged-pipe-layer"; +import { + FLOOD_DNGR_MAP_LAYER_NAME, + FLOOD_DNGR_MAP_LAYER_TYPE, +} from "../components/flood-dngr-map/flood-dngr-map-types"; +import { + findAgedPipeLayer, + prepareAgedPipeLayerRows, + validateAgedPipeLayer, +} from "../components/aged-pipe/aged-pipe-layer"; import { useFloodHistoryClick } from "../lib/use-flood-history-click"; import { useFacilityCodeCatalog } from "@/entities/facility/lib/use-facility-code-catalog"; import { useFloodHistoryVisibility } from "../lib/use-flood-history-visibility"; @@ -35,14 +42,40 @@ import { useWaterRiskLayer } from "../lib/use-water-risk-layer"; import { useFlowDirectionLayer } from "@/features/map-layers/lib/use-flow-direction-layer"; import dynamic from "next/dynamic"; import { type VertexHandleMeta } from "@/features/gis-edit/model/vertex-handles"; -import { type RightPanelTab, findRightPanelTabOverflowCandidate, removeRightPanelTabGroup, RightPanelBookmarkTabs } from "../components/right-panel/right-panel-bookmark-tabs"; -import { FLOW_DIRECTION_DEFAULT_MIN_ZOOM, getFlowDirectionModeByPathname, SWAGE_PRCS_FCLT_LAYER_TYPE, type SwagePrcsFcltLayerMode, getSwagePrcsFcltLayerMode, normalizeFlowDirectionLayerInfos, normalizeRainObservationLayerInteraction, getFlowDirectionMinZoom } from "@/features/map-layers"; +import { + type RightPanelTab, + findRightPanelTabOverflowCandidate, + removeRightPanelTabGroup, + RightPanelBookmarkTabs, +} from "../components/right-panel/right-panel-bookmark-tabs"; +import { + FLOW_DIRECTION_DEFAULT_MIN_ZOOM, + getFlowDirectionModeByPathname, + SWAGE_PRCS_FCLT_LAYER_TYPE, + type SwagePrcsFcltLayerMode, + getSwagePrcsFcltLayerMode, + normalizeFlowDirectionLayerInfos, + normalizeRainObservationLayerInteraction, + getFlowDirectionMinZoom, +} from "@/features/map-layers"; import { ListTree } from "lucide-react"; -import { Fragment, useCallback, useEffect, useMemo, useRef, useState, type ReactNode, type UIEvent } from "react"; +import { + Fragment, + useCallback, + useEffect, + useMemo, + useRef, + useState, + type ReactNode, + type UIEvent, +} from "react"; import { usePathname, useSearchParams } from "next/navigation"; import GeoJSON from "ol/format/GeoJSON.js"; import { openWindowPopup } from "@/features/window-popup/lib/open-window-popup"; -import { isWindowPopupKey, type WindowPopupKey } from "@/features/window-popup/model/popup-definitions"; +import { + isWindowPopupKey, + type WindowPopupKey, +} from "@/features/window-popup/model/popup-definitions"; import { WINDOW_POPUP_MESSAGE_TYPE } from "@/features/window-popup/model/types"; import Gis from "@common/business_components/ui/map/Gis"; import GisApp from "@common/business_components/ui/map/lib/gis.core"; @@ -58,9 +91,27 @@ import GisEditSessionPanel from "../components/gis-edit/gis-edit-session-panel"; import GisEditToolbar from "../components/gis-edit/gis-edit-toolbar"; import GisEditPipeSessionPopup from "../components/gis-edit/gis-edit-pipe-session-popup"; import { useGisEdit } from "../components/gis-edit/use-gis-edit"; -import type { GisEditPipeBasicInfo, GisEditSessionSnapshot } from "../components/gis-edit/gis-edit-types"; -import { PIPE_ANALYSIS_DETAIL_ROW_SELECT_MESSAGE, type PipeAnalysisDetailRow } from "../components/pipe-analysis/pipe-analysis-utils"; -import { AGED_PIPE_DEFAULT_FILTERS, AGED_PIPE_GUIDE_MIN_ZOOM, AGED_PIPE_LAYER_TYPE, AGED_PIPE_PAGE_SIZE, type AgedPipeFilters, type AgedPipeRow, buildAgedPipeCqlFilters, isAgedPipeLayerNode, normalizeAgedPipeFilters, toDisplayPipeRow, validateElapsedYears } from "@/entities/facility/lib/aged-pipe-utils"; +import type { + GisEditPipeBasicInfo, + GisEditSessionSnapshot, +} from "../components/gis-edit/gis-edit-types"; +import { + PIPE_ANALYSIS_DETAIL_ROW_SELECT_MESSAGE, + type PipeAnalysisDetailRow, +} from "../components/pipe-analysis/pipe-analysis-utils"; +import { + AGED_PIPE_DEFAULT_FILTERS, + AGED_PIPE_GUIDE_MIN_ZOOM, + AGED_PIPE_LAYER_TYPE, + AGED_PIPE_PAGE_SIZE, + type AgedPipeFilters, + type AgedPipeRow, + buildAgedPipeCqlFilters, + isAgedPipeLayerNode, + normalizeAgedPipeFilters, + toDisplayPipeRow, + validateElapsedYears, +} from "@/entities/facility/lib/aged-pipe-utils"; import { downloadAgedPipeExcel } from "../components/aged-pipe/aged-pipe-export"; import { useInftwtResultMap } from "../components/inftwt-result/use-inftwt-result-map"; import { useRdiiResultMap } from "../components/rdii-result/use-rdii-result-map"; @@ -70,26 +121,104 @@ import FldngHstryDetailPanel from "../components/fldng-hstry/fldng-hstry-detail- import FldngHstryLayerSettingPanel from "../components/fldng-hstry/fldng-hstry-layer-setting-panel"; import ExmnLayerSettingPanel from "../components/exmn/exmn-layer-setting-panel"; import LayerSettingCard from "../components/layer-setting/layer-setting-card"; -import { EMPTY_EXMN_MAP_FILTERS, appendExmnResultControlNodes, buildExmnMapEntryContext, isExmnResultMnhlNode, isExmnResultPplNode, type ExmnMapFilters } from "../components/exmn/exmn-map-types"; -import { buildSinkholeDefaultYearRange, buildSinkholeFiltersFromYearRange, buildSinkholeScope, isSinkholeLayerNode, isSinkholeRootNode, normalizeSinkholeFilters, normalizeSinkholeYearRange, SINKHOLE_DEFAULT_RADIUS, SINKHOLE_FILTER_SYNC_MESSAGE, SINKHOLE_LAYER_TYPE, SINKHOLE_POPUP_KEY, SINKHOLE_ROW_SELECT_MESSAGE, SINKHOLE_SYNC_COMPLETED_MESSAGE, type SinkholeDetail, type SinkholeFilters, type SinkholeListItem, type SinkholeNearbyPipe, type SinkholeSyncSummary, type SinkholeYearRange } from "../components/sinkhole/sinkhole-types"; -import { FLDNG_HSTRY_LAYER_TYPE, FLDNG_HSTRY_POPUP_KEY, FLDNG_HSTRY_ROW_SELECT_MESSAGE, type FldngHstryYearRange, type FldngHstryItem } from "@/entities/flood-history/model/flood-history-types"; -import { buildFldngHstryDefaultYearRange, isFldngHstryDepthNode, isFldngHstryWtlvNode, isFldngHstryRootNode } from "@/entities/flood-history/lib/flood-history-utils"; -import { SBMRG_DNGR_MAP_POPUP_KEY, isSbmrgDngrMapRootNode } from "../components/sbmrg-dngr-map/sbmrg-dngr-map-types"; -import { FLOOD_DNGR_MAP_POPUP_KEY, isFloodDngrMapRootNode } from "../components/flood-dngr-map/flood-dngr-map-types"; +import { + EMPTY_EXMN_MAP_FILTERS, + appendExmnResultControlNodes, + buildExmnMapEntryContext, + isExmnResultMnhlNode, + isExmnResultPplNode, + type ExmnMapFilters, +} from "../components/exmn/exmn-map-types"; +import { + buildSinkholeDefaultYearRange, + buildSinkholeFiltersFromYearRange, + buildSinkholeScope, + isSinkholeLayerNode, + isSinkholeRootNode, + normalizeSinkholeFilters, + normalizeSinkholeYearRange, + SINKHOLE_DEFAULT_RADIUS, + SINKHOLE_FILTER_SYNC_MESSAGE, + SINKHOLE_LAYER_TYPE, + SINKHOLE_POPUP_KEY, + SINKHOLE_ROW_SELECT_MESSAGE, + SINKHOLE_SYNC_COMPLETED_MESSAGE, + type SinkholeDetail, + type SinkholeFilters, + type SinkholeListItem, + type SinkholeNearbyPipe, + type SinkholeSyncSummary, + type SinkholeYearRange, +} from "../components/sinkhole/sinkhole-types"; +import { + FLDNG_HSTRY_LAYER_TYPE, + FLDNG_HSTRY_POPUP_KEY, + FLDNG_HSTRY_ROW_SELECT_MESSAGE, + type FldngHstryYearRange, + type FldngHstryItem, +} from "@/entities/flood-history/model/flood-history-types"; +import { + buildFldngHstryDefaultYearRange, + isFldngHstryDepthNode, + isFldngHstryWtlvNode, + isFldngHstryRootNode, +} from "@/entities/flood-history/lib/flood-history-utils"; +import { + SBMRG_DNGR_MAP_POPUP_KEY, + isSbmrgDngrMapRootNode, +} from "../components/sbmrg-dngr-map/sbmrg-dngr-map-types"; +import { + FLOOD_DNGR_MAP_POPUP_KEY, + isFloodDngrMapRootNode, +} from "../components/flood-dngr-map/flood-dngr-map-types"; import FeatureClickEventPopup from "@/features/facility-detail/ui/feature-click-event-popup"; import SearchModal from "../search-modal/search-modal"; -import { WATER_DEPTH_LAYER_TYPES, extractWaterDepthLegendItems } from "../water-depth/water-depth"; +import { + WATER_DEPTH_LAYER_TYPES, + extractWaterDepthLegendItems, +} from "../water-depth/water-depth"; import { buildWaterRiskStatusLabel } from "../components/water-risk/water-risk-types"; const AnalysisPopupMenu = dynamic( () => import("../components/analysis-menu/analysis-popup-menu"), { ssr: false }, ); -import { AGED_PIPE_ROW_SELECT_MESSAGE, AGED_PIPE_POPUP_MINIMIZE_MESSAGE, AGED_PIPE_FILTER_SYNC_MESSAGE, EXMN_PROC_SEARCH_EVENT, SOUTH_KOREA_VIEW_EXTENT, FLOW_DIRECTION_SRS, SHORT_TERM_FORECAST_GRID_LAYER_NAME, RIGHT_PANEL_TAB_LIMIT, RIGHT_PANEL_SINKHOLE_PIPE_TAB_ID, AGED_PIPE_FOCUS_PADDING, DEFAULT_FEATURE_FIT_PADDING } from "../model/map-constants"; +import { + AGED_PIPE_ROW_SELECT_MESSAGE, + AGED_PIPE_POPUP_MINIMIZE_MESSAGE, + AGED_PIPE_FILTER_SYNC_MESSAGE, + EXMN_PROC_SEARCH_EVENT, + SOUTH_KOREA_VIEW_EXTENT, + FLOW_DIRECTION_SRS, + SHORT_TERM_FORECAST_GRID_LAYER_NAME, + RIGHT_PANEL_TAB_LIMIT, + RIGHT_PANEL_SINKHOLE_PIPE_TAB_ID, + AGED_PIPE_FOCUS_PADDING, + DEFAULT_FEATURE_FIT_PADDING, +} from "../model/map-constants"; import { getFeatureCollection } from "../lib/map-values"; -import { getSinkholeAccidentId, getSinkholeFallbackDetailFromSelection, getSinkholePointFromSelection, createSinkholeFocusedPipeStyle, appendSinkholeControlNode } from "../lib/sinkhole-features"; -import { getGisEditFeatureFid, isGisEditPreviewFeatureData, highlightGisEditSelectedFeature, isVisibleGisEditSessionChange, getLatestNumericEditSn, findInvalidPipeRequiredChange } from "../lib/gis-edit-features"; -import { getSelectedFeatureLayerTypeName, getRightPanelFeatureIdentifier, getRightPanelFeatureProperty, getRightPanelTabCategory, getRightPanelFeatureDisplayLabel } from "../lib/right-panel-features"; +import { + getSinkholeAccidentId, + getSinkholeFallbackDetailFromSelection, + getSinkholePointFromSelection, + createSinkholeFocusedPipeStyle, + appendSinkholeControlNode, +} from "../lib/sinkhole-features"; +import { + getGisEditFeatureFid, + isGisEditPreviewFeatureData, + highlightGisEditSelectedFeature, + isVisibleGisEditSessionChange, + getLatestNumericEditSn, + findInvalidPipeRequiredChange, +} from "../lib/gis-edit-features"; +import { + getSelectedFeatureLayerTypeName, + getRightPanelFeatureIdentifier, + getRightPanelFeatureProperty, + getRightPanelTabCategory, + getRightPanelFeatureDisplayLabel, +} from "../lib/right-panel-features"; import { normalizeTreeRowSpacing } from "../lib/layer-tree"; import { useMapRuntimeBridge } from "../lib/use-map-runtime-bridge"; import MapControlStyles from "./map-control-styles"; @@ -126,13 +255,13 @@ const MapPageClient = () => { } | null>(null); const [layerLoadError, setLayerLoadError] = useState(null); const gisMaps = useRef(null); -const requestFloodPredictionLayer = useCallback(() => { + const requestFloodPredictionLayer = useCallback(() => { setCheckedLayerRequest((current) => ({ requestKey: (current?.requestKey ?? 0) + 1, layerNames: [FLOOD_DNGR_MAP_LAYER_NAME], })); }, []); -const { handleFloodPredictionPopupSelection } = useFloodPredictionMap({ + const { handleFloodPredictionPopupSelection } = useFloodPredictionMap({ mapRef: gisMaps, floodLayerType: FLOOD_DNGR_MAP_LAYER_TYPE, onRequestFloodLayer: requestFloodPredictionLayer, @@ -371,7 +500,6 @@ const { handleFloodPredictionPopupSelection } = useFloodPredictionMap({ useGisEditPipeSnap({ gisEdit, gisMaps, mapReady }); useGisEditOriginalMask({ gisMaps, gisEdit, mapReady }); - const gisEditVisibleSessionChanges = useMemo( () => gisEdit.changes.filter(isVisibleGisEditSessionChange), @@ -631,7 +759,11 @@ const { handleFloodPredictionPopupSelection } = useFloodPredictionMap({ sinkholeYearRange, ]); - useMapRuntimeBridge({ gisMaps, setMapReady, handleFloodPredictionPopupSelection }); + useMapRuntimeBridge({ + gisMaps, + setMapReady, + handleFloodPredictionPopupSelection, + }); useEffect(() => { if (shouldShowGisEditSession) return; @@ -754,8 +886,12 @@ const { handleFloodPredictionPopupSelection } = useFloodPredictionMap({ "/sewerage-service/api/v1/map/lyrStngs/SN_NETWORK", ); // DB 필터 치환 실패는 노후관로에만 한정하고 다른 시설물 레이어는 유지한다. - const preparedData = prepareAgedPipeLayerRows(data, appliedAgedPipeFilters); - const agedPipeConfigError = findAgedPipeLayer(preparedData)?.agedPipeConfigError; + const preparedData = prepareAgedPipeLayerRows( + data, + appliedAgedPipeFilters, + ); + const agedPipeConfigError = + findAgedPipeLayer(preparedData)?.agedPipeConfigError; if (agedPipeConfigError) alert(agedPipeConfigError); setTreeData( appendExmnResultControlNodes( @@ -1039,7 +1175,10 @@ const { handleFloodPredictionPopupSelection } = useFloodPredictionMap({ sort: "string", }); - const cqlFilters = buildAgedPipeCqlFilters(normalized, layer.agedPipeFilterTemplate ?? layer.flterSql); + const cqlFilters = buildAgedPipeCqlFilters( + normalized, + layer.agedPipeFilterTemplate ?? layer.flterSql, + ); if (cqlFilters.length > 0) { queryParams.append("cqlFiter", cqlFilters.join(" and ")); } @@ -2554,7 +2693,8 @@ const { handleFloodPredictionPopupSelection } = useFloodPredictionMap({ try { validateAgedPipeLayer(row); const filter = buildAgedPipeCqlFilters( - appliedAgedPipeFilters, row.agedPipeFilterTemplate ?? row.flterSql, + appliedAgedPipeFilters, + row.agedPipeFilterTemplate ?? row.flterSql, ).join(" AND "); layerCode.flterSql = filter; const visible = isAgedPipeChecked && isAgedPipeSettingEnabled; @@ -2573,8 +2713,14 @@ const { handleFloodPredictionPopupSelection } = useFloodPredictionMap({ core?.getLayerById?.(id)?.setVisible?.(false); console.error("노후관로 DB 레이어 설정 오류:", error); } - }, [appliedAgedPipeFilters, isAgedPipeChecked, isAgedPipeSettingEnabled, - mapReady, treeData, checkedLayerLegendVersion]); + }, [ + appliedAgedPipeFilters, + isAgedPipeChecked, + isAgedPipeSettingEnabled, + mapReady, + treeData, + checkedLayerLegendVersion, + ]); useFloodHistoryVisibility({ mapReady, gisMaps, diff --git a/apps/sn/src/entities/facility/lib/aged-pipe-utils.ts b/apps/sn/src/entities/facility/lib/aged-pipe-utils.ts index 9c6e7a54d..bba420f60 100644 --- a/apps/sn/src/entities/facility/lib/aged-pipe-utils.ts +++ b/apps/sn/src/entities/facility/lib/aged-pipe-utils.ts @@ -246,13 +246,20 @@ export const getElapsedYearsDisplayText = (value: unknown) => { }; /** DB의 SQL 필터 템플릿을 해석한다. 누락/미지원 토큰은 전체 관로 조회로 대체하지 않는다. */ -export const buildAgedPipeCqlFilters = (filters: AgedPipeFilters, filterTemplate: string) => { +export const buildAgedPipeCqlFilters = ( + filters: AgedPipeFilters, + filterTemplate: string, +) => { const normalized = normalizeAgedPipeFilters(filters); const template = String(filterTemplate ?? "").trim(); if (!template.includes("${cutoffYmd}")) { - throw new Error("노후관로 DB sql_filt에 ${cutoffYmd} 조건을 등록해 주세요."); + throw new Error( + "노후관로 DB sql_filt에 ${cutoffYmd} 조건을 등록해 주세요.", + ); } - const filter = template.split("${cutoffYmd}").join(getCutoffYmd(normalized.elapsedYears)); + const filter = template + .split("${cutoffYmd}") + .join(getCutoffYmd(normalized.elapsedYears)); if (/\$\{[^}]*\}/.test(filter)) { throw new Error("노후관로 DB sql_filt에 지원하지 않는 치환값이 있습니다."); } diff --git a/apps/sn/src/features/fldng-predc-prst/ui/fldng-predc-prst-popup-content.tsx b/apps/sn/src/features/fldng-predc-prst/ui/fldng-predc-prst-popup-content.tsx index c03d3d902..409b0696d 100644 --- a/apps/sn/src/features/fldng-predc-prst/ui/fldng-predc-prst-popup-content.tsx +++ b/apps/sn/src/features/fldng-predc-prst/ui/fldng-predc-prst-popup-content.tsx @@ -60,9 +60,7 @@ type Filters = { const PAGE_SIZE = 10; const EXCEL_DOWNLOAD_PAGE_SIZE = 500; const MAP_FREQUENCIES = new Set([30, 50, 80, 100]); -const FREQUENCY_OPTIONS = [ - 5, 10, 20, 30, 50, 80, 100 -] as const; +const FREQUENCY_OPTIONS = [5, 10, 20, 30, 50, 80, 100] as const; /** 도시침수지도 DB의 3자리 빈도 코드로 변환한다. 30년 이하는 030, 100년 초과는 100으로 제한한다. */ const toFloodMapFrequencyCode = (value: number) => { diff --git a/apps/sn/src/features/map-layers/lib/flow-direction-selection.ts b/apps/sn/src/features/map-layers/lib/flow-direction-selection.ts index 1127aa674..3d718d83e 100644 --- a/apps/sn/src/features/map-layers/lib/flow-direction-selection.ts +++ b/apps/sn/src/features/map-layers/lib/flow-direction-selection.ts @@ -55,7 +55,8 @@ export const extractCheckedPipeUsageStyles = ( checkedNodesData.forEach((node) => { const data = node?.data ?? node; - if (!data || isFlowDirectionLayerInfo(data) || isAgedPipeLayerNode(data)) return; + if (!data || isFlowDirectionLayerInfo(data) || isAgedPipeLayerNode(data)) + return; if (getLayerTypeName(data) !== FLOW_DIRECTION_PIPE_LAYER_TYPE) return; if (!isLayerVisibleAtZoom(data, zoom)) return;