'use client' import { getData, postData } from "@/components/lib/api"; import Modal from "@/components/ui/modal"; import { VerticalTable } from "@/components/ui/verticalTable"; import { useGisContext } from "@common/business_components/ui/map/Gis"; import { Button } from "@common/components/ui"; import { useEffect, useRef, useState, useCallback, useMemo } from "react"; import { getLayerContentComponent } from "./components/common"; import { SwtrmtFcltCol, SwtrmtPrcsZoneCol, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, ExclnSewagePumpCol, MsSwageMhlCol, stofcbrCol, MS_SWAGE_MHL_CODES, DRTW_SEWAGE_PUMP_USE_CODES } from "./components/common/table"; import InfilChart from './components/popupComponent/chart/infilChart'; import RdiiChart from './components/popupComponent/chart/rdiiChart'; import { useInfilChartModalStore, useRdiiChartModalStore } from "./components/popupComponent/chartModalStore"; import { formatDisplayData } from '@/components/lib/utils/formatDisplayValue'; // TODO: const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, featureData: any }) => { const { gisMap } = useGisContext() as unknown as { checkedLayerIds: React.MutableRefObject; treeData: { lyrSn: number }[] | null; gisCore: any; gisMap: any; }; const [layerNm, setLayerNm] = useState(""); // 레이어 이름 상태 const [tableData, setTableData] = useState(null); // 피처 데이터 const [rainMeasureData, setRainMeasureData] = useState([]); // 강우/측정 측정 정보 const [headlist, setHeadlist] = useState<{ id: string; title: string; }[]>([]); // 컬럼리스트 변경상태 const [headlist2, setHeadlist2] = useState<{ id: string; title: string; }[]>([]); // 컬럼리스트 변경상태 const [buttonChk, setButtonChk] = useState(true) const [fetchData, setfetchData] = useState(); // api 호출여부 const contentRef = useRef(null); const [isModalOpen, setIsModalOpen] = useState(false); // 모달 열기 상태 const [isMainSsc, setIsMainSsc] = useState(false); // 중점우수토실 여부 const [isDrtwSewagePump, setIsDrtwSewagePump] = useState(false); // 오수펌프장 여부 // 🎯 InfilChart 및 RdiiChart 관련 상태 추가 const { setIsOpen: setIsModalInfil } = useInfilChartModalStore(); const { setIsOpen: setIsModalRdii } = useRdiiChartModalStore(); const [curPage, setCurPage] = useState(1); // 현재 페이지 상태 // 🎯 관로관리번호 추출 const pplMngNo = featureData?.values_?.fclt_mng_no || ""; // const featureId = featureData.getId(); // 피처의 id 가져오기 const featureId = typeof featureData.getId === 'function' ? featureData.getId() : featureData.fid; console.log('featureId', featureId); // 🎯 데이터 전처리 메모이제이션 const processedData = useMemo(() => { if (!featureData?.values_) return null; return { ...featureData.values_, discharge_pipe_spec: `직경: ${featureData.values_.pipe_diameter || '-'} / 높이: ${featureData.values_.pipe_hg || '-'} / 길이: ${featureData.values_.pipe_lt || '-'}` }; }, [featureData?.values_]); // 피쳐데이터의 현재 레이어 이름 가져오는 함수 const getSelectedLayers = () => { let result = null; const layers = gisMap.getLayers().getArray(); // gisMap에서 모든 레이어 가져오기 let featureLayer: { get: (key: string) => any }; // 피처가 속한 레이어를 찾기 위한 변수 layers.forEach((layer: any) => { const source = layer.getSource(); if (source && source.hasFeature && featureData && typeof featureData.getId === 'function' && source.hasFeature(featureData)) { featureLayer = layer; // 피처가 속한 레이어 찾기 } }); // console.log("featureLayer.get('lyrTyNm');", featureLayer.get('lyrTyNm')); // SearchModal 클릭 이벤트와 Gis 클릭 이벤트 구분하기 if (featureLayer.get('lyrNm') === null) { if (featureData.lyrTypeNm === 'tb_il_swage_prcs_fclt') result = '하수처리시설'; else if (featureData.lyrTypeNm === 'tb_ms_swage_prcs_zone') result = '하수처리구역'; else if (featureData.lyrTypeNm === 'tb_ms_stofcbr') result = '우수토실'; else if (featureData.lyrTypeNm === 'om_dt_untrt_swg_rain') result = '중점우수토실'; else if (featureData.lyrTypeNm === 'tb_ms_swage_ppl') result = '하수관로'; else if (featureData.lyrTypeNm === 'tb_ms_swage_pmstn') { const drtwPumpCode = DRTW_SEWAGE_PUMP_USE_CODES.find(code => code.text === '오수펌프장'); console.log('값 비교', featureData.values_.usg_cd.trim(), drtwPumpCode?.val); if (drtwPumpCode && featureData.values_.usg_cd.trim() === drtwPumpCode.val) { setIsDrtwSewagePump(true); } else { setIsDrtwSewagePump(false); } result = '하수펌프장'; } else if (featureData.lyrTypeNm === 'tb_ms_swage_mhl') result = '하수맨홀'; } else { const lyrTyNm = featureLayer.get('lyrTyNm'); if (lyrTyNm === 'tb_il_swage_prcs_fclt') result = '하수처리시설'; else if (lyrTyNm === 'tb_ms_swage_prcs_zone') result = '하수처리구역'; else if (lyrTyNm === 'tb_ms_stofcbr') result = '우수토실'; else if (lyrTyNm === 'om_dt_untrt_swg_rain') result = '중점우수토실'; else if (lyrTyNm === 'tb_ms_swage_ppl') result = '하수관로'; else if (lyrTyNm === 'tb_ms_swage_pmstn') { const drtwPumpCode = DRTW_SEWAGE_PUMP_USE_CODES.find(code => code.text === '오수펌프장'); console.log('값 비교', featureData.values_.usg_cd.trim(), drtwPumpCode?.val); if (drtwPumpCode && featureData.values_.usg_cd.trim() === drtwPumpCode.val) { setIsDrtwSewagePump(true); } else { setIsDrtwSewagePump(false); } result = '하수펌프장'; } else if (lyrTyNm === 'tb_ms_swage_mhl') result = '하수맨홀'; else result = featureLayer.get('lyrNm'); } return result; // return featureLayer.get('lyrNm'); // 레이어 이름 출력 }; useEffect(() => { const fetchData = async () => { if (!featureId) return; try { const selectedLayerName = getSelectedLayers(); // 레이어 이름 가져오기 setLayerNm(selectedLayerName); // 상태 업데이트 console.log('gis data', featureData.values_); const data = featureData.values_; // 하수맨홀인 경우 용도코드를 텍스트로 변환 if (selectedLayerName === '하수맨홀' && data) { // mqlt_cd 값 변환 (재질코드) if (data.mqlt_cd) { const materialCodeItem = MS_SWAGE_MHL_CODES.find( code => code.val === data.mqlt_cd.trim() ); if (materialCodeItem) data.mqlt_cd = `${materialCodeItem.text}`; } } // 🎯 기본 데이터 포맷팅 const formattedData = formatDisplayData(data); setfetchData(formattedData); setTableData(formattedData); switch (selectedLayerName) { case '하수처리시설': setHeadlist(SwtrmtFcltCol); setButtonChk(false) break; case '하수처리구역': setHeadlist(SwtrmtPrcsZoneCol) setButtonChk(false) break; case '중점우수토실': setHeadlist(untrtSwgRainCol1) setHeadlist2(untrtSwgRainCol2) setButtonChk(false) setIsMainSsc(true) // 🎯 processedData도 포맷팅하여 설정 const processedFormattedData = formatDisplayData(processedData); setfetchData([processedFormattedData]) setTableData(processedFormattedData); // setIsLoading(false); // 기본 렌더링 완료 // 강우/측정 정보 데이터 호출 if (data?.chmbr_xcnts && data?.chmbr_ydnts) { fetchRainMeasureData(data.chmbr_xcnts, data.chmbr_ydnts) .then(response => { console.log('additionalResponse', response); setRainMeasureData(response || []); }) .catch(error => { console.error('추가 데이터 로딩 실패:', error); setRainMeasureData(false); }); } break; case '우수토실': setHeadlist(stofcbrCol) setButtonChk(true) setIsMainSsc(false) break; case '하수관로': setHeadlist(MsSwagePplCol) setButtonChk(true) break; // case '오수펌프': // setButtonChk(true) // break; // case '빗물펌프': // setButtonChk(true) // break; case '하수펌프장': setHeadlist(ExclnSewagePumpCol) setButtonChk(true) break; case '하수맨홀': setHeadlist(MsSwageMhlCol) setButtonChk(true) break; default: break; } // API 엔드포인트 선택 let apiEndpoint = ''; const getFeatureId = featureId.toString().split('.').pop() || null; if (selectedLayerName === '하수관로') apiEndpoint = `v1/fcltppl/${getFeatureId}`; else if (selectedLayerName === '우수토실') apiEndpoint = `v1/fcltstofcbr/${getFeatureId}`; else if (selectedLayerName === '오수펌프' || selectedLayerName === '빗물펌프') apiEndpoint = `v1/fcltpump/${getFeatureId}`; else if (selectedLayerName === '하수맨홀') apiEndpoint = `v1/fcltmhl/${getFeatureId}`; // API에서 상세 데이터 가져오기 if (apiEndpoint) { try { console.log(`API 호출: ${apiEndpoint}`); const result = await getData(apiEndpoint); if (result) { console.log('API 데이터 로드 성공:', result); // 하수맨홀인 경우 용도코드를 텍스트로 변환 if (selectedLayerName === '하수맨홀') { const processedData = { ...result }; // mqlt_cd 값 변환 (재질코드) if (processedData.mqlt_cd) { const materialCodeItem = MS_SWAGE_MHL_CODES.find( code => code.val === processedData.mqlt_cd.trim() ); if (materialCodeItem) { processedData.mqlt_cd = `${materialCodeItem.text}`; } } setfetchData(processedData); } // 🎯 우수토실인 경우 prrtymngYn 값 변환 else if (selectedLayerName === '우수토실' && data) { const processedData = { ...result, ...data }; // prrtymngYn 값 변환 if (processedData.prrtymngYn === 'Y') processedData.prrtymngYn = '중점우수토실'; else if (processedData.prrtymngYn === 'N') processedData.prrtymngYn = '우수토실'; console.log('processedData', processedData); setfetchData(processedData); } else { setfetchData(result); } } } catch (apiError) { console.error('API 데이터 로딩 중 오류:', apiError); } } } catch (error) { console.error('데이터 로딩 중 오류:', error); } }; fetchData(); }, [featureId, processedData]); // 🎯 추가 데이터 API 호출 함수 (독립적으로 실행) const fetchRainMeasureData = useCallback(async (chmbrXcnts: string, chmbrYdnts: string) => { if (!chmbrXcnts || !chmbrYdnts) { console.warn('추가 데이터 호출 실패: 필수 매개변수 누락', { chmbrXcnts, chmbrYdnts }); return []; } try { const queryParams = new URLSearchParams({ chmbrXcnts: chmbrXcnts, chmbrYdnts: chmbrYdnts, pageable: `{}`, }); console.log(`추가 데이터 API 호출 시작: v1/onsemiro/getSwgRainsByGeomety?${queryParams.toString()}`); const result = await getData(`v1/onsemiro/getSwgRainsByGeomety?${queryParams.toString()}`); console.log('추가 데이터 API 호출 성공:', result); // 🎯 result가 페이지네이션 객체인 경우 content 배열 추출 let dataArray: any[] = []; if (result && typeof result === 'object' && 'content' in result && Array.isArray(result.content)) { dataArray = result.content; } else if (Array.isArray(result)) { dataArray = result; } else { console.warn('예상치 못한 API 응답 형식:', result); return []; } // 🎯 각 아이템을 전처리하여 반환 const processedDataArray = dataArray.map((data: any) => { // 🎯 formatDisplayData로 기본 포맷팅 적용 const formattedItem = formatDisplayData(data); // 🎯 추가 데이터 조합 return { ...formattedItem, flwmtrCombined: `${data.flwmtrMesureTpEtc || '-'} / ${data.flwmtrKnd || '-'}`, }; }); return processedDataArray; } catch (error) { console.error('추가 데이터 로딩 실패:', error); return []; } }, []); // 🎯 추가 데이터는 별도 useEffect로 비동기 로딩 useEffect(() => { if (layerNm === '중점우수토실' && featureData?.values_) { const data = featureData.values_; if (data?.chmbr_xcnts && data?.chmbr_ydnts) { // 🎯 추가 데이터를 비동기로 로딩 (UI 블로킹 없음) fetchRainMeasureData(data.chmbr_xcnts, data.chmbr_ydnts) .then(response => { console.log('추가 데이터 로딩 완료:', response); setRainMeasureData(response || []); }) .catch(error => { console.error('추가 데이터 최종 로딩 실패:', error); setRainMeasureData(false); }); } } }, [layerNm, featureData?.values_, fetchRainMeasureData]); // 저장 시 모달 띄우기 const handleSaveClick = () => { setIsModalOpen(true); // 모달 열기 }; const handleModalSave = () => { setIsModalOpen(false); // 모달 닫기 btnClickEvent(); // 저장 이벤트 실행 }; const handleModalClose = () => { setIsModalOpen(false); // 모달 닫기 }; // 저장 버튼 이벤트 const btnClickEvent = async () => { const bodyData: Record = {} if (buttonChk && contentRef.current) { const inputElements = contentRef.current.querySelectorAll('input'); const selectElements = contentRef.current.querySelectorAll('select'); // 카멜케이스 변환 함수 const toCamelCase = (str: string) => str.replace(/_([a-z])/g, (_, char) => char.toUpperCase()); // select 태그의 값 가져오기 selectElements.forEach((select) => { const camelCaseId = toCamelCase(select.id); bodyData[camelCaseId] = select.value; }); // // input 태그의 값 가져오기 inputElements.forEach((input) => { const camelCaseId = toCamelCase(input.id); bodyData[camelCaseId] = input.value; }); // 레이어명에 따라 API 엔드포인트 분기처리 let apiEndpoint = ''; let result = null; if (layerNm === '하수관로') apiEndpoint = 'v1/fcltppl'; else if (layerNm === '우수토실') apiEndpoint = 'v1/fcltstofcbr'; else if (layerNm === '하수펌프장') apiEndpoint = 'v1/fcltpump'; else if (layerNm === '하수맨홀') apiEndpoint = 'v1/fcltmhl'; bodyData['fid'] = featureId.toString().split('.').pop() || null; // 빈 키 제거 if (bodyData[""] !== undefined) delete bodyData[""]; // 🎯 우수토실일 경우 prrtymngYn 값 변환 if (layerNm === '우수토실' && bodyData.prrtymngYn) { if (bodyData.prrtymngYn === '중점우수토실') { bodyData.prrtymngYn = 'Y'; } else if (bodyData.prrtymngYn === '우수토실') { bodyData.prrtymngYn = 'N'; } } console.log('bodyData', bodyData); console.log('apiEndpoint', apiEndpoint); try { result = await postData(apiEndpoint, bodyData); console.log('result', result); if (result) { alert('저장되었습니다'); setfetchData(result.data || result); } else { alert('저장에 실패했습니다'); console.error('API 응답 오류:', result); } } catch (error) { alert('저장 중 오류가 발생했습니다'); console.error('API 요청 오류:', error); } } } // 레이어명에 따라 상세페이지 렌더링 const ContentComponent = layerNm ? getLayerContentComponent(layerNm) : null; return ( ) } export default FeatureClickEventPopup;