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 a56aa7127..86160149c 100644 --- a/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryDetailPanel.tsx +++ b/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryDetailPanel.tsx @@ -1,10 +1,10 @@ "use client"; import { useMemo, useState } from "react"; -import { formatFloodArea, formatFloodDepth, type FloodHistoryItem } from "./fldngHstryTypes"; +import { formatFloodArea, formatFloodDepth, type FldngHstryItem } from "./fldngHstryTypes"; type Props = { - detail: FloodHistoryItem; + detail: FldngHstryItem; onClose: () => void; position: { left: number; 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 147fafdb2..470a7d3c2 100644 --- a/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryPopupPage.tsx +++ b/apps/sn/app/(map-layout)/map/components/fldngHstry/FldngHstryPopupPage.tsx @@ -1,3 +1,6 @@ +/** + * 침수발생이력 popup + */ "use client"; import { useCallback, useEffect, useMemo, useState } from "react"; @@ -8,20 +11,20 @@ import { getRawJson } from "@/components/lib/api"; import useStore from "@/store/useStore"; import LoadingOverlay from "@/components/ui/LoadingBar"; import { - attachFloodHistoryGeometry, - buildFloodHistoryListQueryString, - buildFloodHistoryYearOptions, - FLOOD_HISTORY_DEFAULT_FILTERS, - FLOOD_HISTORY_DOWNLOAD_BATCH_SIZE, - FLOOD_HISTORY_DOWNLOAD_HEADERS, - FLOOD_HISTORY_LIST_HEADLIST, - FLOOD_HISTORY_PAGE_SIZE, - FLOOD_HISTORY_ROW_SELECT_MESSAGE, - normalizeFloodHistoryFilters, - toFloodHistoryTableRows, - type FloodHistoryApiItem, - type FloodHistoryFilters, - type FloodHistoryTableRow, + FLDNG_HSTRY_DEFAULT_FILTERS, + FLDNG_HSTRY_DOWNLOAD_BATCH_SIZE, + FLDNG_HSTRY_DOWNLOAD_HEADERS, + FLDNG_HSTRY_LIST_HEADLIST, + FLDNG_HSTRY_PAGE_SIZE, + FLDNG_HSTRY_ROW_SELECT_MESSAGE, + attachFldngHstryGeometry, + buildFldngHstryListQueryString, + buildFldngHstryYearOptions, + normalizeFldngHstryFilters, + toFldngHstryTableRows, + type FldngHstryApiItem, + type FldngHstryFilters, + type FldngHstryTableRow, } from "./fldngHstryTypes"; const unwrapPayload = (response: any): T => @@ -38,12 +41,12 @@ const resolveOptionText = ( return options.find((item) => String(item.val).trim() === lookup)?.text ?? ""; }; -const resolveFloodHistoryApiSort = (sort?: UiTableSort) => { +const resolveFldngHstryApiSort = (sort?: UiTableSort) => { if (!sort?.key || !sort.direction) return undefined; return { key: sort.key, direction: sort.direction } as UiTableSort; }; -const buildDownloadRows = (rows: FloodHistoryTableRow[]) => +const buildDownloadRows = (rows: FldngHstryTableRow[]) => rows.map((row) => ({ rowNo: row.rowNo, floodYearDisplay: row.floodYearDisplay, @@ -65,10 +68,10 @@ const buildDownloadRows = (rows: FloodHistoryTableRow[]) => })); const resolveRegionNames = ( - row: FloodHistoryTableRow, + row: FldngHstryTableRow, ctpvOptions: Array<{ text: string; val: string | number }>, sggOptions: Array<{ text: string; val: string | number }>, -): FloodHistoryTableRow => ({ +): FldngHstryTableRow => ({ ...row, ctpvNm: resolveOptionText(row.ctpvCd ?? "", ctpvOptions, 2) || row.ctpvNm, sggNm: resolveOptionText(row.sggCd ?? "", sggOptions, 5) || row.sggNm, @@ -76,9 +79,9 @@ const resolveRegionNames = ( export default function FldngHstryPopupPage() { const { ctpv, sgg, fetchCtpv, fetchSgg } = useStore(); - const [filters, setFilters] = useState(FLOOD_HISTORY_DEFAULT_FILTERS); - const [appliedFilters, setAppliedFilters] = useState(FLOOD_HISTORY_DEFAULT_FILTERS); - const [rows, setRows] = useState([]); + const [filters, setFilters] = useState(FLDNG_HSTRY_DEFAULT_FILTERS); + const [appliedFilters, setAppliedFilters] = useState(FLDNG_HSTRY_DEFAULT_FILTERS); + const [rows, setRows] = useState([]); const [total, setTotal] = useState(0); const [currentPage, setCurrentPage] = useState(1); const [selectedIndex, setSelectedIndex] = useState(-1); @@ -100,7 +103,7 @@ export default function FldngHstryPopupPage() { ); }, [ctpv, rows.length, sgg]); - const floodYearOptions = useMemo(() => buildFloodHistoryYearOptions(), []); + const fldngYearOptions = useMemo(() => buildFldngHstryYearOptions(), []); const sggOptions = useMemo( () => @@ -111,20 +114,20 @@ export default function FldngHstryPopupPage() { ); const fetchRows = useCallback( - async (page: number, nextFilters: FloodHistoryFilters, size: number, nextSort?: UiTableSort) => { - const normalized = normalizeFloodHistoryFilters(nextFilters); - const queryString = buildFloodHistoryListQueryString( + async (page: number, nextFilters: FldngHstryFilters, size: number, nextSort?: UiTableSort) => { + const normalized = normalizeFldngHstryFilters(nextFilters); + const queryString = buildFldngHstryListQueryString( normalized, page, size, - resolveFloodHistoryApiSort(nextSort), + resolveFldngHstryApiSort(nextSort), ); const response = await getRawJson(`/sewerage-service/api/v1/fldng/hstry?${queryString}`); - const payload = unwrapPayload<{ items?: FloodHistoryApiItem[]; total?: number }>(response); + const payload = unwrapPayload<{ items?: FldngHstryApiItem[]; total?: number }>(response); const items = Array.isArray(payload?.items) ? payload.items : []; const displayItems = items.map((item) => { - const hydrated = attachFloodHistoryGeometry(item); + const hydrated = attachFldngHstryGeometry(item); return { ...hydrated, ctpvNm: resolveOptionText(hydrated.ctpvCd ?? "", ctpv as any, 2), @@ -133,7 +136,7 @@ export default function FldngHstryPopupPage() { }); return { - rows: toFloodHistoryTableRows(displayItems, page, size), + rows: toFldngHstryTableRows(displayItems, page, size), total: Number(payload?.total ?? 0), }; }, @@ -141,11 +144,11 @@ export default function FldngHstryPopupPage() { ); const loadRows = useCallback( - async (page: number, nextFilters: FloodHistoryFilters, nextSort?: UiTableSort) => { + async (page: number, nextFilters: FldngHstryFilters, nextSort?: UiTableSort) => { setIsLoading(true); try { - const normalized = normalizeFloodHistoryFilters(nextFilters); - const response = await fetchRows(page, normalized, FLOOD_HISTORY_PAGE_SIZE, nextSort); + const normalized = normalizeFldngHstryFilters(nextFilters); + const response = await fetchRows(page, normalized, FLDNG_HSTRY_PAGE_SIZE, nextSort); setRows(response.rows); setTotal(response.total); setCurrentPage(page); @@ -166,13 +169,13 @@ export default function FldngHstryPopupPage() { ); useEffect(() => { - void loadRows(1, FLOOD_HISTORY_DEFAULT_FILTERS, undefined); + void loadRows(1, FLDNG_HSTRY_DEFAULT_FILTERS, undefined); // 최초 로딩은 한 번만 수행한다. // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const handleSearch = async (page = 1) => { - const normalized = normalizeFloodHistoryFilters(filters); + const normalized = normalizeFldngHstryFilters(filters); if (normalized.sggCd !== "0" && normalized.ctpvCd === "0") { alert("시도를 먼저 선택하세요."); @@ -199,7 +202,7 @@ export default function FldngHstryPopupPage() { setSelectedIndex(index); window.opener?.postMessage( { - type: FLOOD_HISTORY_ROW_SELECT_MESSAGE, + type: FLDNG_HSTRY_ROW_SELECT_MESSAGE, row, openDetail: false, }, @@ -218,7 +221,7 @@ export default function FldngHstryPopupPage() { const response = await fetchRows( 1, appliedFilters, - Math.max(total, FLOOD_HISTORY_DOWNLOAD_BATCH_SIZE), + Math.max(total, FLDNG_HSTRY_DOWNLOAD_BATCH_SIZE), appliedSort, ); await downloadExcelWithKoreanHeaders({ @@ -226,7 +229,7 @@ export default function FldngHstryPopupPage() { fileName: `침수발생이력_${new Date().toISOString().slice(0, 10)}.xlsx`, sheetNameArray: ["침수발생이력"], headerRange: "A1:Q1", - headerMapping: FLOOD_HISTORY_DOWNLOAD_HEADERS, + headerMapping: FLDNG_HSTRY_DOWNLOAD_HEADERS, }); } catch (error) { console.error("침수발생이력 다운로드 중 오류:", error); @@ -302,7 +305,7 @@ export default function FldngHstryPopupPage() { } > - {floodYearOptions.map((year) => ( + {fldngYearOptions.map((year) => ( @@ -352,11 +355,11 @@ export default function FldngHstryPopupPage() {
- + headName={<>침수발생이력 조회 결과 총 {total.toLocaleString()}건} tableData={rows} - headlist={FLOOD_HISTORY_LIST_HEADLIST} - pageSize={FLOOD_HISTORY_PAGE_SIZE} + headlist={FLDNG_HSTRY_LIST_HEADLIST} + pageSize={FLDNG_HSTRY_PAGE_SIZE} total={total} cellClick={(index) => handleRowClick(index)} onPageChange={(page) => void handlePageChange(page)} 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 9812c2937..94da67e29 100644 --- a/apps/sn/app/(map-layout)/map/components/fldngHstry/fldngHstryTypes.ts +++ b/apps/sn/app/(map-layout)/map/components/fldngHstry/fldngHstryTypes.ts @@ -3,29 +3,29 @@ import type { UiHeadProps, UiTableSort } from "@common/business_components/ui"; export const FLOOD_HISTORY_POPUP_KEY = "fldngHstryPopup"; -export const FLOOD_HISTORY_ROW_SELECT_MESSAGE = "SN_FLOOD_HISTORY_ROW_SELECT"; +export const FLDNG_HSTRY_ROW_SELECT_MESSAGE = "SN_FLOOD_HISTORY_ROW_SELECT"; export const FLOOD_HISTORY_LAYER_TYPE = "tb_sn_flood_trace_mock"; export const FLOOD_HISTORY_LAYER_NAME = "침수흔적도"; export const FLOOD_HISTORY_AREA_LAYER_ID = "SN_FLOOD_HISTORY_AREA"; export const FLOOD_HISTORY_DEPTH_LAYER_ID = "SN_FLOOD_HISTORY_DEPTH"; -export const FLOOD_HISTORY_PAGE_SIZE = 10; -export const FLOOD_HISTORY_DOWNLOAD_BATCH_SIZE = 2000; +export const FLDNG_HSTRY_PAGE_SIZE = 10; +export const FLDNG_HSTRY_DOWNLOAD_BATCH_SIZE = 2000; -export type FloodHistoryFilters = { +export type FldngHstryFilters = { ctpvCd: string; sggCd: string; floodYear: string; disasterName: string; }; -export type FloodHistoryDepthZone = { +export type FldngHstryDepthZone = { zoneId: string; depthLabel: string; color: string; ring: [number, number][]; }; -export type FloodHistoryApiItem = { +export type FldngHstryApiItem = { fid: string; fldngMapFid?: string; fldngWtlvMapSn?: number | null; @@ -58,7 +58,7 @@ export type FloodHistoryApiItem = { rainStr?: number | null; }; -export type FloodHistoryItem = FloodHistoryApiItem & { +export type FldngHstryItem = FldngHstryApiItem & { historyId: string; ctpvNm: string; sggNm: string; @@ -85,10 +85,10 @@ export type FloodHistoryItem = FloodHistoryApiItem & { totalRainfallMm: number; rainfallIntensityMmHr: number; areaRing: [number, number][]; - depthZones: FloodHistoryDepthZone[]; + depthZones: FldngHstryDepthZone[]; }; -export type FloodHistoryTableRow = FloodHistoryItem & { +export type FldngHstryTableRow = FldngHstryItem & { rowNo: number; floodYearDisplay: string; floodHourDisplay: string; @@ -102,14 +102,14 @@ export type FloodHistoryTableRow = FloodHistoryItem & { rainStrDisplay: string; }; -export const FLOOD_HISTORY_DEFAULT_FILTERS: FloodHistoryFilters = { +export const FLDNG_HSTRY_DEFAULT_FILTERS: FldngHstryFilters = { ctpvCd: "0", sggCd: "0", floodYear: "", disasterName: "", }; -export const FLOOD_HISTORY_DEPTH_LEGEND_ITEMS = [ +export const FLDNG_HSTRY_DEPTH_LEGEND_ITEMS = [ { color: "#fff27a", label: "0.0~0.5m" }, { color: "#c2f13d", label: "0.5~1.0m" }, { color: "#67d8ff", label: "1.0~2.0m" }, @@ -117,7 +117,7 @@ export const FLOOD_HISTORY_DEPTH_LEGEND_ITEMS = [ { color: "#f2528b", label: "5.0m 이상" }, ] as const; -export const FLOOD_HISTORY_LIST_HEADLIST: UiHeadProps[] = [ +export const FLDNG_HSTRY_LIST_HEADLIST: UiHeadProps[] = [ { id: "rowNo", title: "NO", widthPercent: 5, sortable: false }, { id: "floodYearDisplay", title: "침수년도", widthPercent: 6, sortable: true, sortKey: "fldngYr" }, { id: "ctpvNm", title: "시도", widthPercent: 7, sortable: true, sortKey: "ctpvCd" }, @@ -137,7 +137,7 @@ export const FLOOD_HISTORY_LIST_HEADLIST: UiHeadProps[] = [ { id: "damageAmountDisplay", title: "피해금액", widthPercent: 9, sortable: true, sortKey: "damAmt" }, ]; -export const FLOOD_HISTORY_DOWNLOAD_HEADERS: Record = { +export const FLDNG_HSTRY_DOWNLOAD_HEADERS: Record = { rowNo: "NO", floodYearDisplay: "침수년도", ctpvNm: "시도", @@ -198,11 +198,11 @@ const buildGeometrySeed = (fid: string) => { }; }; -const createDepthZones = ( +const createFldngHstryDepthZones = ( historyId: string, centerX: number, centerY: number, -): FloodHistoryDepthZone[] => { +): FldngHstryDepthZone[] => { return [ { zoneId: `${historyId}-depth-1`, @@ -312,7 +312,7 @@ const formatInteger = (value?: number | null, suffix = "") => { return `${numeric.toLocaleString("ko-KR")}${suffix}`; }; -const buildCauseDetailName = (item: FloodHistoryApiItem) => { +const buildCauseDetailName = (item: FldngHstryApiItem) => { const direct = String(item.dtlOcrnCsCn ?? "").trim(); if (direct) return direct; const code = String(item.fldngCsDtlCd ?? "").trim(); @@ -325,27 +325,27 @@ const buildGradeLabel = (avgFloodDepthM: number) => { return "1등급"; }; -export const normalizeFloodHistoryFilters = ( - filters: FloodHistoryFilters, -): FloodHistoryFilters => ({ +export const normalizeFldngHstryFilters = ( + filters: FldngHstryFilters, +): FldngHstryFilters => ({ ctpvCd: String(filters.ctpvCd ?? "0") || "0", sggCd: String(filters.sggCd ?? "0") || "0", floodYear: String(filters.floodYear ?? "").replace(/[^0-9]/g, "").slice(0, 4), disasterName: String(filters.disasterName ?? "").trim(), }); -export const buildFloodHistoryYearOptions = () => { +export const buildFldngHstryYearOptions = () => { const currentYear = new Date().getFullYear(); return Array.from({ length: 30 }, (_, index) => String(currentYear - index)); }; -export const buildFloodHistoryListQueryString = ( - filters: FloodHistoryFilters, +export const buildFldngHstryListQueryString = ( + filters: FldngHstryFilters, page: number, size: number, sort?: UiTableSort, ) => { - const normalized = normalizeFloodHistoryFilters(filters); + const normalized = normalizeFldngHstryFilters(filters); const params = new URLSearchParams({ page: String(page - 1), size: String(size), @@ -364,7 +364,7 @@ export const formatFloodArea = (value: number) => `${value.toFixed(1)}ha`; export const formatFloodDepth = (value: number) => `${value.toFixed(2)}m`; -export const attachFloodHistoryGeometry = (item: FloodHistoryApiItem): FloodHistoryItem => { +export const attachFldngHstryGeometry = (item: FldngHstryApiItem): FldngHstryItem => { const historyId = String(item.fid ?? ""); const geometrySeed = buildGeometrySeed(historyId); const startDate = normalizeDate(item.bgngYmd); @@ -409,15 +409,15 @@ export const attachFloodHistoryGeometry = (item: FloodHistoryApiItem): FloodHist rotationDeg: 9, scales: [1.08, 0.9, 1.04, 0.82, 0.98, 1.12, 0.88, 0.96, 1.03, 0.86], }), - depthZones: createDepthZones(historyId, geometrySeed.centerX, geometrySeed.centerY), + depthZones: createFldngHstryDepthZones(historyId, geometrySeed.centerX, geometrySeed.centerY), }; }; -export const toFloodHistoryTableRows = ( - items: FloodHistoryItem[], +export const toFldngHstryTableRows = ( + items: FldngHstryItem[], page: number, - pageSize = FLOOD_HISTORY_PAGE_SIZE, -): FloodHistoryTableRow[] => + pageSize = FLDNG_HSTRY_PAGE_SIZE, +): FldngHstryTableRow[] => items.map((item, index) => ({ ...item, rowNo: (page - 1) * pageSize + index + 1, @@ -433,14 +433,19 @@ export const toFloodHistoryTableRows = ( rainStrDisplay: formatNumber(item.rainfallIntensityMmHr, 1), })); -const resolveFloodHistoryNodeName = (node: any) => +const resolveFldngHstryNodeName = (node: any) => String(node?.text ?? node?.data?.lyrNm ?? node?.data?.name ?? node?.lyrNm ?? node?.name ?? "").trim(); -const resolveFloodHistoryLayerType = (node: any) => +const resolveFldngHstryLayerType = (node: any) => String(node?.data?.lyrTyNm ?? node?.data?.lyrTypeNm ?? node?.lyrTyNm ?? node?.lyrTypeNm ?? "").trim(); -export const isFloodHistoryNode = (node: any) => { - const name = resolveFloodHistoryNodeName(node); - const layerType = resolveFloodHistoryLayerType(node); +export const isFldngHstryNode = (node: any) => { + const name = resolveFldngHstryNodeName(node); + const layerType = resolveFldngHstryLayerType(node); return name === FLOOD_HISTORY_LAYER_NAME || layerType === FLOOD_HISTORY_LAYER_TYPE; }; + +export const isFloodHistoryNode = isFldngHstryNode; +export const FLOOD_HISTORY_ROW_SELECT_MESSAGE = FLDNG_HSTRY_ROW_SELECT_MESSAGE; +export const FLOOD_HISTORY_PAGE_SIZE = FLDNG_HSTRY_PAGE_SIZE; +export const FLOOD_HISTORY_DOWNLOAD_BATCH_SIZE = FLDNG_HSTRY_DOWNLOAD_BATCH_SIZE; diff --git a/apps/sn/app/(map-layout)/map/page.tsx b/apps/sn/app/(map-layout)/map/page.tsx index 32297e76b..83e99f778 100644 --- a/apps/sn/app/(map-layout)/map/page.tsx +++ b/apps/sn/app/(map-layout)/map/page.tsx @@ -114,10 +114,10 @@ import { FLOOD_HISTORY_AREA_LAYER_ID, FLOOD_HISTORY_DEPTH_LAYER_ID, FLOOD_HISTORY_LAYER_TYPE, - FLOOD_HISTORY_ROW_SELECT_MESSAGE, FLOOD_HISTORY_POPUP_KEY, - isFloodHistoryNode, - type FloodHistoryItem, + FLDNG_HSTRY_ROW_SELECT_MESSAGE, + isFldngHstryNode, + type FldngHstryItem, } from "./components/fldngHstry/fldngHstryTypes"; import FeatureClickEventPopup from "./components/popupComponent/featureClickEventPopup"; import SearchModal from "./searchModal/searchModal"; @@ -973,7 +973,7 @@ const getRightPanelFeatureDisplayLabel = (data: any, category: RightPanelTabCate return getRightPanelFeatureTitle(data); }; -const createFloodHistoryAreaStyle = (label: string) => +const createFldngHstryAreaStyle = (label: string) => new Style({ fill: new Fill({ color: "rgba(30, 136, 229, 0.16)", @@ -993,7 +993,7 @@ const createFloodHistoryAreaStyle = (label: string) => zIndex: 9994, }); -const createFloodHistoryDepthStyle = (label: string, color: string) => +const createFldngHstryDepthStyle = (label: string, color: string) => new Style({ fill: new Fill({ color, @@ -2544,7 +2544,7 @@ const Map = () => { const [checkedLayerLegendVersion, setCheckedLayerLegendVersion] = useState(0); const [isAgedPipeChecked, setIsAgedPipeChecked] = useState(false); const [isSinkholeChecked, setIsSinkholeChecked] = useState(false); - const [isFloodHistoryChecked, setIsFloodHistoryChecked] = useState(false); + const [isFldngHstryChecked, setIsFldngHstryChecked] = useState(false); const [swagePrcsFcltLayerMode, setSwagePrcsFcltLayerMode] = useState("all"); const [activeLayerSettingOrder, setActiveLayerSettingOrder] = useState([]); const [draftAgedPipeFilters, setDraftAgedPipeFilters] = @@ -2559,8 +2559,8 @@ const Map = () => { ); const [isSinkholePopupFilterActive, setIsSinkholePopupFilterActive] = useState(false); const [sinkholeRadiusMeters, setSinkholeRadiusMeters] = useState(SINKHOLE_DEFAULT_RADIUS); - const [selectedFloodHistoryDetail, setSelectedFloodHistoryDetail] = useState(null); - const [floodHistoryDetailPopupPosition, setFloodHistoryDetailPopupPosition] = useState<{ left: number; top: number } | null>(null); + const [selectedFldngHstryDetail, setSelectedFldngHstryDetail] = useState(null); + const [fldngHstryDetailPopupPosition, setFldngHstryDetailPopupPosition] = useState<{ left: number; top: number } | null>(null); const [selectedSinkholeDetail, setSelectedSinkholeDetail] = useState(null); const [selectedSinkholeNearbyPipes, setSelectedSinkholeNearbyPipes] = useState([]); const [lastSinkholeSyncSummary, setLastSinkholeSyncSummary] = useState(null); @@ -2593,8 +2593,8 @@ const Map = () => { const agedPipePopupWindowRef = useRef(null); const sinkholePopupWindowRef = useRef(null); // 침수발생이력 overlay layer는 지도 드래그 중에도 유지돼야 하므로 React state 대신 ref로 보관한다. - const floodHistoryAreaLayerRef = useRef | null>(null); - const floodHistoryDepthLayerRef = useRef | null>(null); + const fldngHstryAreaLayerRef = useRef | null>(null); + const fldngHstryDepthLayerRef = useRef | null>(null); const sinkholePopupCloseWatcherRef = useRef(null); const pipeAnalysisPopupWindowRef = useRef(null); const gisEditSessionPopupWindowRef = useRef(null); @@ -4289,10 +4289,10 @@ const Map = () => { [clearSinkholeFocusedPipeLayer, ensureSinkholeFocusedPipeLayer], ); - const ensureFloodHistoryAreaSource = useCallback(() => { + const ensureFldngHstryAreaSource = useCallback(() => { if (!mapReady || !gisMaps.current) return null; - if (!floodHistoryAreaLayerRef.current) { + if (!fldngHstryAreaLayerRef.current) { const source = new VectorSource(); const layer = new VectorLayer({ source, @@ -4303,16 +4303,16 @@ const Map = () => { layer.set("lyrTyNm", FLOOD_HISTORY_LAYER_TYPE); layer.set("clickPsblYn", "N"); gisMaps.current.addLayer(layer); - floodHistoryAreaLayerRef.current = layer; + fldngHstryAreaLayerRef.current = layer; } - return floodHistoryAreaLayerRef.current.getSource(); + return fldngHstryAreaLayerRef.current.getSource(); }, [mapReady]); - const ensureFloodHistoryDepthSource = useCallback(() => { + const ensureFldngHstryDepthSource = useCallback(() => { if (!mapReady || !gisMaps.current) return null; - if (!floodHistoryDepthLayerRef.current) { + if (!fldngHstryDepthLayerRef.current) { const source = new VectorSource(); const layer = new VectorLayer({ source, @@ -4323,21 +4323,21 @@ const Map = () => { layer.set("lyrTyNm", FLOOD_HISTORY_LAYER_TYPE); layer.set("clickPsblYn", "N"); gisMaps.current.addLayer(layer); - floodHistoryDepthLayerRef.current = layer; + fldngHstryDepthLayerRef.current = layer; } - return floodHistoryDepthLayerRef.current.getSource(); + return fldngHstryDepthLayerRef.current.getSource(); }, [mapReady]); - const clearFloodHistoryLayers = useCallback(() => { - floodHistoryAreaLayerRef.current?.getSource?.()?.clear?.(); - floodHistoryDepthLayerRef.current?.getSource?.()?.clear?.(); + const clearFldngHstryLayers = useCallback(() => { + fldngHstryAreaLayerRef.current?.getSource?.()?.clear?.(); + fldngHstryDepthLayerRef.current?.getSource?.()?.clear?.(); }, []); - const renderSelectedFloodHistory = useCallback( - (detail: FloodHistoryItem | null) => { - const areaSource = ensureFloodHistoryAreaSource(); - const depthSource = ensureFloodHistoryDepthSource(); + const renderSelectedFldngHstry = useCallback( + (detail: FldngHstryItem | null) => { + const areaSource = ensureFldngHstryAreaSource(); + const depthSource = ensureFldngHstryDepthSource(); if (!areaSource || !depthSource) return; areaSource.clear(); @@ -4348,21 +4348,21 @@ const Map = () => { const areaFeature = new Feature({ geometry: new Polygon([detail.areaRing]), }); - areaFeature.setStyle(createFloodHistoryAreaStyle(`${detail.floodYear}년 ${detail.districtName}`)); + areaFeature.setStyle(createFldngHstryAreaStyle(`${detail.floodYear}년 ${detail.districtName}`)); areaSource.addFeature(areaFeature); detail.depthZones.forEach((zone) => { const zoneFeature = new Feature({ geometry: new Polygon([zone.ring]), }); - zoneFeature.setStyle(createFloodHistoryDepthStyle(zone.depthLabel, zone.color)); + zoneFeature.setStyle(createFldngHstryDepthStyle(zone.depthLabel, zone.color)); depthSource.addFeature(zoneFeature); }); }, - [ensureFloodHistoryAreaSource, ensureFloodHistoryDepthSource], + [ensureFldngHstryAreaSource, ensureFldngHstryDepthSource], ); - const focusFloodHistoryOnMap = useCallback((detail: FloodHistoryItem) => { + const focusFldngHstryOnMap = useCallback((detail: FldngHstryItem) => { if (!gisMaps.current) return; const geometry = new Polygon([detail.areaRing]); @@ -4375,27 +4375,27 @@ const Map = () => { }); }, []); - const clearFloodHistorySelection = useCallback(() => { - setSelectedFloodHistoryDetail(null); - setFloodHistoryDetailPopupPosition(null); - clearFloodHistoryLayers(); - }, [clearFloodHistoryLayers]); + const clearFldngHstrySelection = useCallback(() => { + setSelectedFldngHstryDetail(null); + setFldngHstryDetailPopupPosition(null); + clearFldngHstryLayers(); + }, [clearFldngHstryLayers]); - const closeFloodHistoryDetail = useCallback(() => { - setFloodHistoryDetailPopupPosition(null); + const closeFldngHstryDetail = useCallback(() => { + setFldngHstryDetailPopupPosition(null); }, []); - const handleFloodHistoryRowSelect = useCallback( - (detail: FloodHistoryItem) => { - setSelectedFloodHistoryDetail(detail); - renderSelectedFloodHistory(detail); - focusFloodHistoryOnMap(detail); + const handleFldngHstryRowSelect = useCallback( + (detail: FldngHstryItem) => { + setSelectedFldngHstryDetail(detail); + renderSelectedFldngHstry(detail); + focusFldngHstryOnMap(detail); setIsSearchModalOpen(false); }, - [focusFloodHistoryOnMap, renderSelectedFloodHistory, setIsSearchModalOpen], + [focusFldngHstryOnMap, renderSelectedFldngHstry, setIsSearchModalOpen], ); - const openFloodHistoryPopupWindow = useCallback(() => { + const openFldngHstryPopupWindow = useCallback(() => { const popup = openWindowPopup(FLOOD_HISTORY_POPUP_KEY as WindowPopupKey); if (!popup) { alert("브라우저 팝업이 차단되었습니다. 팝업 허용 후 다시 시도해주세요."); @@ -5105,16 +5105,16 @@ const Map = () => { }, [loadSinkholeDetail, sinkholeScope]); useEffect(() => { - const handleFloodHistoryPopupMessage = (event: MessageEvent) => { + const handleFldngHstryPopupMessage = (event: MessageEvent) => { if (event.origin !== window.location.origin) return; - if (event.data?.type !== FLOOD_HISTORY_ROW_SELECT_MESSAGE || !event.data?.row) return; + if (event.data?.type !== FLDNG_HSTRY_ROW_SELECT_MESSAGE || !event.data?.row) return; - handleFloodHistoryRowSelect(event.data.row as FloodHistoryItem); + handleFldngHstryRowSelect(event.data.row as FldngHstryItem); }; - window.addEventListener("message", handleFloodHistoryPopupMessage); - return () => window.removeEventListener("message", handleFloodHistoryPopupMessage); - }, [handleFloodHistoryRowSelect]); + window.addEventListener("message", handleFldngHstryPopupMessage); + return () => window.removeEventListener("message", handleFldngHstryPopupMessage); + }, [handleFldngHstryRowSelect]); // WaterDepth 표시 여부를 결정하는 함수 const handleWaterDepthVisibility = useCallback((checkedIds: string[], checkedNodesData: any[]) => { @@ -5171,10 +5171,10 @@ const Map = () => { WATER_DEPTH_LAYER_TYPES.includes(String(node?.data?.lyrTyNm ?? "")), ); setIsAgedPipeChecked(agedPipeChecked); - const floodHistoryChecked = checkedNodesData.some((node) => isFloodHistoryNode(node)); - setIsFloodHistoryChecked(floodHistoryChecked); - if (!floodHistoryChecked) { - clearFloodHistorySelection(); + const fldngHstryChecked = checkedNodesData.some((node) => isFldngHstryNode(node)); + setIsFldngHstryChecked(fldngHstryChecked); + if (!fldngHstryChecked) { + clearFldngHstrySelection(); } const sinkholeChecked = checkedNodesData.some((node) => isSinkholeLayerNode(node)); setIsSinkholeChecked(sinkholeChecked); @@ -5197,7 +5197,7 @@ const Map = () => { removeSinkholeLayer(); closeSinkholeDetail(); } - }, [clearFloodHistorySelection, closeSinkholeDetail, handleWaterDepthVisibility, removeFlowDirectionLayer, removeSinkholeLayer, retainFlowDirectionUsageCodes]); + }, [clearFldngHstrySelection, closeSinkholeDetail, handleWaterDepthVisibility, removeFlowDirectionLayer, removeSinkholeLayer, retainFlowDirectionUsageCodes]); const waterDepthLegendItems = useMemo( () => extractWaterDepthLegendItems(checkedNodesDataRef.current ?? []), @@ -5228,14 +5228,14 @@ const Map = () => { openSinkholePopupWindow(); return false; } - if (isFloodHistoryNode(node)) { - openFloodHistoryPopupWindow(); + if (isFldngHstryNode(node)) { + openFldngHstryPopupWindow(); return false; } return true; }, - [openAgedPipeList, openFloodHistoryPopupWindow, openSinkholePopupWindow], + [openAgedPipeList, openFldngHstryPopupWindow, openSinkholePopupWindow], ); // 현재 체크된 특수 레이어만 하단 설정영역에 모아 렌더링하기 위한 패널 목록이다. @@ -7110,25 +7110,25 @@ const Map = () => { }, [renderSelectedSinkhole, selectedSinkholeDetail, sinkholeRadiusMeters]); useEffect(() => { - renderSelectedFloodHistory(selectedFloodHistoryDetail); - }, [renderSelectedFloodHistory, selectedFloodHistoryDetail]); + renderSelectedFldngHstry(selectedFldngHstryDetail); + }, [renderSelectedFldngHstry, selectedFldngHstryDetail]); useEffect(() => { if (!mapReady || !gisMaps.current) return; const map = gisMaps.current; const clickKey = map.on("singleclick", (event: any) => { - if (!selectedFloodHistoryDetail || !isFloodHistoryChecked) return; + if (!selectedFldngHstryDetail || !isFldngHstryChecked) return; - let clickedFloodHistory = false; + let clickedFldngHstry = false; map.forEachFeatureAtPixel( event.pixel, (feature: any, layer: any) => { if ( - layer === floodHistoryAreaLayerRef.current || - layer === floodHistoryDepthLayerRef.current + layer === fldngHstryAreaLayerRef.current || + layer === fldngHstryDepthLayerRef.current ) { - clickedFloodHistory = true; + clickedFldngHstry = true; return feature; } return undefined; @@ -7136,14 +7136,14 @@ const Map = () => { { hitTolerance: 4 }, ); - if (!clickedFloodHistory) return; + if (!clickedFldngHstry) return; const size = map.getSize?.() ?? [1200, 800]; const popupWidth = 220; const popupHeight = 210; const nextLeft = Math.min(Math.max(event.pixel[0] + 12, 12), size[0] - popupWidth - 12); const nextTop = Math.min(Math.max(event.pixel[1] - 12, 12), size[1] - popupHeight - 12); - setFloodHistoryDetailPopupPosition({ + setFldngHstryDetailPopupPosition({ left: nextLeft, top: nextTop, }); @@ -7153,13 +7153,13 @@ const Map = () => { return () => { unByKey(clickKey); }; - }, [isFloodHistoryChecked, mapReady, selectedFloodHistoryDetail, setIsSearchModalOpen]); + }, [isFldngHstryChecked, mapReady, selectedFldngHstryDetail, setIsSearchModalOpen]); useEffect(() => { return () => { - clearFloodHistoryLayers(); + clearFldngHstryLayers(); }; - }, [clearFloodHistoryLayers]); + }, [clearFldngHstryLayers]); return ( @@ -7287,11 +7287,11 @@ const Map = () => {
) : null} - {selectedFloodHistoryDetail && floodHistoryDetailPopupPosition ? ( + {selectedFldngHstryDetail && fldngHstryDetailPopupPosition ? ( ) : null} { treeTogglePosition="center" zoomGuide={zoomGuide} layerIconVisible={(node: any) => - isAgedPipeLayerNode(node) || isSinkholeRootNode(node) || isFloodHistoryNode(node) + isAgedPipeLayerNode(node) || isSinkholeRootNode(node) || isFldngHstryNode(node) } defaultZoom={7.5}