"use client" import NewWindowPortal from '@/app/map/newWindowPortal'; import { useWrStore } from "@/app/store"; import type { customHtdflBdst } from "@/app/store/ruseFcltMng/fcltReg/htdflReg"; import type { customPbnst, pubHasuType } from "@/app/store/ruseFcltMng/fcltReg/pbnstReg/type"; import type { customRainBdst } from "@/app/store/ruseFcltMng/fcltReg/rainReg"; import type { customRswtBdst } from "@/app/store/ruseFcltMng/fcltReg/rswtReg"; import type { WaterReuseFacility } from "@/app/store/ruseFcltMng/fcltSttn/pbnstSttn/type"; import { fetchType, getFetch, postFectch } from "@/components/lib/api"; import { tableData } from "@/components/lib/func/commom"; import { PbnstSttnModal } from "@/components/ui/modal/sttn/pbnstSttnModal/pbnstSttnModal"; import SttnDetailModal from "@/components/ui/modal/sttn/sttnDetailModal/sttnDetailModal"; import { Title, UITab, UiTable } from '@common/business_components'; import { useGisContext } from "@common/business_components/ui/map/Gis"; import { HeadMakeColSpan } from "@common/business_components/ui/table/HeadMakeColSpan"; import React, { useCallback, useEffect, useState } from 'react'; interface NewWindowPopupProps { featureData: any; seletectedLayerNm?: string viewMode?: 'list' | 'detail' | 'nothing' onFeatureSelect: (data: any) => void; onClose: () => void; } const NewWindowPopup: React.FC = ({ featureData, seletectedLayerNm, onFeatureSelect, onClose }) => { const { gisMap } = useGisContext() as unknown as { checkedLayerIds: React.MutableRefObject; treeData: { lyrSn: number }[] | null; gisCore: any; gisMap: any; }; const [tabData, setTabData] = useState<{ id: string; name: string; data: any }[]>([]); const [activeTab, setActiveTab] = useState('0'); const [viewMode, setViewMode] = useState<'list' | 'detail' | 'nothing'>('list'); const [fcltPk, setFcltPk] = useState(''); // onClose 함수를 useCallback으로 메모이제이션 const memoizedOnClose = useCallback(() => { onClose(); }, [onClose]); // 하수재이용시설 변수 const { code, pbnstSttn, pbnstSttnSearch, pbnSttnInit, getFlcts } = useWrStore((state) => state); const { fclts, pbnstSttnResCount } = pbnstSttn const [bdstTable, setBdstTable] = useState() // 빗물재이용시설 변수 const { rainSttn, rainSttnSearch, rainSttnInit } = useWrStore( (state) => state ); const { rainSttnRes, rainSttnResCount } = rainSttn; const [rainTable, setRainTable] = useState(); const [rainPage, setRainPage] = useState(1) const [rainDetailModal, setRainDetailModal] = useState<{ isOpen: boolean, data: customRainBdst | undefined }>({ data: undefined, isOpen: false }); const [rainList, setRainList] = useState(rainSttnRes || []); // 중수도시설 변수 const { rswtSttn, rswtSttnSearch, rswtSttnInit } = useWrStore( (state) => state ); const { rswtSttnRes, rswtSttnResCount } = rswtSttn; const [rswtrTable, setRswtrTable] = useState(); const [rswtrDetailModal, setRswtrDetailModal] = useState<{ isOpen: boolean, data: customRswtBdst | undefined }>({ data: undefined, isOpen: false }); const [rswtrPage, setRswtrPage] = useState(1); const [rswtrList, setRswtrList] = useState(rswtSttnRes || []); // 온배수시설 변수 const { htdflSttn, htdflSttnSearch, initHtdfl } = useWrStore((state) => state); const { htdflSttnRes,htdflSttnResCount } = htdflSttn; const [htdflTable, setHtdflTable] = useState(); const [htdflDetailModal, setHtdflDetailModal] = useState<{ isOpen: boolean, data: customHtdflBdst | undefined }>({ data: undefined, isOpen: false }); const [htdflPage, setHtdflPage] = useState(1) const [htdflList, setHtdflList] = useState(htdflSttnRes || []); //하수처리시설 변수 const { pbnst, pubHasuInit, } = useWrStore((state) => state); const { pubFacHeadList, pbnstHasuRes } = pbnst; const [hasuList, setHasuList] = useState(pbnstHasuRes || []); const [isRuseReg, setIsRuseReg] = useState<{ data: any | undefined; }>({ data: undefined }); const [hasuTable, setHasuTable] = useState(); const [hasuPage, setHasuPage] = useState(1); ///////////////////////////////////////////// 피쳐데이터 선택 시 각 시설별 데이터 처리 /////////////////////////////////////////////// const getSelectedLayers = () => { let result = null; const layers = gisMap ? gisMap.getLayers().getArray().filter((l: any) => l.getVisible()) : []; // gisMap이 null인지 확인 후 레이어 가져오기 let featureLayer: { get: (key: string) => any } = {get:()=> null}; layers.forEach((layer: any) => { const source = layer.getSource(); if (source && source.hasFeature && featureData && typeof featureData.getId === 'function' && source.hasFeature(featureData)) { featureLayer = layer; // 피처가 속한 레이어 찾기) } }); result = featureLayer.get('lyrNm'); return result; }; const fetchpbnstDetail = async (featureCd: string) => { try { const response = await getFetch("wr", `/reuseFc/pubFc/${featureCd}`); // 중복 데이터 추가 방지 setTabDataFunc(response, featureCd); } catch (error) { console.error("Error fetching data:", error); } }; 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) setHasuList( rainRes.data.map((item: any) => { return { ...item, fctCpc: Number(item.fctCpc) || 0, ruse: item.ruse === false ? "N" : "Y", }; }) ) } catch (error) { console.error("Error fetching data:", error); } }; const detainSttn = async (featureCd: string, layerNm: string) => { if (layerNm == '빗물이용시설') { const res = await getFetch(fetchType.WR, `/reuseFc/rainyInfoList/1/20/0/${featureCd}`) setRainList(res) } else if(layerNm == '중수도시설'){ const res = await getFetch(fetchType.WR,`/reuseFc/waterreuseFc/1/20/0/${featureCd}`) setRswtrList(res) } else{ const res = await getFetch(fetchType.WR, `/drain/facilityList/1/20/0/${featureCd}`) setHtdflList(res) setHtdflDetailModal({ isOpen: true, data: htdflSttnRes[0] }); } } // 상세 목록 데이터 상태 처리 useEffect(()=>{ if (hasuList.length > 0) setIsRuseReg({ data: [hasuList[0]] }); },[hasuList]) useEffect(()=>{ if (rainList.length > 0) setRainDetailModal({ isOpen: true, data: rainList[0] }); },[rainList]) useEffect(()=>{ if (rswtrList.length > 0) setRswtrDetailModal({ isOpen: true, data: rswtrList[0] }); },[rswtrList]) useEffect(()=>{ if (htdflList.length > 0) setHtdflDetailModal({ isOpen: true, data: htdflList[0] }); },[htdflList]) const layerId = getSelectedLayers(); if (featureData && typeof featureData.getProperties === "function") { const selectedVal = featureData.getProperties(); let featureCd = layerId == '하수재이용시설' ? selectedVal?.swtrmt_fclt_cd : 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") } } else if (layerId === null && seletectedLayerNm) { setViewMode("list") } ///////////////////////////////////////////// 피쳐데이터 선택 시 각 시설별 데이터 처리 /////////////////////////////////////////////// ///////////////////////////////////////////// 하수재이용시설 ////////////////////////////////////////////////// // 재이용시설 cellClick 이벤트 (상세정보) const pbnstCellClick = (index: number | undefined) => { if ( index !== undefined && pbnstSttn.pbnstSttnRes && pbnstSttn.pbnstSttnRes[index] ) { setFcltPk(pbnstSttn.pbnstSttnRes[index].pbnstRuseFcltId); onFeatureSelect(pbnstSttn.pbnstSttnRes[index]); onClose() } }; // 재이용 현황 초기값 useEffect(() => { if (!pbnstSttn.isInit) { getFlcts() } }, [seletectedLayerNm, pbnstSttn.isInit, getFlcts]); useEffect(()=>{ pbnSttnInit("1", "15", { partValue: "A", sidoValue: '0', sigunValue: "0", regionValue: "", unitWaterShedValue: "", middleRegionValue: "", envPartValue: "", sidoText: "", sigunText: "" }, String(new Date().getFullYear()), pbnstSttn.fclts); }, [fclts, pbnSttnInit, pbnstSttn.fclts]) useEffect(() => { setBdstTable(pbnstSttn.pbnstSttnRes); }, [seletectedLayerNm, pbnstSttn.pbnstSttnRes]); // 재이용시설 상세정보 const setTabDataFunc = (res: any, pk: string) => { setTabData((prev) => { if (prev.some((tab) => tab.id === pk)) { return prev; // 이미 존재하는 탭이면 추가하지 않음 } return [...prev, { id: pk, name: `재이용시설 ${prev.length + 1}`, data: res }]; }); } // 재이용시설 조회 // 재이용시설 페이징처리 관련 함수 const onPageChangeHandler = useCallback((page: number) => { pbnstSttnSearch( false, String(page), String(13), { partValue: "A", sidoValue: "0", sigunValue: "0", regionValue: "", unitWaterShedValue: "", middleRegionValue: "", envPartValue: "", sidoText: "", sigunText: "", }, "", String(new Date().getFullYear()), fclts ); }, [fclts, pbnstSttnSearch]); // FIXME: 윤선화차장님 요구사항으로 엑셀 다운로드 삭제. // const excelClick = useCallback(() => { // // if (codeData) pbnstSttnSearch(1, "10000", codeData); // excelDownload( // [[]], // "하수재이용시설 현황", // "sample_pbnstSttn.xlsx", // "A1:U2" // ); // }, [pbnstSttnSearch]); ///////////////////////////////////////////// 하수재이용시설 ////////////////////////////////////////////////// ///////////////////////////////////////////// 빗물 재이용 ////////////////////////////////////////////////// // 빗물재이용시설 cellClick 이벤트 (상세정보) const rainCellClick = (index: number | undefined, headId: string) => { if ( index !== undefined && rainTable !== undefined && headId !== 'chBuildingYn') { // setRainDetailModal({ isOpen: true, data: rainTable[index] }) // setViewMode('detail') onFeatureSelect(rainTable[index]); onClose(); } } useEffect(() => { if (!rainSttn.isInit) { rainSttnInit(false, 1, "20", "0", '', code.cityCd, code.sggCd); } }, [code.cityCd, code.sggCd, rainSttn.isInit, rainSttnInit]); useEffect(() => { const data = tableData(rainSttnRes, { code }); const chData = data .map((item: any) => { return { ...item, ...item.reuseBuilding[0], ...item.reuseBuilding[0].rainyObj, dtfcltCpct: item.reuseBuilding[0].rainyObj.dtfcltCpct === -1 ? "확인불가" : item.reuseBuilding[0].rainyObj.dtfcltCpct, instlCst: item.reuseBuilding[0].instlCst === -1 ? "확인불가" : item.reuseBuilding[0].instlCst, instlCstSprtAmt: item.reuseBuilding[0].instlCstSprtAmt === -1 ? "확인불가" : item.reuseBuilding[0].instlCstSprtAmt, chBuildingYn: item.chgBuilding[0]?.bdstChgNm !== null ? "Y" : "N", pntfColArea: item.reuseBuilding[0].rainyObj.pntfColArea === -1 ? "확인불가" : item.reuseBuilding[0].rainyObj.pntfColArea, filtrTrtmfctCpct: item.reuseBuilding[0].rainyObj.filtrTrtmfctCpct === -1 ? "확인불가" : item.reuseBuilding[0].rainyObj.filtrTrtmfctCpct, archArea: Math.floor(item.archArea) === -1 ? "확인불가" : item.archArea, }; }) .filter((item: any) => item.rainyObj !== undefined); setRainTable(chData); }, [code, rainSttnRes, rainSttn.rainSttHeadList]); useEffect(() => { rainSttnSearch(false, rainPage, "20", '', '', code.cityCd, code.sggCd); }, [code.cityCd, code.sggCd, rainPage, rainSttnSearch]); ///////////////////////////////////////////// 빗물 재이용 ////////////////////////////////////////////////// ///////////////////////////////////////////// 중수도 시설 ////////////////////////////////////////////////// // 중수도시설 cellClick 이벤트 (상세정보) const rswtCellClick = (index: number | undefined, headId: string) => { if (headId !== 'chBuildingYn' && index !== undefined && rswtrTable !== undefined) { // setRswtrDetailModal({ isOpen: true, data: rswtrTable[index] }); // setViewMode('detail') onFeatureSelect(rswtrTable[index]); onClose(); } } useEffect(() => { if (!rswtSttn.isInit) { rswtSttnInit(false, 1, "20", "0", '', code.cityCd, code.sggCd); } }, [code.cityCd, code.sggCd, rswtSttn.isInit, rswtSttnInit]); useEffect(() => { const data = tableData(rswtSttnRes, { code }); const chData = data .map((item: customRswtBdst) => { return { ...item, ...item.reuseBuilding[0], ...item.reuseBuilding[0]?.rswtrObj, chBuildingYn: item?.chgBuilding[0]?.bdstChgNm !== null && item?.chgBuilding.length > 0 ? 'Y' : 'N', instlCst: item.reuseBuilding[0]?.instlCst === -1 ? "확인불가" : item.reuseBuilding[0]?.instlCst, instlCstSprtAmt: item.reuseBuilding[0]?.instlCstSprtAmt === -1 ? "확인불가" : item.reuseBuilding[0]?.instlCstSprtAmt, archArea: item?.archArea.split('.')[0] !== '-1' ? item?.archArea.split('.')[0] : '확인불가' } }) .filter( (item: customRswtBdst) => item.reuseBuilding[0]?.rswtrObj !== undefined ); setRswtrTable(chData); }, [code, rswtSttnRes]); // FIXME: 윤선화 차장님 요구사항으로 엑셀 다운로드 삭제. // const rswtSttnExcelDownload = useCallback(() => { // if (rswtSttn.excelList.length > 0) { // if (rswtSttn.excelList.length === 0) return; // excelDownload( // rswtSttn.excelList, // "중수도시설 현황", // "sample_rswtSttn.xlsx", // "A1:W3", // ); // } // }, [rswtSttn.excelList]) useEffect(() => { rswtSttnSearch(false, rswtrPage, "20", '', '', code.cityCd, code.sggCd); }, [code.cityCd, code.sggCd, rswtSttnSearch, rswtrPage]); ///////////////////////////////////////////// 중수도 시설 ////////////////////////////////////////////////// ///////////////////////////////////////////// 온배수 시설 ////////////////////////////////////////////////// // 온배수시설 cellClick 이벤트 (상세정보) const htdflCellClick = (index: number | undefined) => { if (index !== undefined && htdflTable !== undefined) { onFeatureSelect(htdflTable[index]); onClose(); } }; useEffect(() => { if (!htdflSttn.isInit) { initHtdfl(false, 1, "20", "0", '', code.cityCd, code.sggCd); } }, [code.cityCd, code.sggCd, htdflSttn.isInit, initHtdfl]); useEffect(() => { const data = tableData(htdflSttnRes, { code }); const chData = data .map((item: any) => ({ ...item, ...item.reuseBuilding[0], ...item.reuseBuilding[0].htdflObj, chBuildingYn: item.chgBuilding[0]?.bdstChgNm !== null ? "Y" : "N", })) .filter((item: any) => item.htdflObj !== undefined); setHtdflTable(chData); }, [code, htdflSttnRes, htdflSttn.htdflSttHeadList]); useEffect(() => { htdflSttnSearch(true, htdflPage, "20", '', '', code.cityCd, code.sggCd); }, [code.cityCd, code.sggCd, htdflPage, htdflSttnSearch]); ///////////////////////////////////////////// 온배수 시설 ////////////////////////////////////////////////// ///////////////////////////////////////////// 하수처리 시설 ////////////////////////////////////////////////// useEffect(() => { if (code.sggCd.length && pbnstHasuRes.length > 0) { setHasuTable(tableData(pbnstHasuRes, { code })); } }, [code, pbnstHasuRes]); useEffect(() => { if (!pbnst.isInit) { pubHasuInit("1", "0"); } }, [pbnst.isInit, pubHasuInit]); useEffect(() => { pubHasuInit(String(hasuPage), "0"); }, [hasuPage, pubHasuInit]); const hasuCellClick = (index: number | undefined) => { if (index !== undefined && pbnstHasuRes !== undefined) { onFeatureSelect(pbnstHasuRes[index]); onClose(); } }; ///////////////////////////////////////////// 하수처리 시설 ////////////////////////////////////////////////// // 체크된 레이어에 따른 조건부 컴포넌트 렌더링 함수 const renderConditionalContent = () => { const actTabData = tabData.find((tab) => tab.id === activeTab); let layerId:string | undefined | null = getSelectedLayers(); if (layerId === null || layerId === undefined) { layerId = seletectedLayerNm || ''; } //하수처리시설 const isPrcsFclt = layerId == '하수처리시설' // 재이용시설 const isPbnst = layerId == '하수재이용시설'; // 빗물이용시설 const isRain = layerId == '빗물이용시설'; // 중수도시설 const isRswt = layerId == '중수도시설'; // 온배수시설 const isHtdfl = layerId == '온배수시설'; if (isPrcsFclt) { if (viewMode == 'list') { return ( <>
</div> {/* 높이 조정 */} <UiTable tableData={hasuTable || []} headlist={pubFacHeadList} pageSize={10} total={5000} headName={""} cellClick={hasuCellClick} onPageChange={setHasuPage} /> </> ) } else { return ( <> <div className="flex justify-between items-center mb-4"> <Title title="하수처리시설 상세정보" /> </div> {/* 높이 조정 */} <UiTable tableData={isRuseReg?.data || []} headlist={pubFacHeadList.slice(0, 4)} pageSize={1} total={0} headName={"위치정보"} cellClick={() => { }} onPageChange={() => { }} /> <UiTable tableData={isRuseReg?.data || []} headlist={pubFacHeadList.slice(4)} pageSize={1} total={0} headName={"기본정보"} cellClick={() => { }} onPageChange={() => { }} /> </> ) } } if (isPbnst) { if (viewMode == 'detail') { // 재이용시설 상세 return ( <> <div className="flex justify-between items-center mb-4"> <Title title="하수재이용시설 상세정보" /> </div> <div className="flex justify-between items-center mb-8"> <UITab defaultValue={activeTab} tabList={tabData.map((tab) => ({ value: tab.id, label: tab.name, onClick: () => setActiveTab(tab.id), }))} /> </div> <PbnstSttnModal data={actTabData?.data[0] || ({} as customPbnst)} titleVisible={false} /> </> ); } else { // 재이용시설 목록 return ( <> <div className="flex justify-between items-center"> <Title title="하수재이용시설 현황" /> {/* <div className="flex gap-2 mt-8"> <Button className={btnClass} color="primary" onClick={excelClick}> 엑셀다운로드 </Button> </div> */} </div> <UiTable headName={[]} tableData={bdstTable || []} headlist={pbnstSttn.pbnstSttHeadList} pageSize={20} total={pbnstSttnResCount || 0} cellClick={(index: number | undefined) => { pbnstCellClick(index); }} onPageChange={onPageChangeHandler} > <HeadMakeColSpan upHeadList={pbnstSttn.pbnstSttNodeList} /> </UiTable> </> ); } } if (isRain) { if (viewMode == 'detail') { // 빗물이용시설 상세 return ( <SttnDetailModal type={"RNB"} formObj={rainDetailModal.data as customRainBdst} /> ); } else { // 빗물이용시설 목록 return ( <> <div className="flex justify-between items-center"> <Title title="빗물이용시설 현황" /> {/* <div className="flex gap-2 mt-8"> <Button className={btnClass} color="primary" onClick={excelClick}> 엑셀다운로드 </Button> </div> */} </div> <UiTable headName={[]} tableData={rainTable || []} headlist={rainSttn.rainSttHeadList} pageSize={20} total={rainSttnResCount} cellClick={(index: number | undefined, headId: string) => { rainCellClick(index ?? undefined, headId); }} onPageChange={setRainPage} > <HeadMakeColSpan upHeadList={rainSttn.rainSttNodeList} /> </UiTable> </> ); } } if (isRswt) { if (viewMode == 'detail') { // 중수도시설 상세 return ( <SttnDetailModal type={"RST"} formObj={rswtrDetailModal.data as customRswtBdst} /> ); } else { // 중수도시설 목록 return ( <> <div className="flex justify-between items-center"> <Title title="중수도시설 현황" /> {/* <div className="flex gap-2 mt-8"> <Button className={btnClass} color="primary" onClick={rswtSttnExcelDownload}> 엑셀다운로드 </Button> </div> */} </div> <UiTable headName={[]} tableData={rswtrTable || []} headlist={rswtSttn.rswtSttHeadList} pageSize={20} total={rswtSttnResCount} cellClick={(index: number | undefined, headId: string) => { rswtCellClick(index, headId); }} onPageChange={setRswtrPage} > <HeadMakeColSpan upHeadList={rswtSttn.rswtSttNodeList} /> </UiTable> </> ); } } if (isHtdfl) { if (viewMode == 'detail') { // 온배수시설 상세 return ( <SttnDetailModal type={"HTB"} formObj={htdflDetailModal.data as customHtdflBdst} /> ); } else { // 온배수시설 목록 return ( <> <div className="flex justify-between items-center"> <Title title="온배수시설 현황" /> {/* <div className="flex gap-2 mt-8"> <Button className={btnClass} color="primary" onClick={excelClick}> 엑셀다운로드 </Button> </div> */} </div> <UiTable headName={[]} tableData={htdflTable || []} headlist={htdflSttn.htdflSttHeadList} pageSize={20} total={htdflSttnResCount || 0} cellClick={(index: number | undefined) => { htdflCellClick(index ?? undefined); }} onPageChange={setHtdflPage} > <HeadMakeColSpan upHeadList={htdflSttn.htdflSttNodeList} /> </UiTable> </> ); } } return null; // 조건에 맞는 콘텐츠가 없을 경우 }; return ( viewMode == 'nothing' ? <></> : <NewWindowPortal onClose={memoizedOnClose} title="시설 상세 정보"> {/* 체크된 레이어에 따른 조건부 렌더링 */} {renderConditionalContent()} </NewWindowPortal> ); }; export default NewWindowPopup;