diff --git a/apps/fo/app/pages/(map-layout)/map/page.tsx b/apps/fo/app/pages/(map-layout)/map/page.tsx index ad3f70295..984a8afa7 100644 --- a/apps/fo/app/pages/(map-layout)/map/page.tsx +++ b/apps/fo/app/pages/(map-layout)/map/page.tsx @@ -3,7 +3,7 @@ import Gis from "@common/business_components/ui/map/Gis"; import GisApp from "@common/business_components/ui/map/lib/gis.core"; import { useEffect, useRef, useState } from "react"; -import { ProcSearchBar } from "@common/business_components/ui/map/searchBar"; +import { SearchBar } from "@common/business_components/ui/map/searchBar"; // OpenLayers overlay/extent 유틸 import Overlay from "ol/Overlay"; @@ -278,7 +278,19 @@ const Map = () => { setIsSearchModalOpen(false); }; - // (선택) 다른 위치 클릭 시 오버레이 닫고 싶다면 Gis 쪽에서 지도 클릭 이벤트 받아 여기서 제거하는 훅을 연결하면 됨. + const onInit = () => { + + const map = gisMaps.current; + if (!map) { + console.warn("지도가 초기화되지 않았습니다."); + return; + } + + if (overlayRef.current) { + map.removeOverlay?.(overlayRef.current); + overlayRef.current = null; + } + } return (
@@ -299,7 +311,7 @@ const Map = () => { onCheckedLayersChange={undefined} imgVisble={false} searchBar={ - + } waterDepth={undefined} /> diff --git a/packages/common/business_components/src/ui/map/searchBar/searchBar.tsx b/packages/common/business_components/src/ui/map/searchBar/searchBar.tsx index 3f5fc1820..623758ec3 100644 --- a/packages/common/business_components/src/ui/map/searchBar/searchBar.tsx +++ b/packages/common/business_components/src/ui/map/searchBar/searchBar.tsx @@ -26,12 +26,14 @@ interface SearchBarProps { gisMaps: React.RefObject; facilityTypes: { text: string; val: string }[]; onFeatureFocus: any; + onInit?: any; } export const SearchBar = ({ gisMaps, facilityTypes, onFeatureFocus, + onInit = () => { }, }: SearchBarProps) => { const [sidoValue, setSidoValue] = useState("0"); const [sigunValue, setSigunValue] = useState("0"); @@ -134,10 +136,8 @@ export const SearchBar = ({ text: f.properties.swtrmt_fclt_nm ?? "(이름없음)", val: f.id, })); - } else if ( - type === "tb_wr_bdst_ruse_fclt" // 재이용시설 - ) { - //재이용에서 참조하는 하수처리시설 목록 + } else if (type === "tb_wr_bdst_ruse_fclt") { + // 재이용시설 const procRes = await fetch("/reuse-service/reuseFc/pubFc"); const procJson = await procRes.json(); const procData = procJson.data; @@ -147,8 +147,8 @@ export const SearchBar = ({ return code; }); - //처리시설명으로 처리시설코드 조회 - let procUrl2 = "/operation-service/prcsFclt/ruseInfo/1/1000/A/{sggCd}/0/1/SW/{fcltyNm}"; + let procUrl2 = + "/operation-service/prcsFclt/ruseInfo/1/1000/A/{sggCd}/0/1/SW/{fcltyNm}"; procUrl2 = procUrl2 .replace("{sggCd}", sigunValue) .replace("{fcltyNm}", encodeURIComponent(fcltyNm)); @@ -161,9 +161,10 @@ export const SearchBar = ({ body: JSON.stringify(procResult), }); const procJson2 = await procRes2.json(); - const procResult2 = (procJson2.data || []).map((item: any) => item.bscFctCd); + const procResult2 = (procJson2.data || []).map( + (item: any) => item.bscFctCd + ); - //최종 처리시설코드로 재이용시설조회 const res = await fetch(url, { method: "POST", headers: { @@ -177,20 +178,16 @@ export const SearchBar = ({ text: item.ruseUtztnFcltNm ?? "(이름없음)", val: item.pbnstRuseFcltId, })); - - } else if ( - type === "tb_wr_ruse_fclt_dmd_co" //수요처 - ) { + } else if (type === "tb_wr_ruse_fclt_dmd_co") { + // 수요처 const res = await fetch(url); const json = await res.json(); list = (json.data || []).map((item: any) => ({ text: item.dmdCoNm ?? "(이름없음)", val: item.dmdInfoId, })); - } else if ( - type === "tb_wr_tmpr_dmd_co" //잠재수요처 - ) { - // GET 방식 + } else if (type === "tb_wr_tmpr_dmd_co") { + // 잠재수요처 (GET) const res = await fetch(url); const json = await res.json(); list = (json.data || []).map((item: any) => ({ @@ -198,7 +195,7 @@ export const SearchBar = ({ val: item.fctryMngSn, })); } else { - // GET 방식 + // 기타 (GET) const res = await fetch(url); const json = await res.json(); list = (json.data || []).map((item: any) => ({ @@ -222,14 +219,12 @@ export const SearchBar = ({ setSearchList(newList); }; - //해당 시설물로 이동 + //해당 시설물로 이동 const handleFeatureFocus = (data: any) => { - let featureId = data.fid; const layerNm = data.layerNm; if (!isNaN(Number(featureId))) { - // 숫자면 문자열로 변환 featureId = String(featureId); } @@ -246,12 +241,9 @@ export const SearchBar = ({ console.warn("지도가 초기화되지 않았습니다."); return; } - // 항상 같은 select 객체 사용 const select = GisApp.Module.select as any; if (!select) return; - // 1. 기존 선택 초기화 - //select.resetSelectedFeature(); - // 2. data가 OpenLayers Feature 인스턴스인지 확인 + let foundFeature: any = null; map @@ -264,7 +256,7 @@ export const SearchBar = ({ if (feature) foundFeature = feature; } }); - // 3. 피처 선택 + if (foundFeature) { const geometry = foundFeature.getGeometry(); if (geometry) { @@ -277,13 +269,35 @@ export const SearchBar = ({ nearest: true, }); } else { + alert("위치정보를 찾을 수 없습니다."); console.warn("geometry를 찾을 수 없습니다:", data); } } else { console.warn("Feature를 찾을 수 없습니다:", data); } - onFeatureFocus(foundFeature); + if (onFeatureFocus) { + onFeatureFocus(foundFeature); + } + }; + + // 초기화(검색 조건 리셋) + const handleInit = () => { + // 시설 구분 기본값: 단일 항목이면 그 값, 아니면 "0" + const defaultFacilityType = + facilityTypes?.length === 1 && facilityTypes[0] + ? facilityTypes[0].val + : "0"; + + // 시도/시군구/시설구분/시설명/검색목록 초기화 + setSidoValue("0"); + initializeSigunData("0"); // 시군구 목록도 "시군구/0"로 리셋되고, sigunValue도 "0"으로 맞춤 + setFacilityType(defaultFacilityType); + setFcltyNm(""); + setSearchList([]); + + // 필요 시 외부 초기화 콜백 실행 + onInit?.(); }; return ( @@ -313,7 +327,9 @@ export const SearchBar = ({ selectClass="rounded-lg bg-white" label="" selectArray={sidoData} - onSelectValue={(val: any) => onSelectValue(val.toString(), "ctpvCd")} + onSelectValue={(val: any) => + onSelectValue(val.toString(), "ctpvCd") + } value={sidoValue} /> onSelectValue(val.toString(), "sggCd")} + onSelectValue={(val: any) => + onSelectValue(val.toString(), "sggCd") + } value={sigunValue} /> { - // 선택된 항목이 있을 경우 onFeatureSelect 실행 const type = facilityType; handleFeatureFocus({ layerNm: type, @@ -352,6 +369,16 @@ export const SearchBar = ({ > 조회 + {onInit && ( + + )}