diff --git a/apps/wr/app/map/mainMap/page.tsx b/apps/wr/app/map/mainMap/page.tsx index cc71e69aa..c9d58c422 100644 --- a/apps/wr/app/map/mainMap/page.tsx +++ b/apps/wr/app/map/mainMap/page.tsx @@ -11,7 +11,7 @@ const Map = () => { const gisMaps = useRef(null); const [isOpen, setIsOpen] = useState(false); // 팝업 열기/닫기 상태 const [isSearchModalOpen, setIsSearchModalOpen] = useState(true); // SearchModal 열림 상태 - const [featureData, setFeatureData] = useState(null); // 선택된 피쳐 데이터 + const [featureData, setFeatureData] = useState(null); // 선택된 피쳐 데이터 const [checkedLayers, setCheckedLayers] = useState([]); const [checkedLayersData, setCheckedLayersData] = useState([]); @@ -114,7 +114,9 @@ const Map = () => { } else { console.warn("OpenLayers Feature를 찾을 수 없습니다:", data); } - + const currentId = data?.fid || data?.id || data?.ftrIdn; + const lastId = featureData?.fid || featureData?.id || featureData?.ftrIdn; + if (featureData && currentId === lastId) return; // 이전과 같으면 무시 setFeatureData(data); setIsOpen(true); setIsSearchModalOpen(false); @@ -130,7 +132,17 @@ const Map = () => { // /> // ); // }; - + const renderDetailView = useCallback( + (props: any) => ( + + ), + [handlePopupClose, checkedLayers, checkedLayersData] // 필요 시 의존성 넣기 + ); return (
{ gisMaps={gisMaps} isMiniMap={false} searchView={undefined} - detailView={(props: any) => ( - - )} + detailView={renderDetailView} onFeatureSelect={onFeatureSelect} setIsOpen={setIsOpen} setFeatureData={setFeatureData} diff --git a/apps/wr/app/map/newWindowPopup.tsx b/apps/wr/app/map/newWindowPopup.tsx index 76529b31b..ea13d85de 100644 --- a/apps/wr/app/map/newWindowPopup.tsx +++ b/apps/wr/app/map/newWindowPopup.tsx @@ -15,7 +15,7 @@ import { useGisContext } from "@common/business_components/ui/map/Gis"; import type { DemandCompType } from '@common/business_components/ui/sdmInsertForm/form'; import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan"; import moment from 'moment'; -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; interface NewWindowPopupProps { featureData: any; @@ -87,7 +87,7 @@ const NewWindowPopup: React.FC = ({ pbnst, pubHasuInit, } = useWrStore((state) => state); - const { pubFacHeadList, pbnstHasuRes } = pbnst; + const { pubFacHeadList, pbnstHasuRes, pbnstHasuResCount } = pbnst; const [hasuList, setHasuList] = useState(pbnstHasuRes || []); const [isRuseReg, setIsRuseReg] = useState<{ data: any | undefined; @@ -100,11 +100,6 @@ const NewWindowPopup: React.FC = ({ coSttn, coSttnInit, coSttnSearch, - // getDemandCompList, - // regDemandCompany, - // updateDemandCompany, - // coSttnTxtSearch, - // demandCompList, } = useWrStore((state) => state); const [mngTable, setMngTable] = useState(); const [mngPage, setMngPage] = useState(1); @@ -112,11 +107,11 @@ const NewWindowPopup: React.FC = ({ const [isDmdModal, setIsDmdModal] = useState<{ isMoal: boolean; data: any | undefined; - }>({ isMoal: false, data: undefined}); + }>({ isMoal: false, data: undefined }); const [mngList, setMngList] = useState(coSttnRes || []); ///////////////////////////////////////////// 피쳐데이터 선택 시 각 시설별 데이터 처리 /////////////////////////////////////////////// const getSelectedLayers = () => { - console.log(1) + console.trace('호출확인',1) let result = null; const layers = gisMap ? gisMap.getLayers().getArray().filter((l: any) => l.getVisible()) : []; // gisMap이 null인지 확인 후 레이어 가져오기 let featureLayer: { get: (key: string) => any } = { get: () => null }; @@ -128,8 +123,6 @@ const NewWindowPopup: React.FC = ({ } }); result = featureLayer.get('lyrNm'); - console.log(result) - return result; }; const fetchpbnstDetail = async (featureCd: string) => { @@ -143,7 +136,7 @@ const NewWindowPopup: React.FC = ({ }; const fetchHasuDetail = async (featureCd: string, data: string) => { try { - const rainRes = await postFectch(`/prcsFclt/ruseInfo/1/10/A/0/0/1/SW/${featureCd}`, [data], fetchType.COMMON) + const rainRes = await postFectch(`/prcsFclt/ruseInfo/1/20/A/0/0/1/SW/${featureCd}`, [data], fetchType.COMMON) setHasuList( rainRes.data.map((item: any) => { return { @@ -166,7 +159,7 @@ const NewWindowPopup: React.FC = ({ const res = await getFetch(fetchType.WR, `/reuseFc/waterreuseFc/1/20/0/${featureCd}`) setRswtrList(res) } - else if(layerNm =='수요처'){ //수요처 + else if (layerNm == '수요처') { //수요처 const res = await getFetch(fetchType.WR, `/reuseFc/request/1/20/0/${featureCd}`) setMngList(res) } @@ -190,36 +183,43 @@ const NewWindowPopup: React.FC = ({ if (htdflList.length > 0) setHtdflDetailModal({ isOpen: true, data: htdflList[0] }); }, [htdflList]) useEffect(() => { - if(mngList.length > 0) setIsDmdModal({ isMoal: true, data: [mngList[0]] }); - },[mngList]) + if (mngList.length > 0) setIsDmdModal({ isMoal: true, data: [mngList[0]] }); + }, [mngList]) + const lastCalledIdRef = useRef(null); + const [layerId, setLayerId] = useState(); +useEffect(() => { + const layers = getSelectedLayers(); + setLayerId(layers); +}, []); // 최초 렌더링 시 호출 - const layerId = getSelectedLayers(); - console.log(layerId) - if (featureData && typeof featureData.getProperties === "function") { - const selectedVal = featureData.getProperties(); - let featureCd = layerId == '하수재이용시설' ? selectedVal?.swtrmt_fclt_cd : layerId == '빗물이용시설' || layerId == '중수도시설' || layerId == '온배수시설' || layerId == '수요처' ? selectedVal?.bdst_nm : layerId == '하수처리시설' ? selectedVal?.swtrmt_fclt_nm : null; - if (featureCd && featureCd !== fcltPk) { - if (layerId == '하수재이용시설') { - featureCd = selectedVal?.swtrmt_fclt_cd; - setFcltPk(featureCd); // 현재 호출된 featureCd 저장 - setActiveTab(featureCd) - fetchpbnstDetail(featureCd); // 상세정보 - } - else if (layerId == '하수처리시설') { - featureCd = selectedVal?.swtrmt_fclt_nm; - setFcltPk(featureCd); // 현재 호출된 featureCd 저장 - fetchHasuDetail(featureCd, selectedVal?.swtrmt_fclt_cd); - } - else { - featureCd = selectedVal?.bdst_nm; - setFcltPk(featureCd) - if (layerId) { - detainSttn(featureCd, layerId); - } - } - setViewMode("detail") + useEffect(() => { + if (!featureData || typeof featureData.getProperties !== "function" || featureData.getProperties() == '') return; + const selectedProps = featureData.getProperties(); + const currentId = featureData.getId?.() || selectedProps?.id || selectedProps?.fid; + // 유효하지 않은 ID는 아예 무시 + if (!currentId || typeof currentId !== 'string') return; + // 이전과 동일하면 무시 + if (!currentId || currentId === lastCalledIdRef.current) return; + lastCalledIdRef.current = currentId // 새로운 피처일 때만 API 호출 + const layerId = getSelectedLayers?.(); + if (!layerId || typeof layerId !== 'string') return; + const featureCd = + layerId === '하수재이용시설' ? selectedProps?.swtrmt_fclt_cd : + ['빗물이용시설', '중수도시설', '온배수시설', '수요처'].includes(layerId) ? selectedProps?.bdst_nm : + layerId === '하수처리시설' ? selectedProps?.swtrmt_fclt_nm : + null; + if (!featureCd || featureCd === fcltPk) return; + if (layerId === '하수재이용시설') { + fetchpbnstDetail(featureCd); + } else if (layerId === '하수처리시설') { + fetchHasuDetail(featureCd, selectedProps?.swtrmt_fclt_cd); + } else { + detainSttn(featureCd, layerId); } - } else if (layerId === null && seletectedLayerNm) { setViewMode("list") } + setFcltPk(featureCd); + setViewMode("detail"); + setActiveTab(featureCd); + }, [featureData]); ///////////////////////////////////////////// 피쳐데이터 선택 시 각 시설별 데이터 처리 /////////////////////////////////////////////// ///////////////////////////////////////////// 하수재이용시설 ////////////////////////////////////////////////// @@ -238,12 +238,14 @@ const NewWindowPopup: React.FC = ({ // 재이용 현황 초기값 useEffect(() => { - if (!pbnstSttn.isInit) { + if (!pbnstSttn.isInit && seletectedLayerNm === '하수재이용시설') { getFlcts() } }, [seletectedLayerNm, pbnstSttn.isInit, getFlcts]); useEffect(() => { - pbnSttnInit("1", "15", { + if(seletectedLayerNm !== '하수재이용시설') return; + console.trace('check', 1) + pbnSttnInit("1", "20", { partValue: "A", sidoValue: '0', sigunValue: "0", @@ -254,7 +256,7 @@ const NewWindowPopup: React.FC = ({ sidoText: "", sigunText: "" }, String(new Date().getFullYear()), pbnstSttn.fclts); - }, [fclts, pbnSttnInit, pbnstSttn.fclts]) + }, [fclts, pbnSttnInit, pbnstSttn.fclts, seletectedLayerNm]) useEffect(() => { setBdstTable(pbnstSttn.pbnstSttnRes); }, [seletectedLayerNm, pbnstSttn.pbnstSttnRes]); @@ -271,10 +273,11 @@ const NewWindowPopup: React.FC = ({ // 재이용시설 조회 // 재이용시설 페이징처리 관련 함수 const onPageChangeHandler = useCallback((page: number) => { + if(seletectedLayerNm!== '하수재이용시설') return; pbnstSttnSearch( false, String(page), - String(13), + String(20), { partValue: "A", sidoValue: "0", @@ -318,6 +321,7 @@ const NewWindowPopup: React.FC = ({ useEffect(() => { + if(seletectedLayerNm !== '빗물이용시설') return; if (!rainSttn.isInit) { rainSttnInit(false, 1, "20", "0", '', code.cityCd, code.sggCd); } @@ -355,6 +359,7 @@ const NewWindowPopup: React.FC = ({ }, [code, rainSttnRes, rainSttn.rainSttHeadList]); useEffect(() => { + if(seletectedLayerNm !== '빗물이용시설') return; rainSttnSearch(false, rainPage, "20", '', '', code.cityCd, code.sggCd); }, [code.cityCd, code.sggCd, rainPage, rainSttnSearch]); ///////////////////////////////////////////// 빗물 재이용 ////////////////////////////////////////////////// @@ -370,12 +375,14 @@ const NewWindowPopup: React.FC = ({ } } useEffect(() => { + if(seletectedLayerNm !== '중수도시설') return; if (!rswtSttn.isInit) { rswtSttnInit(false, 1, "20", "0", '', code.cityCd, code.sggCd); } }, [code.cityCd, code.sggCd, rswtSttn.isInit, rswtSttnInit]); useEffect(() => { + if(seletectedLayerNm !== '중수도시설') return; const data = tableData(rswtSttnRes, { code }); const chData = data .map((item: customRswtBdst) => { @@ -409,6 +416,7 @@ const NewWindowPopup: React.FC = ({ // }, [rswtSttn.excelList]) useEffect(() => { + if(seletectedLayerNm !== '중수도시설') return; rswtSttnSearch(false, rswtrPage, "20", '', '', code.cityCd, code.sggCd); }, [code.cityCd, code.sggCd, rswtSttnSearch, rswtrPage]); ///////////////////////////////////////////// 중수도 시설 ////////////////////////////////////////////////// @@ -422,12 +430,14 @@ const NewWindowPopup: React.FC = ({ } }; useEffect(() => { + if(seletectedLayerNm !== '온배수시설') return; if (!htdflSttn.isInit) { initHtdfl(false, 1, "20", "0", '', code.cityCd, code.sggCd); } }, [code.cityCd, code.sggCd, htdflSttn.isInit, initHtdfl]); useEffect(() => { + if(seletectedLayerNm !== '온배수시설') return; const data = tableData(htdflSttnRes, { code }); const chData = data .map((item: any) => ({ @@ -441,6 +451,7 @@ const NewWindowPopup: React.FC = ({ }, [code, htdflSttnRes, htdflSttn.htdflSttHeadList]); useEffect(() => { + if(seletectedLayerNm !== '온배수시설') return; htdflSttnSearch(true, htdflPage, "20", '', '', code.cityCd, code.sggCd); }, [code.cityCd, code.sggCd, htdflPage, htdflSttnSearch]); ///////////////////////////////////////////// 온배수 시설 ////////////////////////////////////////////////// @@ -452,6 +463,7 @@ const NewWindowPopup: React.FC = ({ } }, [code, pbnstHasuRes]); useEffect(() => { + if(seletectedLayerNm !== '하수처리시설') return; if (!pbnst.isInit) { pubHasuInit("1", "0"); } @@ -470,8 +482,9 @@ const NewWindowPopup: React.FC = ({ ///////////////////////////////////////////// 수요처 관리 ////////////////////////////////////////////////// useEffect(() => { + if(seletectedLayerNm !== '수요처') return; if (!coSttn.isInit) { - coSttnInit("1", "13", "0"); + coSttnInit("1", "20", "0"); } }, [coSttn.isInit, coSttnInit]); const coMngCellClick = (index: number | undefined) => { @@ -481,6 +494,7 @@ const NewWindowPopup: React.FC = ({ } }; useEffect(() => { + if(seletectedLayerNm !== '수요처') return; if (coSttnRes) { if (coSttnRes?.length > 0 && code.cityCd.length > 0) { const data = tableData(coSttnRes, { code }); @@ -496,21 +510,21 @@ const NewWindowPopup: React.FC = ({ } }, [coSttnRes, code]); useEffect(() => { - coSttnSearch(String(mngPage), "13", String(0)); + if(seletectedLayerNm !== '수요처') return; + coSttnSearch(String(mngPage), "20", String(0)); }, [coSttnSearch, mngPage]); ///////////////////////////////////////////// 수요처 관리 ////////////////////////////////////////////////// // 체크된 레이어에 따른 조건부 컴포넌트 렌더링 함수 const renderConditionalContent = () => { const actTabData = tabData.find((tab) => tab.id === activeTab); - let layerId: string | undefined | null = getSelectedLayers(); if (layerId === null || layerId === undefined) { - layerId = seletectedLayerNm || ''; + setLayerId(seletectedLayerNm || ''); } //하수처리시설 const isPrcsFclt = layerId == '하수처리시설' // 재이용시설 - const isPbnst = layerId == '재이용시설'; + const isPbnst = layerId == '하수재이용시설'; // 빗물이용시설 const isRain = layerId == '빗물이용시설'; // 중수도시설 @@ -518,7 +532,7 @@ const NewWindowPopup: React.FC = ({ // 온배수시설 const isHtdfl = layerId == '온배수시설'; // 수요처관리 - const isReuseMng = layerId == '수요처관리'; + const isReuseMng = layerId == '수요처'; if (isPrcsFclt) { if (viewMode == 'list') { return ( @@ -530,8 +544,8 @@ const NewWindowPopup: React.FC = ({ = ({ } if (isReuseMng) { if (viewMode == 'detail') { - return ( -
-
- - </div> - {/* 높이 조정 */} - <UiTable - tableData={isDmdModal?.data || []} - headlist={coSttHeadList.slice(0, 3)} - pageSize={1} - total={0} - headName={"위치정보"} - cellClick={() => { }} - onPageChange={() => { }} - /> - <UiTable - tableData={isDmdModal?.data || []} - headlist={coSttHeadList.slice(3)} - pageSize={1} - total={0} - headName={"기본정보"} - cellClick={() => { }} - onPageChange={() => { }} - /> + return ( + <div style={{ overflowX: 'hidden' }}> + <div className="flex justify-between items-center mb-4"> + <Title title="수요처 상세정보" /> </div> - ) - } else if(viewMode == 'list') { - return ( <div> + {/* 높이 조정 */} + <UiTable + tableData={isDmdModal?.data || []} + headlist={coSttHeadList.slice(0, 3)} + pageSize={1} + total={0} + headName={"위치정보"} + cellClick={() => { }} + onPageChange={() => { }} + /> + <UiTable + tableData={isDmdModal?.data || []} + headlist={coSttHeadList.slice(3)} + pageSize={1} + total={0} + headName={"기본정보"} + cellClick={() => { }} + onPageChange={() => { }} + /> + </div> + ) + } else if (viewMode == 'list') { + return (<div> <div className="flex justify-between items-center"> - <Title title="수요처 현황" /> - </div> - <UiTable - headName={[]} - tableData={mngTable || []} - headlist={coSttHeadList} - pageSize={20} - total={coSttnResCount + 10 || 0} - cellClick={(index: number | undefined) => { - coMngCellClick(index); - // setUpdateData(coSttnRes[index as number]); - }} - onPageChange={(page) => { - setMngPage(page); - }} - ></UiTable></div>) + <Title title="수요처 현황" /> + </div> + <UiTable + headName={[]} + tableData={mngTable || []} + headlist={coSttHeadList} + pageSize={20} + total={coSttnResCount + 10 || 0} + cellClick={(index: number | undefined) => { + coMngCellClick(index); + // setUpdateData(coSttnRes[index as number]); + }} + onPageChange={(page) => { + setMngPage(page); + }} + ></UiTable></div>) } } return null; // 조건에 맞는 콘텐츠가 없을 경우