diff --git a/apps/wr/app/(map-layout)/map/mainMap/page.tsx b/apps/wr/app/(map-layout)/map/mainMap/page.tsx index 331e487bd..7451ae4b5 100644 --- a/apps/wr/app/(map-layout)/map/mainMap/page.tsx +++ b/apps/wr/app/(map-layout)/map/mainMap/page.tsx @@ -24,7 +24,7 @@ const Map = () => { const fetchData = async () => { try { - const response = await mapService.getLyrStngs(); + const response = await mapService.getLyrStngs('WR_NETWORK'); setTreeData(response); // API 응답 저장 } catch (error) { console.error("데이터 불러오기 실패:", error); diff --git a/apps/wr/app/(map-layout)/service/map.ts b/apps/wr/app/(map-layout)/service/map.ts index 5002afef7..79ba7fe9e 100644 --- a/apps/wr/app/(map-layout)/service/map.ts +++ b/apps/wr/app/(map-layout)/service/map.ts @@ -30,8 +30,8 @@ export type LyrStngProps = { export const mapService = { //레이어 설정 조회 - getLyrStngs: async () => { - const response = await fetch(`${API_URL}/lyrStngs/WR_NETWORK`, { + getLyrStngs: async (lyrGrp : string) => { + const response = await fetch(`${API_URL}/lyrStngs/${lyrGrp}`, { method: 'GET', headers: { 'Accept': 'application/json', diff --git a/apps/wr/app/(popUp-layout)/mapDrgtPopUp/drgtLegend.tsx b/apps/wr/app/(popUp-layout)/mapDrgtPopUp/drgtLegend.tsx new file mode 100644 index 000000000..9c558851c --- /dev/null +++ b/apps/wr/app/(popUp-layout)/mapDrgtPopUp/drgtLegend.tsx @@ -0,0 +1,70 @@ +"use client"; + +import React from "react"; +import { Label } from "@common/components/ui/label"; + +export const DRGT_LAYER_TYPES: string[] = [ + // 수정 필요 + 'drought1', + 'drought2', + 'drought3', + 'drought4', + 'drought5', + 'drought6', +]; +// 지정된 순서에 따른 lyr_sn 배열 +export const EXPRS_ORDERED_LAYERS: string[] = [ + // 수정 필요 + '106', // 침수위험지도(tb_ms_sbmrg_dngr_map) - 30년 빈도 + '107', // 침수위험지도(tb_ms_sbmrg_dngr_map) - 50년 빈도 + '108', // 침수위험지도(tb_ms_sbmrg_dngr_map) - 80년 빈도 + '109', // 침수위험지도(tb_ms_sbmrg_dngr_map) - 100년 빈도 + '110', // 도시침수지도(tb_ms_flood_dngr_map) - 30년 빈도 + '111', // 도시침수지도(tb_ms_flood_dngr_map) - 50년 빈도 +]; + +export function DrgtLegend() { + + + return ( + <> +
+
+ +
+
+
+
+
+
+
+
가 뭄 정 보
+
+ + {/* 관심 - 1회 미만 */} + {/* 관심 - 1회 이상 */} + + {/* 주의 - 1회 미만 */} + {/* 주의 - 1회 이상 */} + + {/* 관심+주의 - 1회 미만 */} + {/* 관심+주의 - 1회 이상 */} +
+
+
+
+ + ); +} + +function LegendItem({ color, label }: { color: string; label: string }) { + return ( +
+ + {label} +
+ ); +} \ No newline at end of file diff --git a/apps/wr/app/(popUp-layout)/mapDrgtPopUp/median.ts b/apps/wr/app/(popUp-layout)/mapDrgtPopUp/median.ts new file mode 100644 index 000000000..ab63e7c91 --- /dev/null +++ b/apps/wr/app/(popUp-layout)/mapDrgtPopUp/median.ts @@ -0,0 +1,24 @@ +import { boundingExtent, getCenter } from 'ol/extent'; +import Feature from 'ol/Feature'; +import Geometry from 'ol/geom/Geometry'; + +export function medianCoordinate2D(feature: Feature) { + // Feature를 입력 받아 중심 좌표를 계산하는 함수 + if (!feature) { + console.warn("유효한 피처가 없습니다."); + return; + } + + console.log(feature) + + const geometry = feature.getGeometry(); + if (!geometry) { + console.warn("피처에 geometry가 없습니다."); + return; + } + + const extent = geometry.getExtent(); + const center = getCenter(extent); + const centerExtent = boundingExtent([center]); + return centerExtent; +} \ No newline at end of file diff --git a/apps/wr/app/(popUp-layout)/mapDrgtPopUp/page.tsx b/apps/wr/app/(popUp-layout)/mapDrgtPopUp/page.tsx new file mode 100644 index 000000000..a2c843351 --- /dev/null +++ b/apps/wr/app/(popUp-layout)/mapDrgtPopUp/page.tsx @@ -0,0 +1,88 @@ +"use client"; + +import Gis from "@common/business_components/ui/map/Gis"; +import { useEffect, useRef, useState, useCallback } from "react"; +import { useSearchParams } from "next/navigation"; +import { mapService } from "../../(map-layout)/service"; +import { DrgtLegend, DRGT_LAYER_TYPES, EXPRS_ORDERED_LAYERS } from "./drgtLegend"; +import { SearchBar } from "./searchBar"; + + +export default function MapDrgtPopUp() { + const searchParams = useSearchParams(); + const ctpvCd = searchParams.get('ctpvCd') || ''; + const sggCd = searchParams.get('sggCd') || ''; + const fromDate = searchParams.get('fromDate') || ''; + const toDate = searchParams.get('toDate') || ''; + + const gisMaps = useRef(null); + const [treeData, setTreeData] = useState([]); // 초기값을 객체 또는 null로 설정 + const [isOpen, setIsOpen] = useState(false); // 팝업 열기/닫기 상태 + const [showDrgtLegend, setShowDrgtLegend] = useState(false); // DrgtLegend 표시 여부 + const [isPlaying, setIsPlaying] = useState(false); + + // 컴포넌트 마운트 시 1회 실행 + useEffect(() => { + fetchData(); + }, []); + + function fetchData() { + (async () => { + try { + const response = await mapService.getLyrStngs('WR_DROUGHT'); + setTreeData(response); // API 응답 저장 + console.log("Drought layers fetched:", response); + } catch (error) { + console.error("데이터 불러오기 실패:", error); + } + })(); + } + + // WaterDepth 표시 여부를 결정하는 함수 + const handleDrgtLegndVisibility = useCallback((checkedIds: string[], checkedNodesData: any[]) => { + const drgtLegndLayers = checkedNodesData.filter(node => + DRGT_LAYER_TYPES.includes(node.data?.lyrTyNm) + ); + + const hasDrgtLegndLayer = drgtLegndLayers.length > 0; + setShowDrgtLegend(hasDrgtLegndLayer); + }, []); + + // 체크된 레이어 변경 처리 함수 + const handleCheckedLayersChange = useCallback((checkedIds: string[], checkedNodesData: any[]) => { + handleDrgtLegndVisibility(checkedIds, checkedNodesData); + }, [handleDrgtLegndVisibility]); + + + + return ( +
+ } + waterDepth={showDrgtLegend ? DrgtLegend : undefined} + isPlaying={isPlaying} + setIsPlaying={setIsPlaying as any} + targetLayerTypes={DRGT_LAYER_TYPES as any} + orderedLayers={EXPRS_ORDERED_LAYERS as any} + checkInterval={2500} + height={`h-[100vh]`} + droughtDates={{ startYmd: fromDate, endYmd: toDate }} + /> +
+ ); +} diff --git a/apps/wr/app/(popUp-layout)/mapDrgtPopUp/searchBar.tsx b/apps/wr/app/(popUp-layout)/mapDrgtPopUp/searchBar.tsx new file mode 100644 index 000000000..21a98d696 --- /dev/null +++ b/apps/wr/app/(popUp-layout)/mapDrgtPopUp/searchBar.tsx @@ -0,0 +1,173 @@ +"use client"; + +import React, { useState, useEffect } from "react"; +import { SelectBox } from '@common/business_components/ui' +import { Label, Button } from '@common/components'; +import { type SelectDataType } from "@common/business_components/ui"; +import GisApp from "@common/business_components/ui/map/lib/gis.core"; +import GeoJSON from "ol/format/GeoJSON"; +import Feature from "ol/Feature"; +import Geometry from "ol/geom/Geometry"; +import { medianCoordinate2D } from "./median"; + +interface CtpvSggPrcsFcltSelectBoxProps { + gisMaps: React.RefObject; + ctpvCode: string; + sggCode: string; + fromDate: string; + toDate: string; +} + +const DEFAULT_OPTION: SelectDataType = { val: '0', text: '전체' }; + +export function SearchBar({ gisMaps, ctpvCode, sggCode }: CtpvSggPrcsFcltSelectBoxProps) { + const [ctpvCd, setCtpvCd] = useState(ctpvCode); + const [sggCd, setSggCd] = useState(sggCode); + const [ctpv, setCtpv] = useState([]); + const [sgg, setSgg] = useState([]); + + useEffect(() => { + (async () => { + await fetchSido(); + await fetchSigungu(); + setCtpvCd(ctpvCode); + setSggCd(sggCode); + })(); + }, []); + + function onViewMapClick() { + if (sggCd && sggCd !== '0') { + fetchSggData(); + return; + } + if (ctpvCd && ctpvCd !== '0') fetchCtpvData(); + } + + async function fetchCtpvData() { + try { + const ctpvData = await fetch(`/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo%3Atb_ms_ctpv&outputFormat=application%2Fjson&cql_filter=mctpv_cd=%27${ctpvCd.trim()}%27&srsName=EPSG:5179`) + .then(res => res.json()); + console.log('시도 데이터', ctpvData.features[0]); + + const format = new GeoJSON(); + const feature: Feature = format.readFeature(ctpvData.features[0], { + dataProjection: "EPSG:5179", // GeoJSON 좌표계 + featureProjection: GisApp.TO_PROJ // 지도 좌표계 + }); + + console.log('feature', feature); + + const extent = medianCoordinate2D(feature); + console.log('GisApp.TO_PROJ', GisApp.TO_PROJ); + console.log('extent', extent) + + handleFeatureFocus(extent); + } + catch (error) { + console.error("시도 data fetching Error:", error); + } + } + + async function fetchSggData() { + try { + const sggData = await fetch(`/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo%3Atb_ms_sgg&outputFormat=application%2Fjson&cql_filter=sgg_cd=%27${sggCd}%27&srsName=EPSG:5179`) + .then(res => res.json()); + console.log('시군구 데이터', sggData.features[0]); + + + const format = new GeoJSON(); + const feature: Feature = format.readFeature(sggData.features[0], { + dataProjection: "EPSG:5179", // GeoJSON 좌표계 + featureProjection: GisApp.TO_PROJ // 지도 좌표계 + }); + + const extent = medianCoordinate2D(feature); + + handleFeatureFocus(extent); + } + catch (error) { + console.error("시군구 data fetching Error:", error); + } + } + + function handleFeatureFocus(extent: any) { + console.log('ctpv', ctpv); + console.log('sgg', sgg); + const map = gisMaps.current; + if (!map) { + console.warn("지도가 초기화되지 않았습니다."); + return; + } + + map.getView().fit(extent, { + duration: 300, + padding: [50, 50, 50, 50], + maxZoom: 11 + }); + }; + + const fetchSido = async () => { + const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_ctpv&outputFormat=application/json&propertyName=mctpv_korn_nm,mctpv_cd`; + const res = await fetch(url).then(res => res.json()); + + const list = res.features.map((f: any) => ({ + text: f.properties.mctpv_korn_nm, + val: f.properties.mctpv_cd, + })); + + console.log('시도 데이터', list); + setCtpv(list); + }; + + const fetchSigungu = async () => { + const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_sgg&outputFormat=application/json&propertyName=sgg_cd,sgg_korn_nm`; + const res = await fetch(url).then(res => res.json()); + + const list = res.features.map((f: any) => ({ + text: f.properties.sgg_korn_nm, + val: f.properties.sgg_cd, + })); + + console.log('시군구 데이터', list); + setSgg(list); + }; + + + + return ( +
+
+ + { + setCtpvCd(String(val)); + setSggCd(String(0)); + }} + selectContentClass="z-[101]" + /> + + String(opt.val).slice(0, 2) === String(ctpvCd).trim()) + ] + } + value={sggCd} + onSelectValue={val => { setSggCd(String(val)) }} + selectContentClass="z-[101]" + /> +
+
+ +
+
+ ); +} \ No newline at end of file diff --git a/apps/wr/app/(with-layout)/matMng/coMng/drgtSttn/page.tsx b/apps/wr/app/(with-layout)/matMng/coMng/drgtSttn/page.tsx index be7210f3f..f6881688a 100644 --- a/apps/wr/app/(with-layout)/matMng/coMng/drgtSttn/page.tsx +++ b/apps/wr/app/(with-layout)/matMng/coMng/drgtSttn/page.tsx @@ -9,7 +9,7 @@ import type { objSearchType } from "@/components/ui/modal/fcltReg/bdstRegModal/b import { ContentsDiv, DateMonthPicker, downloadExcel, SearchDiv, SearchFormLeft, SearchFormRight, SelectBox, Title, UiModal, UiTable, type SelectDataType } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; import { Button, Label, ScrollArea } from "@common/components/ui"; -import { useEffect, useState } from "react"; +import { useEffect, useState, useRef } from "react"; import { toast, Toaster } from "react-hot-toast"; export default function DrgtSttn() { @@ -26,6 +26,7 @@ export default function DrgtSttn() { isOpen: boolean; data: customDrgt[] | undefined; }>({ data: undefined, isOpen: false }); + const popupRef = useRef(null); const cellClick = (index: number) => { if (fromDate && toDate && drgtRes[index]) { @@ -121,6 +122,19 @@ export default function DrgtSttn() { setToDate(formatted); } }, [fromDate, toDate]) + + function onViewMapClick() { + const params = new URLSearchParams({ + ctpvCd: String(objSearch.city), + sggCd: String(objSearch.sgg), + fromDate: fromDate || '', + toDate: toDate || '' + }); + const popupOptions = `width=${window.screen.availWidth},height=${window.screen.availHeight},left=0,top=0,resizable=yes,scrollbars=yes`; + popupRef.current = window.open(`/mapDrgtPopUp?${params.toString()}`, "가뭄 지도 보기 팝업", popupOptions); + } + + return ( <> @@ -136,7 +150,7 @@ export default function DrgtSttn() { selectClass={""} selectArray={code.cityCd || []} onSelectValue={getSelCity} - value={objSearch?.city ||code.cityCd[0]?.val ||""} + value={objSearch?.city || code.cityCd[0]?.val || ""} />
@@ -156,7 +170,7 @@ export default function DrgtSttn() { onChange: (date: string | undefined) => { const year = date ? date.slice(0, 4) : ''; let month = date?.slice(4); - if (month&&month?.length < 2) { + if (month && month?.length < 2) { month = month?.padStart(2, "0"); } const formatted = `${year}${month}`; @@ -172,7 +186,7 @@ export default function DrgtSttn() { onChange: (date: string | undefined) => { const year = date ? date.slice(0, 4) : ''; let month = date?.slice(4); - if (month&&month.length < 2) { + if (month && month.length < 2) { month = month?.padStart(2, "0"); } const formatted = `${year}${month}`; @@ -211,7 +225,7 @@ export default function DrgtSttn() { sggText = sidoText; } - const searchArr:string[] = []; + const searchArr: string[] = []; if (sidoText) searchArr.push(sidoText); if (Array.isArray(sggText)) { searchArr.push(...sggText); @@ -234,7 +248,7 @@ export default function DrgtSttn() { diff --git a/apps/wr/middleware.ts b/apps/wr/middleware.ts index d068f6aa5..c5c7f8c01 100644 --- a/apps/wr/middleware.ts +++ b/apps/wr/middleware.ts @@ -91,6 +91,8 @@ export function middleware(req: NextRequest) { let queryParams = searchParams.toString(); const typename = searchParams.get("TYPENAME"); console.log("typename ", typename); + const startYmd = searchParams.get("START_YMD") ?? null; + const endYmd = searchParams.get("END_YMD") ?? null; let newUrl = `${GEOSERVER_URL}${pathname.replace("/geoserver", "")}${queryParams ? `?${queryParams}` : ""}`; @@ -116,10 +118,13 @@ export function middleware(req: NextRequest) { typename == "hasudo:tb_wr_rswtr_fclt" || //중수도시설 typename == "hasudo:tb_wr_htdfl_fclt" || //온배수시설 typename == "hasudo:tb_wr_ruse_fclt_dmd_co" || //수요처 - typename == "hasudo:tb_wr_tmpr_dmd_co" //잠재수요처 + typename == "hasudo:tb_wr_tmpr_dmd_co" || //잠재수요처 + typename?.startsWith("hasudo:drought") //가뭄 지도 ) { const url = req.nextUrl.clone(); url.searchParams.set("TYPENAME", typename.replace("hasudo:", "")); + if (startYmd) url.searchParams.set("startYmd", startYmd); + if (endYmd) url.searchParams.set("endYmd", endYmd); queryParams = url.searchParams.toString(); newUrl = `${SEWERAGE_API_URL}/v1/map/geometry${queryParams ? `?${queryParams}` : ""}`; } diff --git a/apps/wr/package.json b/apps/wr/package.json index a29dcd66b..bb170c820 100644 --- a/apps/wr/package.json +++ b/apps/wr/package.json @@ -21,6 +21,8 @@ "lucide-react": "^0.474.0", "moment": "^2.30.1", "next": "15.1.7", + "ol": "^7.3.0", + "ol-ext": "^4.0.11", "react-hook-form": "^7.54.2", "react-hot-toast": "^2.5.2", "react-i18next": "^15.6.0", diff --git a/packages/common/business_components/src/ui/map/Gis.js b/packages/common/business_components/src/ui/map/Gis.js index 2ca7ed051..3d810b48d 100644 --- a/packages/common/business_components/src/ui/map/Gis.js +++ b/packages/common/business_components/src/ui/map/Gis.js @@ -123,8 +123,8 @@ function Gis({ orderedLayers = [], checkInterval = 3000, height: height = "h-[calc(100vh-5rem)]", - onOpenPopup=(data)=>{} - + onOpenPopup = (data) => { }, + droughtDates = { startYmd: '', endYmd: '' } }) { const mapRef = useRef(); const [mapObject, setMapObject] = useState({}); @@ -283,6 +283,17 @@ function Gis({ GisApp.layerCode = layerCode; // 전역 레이어 코드 설정 }, [treeData]); + // droughtDates를 전역(GisApp)에 반영 + useEffect(() => { + if (typeof window === "undefined") return; + if (droughtDates?.startYmd && droughtDates?.endYmd) { + GisApp.DROUGHT_DATES = { + startYmd: String(droughtDates.startYmd), + endYmd: String(droughtDates.endYmd), + }; + } + }, [droughtDates?.startYmd, droughtDates?.endYmd]); + const getLayerItems = (layerCode) => { const layerItems = Object.entries(layerCode) .filter(([key, obj], idx) => obj?.updtPsblYn === "Y") diff --git a/packages/common/business_components/src/ui/map/lib/gis.core.js b/packages/common/business_components/src/ui/map/lib/gis.core.js index d2379e417..5a6e705da 100644 --- a/packages/common/business_components/src/ui/map/lib/gis.core.js +++ b/packages/common/business_components/src/ui/map/lib/gis.core.js @@ -27,6 +27,8 @@ const GisApp = {}; */ //레이어 정보 GisApp.layerInfos = []; +// 가뭄 레이어 날짜 전역 보관소 추가 +GisApp.DROUGHT_DATES = { startYmd: '', endYmd: '' }; //기본정보 GisApp.GEOSERVER_URL = '/geoserver/hasudo/ows'; GisApp.GEOSERVER_WMS_URL = '/geoserver/hasudo/wms'; diff --git a/packages/common/business_components/src/ui/map/lib/gis.layer.js b/packages/common/business_components/src/ui/map/lib/gis.layer.js index 2d436ed12..6cbc054f8 100644 --- a/packages/common/business_components/src/ui/map/lib/gis.layer.js +++ b/packages/common/business_components/src/ui/map/lib/gis.layer.js @@ -112,7 +112,7 @@ GisOlLayer.prototype = { let toProj = GisApp.TO_PROJ; let lyrTyNm = options.lyrTyNm; let typename = this.storageNm + lyrTyNm; - let filter = options?.flterSql && options.flterSql && options.flterSql.trim() !== '' + let filter = options?.flterSql && options.flterSql && options.flterSql.trim() !== ''; let params = {}; params['TYPENAME'] = typename; @@ -122,6 +122,10 @@ GisOlLayer.prototype = { params['SRS'] = toProj; params['OUTPUTFORMAT'] = 'application/json'; if (filter) params['CQL_FILTER'] = filter; + else if (GisApp.DROUGHT_DATES) { + params['START_YMD'] = GisApp.DROUGHT_DATES.startYmd; + params['END_YMD'] = GisApp.DROUGHT_DATES.endYmd; + } let strParams = new URLSearchParams(params).toString(); let source = new VectorSource({ diff --git a/packages/common/business_components/src/ui/map/searchBar/comboSearchBar.tsx b/packages/common/business_components/src/ui/map/searchBar/comboSearchBar.tsx index 999b46569..3289ae53f 100644 --- a/packages/common/business_components/src/ui/map/searchBar/comboSearchBar.tsx +++ b/packages/common/business_components/src/ui/map/searchBar/comboSearchBar.tsx @@ -54,30 +54,25 @@ export const ComboSearchBar = ({ //시도, 시군구 조회 const fetchSido = async () => { - const url = `/cms-service/api/v1/code/cache/ADSTDSTRCD/Y`; - const res = await fetch(url); - const json = await res.json(); - const sidoList = json - .filter( - (item: any) => - typeof item.lwpoCd === "string" && item.lwpoCd.length === 2, - ) - .map((feature: any) => ({ - val: feature.lwpoCd, - text: feature.lwpoCdNm, - })); - setSidoData([{ text: "선택", val: "0" }, ...sidoList]); + const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_ctpv&outputFormat=application/json&propertyName=mctpv_korn_nm,mctpv_cd`; + const res = await fetch(url).then(res => res.json()); - const sigunList = json - .filter( - (item: any) => - typeof item.lwpoCd === "string" && item.lwpoCd.length !== 2, - ) - .map((feature: any) => ({ - val: feature.lwpoCd, - text: feature.lwpoCdNm, - })); - setSigunData(sigunList); + const list = res.features.map((f: any) => ({ + text: f.properties.mctpv_korn_nm, + val: f.properties.mctpv_cd, + })); + setSidoData([{ text: "선택", val: "0" }, ...list]); + }; + + const fetchSigungu = async () => { + const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_sgg&outputFormat=application/json&propertyName=sgg_cd,sgg_korn_nm`; + const res = await fetch(url).then(res => res.json()); + + const list = res.features.map((f: any) => ({ + text: f.properties.sgg_korn_nm, + val: f.properties.sgg_cd, + })); + setSigunData(list); }; //시설명 콤보박스 조회 @@ -170,6 +165,7 @@ export const ComboSearchBar = ({ //시도, 시군구 초기 데이터 조회 useEffect(() => { fetchSido(); + fetchSigungu(); }, []); //시군구 데이터 초기화 diff --git a/packages/common/business_components/src/ui/map/searchBar/procSearchBar.tsx b/packages/common/business_components/src/ui/map/searchBar/procSearchBar.tsx index b5f00d07b..dbded59af 100644 --- a/packages/common/business_components/src/ui/map/searchBar/procSearchBar.tsx +++ b/packages/common/business_components/src/ui/map/searchBar/procSearchBar.tsx @@ -39,32 +39,26 @@ export const ProcSearchBar = ({ gisMaps, facilityTypes }: SearchBarProps) => { : "0", ); - //시도, 시군구 조회 const fetchSido = async () => { - const url = `/cms-service/api/v1/code/cache/ADSTDSTRCD/Y`; - const res = await fetch(url); - const json = await res.json(); - const sidoList = json - .filter( - (item: any) => - typeof item.lwpoCd === "string" && item.lwpoCd.length === 2, - ) - .map((feature: any) => ({ - val: feature.lwpoCd, - text: feature.lwpoCdNm, - })); - setSidoData([{ text: "시도", val: "0" }, ...sidoList]); + const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_ctpv&outputFormat=application/json&propertyName=mctpv_korn_nm,mctpv_cd`; + const res = await fetch(url).then(res => res.json()); - const sigunList = json - .filter( - (item: any) => - typeof item.lwpoCd === "string" && item.lwpoCd.length !== 2, - ) - .map((feature: any) => ({ - val: feature.lwpoCd, - text: feature.lwpoCdNm, - })); - setSigunData(sigunList); + const list = res.features.map((f: any) => ({ + text: f.properties.mctpv_korn_nm, + val: f.properties.mctpv_cd, + })); + setSidoData([{ text: "선택", val: "0" }, ...list]); + }; + + const fetchSigungu = async () => { + const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_sgg&outputFormat=application/json&propertyName=sgg_cd,sgg_korn_nm`; + const res = await fetch(url).then(res => res.json()); + + const list = res.features.map((f: any) => ({ + text: f.properties.sgg_korn_nm, + val: f.properties.sgg_cd, + })); + setSigunData(list); }; //시설명 콤보박스 조회 @@ -157,6 +151,7 @@ export const ProcSearchBar = ({ gisMaps, facilityTypes }: SearchBarProps) => { //시도, 시군구 초기 데이터 조회 useEffect(() => { fetchSido(); + fetchSigungu(); }, []); //시군구 데이터 초기화