diff --git a/apps/sn/.env.local b/apps/sn/.env.local index 3d871b007..dce96bf40 100644 --- a/apps/sn/.env.local +++ b/apps/sn/.env.local @@ -12,8 +12,8 @@ NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr NEXT_PUBLIC_NGII_PARAM = 04trYP9_xwLAfALjwZ-B8g&service=WMTS&request=GetTile&version=1.0.0&format=image/png&layer=korean_map&style=korean&tilematrixset=korean&tilematrix={z}&tilecol={x}&tilerow={y} SERVER_API_URL = http://dev.onasys.co.kr:8000 -# SEWERAGE_API_URL = http://localhost:8883 -SEWERAGE_API_URL = http://con.mind-one.co.kr:11083 +SEWERAGE_API_URL = http://localhost:8883 +# SEWERAGE_API_URL = http://con.mind-one.co.kr:11083 DC_URL = https://apigateway.apps.rsonesoft.com # NEXT_PUBLIC_CM_LOGIN_PAGE_URL = http://dev.onasys.co.kr:3000/auth/login NEXT_PUBLIC_CM_LOGIN_PAGE_URL = /auth/login diff --git a/apps/sn/app/(map-layout)/map/components/InputSection.tsx b/apps/sn/app/(map-layout)/map/components/InputSection.tsx index 68c4a3a83..87b904d58 100644 --- a/apps/sn/app/(map-layout)/map/components/InputSection.tsx +++ b/apps/sn/app/(map-layout)/map/components/InputSection.tsx @@ -1,3 +1,4 @@ +/** 시설 상세정보 화면의 운영정보 입력 영역을 공통 형식으로 표시한다. */ import { Table, TableHeader, diff --git a/apps/sn/app/(map-layout)/map/components/agedPipe/AgedPipeLayerSettingPanel.tsx b/apps/sn/app/(map-layout)/map/components/agedPipe/AgedPipeLayerSettingPanel.tsx index 94edaeaef..7e29c6c4f 100644 --- a/apps/sn/app/(map-layout)/map/components/agedPipe/AgedPipeLayerSettingPanel.tsx +++ b/apps/sn/app/(map-layout)/map/components/agedPipe/AgedPipeLayerSettingPanel.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 노후관로 레이어 설정 + * 사업차수와 구조적·운영적 상태등급별 지도 표시 조건을 설정한다. + */ "use client"; import { useEffect, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/agedPipe/AgedPipePopupPage.tsx b/apps/sn/app/(map-layout)/map/components/agedPipe/AgedPipePopupPage.tsx index b2a12c783..7fe989125 100644 --- a/apps/sn/app/(map-layout)/map/components/agedPipe/AgedPipePopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/agedPipe/AgedPipePopupPage.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 노후관로 목록 + * 노후관로를 검색하고 목록·엑셀 다운로드·지도 위치 확인 기능을 제공한다. + */ "use client"; import { useCallback, useEffect, useMemo, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/agedPipe/agedPipeExport.ts b/apps/sn/app/(map-layout)/map/components/agedPipe/agedPipeExport.ts index c915c21ee..dad972961 100644 --- a/apps/sn/app/(map-layout)/map/components/agedPipe/agedPipeExport.ts +++ b/apps/sn/app/(map-layout)/map/components/agedPipe/agedPipeExport.ts @@ -1,3 +1,4 @@ +/** 노후관로 목록의 엑셀 다운로드 데이터와 서식을 생성한다. */ "use client"; import { postBlobData } from "@/components/lib/api"; diff --git a/apps/sn/app/(map-layout)/map/components/agedPipe/agedPipeUtils.ts b/apps/sn/app/(map-layout)/map/components/agedPipe/agedPipeUtils.ts index 736bb9478..a08f997d7 100644 --- a/apps/sn/app/(map-layout)/map/components/agedPipe/agedPipeUtils.ts +++ b/apps/sn/app/(map-layout)/map/components/agedPipe/agedPipeUtils.ts @@ -1,3 +1,4 @@ +/** 노후관로 검색 조건, 표시값 변환 및 지도 연계 유틸을 제공한다. */ "use client"; import type { SelectDataType } from "@common/business_components"; diff --git a/apps/sn/app/(map-layout)/map/components/agedPipeStatusByCtpv/AgedPipeStatusByCtpvPopupPage.tsx b/apps/sn/app/(map-layout)/map/components/agedPipeStatusByCtpv/AgedPipeStatusByCtpvPopupPage.tsx index 499722b85..1a9d8a220 100644 --- a/apps/sn/app/(map-layout)/map/components/agedPipeStatusByCtpv/AgedPipeStatusByCtpvPopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/agedPipeStatusByCtpv/AgedPipeStatusByCtpvPopupPage.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 시도별 노후관로현황 + * 기준연도별 시도 단위 노후관로 현황을 조회하고 엑셀로 내려받는다. + */ "use client"; import { useCallback, useEffect, useMemo, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/agedPipeStatusByCtpv/agedPipeStatusByCtpvExport.ts b/apps/sn/app/(map-layout)/map/components/agedPipeStatusByCtpv/agedPipeStatusByCtpvExport.ts index 9946bc815..e7f797f34 100644 --- a/apps/sn/app/(map-layout)/map/components/agedPipeStatusByCtpv/agedPipeStatusByCtpvExport.ts +++ b/apps/sn/app/(map-layout)/map/components/agedPipeStatusByCtpv/agedPipeStatusByCtpvExport.ts @@ -1,3 +1,4 @@ +/** 시도별 노후관로 현황의 연도 그룹형 엑셀 데이터를 생성한다. */ "use client"; import * as XLSX from "xlsx"; diff --git a/apps/sn/app/(map-layout)/map/components/agedPipeStatusByCtpv/agedPipeStatusByCtpvUtils.ts b/apps/sn/app/(map-layout)/map/components/agedPipeStatusByCtpv/agedPipeStatusByCtpvUtils.ts index d65a9a18a..430e81a73 100644 --- a/apps/sn/app/(map-layout)/map/components/agedPipeStatusByCtpv/agedPipeStatusByCtpvUtils.ts +++ b/apps/sn/app/(map-layout)/map/components/agedPipeStatusByCtpv/agedPipeStatusByCtpvUtils.ts @@ -1,3 +1,4 @@ +/** 시도별 노후관로 현황의 조회 연도와 그룹 컬럼을 구성한다. */ "use client"; import type { UiHeadProps } from "@common/business_components/ui"; diff --git a/apps/sn/app/(map-layout)/map/components/analysisMenu/AnalysisPopupMenu.tsx b/apps/sn/app/(map-layout)/map/components/analysisMenu/AnalysisPopupMenu.tsx index 3a11a4f99..0bf3b952f 100644 --- a/apps/sn/app/(map-layout)/map/components/analysisMenu/AnalysisPopupMenu.tsx +++ b/apps/sn/app/(map-layout)/map/components/analysisMenu/AnalysisPopupMenu.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 분석도구 메뉴 + * 지도에서 실행할 분석·현황 팝업 메뉴를 펼치고 선택한다. + */ "use client"; import { useEffect, useState, type ComponentType, type ReactNode } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/common/codeMapper.ts b/apps/sn/app/(map-layout)/map/components/common/codeMapper.ts index 7b591b09c..df355381e 100644 --- a/apps/sn/app/(map-layout)/map/components/common/codeMapper.ts +++ b/apps/sn/app/(map-layout)/map/components/common/codeMapper.ts @@ -1,3 +1,4 @@ +/** 지도 시설 상세정보의 코드값을 업무 표시명으로 변환한다. */ import { MS_SWAGE_PPL_USE_CODES, MS_SWAGE_PPL_CODES, MS_SWAGE_MHL_CODES, MS_SWAGE_MHL_USE_CODES, DRTW_SEWAGE_PUMP_USE_CODES } from './table'; interface CodeMapperProps { @@ -159,4 +160,4 @@ export const reverseCodeMapper = ({ layerName, data }: CodeMapperProps): any => }; // 기본 내보내기 -export default { codeMapper, reverseCodeMapper }; \ No newline at end of file +export default { codeMapper, reverseCodeMapper }; diff --git a/apps/sn/app/(map-layout)/map/components/common/index.ts b/apps/sn/app/(map-layout)/map/components/common/index.ts index 377df2344..bba16ce69 100644 --- a/apps/sn/app/(map-layout)/map/components/common/index.ts +++ b/apps/sn/app/(map-layout)/map/components/common/index.ts @@ -1,3 +1,4 @@ +/** 선택한 지도 레이어 종류에 맞는 시설 상세 컴포넌트를 반환한다. */ import MsSwagePpl from "../popupComponent/MsSwagePpl"; // 하수관로 import sewagePump from "../popupComponent/sewagePump"; // 하수펌프 import smh from "../popupComponent/smh"; diff --git a/apps/sn/app/(map-layout)/map/components/common/table.ts b/apps/sn/app/(map-layout)/map/components/common/table.ts index b8ba17b4f..8a13eb830 100644 --- a/apps/sn/app/(map-layout)/map/components/common/table.ts +++ b/apps/sn/app/(map-layout)/map/components/common/table.ts @@ -1,3 +1,4 @@ +/** 지도 시설 상세 및 목록에서 사용하는 컬럼·코드 정의를 제공한다. */ // 하수관로 export const MsSwagePplCol = [ { id: 'fclt_mng_no', title: '시설관리번호' }, diff --git a/apps/sn/app/(map-layout)/map/components/exmn/ExmnLayerSettingPanel.tsx b/apps/sn/app/(map-layout)/map/components/exmn/ExmnLayerSettingPanel.tsx index 42131793e..a46f7a714 100644 --- a/apps/sn/app/(map-layout)/map/components/exmn/ExmnLayerSettingPanel.tsx +++ b/apps/sn/app/(map-layout)/map/components/exmn/ExmnLayerSettingPanel.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 관로조사 레이어 설정 + * 사업차수와 조사 종류·상태등급별 지도 표시 조건을 설정한다. + */ "use client"; import type { ExmnMapFilters, ExmnMapJobType } from "./exmnMapTypes"; diff --git a/apps/sn/app/(map-layout)/map/components/exmn/ExmnSurveyResultSection.tsx b/apps/sn/app/(map-layout)/map/components/exmn/ExmnSurveyResultSection.tsx index 601d34a30..67bbf2ae5 100644 --- a/apps/sn/app/(map-layout)/map/components/exmn/ExmnSurveyResultSection.tsx +++ b/apps/sn/app/(map-layout)/map/components/exmn/ExmnSurveyResultSection.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 관로조사 결과 + * 선택 시설의 조사 결과와 상세 판정 정보를 표시한다. + */ "use client"; import { diff --git a/apps/sn/app/(map-layout)/map/components/exmn/exmnMapApi.ts b/apps/sn/app/(map-layout)/map/components/exmn/exmnMapApi.ts index 390bdf31f..4c959f4f4 100644 --- a/apps/sn/app/(map-layout)/map/components/exmn/exmnMapApi.ts +++ b/apps/sn/app/(map-layout)/map/components/exmn/exmnMapApi.ts @@ -1,3 +1,4 @@ +/** 관로조사 지도 데이터 조회 API와 응답 변환 함수를 제공한다. */ import { getRawJson } from "../../../../components/lib/api"; import type { ExmnMapFilters, ExmnMapJobType } from "./exmnMapTypes"; diff --git a/apps/sn/app/(map-layout)/map/components/exmn/exmnMapTypes.ts b/apps/sn/app/(map-layout)/map/components/exmn/exmnMapTypes.ts index 248c8547b..f06b12e3e 100644 --- a/apps/sn/app/(map-layout)/map/components/exmn/exmnMapTypes.ts +++ b/apps/sn/app/(map-layout)/map/components/exmn/exmnMapTypes.ts @@ -1,3 +1,4 @@ +/** 관로조사 지도 화면에서 사용하는 타입·상수와 표시 조건을 정의한다. */ export const EXMN_RESULT_ROOT_NODE_ID = "SN_EXMN_RESULT"; export const EXMN_RESULT_PPL_NODE_ID = "SN_EXMN_RESULT_PPL"; export const EXMN_RESULT_MNHL_NODE_ID = "SN_EXMN_RESULT_MNHL"; diff --git a/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryDetailPanel.tsx b/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryDetailPanel.tsx index d0ad85a20..7398a4d70 100644 --- a/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryDetailPanel.tsx +++ b/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryDetailPanel.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 침수흔적도 상세정보 + * 지도에서 선택한 침수흔적의 기본정보·강우정보·피해정보를 표시한다. + */ "use client"; import { useMemo, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryLayerSettingPanel.tsx b/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryLayerSettingPanel.tsx index ac00e2220..c5a8cd190 100644 --- a/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryLayerSettingPanel.tsx +++ b/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryLayerSettingPanel.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 침수흔적도 레이어 설정 + * 침수흔적위선·심선의 표시 여부와 조회 연도 범위를 설정한다. + */ "use client"; import { SelectBox } from "@common/business_components/ui"; diff --git a/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryPopupPage.tsx b/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryPopupPage.tsx index 42750f87d..43bd0d5f0 100644 --- a/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryPopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryPopupPage.tsx @@ -1,5 +1,6 @@ /** - * 침수발생이력 popup + * 화면명: 침수발생이력 목록 + * 침수발생이력을 검색하고 엑셀 다운로드 및 지도 위치 확인 기능을 제공한다. */ "use client"; diff --git a/apps/sn/app/(map-layout)/map/components/fldngHstry/fldngHstryTypes.ts b/apps/sn/app/(map-layout)/map/components/fldngHstry/fldngHstryTypes.ts index 3d5649b7f..10eb2e363 100644 --- a/apps/sn/app/(map-layout)/map/components/fldngHstry/fldngHstryTypes.ts +++ b/apps/sn/app/(map-layout)/map/components/fldngHstry/fldngHstryTypes.ts @@ -1,7 +1,14 @@ +/** + * 침수흔적 화면에서 사용하는 타입·상수·조회 조건과 feature 캐시 유틸을 제공한다. + */ "use client"; import type { UiHeadProps } from "@common/business_components/ui"; import { appendApiSearchParams } from "@/shared/util/util"; +import { getData } from "@/components/lib/api"; +import GisApp from "@common/business_components/ui/map/lib/gis.core"; +import type Feature from "ol/Feature.js"; +import VectorSource from "ol/source/Vector.js"; export const FLOOD_HISTORY_POPUP_KEY = "fldngHstryPopup"; export const FLDNG_HSTRY_ROW_SELECT_MESSAGE = "SN_FLOOD_HISTORY_ROW_SELECT"; @@ -17,6 +24,174 @@ export const FLDNG_HSTRY_PAGE_SIZE = 10; export const FLDNG_HSTRY_DOWNLOAD_BATCH_SIZE = 2000; export const FLOOD_HISTORY_MIN_YEAR = 2002; +export type FldngHstryDetailCacheValue = { + rainAnalysis: Record; + depthRows: Record[]; + waterLevelRows: Record[]; + complete: boolean; +}; + +const normalizeFldngHstryRainAnalysisPayload = (data: any) => { + if (!data || typeof data !== "object") return {}; + return { + rain_bgng_tm: data.rainBgngTm ?? data.rain_bgng_tm ?? null, + rainBgngTm: data.rainBgngTm ?? data.rain_bgng_tm ?? null, + rain_end_tm: data.rainEndTm ?? data.rain_end_tm ?? null, + rainEndTm: data.rainEndTm ?? data.rain_end_tm ?? null, + rain_tot: data.rainTot ?? data.rain_tot ?? null, + rainTot: data.rainTot ?? data.rain_tot ?? null, + rain_str: data.rainStr ?? data.rain_str ?? null, + rainStr: data.rainStr ?? data.rain_str ?? null, + }; +}; + +/** 침수흔적 강우분석과 연결된 심선·위선 목록을 함께 조회한다. */ +export const loadFldngHstryDetail = async ( + fldngHstryFid: string, +): Promise => { + const [rainResult, depthResult] = await Promise.allSettled([ + getData( + `v1/fldng/hstry/rain-anls/${encodeURIComponent(fldngHstryFid)}`, + ), + getData( + `v1/fldng/hstry/depth-map/${encodeURIComponent(fldngHstryFid)}`, + ), + ]); + + if (rainResult.status === "rejected") { + console.warn("침수강우분석 조회 실패:", rainResult.reason); + } + if (depthResult.status === "rejected") { + console.warn("침수깊이지도 조회 실패:", depthResult.reason); + } + + const depthPayload = + depthResult.status === "fulfilled" + ? (depthResult.value?.data ?? depthResult.value) + : null; + const depthItems = Array.isArray(depthPayload) + ? depthPayload + : depthPayload?.depthMaps; + const waterLevelItems = Array.isArray(depthPayload?.waterLevelMaps) + ? depthPayload.waterLevelMaps + : []; + + return { + rainAnalysis: + rainResult.status === "fulfilled" + ? normalizeFldngHstryRainAnalysisPayload(rainResult.value) + : {}, + depthRows: Array.isArray(depthItems) + ? depthItems.filter((row) => row && typeof row === "object") + : [], + waterLevelRows: waterLevelItems.filter( + (row: unknown) => row && typeof row === "object", + ), + complete: + rainResult.status === "fulfilled" && depthResult.status === "fulfilled", + }; +}; + +type FldngHstryGisLayer = { + searchLayer?: { + getSource?: () => VectorSource | null; + } | null; + clearSearchLayer: (option: unknown) => void; + ensureSearchLayer: (option: unknown) => { + set: (key: string, value: unknown) => void; + setSource: (source: VectorSource) => void; + }; + showSearchResultsFromGeoJSON: ( + layerTypeName: string, + featureId: string, + ) => void | Promise; +}; + +/** 침수흔적 심선·위선의 GeoServer 조회 결과를 화면 생명주기와 분리해 보관한다. */ +export const fldngHstryFeatureCache = new Map< + string, + Promise +>(); + +/** OpenLayers Feature.clone()이 복사하지 않는 feature ID까지 보존한다. */ +const cloneFldngHstryFeature = (feature: Feature) => { + const clonedFeature = feature.clone(); + const featureId = feature.getId(); + if (featureId !== undefined) { + clonedFeature.setId(featureId); + } + return clonedFeature; +}; + +const displayCachedFldngHstryFeatures = ( + gisLayer: FldngHstryGisLayer, + layerTypeName: string, + features: Feature[], +) => { + const matched = Object.values(GisApp.layerCode ?? {}).find( + (item: any) => item?.lyrTyNm === layerTypeName, + ) as any; + if (!matched || features.length === 0) return; + + gisLayer.clearSearchLayer(matched); + const layer = gisLayer.ensureSearchLayer(matched); + layer.set("gobjTy", matched.gobjTy); + const clonedFeatures = features.map(cloneFldngHstryFeature); + layer.setSource(new VectorSource({ features: clonedFeatures })); + (GisApp.Module.select as any)?.selectFeature(clonedFeatures[0], false); +}; + +/** 침수흔적 심선·위선을 최초 한 번만 조회하고 이후에는 캐시로 highlight한다. */ +export const showFldngHstryFeature = async ( + gisLayer: FldngHstryGisLayer, + layerTypeName: string, + featureId: string, +) => { + const cacheKey = `${layerTypeName}:${featureId}`; + const cachedRequest = fldngHstryFeatureCache.get(cacheKey); + if (cachedRequest) { + const cachedFeatures = await cachedRequest; + displayCachedFldngHstryFeatures( + gisLayer, + layerTypeName, + cachedFeatures, + ); + return; + } + + await gisLayer.showSearchResultsFromGeoJSON(layerTypeName, featureId); + const source = gisLayer.searchLayer?.getSource?.(); + if (!source) return; + + const featureRequest = new Promise((resolve, reject) => { + const resolveFeatures = () => { + const features = source.getFeatures(); + if (features.length > 0) { + resolve(features.map(cloneFldngHstryFeature)); + } else { + reject(new Error("침수흔적 위치 정보가 없습니다.")); + } + }; + const rejectFeatures = () => + reject(new Error("침수흔적 위치 조회에 실패했습니다.")); + + if (source.getFeatures().length > 0) { + resolveFeatures(); + return; + } + source.once("featuresloadend", resolveFeatures); + source.once("featuresloaderror", rejectFeatures); + }); + + fldngHstryFeatureCache.set(cacheKey, featureRequest); + try { + await featureRequest; + } catch (error) { + fldngHstryFeatureCache.delete(cacheKey); + console.warn(error); + } +}; + /** 지도 침수흔적위선·심선이 공통으로 사용하는 침수년도 범위다. */ export type FloodHistoryYearRange = { startYear: string; diff --git a/apps/sn/app/(map-layout)/map/components/floodDngrMap/FloodDngrMapPopupPage.tsx b/apps/sn/app/(map-layout)/map/components/floodDngrMap/FloodDngrMapPopupPage.tsx index 6b272923c..4124dbe94 100644 --- a/apps/sn/app/(map-layout)/map/components/floodDngrMap/FloodDngrMapPopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/floodDngrMap/FloodDngrMapPopupPage.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 도시침수지도 목록 + * 빈도별 도시침수지도를 검색하고 목록·엑셀·지도 보기 기능을 제공한다. + */ "use client"; import { useCallback, useEffect, useMemo, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/floodDngrMap/floodDngrMapTypes.ts b/apps/sn/app/(map-layout)/map/components/floodDngrMap/floodDngrMapTypes.ts index 1d4d2df65..d6356607b 100644 --- a/apps/sn/app/(map-layout)/map/components/floodDngrMap/floodDngrMapTypes.ts +++ b/apps/sn/app/(map-layout)/map/components/floodDngrMap/floodDngrMapTypes.ts @@ -1,3 +1,4 @@ +/** 도시침수지도 화면의 검색 조건, 범례, 컬럼과 응답 변환을 정의한다. */ "use client"; import type { UiHeadProps } from "@common/business_components/ui"; diff --git a/apps/sn/app/(map-layout)/map/components/gisEdit/GisEditPipeSessionPopup.tsx b/apps/sn/app/(map-layout)/map/components/gisEdit/GisEditPipeSessionPopup.tsx index 2591591c6..0c8f062eb 100644 --- a/apps/sn/app/(map-layout)/map/components/gisEdit/GisEditPipeSessionPopup.tsx +++ b/apps/sn/app/(map-layout)/map/components/gisEdit/GisEditPipeSessionPopup.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 하수관로 편집정보 + * 편집 중인 하수관로의 기본정보와 입력정보를 표시하고 수정한다. + */ "use client"; import { useEffect, useMemo, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/gisEdit/GisEditSessionPanel.tsx b/apps/sn/app/(map-layout)/map/components/gisEdit/GisEditSessionPanel.tsx index c5ef3e8d5..931c7b993 100644 --- a/apps/sn/app/(map-layout)/map/components/gisEdit/GisEditSessionPanel.tsx +++ b/apps/sn/app/(map-layout)/map/components/gisEdit/GisEditSessionPanel.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 하수관로 편집 세션 + * 현재 편집 대상과 변경 상태를 표시하고 저장·취소 동작을 제공한다. + */ "use client"; import { Button } from "@common/components"; diff --git a/apps/sn/app/(map-layout)/map/components/gisEdit/GisEditToolbar.tsx b/apps/sn/app/(map-layout)/map/components/gisEdit/GisEditToolbar.tsx index b12290773..a5f7a9dd1 100644 --- a/apps/sn/app/(map-layout)/map/components/gisEdit/GisEditToolbar.tsx +++ b/apps/sn/app/(map-layout)/map/components/gisEdit/GisEditToolbar.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 하수관로 편집 도구 + * 관로 추가·이동·꼭지점 편집·삭제 도구를 선택하고 제어한다. + */ "use client"; import { Check, Move, PenTool, Plus, Trash2, X } from "lucide-react"; diff --git a/apps/sn/app/(map-layout)/map/components/gisEdit/gisEditTypes.ts b/apps/sn/app/(map-layout)/map/components/gisEdit/gisEditTypes.ts index 930e48c07..ed6021e94 100644 --- a/apps/sn/app/(map-layout)/map/components/gisEdit/gisEditTypes.ts +++ b/apps/sn/app/(map-layout)/map/components/gisEdit/gisEditTypes.ts @@ -1,3 +1,4 @@ +/** 하수관로 GIS 편집에서 사용하는 도구·세션·변경 데이터 타입을 정의한다. */ export type GisEditTool = "ADD" | "MOVE" | "VERTEX_EDIT" | "DELETE"; export type GisEditGeometryType = "Point" | "LineString" | "Polygon"; diff --git a/apps/sn/app/(map-layout)/map/components/gisEdit/useGisEdit.ts b/apps/sn/app/(map-layout)/map/components/gisEdit/useGisEdit.ts index a27bcc6b5..9cdd5de4a 100644 --- a/apps/sn/app/(map-layout)/map/components/gisEdit/useGisEdit.ts +++ b/apps/sn/app/(map-layout)/map/components/gisEdit/useGisEdit.ts @@ -1,3 +1,4 @@ +/** 하수관로 GIS 편집 도구의 선택 상태와 변경 내역을 관리하는 훅이다. */ "use client"; import { useCallback, useMemo, useRef, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/gisEdit/useGisEditCommonCodes.ts b/apps/sn/app/(map-layout)/map/components/gisEdit/useGisEditCommonCodes.ts index 6fba5128c..b543d6997 100644 --- a/apps/sn/app/(map-layout)/map/components/gisEdit/useGisEditCommonCodes.ts +++ b/apps/sn/app/(map-layout)/map/components/gisEdit/useGisEditCommonCodes.ts @@ -1,3 +1,4 @@ +/** 하수관로 GIS 편집에 필요한 공통코드를 조회하는 훅이다. */ "use client"; import { useEffect, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/gisManagement/GisManagementPopupPage.tsx b/apps/sn/app/(map-layout)/map/components/gisManagement/GisManagementPopupPage.tsx index a4a224440..708cedb58 100644 --- a/apps/sn/app/(map-layout)/map/components/gisManagement/GisManagementPopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/gisManagement/GisManagementPopupPage.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: GIS 관리 + * GIS 자료 업로드 이력을 조회하고 등록·검증·반영 기능을 제공한다. + */ "use client"; import type { ChangeEvent } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/gisManagement/GisUploadPreviewMap.tsx b/apps/sn/app/(map-layout)/map/components/gisManagement/GisUploadPreviewMap.tsx index 95e60dff7..dd842a155 100644 --- a/apps/sn/app/(map-layout)/map/components/gisManagement/GisUploadPreviewMap.tsx +++ b/apps/sn/app/(map-layout)/map/components/gisManagement/GisUploadPreviewMap.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: GIS 업로드 미리보기 지도 + * 업로드한 공간정보를 지도에 미리 표시하고 검증 결과를 확인한다. + */ "use client"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/gisManagement/useGisManagementCommonCodes.ts b/apps/sn/app/(map-layout)/map/components/gisManagement/useGisManagementCommonCodes.ts index f1a75f2f5..f8c5fffc3 100644 --- a/apps/sn/app/(map-layout)/map/components/gisManagement/useGisManagementCommonCodes.ts +++ b/apps/sn/app/(map-layout)/map/components/gisManagement/useGisManagementCommonCodes.ts @@ -1,3 +1,4 @@ +/** GIS 관리 화면에 필요한 공통코드를 조회하고 선택 항목으로 제공한다. */ "use client"; import { useEffect, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/inftwtResult/InftwtResultPopupPage.tsx b/apps/sn/app/(map-layout)/map/components/inftwtResult/InftwtResultPopupPage.tsx index a0cf5765e..e3772768a 100644 --- a/apps/sn/app/(map-layout)/map/components/inftwtResult/InftwtResultPopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/inftwtResult/InftwtResultPopupPage.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 침입수 분석결과 목록 + * 침입수 분석결과를 검색하고 목록·엑셀·지도 보기 기능을 제공한다. + */ "use client"; import { useCallback, useEffect, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/inftwtResult/inftwtResultTypes.ts b/apps/sn/app/(map-layout)/map/components/inftwtResult/inftwtResultTypes.ts index 5112afe49..8e03a3d89 100644 --- a/apps/sn/app/(map-layout)/map/components/inftwtResult/inftwtResultTypes.ts +++ b/apps/sn/app/(map-layout)/map/components/inftwtResult/inftwtResultTypes.ts @@ -1,3 +1,4 @@ +/** 침입수 분석결과 화면의 타입·검색 조건·컬럼과 응답 변환을 정의한다. */ "use client"; export const INFTWT_RESULT_ROW_SELECT_MESSAGE = "SN_INFTWT_RESULT_ROW_SELECT"; diff --git a/apps/sn/app/(map-layout)/map/components/inftwtResult/useInftwtResultMap.ts b/apps/sn/app/(map-layout)/map/components/inftwtResult/useInftwtResultMap.ts index c36e83898..c81d97854 100644 --- a/apps/sn/app/(map-layout)/map/components/inftwtResult/useInftwtResultMap.ts +++ b/apps/sn/app/(map-layout)/map/components/inftwtResult/useInftwtResultMap.ts @@ -1,5 +1,6 @@ "use client"; +/** 침입수 분석결과 선택 시 부모 지도에 결과 레이어를 표시하는 훅이다. */ import { useCallback, useEffect, useRef, useState, type MutableRefObject } from "react"; import GeoJSON from "ol/format/GeoJSON.js"; import VectorLayer from "ol/layer/Vector.js"; diff --git a/apps/sn/app/(map-layout)/map/components/layerSetting/LayerSettingCard.tsx b/apps/sn/app/(map-layout)/map/components/layerSetting/LayerSettingCard.tsx index 91c9766f8..2789f6807 100644 --- a/apps/sn/app/(map-layout)/map/components/layerSetting/LayerSettingCard.tsx +++ b/apps/sn/app/(map-layout)/map/components/layerSetting/LayerSettingCard.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 선택 레이어 설정 카드 + * 레이어별 설정 제목과 활성화·닫기 영역을 공통 레이아웃으로 제공한다. + */ "use client"; import type { ReactNode } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/pipeAnalysis/PipeAnalysisDetailPopupPage.tsx b/apps/sn/app/(map-layout)/map/components/pipeAnalysis/PipeAnalysisDetailPopupPage.tsx index 969f472d8..49e025a19 100644 --- a/apps/sn/app/(map-layout)/map/components/pipeAnalysis/PipeAnalysisDetailPopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/pipeAnalysis/PipeAnalysisDetailPopupPage.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 관로현황 목록 + * 관로분석 집계 항목에 해당하는 개별 관로 목록을 표시한다. + */ "use client"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/pipeAnalysis/PipeAnalysisPopupPage.tsx b/apps/sn/app/(map-layout)/map/components/pipeAnalysis/PipeAnalysisPopupPage.tsx index e657c6f2d..f053073d3 100644 --- a/apps/sn/app/(map-layout)/map/components/pipeAnalysis/PipeAnalysisPopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/pipeAnalysis/PipeAnalysisPopupPage.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 관로분석 + * 행정구역·처리구역과 분석구분별 관로 집계 결과를 조회한다. + */ "use client"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/pipeAnalysis/pipeAnalysisUtils.ts b/apps/sn/app/(map-layout)/map/components/pipeAnalysis/pipeAnalysisUtils.ts index dbce492b3..6e8327d1e 100644 --- a/apps/sn/app/(map-layout)/map/components/pipeAnalysis/pipeAnalysisUtils.ts +++ b/apps/sn/app/(map-layout)/map/components/pipeAnalysis/pipeAnalysisUtils.ts @@ -1,3 +1,4 @@ +/** 관로분석 검색 조건, 집계 컬럼과 표시값 변환 유틸을 제공한다. */ "use client"; import type { SelectDataType } from "@common/business_components"; diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx index b081f5506..aadf5751b 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx @@ -1,4 +1,5 @@ /** + * 화면명: 하수관로 정보 * ➡️ 경로 : 하수관망도 메인 페이지 (시설물 클릭) - 오른쪽 팝업창 (하수관로) * * 📄 MsSwagePpl diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx index 3a070cce1..5a0fcadde 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx @@ -1,4 +1,5 @@ /** + * 화면명: 우수토실 정보 * ➡️ 경로 : 하수관망도 메인 페이지 (시설물 클릭) - 오른쪽 팝업창 (우수토실) * * 📄 Ssc diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/SwtrmtFclt.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/SwtrmtFclt.tsx index aaee3f048..3ef836edf 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/SwtrmtFclt.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/SwtrmtFclt.tsx @@ -1,4 +1,5 @@ /** + * 화면명: 하수처리시설 정보 * ➡️ 경로 : 하수관망도 메인 페이지 (시설물 클릭) - 오른쪽 팝업창 (하수처리시설) * * 📄 SwtrmtFclt diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/SwtrmtPrcsZoneAnalysis.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/SwtrmtPrcsZoneAnalysis.tsx index 68ee568c1..a15e37b55 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/SwtrmtPrcsZoneAnalysis.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/SwtrmtPrcsZoneAnalysis.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 처리구역내 관로분석정보 + * 선택한 하수처리구역의 관로 분석 현황과 보수이력 연계 기능을 제공한다. + */ "use client"; import React, { diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/aplcnYms.ts b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/aplcnYms.ts index eab5b6e9d..0c33df1e1 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/aplcnYms.ts +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/aplcnYms.ts @@ -1,3 +1,4 @@ +/** 침입수·RDII 분석의 적용연월 선택 상태와 월 목록을 제공한다. */ import { useState, useEffect } from "react"; import moment from "moment"; import { getData } from "@/components/lib/api"; @@ -295,4 +296,4 @@ export const getChartDataRainData = (arr: TRainData[]) => { lineVal0: 0, barVal0: roundTo(data.amrf, 2), })); -}; \ No newline at end of file +}; diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx index 515d6ad8a..4cf5c5d45 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 침입수 분석 + * 침입수 분석 조건 입력, 실행 상태와 분석결과를 표시한다. + */ "use client"; import React, { useEffect, useMemo, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx index 0a5abc436..44c384ace 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: RDII 분석 + * RDII 분석 조건 입력, 실행 상태와 분석결과를 표시한다. + */ "use client"; import React, { useEffect, useMemo, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/featureClickEventPopup.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/featureClickEventPopup.tsx index 29654473d..3d2a2c5c5 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/featureClickEventPopup.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/featureClickEventPopup.tsx @@ -1,4 +1,5 @@ /** + * 화면명: 시설 상세정보 * ➡️ 경로 : 하수관망도 메인 페이지 (시설물 클릭) - 오른쪽 팝업창 * * 📄 FeatureClickEventPopup @@ -69,6 +70,11 @@ import { useAlertStore } from "@/shared/lib"; import { useConfirm } from "@frontend-opensource/use-react-hooks"; import useStore from "@/store/useStore"; import ExmnSurveyResultSection from "../exmn/ExmnSurveyResultSection"; +import { + loadFldngHstryDetail, + showFldngHstryFeature, + type FldngHstryDetailCacheValue, +} from "../fldngHstry/fldngHstryTypes"; const linkedFacilityHighlightStyle = new Style({ image: new CircleStyle({ @@ -105,20 +111,6 @@ const normalizeFldngWtlvMapApiFid = (value: unknown) => { return normalizeFldngWtlvMapDisplayId(normalized); }; -const normalizeRainAnalysisPayload = (data: any) => { - if (!data || typeof data !== "object") return {}; - return { - rain_bgng_tm: data.rainBgngTm ?? data.rain_bgng_tm ?? null, - rainBgngTm: data.rainBgngTm ?? data.rain_bgng_tm ?? null, - rain_end_tm: data.rainEndTm ?? data.rain_end_tm ?? null, - rainEndTm: data.rainEndTm ?? data.rain_end_tm ?? null, - rain_tot: data.rainTot ?? data.rain_tot ?? null, - rainTot: data.rainTot ?? data.rain_tot ?? null, - rain_str: data.rainStr ?? data.rain_str ?? null, - rainStr: data.rainStr ?? data.rain_str ?? null, - }; -}; - // 침수흔적도 침수시작일시, 침수종료일시 한줄로 보이도록 const formatFldngWtlvDateTime = (dateValue: unknown, timeValue: unknown) => { const rawDate = String(dateValue ?? "").trim(); @@ -182,6 +174,9 @@ const FeatureClickEventPopup = ({ const flowDirectionBasisRequestCacheRef = useRef( new Map>(), ); + const fldngHstryDetailCacheRef = useRef( + new Map>(), + ); const [mngInstOptions, setMngInstOptions] = useState([]); const [floodDepthRows, setFloodDepthRows] = useState< Record[] @@ -855,60 +850,41 @@ const FeatureClickEventPopup = ({ } if (selectedLayerName === "침수흔적위선" && featureId) { - const depthLookupKey = normalizeFldngWtlvMapApiFid(featureId); setFloodDepthRows([]); setFloodWtlvRows([]); setSelectedFloodDepthFid(null); setSelectedFloodWtlvFid(null); - try { - const normalizedFloodMapFid = - normalizeFldngWtlvMapApiFid(featureId); - if (!normalizedFloodMapFid) { - throw new Error("침수흔적도 fid가 비어 있습니다."); - } - const rainAnalysis = await getData( - `v1/fldng/hstry/rain-anls/${encodeURIComponent(normalizedFloodMapFid)}`, + const fldngHstryFid = normalizeFldngWtlvMapApiFid(featureId); + if (!fldngHstryFid) { + throw new Error("침수흔적도 fid가 비어 있습니다."); + } + + const fldngHstryCacheKey = `tb_ms_fldng_wtlv_map:${fldngHstryFid}`; + let fldngHstryDetailRequest = + fldngHstryDetailCacheRef.current.get(fldngHstryCacheKey); + if (!fldngHstryDetailRequest) { + fldngHstryDetailRequest = loadFldngHstryDetail(fldngHstryFid); + fldngHstryDetailCacheRef.current.set( + fldngHstryCacheKey, + fldngHstryDetailRequest, ); - if (rainAnalysis) { - const mergedData = { - ...formattedData, - ...normalizeRainAnalysisPayload(rainAnalysis), - }; - setFetchData(mergedData); - setTableData(mergedData); - } - } catch (rainError) { - console.warn("침수강우분석 조회 실패:", rainError); } - try { - if (depthLookupKey) { - const depthRows = await getData( - `v1/fldng/hstry/depth-map/${encodeURIComponent(depthLookupKey)}`, - ); - const depthPayload = depthRows?.data ?? depthRows; - const depthItems = Array.isArray(depthPayload) - ? depthPayload - : depthPayload?.depthMaps; - const waterLevelItems = Array.isArray( - depthPayload?.waterLevelMaps, - ) - ? depthPayload.waterLevelMaps - : []; - const normalizedDepthRows = Array.isArray(depthItems) - ? depthItems.filter((row) => row && typeof row === "object") - : []; - const normalizedWaterLevelRows = waterLevelItems.filter( - (row: unknown) => row && typeof row === "object", - ); - setFloodDepthRows(normalizedDepthRows); - setFloodWtlvRows(normalizedWaterLevelRows); - // 최초에는 연계 항목을 선택하지 않고 버튼 목록만 표시한다. - setSelectedFloodDepthFid(null); - setSelectedFloodWtlvFid(null); - } - } catch (depthError) { - console.warn("침수깊이지도 조회 실패:", depthError); + + const fldngHstryDetail = await fldngHstryDetailRequest; + if (!fldngHstryDetail.complete) { + fldngHstryDetailCacheRef.current.delete(fldngHstryCacheKey); } + const mergedFldngHstryData = { + ...formattedData, + ...fldngHstryDetail.rainAnalysis, + }; + setFetchData(mergedFldngHstryData); + setTableData(mergedFldngHstryData); + setFloodDepthRows(fldngHstryDetail.depthRows); + setFloodWtlvRows(fldngHstryDetail.waterLevelRows); + // 최초에는 연계 항목을 선택하지 않고 버튼 목록만 표시한다. + setSelectedFloodDepthFid(null); + setSelectedFloodWtlvFid(null); } } catch (error) { console.error("데이터 로딩 중 오류:", error); @@ -1170,7 +1146,8 @@ const FeatureClickEventPopup = ({ setSelectedFloodDepthFid(depthFid); setSelectedFloodWtlvFid(null); const core = GisApp.Module.layer as any; - await core.showSearchResultsFromGeoJSON?.( + await showFldngHstryFeature( + core, "tb_ms_fldng_dpth_map", `tb_ms_fldng_dpth_map.${depthFid.replace(/^tb_ms_fldng_dpth_map\./, "")}`, ); @@ -1233,7 +1210,8 @@ const FeatureClickEventPopup = ({ setSelectedFloodWtlvFid(waterLevelFid); setSelectedFloodDepthFid(null); const core = GisApp.Module.layer as any; - await core.showSearchResultsFromGeoJSON?.( + await showFldngHstryFeature( + core, "tb_ms_fldng_wtlv_map", `tb_ms_fldng_wtlv_map.${waterLevelFid.replace(/^tb_ms_fldng_wtlv_map\./, "")}`, ); diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx index 07d78a7d1..8712a7b31 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx @@ -1,4 +1,5 @@ /** + * 화면명: 하수펌프장 정보 * ➡️ 경로 : 하수관망도 메인 페이지 (시설물 클릭) - 오른쪽 팝업창 (하수펌프장) * * 📄 sewagePump diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/smh.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/smh.tsx index e4a8fa0ba..9b7042c17 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/smh.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/smh.tsx @@ -1,4 +1,5 @@ /** + * 화면명: 하수맨홀 정보 * ➡️ 경로 : 하수관망도 메인 페이지 (시설물 클릭) - 오른쪽 팝업창 (하수맨홀) * * 📄 Smh diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/stormWaterPump.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/stormWaterPump.tsx index 92973b133..7b365b59e 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/stormWaterPump.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/stormWaterPump.tsx @@ -1,4 +1,5 @@ /** + * 화면명: 빗물펌프 정보 * ➡️ 경로 : 하수관망도 메인 페이지 (시설물 클릭) - 오른쪽 팝업창 (빗물펌프) * * 📄 StormWaterPump @@ -34,4 +35,4 @@ const StormWaterPump = ({ featureData }: { featureData: Record }) = ) } -export default StormWaterPump \ No newline at end of file +export default StormWaterPump diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/swtrmtPrcsZoneAnalysisApi.ts b/apps/sn/app/(map-layout)/map/components/popupComponent/swtrmtPrcsZoneAnalysisApi.ts index 21b6899dc..d0c92d678 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/swtrmtPrcsZoneAnalysisApi.ts +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/swtrmtPrcsZoneAnalysisApi.ts @@ -1,3 +1,4 @@ +/** 처리구역 관로분석정보와 보수이력을 조회·다운로드하는 API를 제공한다. */ import { getBlobDataWithHeaders, getData } from "@/components/lib/api"; export type SwtrmtPrcsZoneAnalysisMetric = { diff --git a/apps/sn/app/(map-layout)/map/components/rdiiResult/RdiiResultPopupPage.tsx b/apps/sn/app/(map-layout)/map/components/rdiiResult/RdiiResultPopupPage.tsx index 06641fed8..eea62cc47 100644 --- a/apps/sn/app/(map-layout)/map/components/rdiiResult/RdiiResultPopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/rdiiResult/RdiiResultPopupPage.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: RDII 분석결과 목록 + * RDII 분석결과를 검색하고 목록·엑셀·지도 보기 기능을 제공한다. + */ "use client"; import { useCallback, useEffect, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/rdiiResult/rdiiResultTypes.ts b/apps/sn/app/(map-layout)/map/components/rdiiResult/rdiiResultTypes.ts index 7dc76db34..a90b88591 100644 --- a/apps/sn/app/(map-layout)/map/components/rdiiResult/rdiiResultTypes.ts +++ b/apps/sn/app/(map-layout)/map/components/rdiiResult/rdiiResultTypes.ts @@ -1,3 +1,4 @@ +/** RDII 분석결과 화면의 타입·검색 조건·컬럼과 응답 변환을 정의한다. */ "use client"; export const RDII_RESULT_ROW_SELECT_MESSAGE = "SN_RDII_RESULT_ROW_SELECT"; @@ -44,4 +45,4 @@ export type RdiiResultMapViewResponse = { pipeGeometry: Record; pipes: RdiiResultMapViewPipe[]; pipeCount: number; -}; \ No newline at end of file +}; diff --git a/apps/sn/app/(map-layout)/map/components/rdiiResult/useRdiiResultMap.ts b/apps/sn/app/(map-layout)/map/components/rdiiResult/useRdiiResultMap.ts index 6369daa08..98db366c5 100644 --- a/apps/sn/app/(map-layout)/map/components/rdiiResult/useRdiiResultMap.ts +++ b/apps/sn/app/(map-layout)/map/components/rdiiResult/useRdiiResultMap.ts @@ -1,3 +1,4 @@ +/** RDII 분석결과 선택 시 부모 지도에 결과 레이어를 표시하는 훅이다. */ "use client"; import { useCallback, useEffect, useRef, useState, type MutableRefObject } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/repairHistory/RepairHistoryPopupPage.tsx b/apps/sn/app/(map-layout)/map/components/repairHistory/RepairHistoryPopupPage.tsx index 6b7c2ad33..228b1c1b8 100644 --- a/apps/sn/app/(map-layout)/map/components/repairHistory/RepairHistoryPopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/repairHistory/RepairHistoryPopupPage.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 보수이력 목록 + * 선택 시설의 보수이력을 조회하고 목록으로 표시한다. + */ "use client"; import { useCallback, useEffect, useMemo, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/sbmrgDngrMap/SbmrgDngrMapPopupPage.tsx b/apps/sn/app/(map-layout)/map/components/sbmrgDngrMap/SbmrgDngrMapPopupPage.tsx index a6e2190e4..cf09f4cf2 100644 --- a/apps/sn/app/(map-layout)/map/components/sbmrgDngrMap/SbmrgDngrMapPopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/sbmrgDngrMap/SbmrgDngrMapPopupPage.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 침수위험지도 목록 + * 침수위험지도를 검색하고 목록·엑셀·지도 보기 기능을 제공한다. + */ "use client"; import { useCallback, useEffect, useMemo, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/sbmrgDngrMap/sbmrgDngrMapTypes.ts b/apps/sn/app/(map-layout)/map/components/sbmrgDngrMap/sbmrgDngrMapTypes.ts index 3d27a82c9..c21c749cf 100644 --- a/apps/sn/app/(map-layout)/map/components/sbmrgDngrMap/sbmrgDngrMapTypes.ts +++ b/apps/sn/app/(map-layout)/map/components/sbmrgDngrMap/sbmrgDngrMapTypes.ts @@ -1,3 +1,4 @@ +/** 침수위험지도 화면의 검색 조건, 컬럼과 응답 변환을 정의한다. */ "use client"; import type { UiHeadProps } from "@common/business_components/ui"; diff --git a/apps/sn/app/(map-layout)/map/components/sinkhole/SinkholeDetailPanel.tsx b/apps/sn/app/(map-layout)/map/components/sinkhole/SinkholeDetailPanel.tsx index bd5a44c58..7ed216afc 100644 --- a/apps/sn/app/(map-layout)/map/components/sinkhole/SinkholeDetailPanel.tsx +++ b/apps/sn/app/(map-layout)/map/components/sinkhole/SinkholeDetailPanel.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 지반침하 상세정보 + * 선택한 지반침하 정보와 주변 관로 조회 결과를 표시한다. + */ "use client"; import { useEffect, useMemo, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/sinkhole/SinkholeLayerSettingPanel.tsx b/apps/sn/app/(map-layout)/map/components/sinkhole/SinkholeLayerSettingPanel.tsx index 7448849ba..d230f8269 100644 --- a/apps/sn/app/(map-layout)/map/components/sinkhole/SinkholeLayerSettingPanel.tsx +++ b/apps/sn/app/(map-layout)/map/components/sinkhole/SinkholeLayerSettingPanel.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 지반침하정보 레이어 설정 + * 발생연도와 위험도 등 지도 표시 조건을 설정한다. + */ "use client"; import { useEffect, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/sinkhole/SinkholePopupPage.tsx b/apps/sn/app/(map-layout)/map/components/sinkhole/SinkholePopupPage.tsx index c5268b167..8f55f825d 100644 --- a/apps/sn/app/(map-layout)/map/components/sinkhole/SinkholePopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/sinkhole/SinkholePopupPage.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 지반침하 목록 + * 지반침하 정보를 검색하고 목록·엑셀·지도 보기 기능을 제공한다. + */ "use client"; import { useCallback, useEffect, useMemo, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/sinkhole/sinkholeTypes.ts b/apps/sn/app/(map-layout)/map/components/sinkhole/sinkholeTypes.ts index e526ec992..ef392c48f 100644 --- a/apps/sn/app/(map-layout)/map/components/sinkhole/sinkholeTypes.ts +++ b/apps/sn/app/(map-layout)/map/components/sinkhole/sinkholeTypes.ts @@ -1,3 +1,4 @@ +/** 지반침하 화면에서 사용하는 타입·상수·검색 조건을 정의한다. */ "use client"; import type { SelectDataType } from "@common/business_components"; diff --git a/apps/sn/app/(map-layout)/map/components/sinkhole/useSinkholeCommonCodes.ts b/apps/sn/app/(map-layout)/map/components/sinkhole/useSinkholeCommonCodes.ts index f5de60b24..445bab9ff 100644 --- a/apps/sn/app/(map-layout)/map/components/sinkhole/useSinkholeCommonCodes.ts +++ b/apps/sn/app/(map-layout)/map/components/sinkhole/useSinkholeCommonCodes.ts @@ -1,3 +1,4 @@ +/** 지반침하 화면에 필요한 공통코드를 조회하고 선택 항목으로 제공한다. */ "use client"; import { useEffect, useMemo, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/waterRisk/WaterRiskPopupPage.tsx b/apps/sn/app/(map-layout)/map/components/waterRisk/WaterRiskPopupPage.tsx index 6758738f5..96a47fb8c 100644 --- a/apps/sn/app/(map-layout)/map/components/waterRisk/WaterRiskPopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/waterRisk/WaterRiskPopupPage.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 통수위험 분석 + * 통수위험 분석 결과와 과거 분석이력을 조회하고 지도에 표시한다. + */ "use client"; import { useEffect, useMemo, useState } from "react"; diff --git a/apps/sn/app/(map-layout)/map/components/waterRisk/waterRiskClient.ts b/apps/sn/app/(map-layout)/map/components/waterRisk/waterRiskClient.ts index 9cbf64e65..0094c8c16 100644 --- a/apps/sn/app/(map-layout)/map/components/waterRisk/waterRiskClient.ts +++ b/apps/sn/app/(map-layout)/map/components/waterRisk/waterRiskClient.ts @@ -1,3 +1,4 @@ +/** 통수위험 분석 대상과 결과를 조회하는 API 함수를 제공한다. */ import { getData } from "@/app/components/lib/api"; import type { UiTableSort } from "@common/business_components/ui/table"; diff --git a/apps/sn/app/(map-layout)/map/components/waterRisk/waterRiskTypes.ts b/apps/sn/app/(map-layout)/map/components/waterRisk/waterRiskTypes.ts index c60e09dc9..00bf70dff 100644 --- a/apps/sn/app/(map-layout)/map/components/waterRisk/waterRiskTypes.ts +++ b/apps/sn/app/(map-layout)/map/components/waterRisk/waterRiskTypes.ts @@ -1,3 +1,4 @@ +/** 통수위험 분석 화면에서 사용하는 타입·상수와 표시값 변환을 정의한다. */ "use client"; export type WaterRiskStatus = "DANGER" | "NORMAL"; diff --git a/apps/sn/app/(map-layout)/map/page.tsx b/apps/sn/app/(map-layout)/map/page.tsx index e5266b909..71d22ff65 100644 --- a/apps/sn/app/(map-layout)/map/page.tsx +++ b/apps/sn/app/(map-layout)/map/page.tsx @@ -7007,7 +7007,9 @@ const Map = () => { } const desiredLayerIds = new Set(desiredLayers.map((item) => item.id)); - const mapLayers = gisMaps.current?.getLayers?.()?.getArray?.() ?? []; + const mapLayers = [ + ...(gisMaps.current?.getLayers?.()?.getArray?.() ?? []), + ]; const isManagedFloodLayerId = (id: string) => id === FLDNG_HSTRY_WFS_LAYER_ID || id.startsWith(`${FLDNG_DEPTH_WFS_LAYER_ID_PREFIX}_`); @@ -7016,7 +7018,7 @@ const Map = () => { mapLayers.forEach((mapLayer: any) => { const layerId = String(mapLayer?.get?.("id") ?? ""); if (isManagedFloodLayerId(layerId) && !desiredLayerIds.has(layerId)) { - core?.deleteLayer?.(layerId); + gisMaps.current?.removeLayer?.(mapLayer); } }); diff --git a/apps/sn/app/(with-base-layout)/oper/dredging/components/DredgingRegisterModal.tsx b/apps/sn/app/(with-base-layout)/oper/dredging/components/DredgingRegisterModal.tsx index 0f8b0fc0b..234405264 100644 --- a/apps/sn/app/(with-base-layout)/oper/dredging/components/DredgingRegisterModal.tsx +++ b/apps/sn/app/(with-base-layout)/oper/dredging/components/DredgingRegisterModal.tsx @@ -1,3 +1,7 @@ +/** + * 화면명: 준설실적 등록 + * 준설 사진을 등록하고 촬영정보·위치·인접 관로를 확인하여 준설실적을 저장하는 화면이다. + */ "use client"; import dynamic from "next/dynamic"; @@ -789,7 +793,11 @@ const DredgingRegisterModal = ({