'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, useMemo } from "react"; import { getLayerContentComponent } from "../common"; import { SwtrmtFcltCol, SwtrmtFcltCol2, SwtrmtPrcsZoneCol, SwtrmtPrcsZoneCol2, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, MsSwagePplCol2, ExclnSewagePumpCol, ExclnSewagePumpCol2, DrtwSewagePumpCol, DrtwSewagePumpCol2, MsSwageMhlCol, MsSwageMhlCol2, stofcbrCol, stofcbrCol2, MS_SWAGE_MHL_CODES, DRTW_SEWAGE_PUMP_USE_CODES } from "../common/table"; import InfilChart from './chart/infilChart'; import RdiiChart from './chart/rdiiChart'; import { useInfilChartModalStore, useRdiiChartModalStore } from "./chartModalStore"; import { formatDisplayData } from '@/components/lib/utils/formatDisplayValue'; import { codeMapper } from "../common/codeMapper"; import { searchUpperPpls } from '@common/business_components/ui/map/Gis'; import LoadingOverlay from '@/components/ui/LoadingBar'; 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 [layerSpecificNm, setLayerSpecificNm] = useState(""); // 레이어 이름 상태 const [tableData, setTableData] = useState(null); // 피처 데이터 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 [isClicked, setIsClicked] = useState(true); // 클릭 여부 상태 const [isLoading, setIsLoading] = useState(false); // 로딩 상태 const [chmbrXcnts, setChmbrXcnts] = useState(''); // 로딩 상태 const [chmbrYdnts, setChmbrYdnts] = useState(''); // 로딩 상태 // 🎯 관로관리번호 추출 const pplMngNo = featureData?.values_?.fclt_mng_no || ""; const featureId = typeof featureData.getId === 'function' ? featureData.getId() : featureData.fid; // 🎯 데이터 전처리 메모이제이션 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.some((layer: any) => { const source = layer.getSource(); // if (source && featureData && featureData.fid) { // featureLayer = layer; // 피처가 속한 레이어 찾기 // } if (source && source.hasFeature && featureData && typeof featureData.getId === 'function' && source.hasFeature(featureData)) { featureLayer = layer; // 피처가 속한 레이어 찾기 return true; // 반복 종료 } return false; }); if (featureData['ol_uid']) { // Gis 레이어 클릭 이벤트 setIsClicked(true); console.log('gis data', featureData.values_); const lyrTyNm = featureData.id_.split('.')[0]; if (lyrTyNm === 'tb_ms_swage_ppl') { result = '하수관로'; setHeadlist(MsSwagePplCol); setLayerSpecificNm(featureData.values_.fclt_mng_no); } else if (lyrTyNm === 'tb_ms_swage_mhl') { result = '하수맨홀'; setHeadlist(MsSwageMhlCol); setLayerSpecificNm(featureData.values_.fclt_mng_no); } else if (lyrTyNm === 'tb_ms_swage_pmstn') { // 하수펌프장 const drtwPumpCode = DRTW_SEWAGE_PUMP_USE_CODES.find(code => code.text === '오수펌프장'); if (drtwPumpCode && featureData.values_.usg_cd.trim() === drtwPumpCode.val) { setIsDrtwSewagePump(true); setHeadlist(DrtwSewagePumpCol); } else { setIsDrtwSewagePump(false); setHeadlist(ExclnSewagePumpCol); } setLayerSpecificNm(featureData.values_.fclt_mng_no); result = '하수펌프장'; } else if (lyrTyNm === 'tb_il_swage_prcs_fclt') { result = '하수처리시설'; setHeadlist(SwtrmtFcltCol); setLayerSpecificNm(featureData.values_.swtrmt_fclt_cd); } else if (lyrTyNm === 'tb_ms_swage_prcs_zone') { result = '하수처리구역'; setHeadlist(SwtrmtPrcsZoneCol); setLayerSpecificNm(featureData.values_.swtrmt_fclt_cd); } else if (lyrTyNm === 'tb_ms_stofcbr') { result = '우수토실'; setHeadlist(stofcbrCol); setLayerSpecificNm(featureData.values_.fclt_mng_no); } else if (lyrTyNm === 'om_dt_untrt_swg_rain') { result = '중점우수토실'; setHeadlist(untrtSwgRainCol1); setHeadlist2(untrtSwgRainCol2); setLayerSpecificNm(featureData.values_.manage_no); } else result = featureLayer.get('lyrNm'); } else { // SearchModal 클릭 이벤트 setIsClicked(false); console.log('SearchModal data', featureData); const lyrTyNm = featureData.lyrTypeNm; if (featureData.lyrTypeNm === 'tb_ms_swage_ppl') { result = '하수관로'; setHeadlist(MsSwagePplCol2) setLayerSpecificNm(featureData.swtrmtFcltCd); } else if (featureData.lyrTypeNm === 'tb_ms_swage_mhl') { result = '하수맨홀'; setHeadlist(MsSwageMhlCol2) setLayerSpecificNm(featureData.fcltMngNo); } else if (featureData.lyrTypeNm === 'tb_ms_swage_pmstn') { // 하수펌프장 const drtwPumpCode = DRTW_SEWAGE_PUMP_USE_CODES.find(code => code.text === '오수펌프장'); if (drtwPumpCode && featureData.usgCd.trim() === drtwPumpCode.val) { console.log('오수펌프장'); setIsDrtwSewagePump(false); setHeadlist(ExclnSewagePumpCol2) } else { console.log('빗물펌프장'); setIsDrtwSewagePump(true); setHeadlist(DrtwSewagePumpCol2) } setLayerSpecificNm(featureData.fcltMngNo); result = '하수펌프장'; } else if (featureData.lyrTypeNm === 'tb_il_swage_prcs_fclt') { result = '하수처리시설'; setHeadlist(SwtrmtFcltCol2) setLayerSpecificNm(featureData.swtrmtFcltCd); } else if (featureData.lyrTypeNm === 'tb_ms_swage_prcs_zone') { result = '하수처리구역'; setHeadlist(SwtrmtPrcsZoneCol2); setLayerSpecificNm(featureData.swtrmtFcltCd); } else if (featureData.lyrTypeNm === 'tb_ms_stofcbr') { result = '우수토실'; setHeadlist(stofcbrCol2) setLayerSpecificNm(featureData.fcltMngNo); } // else if (featureData.lyrTypeNm === 'om_dt_untrt_swg_rain') result = '중점우수토실'; } return result; }; useEffect(() => { const fetchData = async () => { if (!featureId) return; try { const selectedLayerName = getSelectedLayers(); // 레이어 이름 가져오기 setLayerNm(selectedLayerName); // 상태 업데이트 let data; if (featureData['ol_uid']) data = featureData.values_; // Gis 레이어 클릭 이벤트일 때 else data = featureData; // SearchModal 클릭 이벤트일 때 // 하수맨홀인 경우 용도코드를 텍스트로 변환 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 '하수관로': setButtonChk(true) // ✅ codeMapper 사용하여 API 결과도 변환 setTableData(codeMapper({ layerName: selectedLayerName, data: { ...formattedData } })); break; case '하수맨홀': setButtonChk(true) // ✅ codeMapper 사용하여 API 결과도 변환 setTableData(codeMapper({ layerName: selectedLayerName, data: { ...formattedData } })); break; case '하수펌프장': setButtonChk(true) setTableData(codeMapper({ layerName: selectedLayerName, data: { ...formattedData } })); break; case '하수처리시설': setButtonChk(false) break; case '하수처리구역': setButtonChk(false) break; case '우수토실': setButtonChk(true) setIsMainSsc(false) break; case '중점우수토실': setButtonChk(false) setIsMainSsc(true) // 🎯 processedData도 포맷팅하여 설정 const processedFormattedData = formatDisplayData(processedData); setFetchData([processedFormattedData]) setTableData(processedFormattedData); // setIsLoading(false); // 기본 렌더링 완료 setTableData(codeMapper({ layerName: selectedLayerName, data: { ...processedFormattedData } })); setChmbrXcnts(data.chmbr_xcnts); setChmbrYdnts(data.chmbr_ydnts); break; default: break; } // 자체입력정보 API 엔드포인트 선택 let apiEndpoint = ''; const fcltMngNo = featureData?.values_?.fclt_mng_no || null; const mngInstCd = featureData?.values_?.mng_inst_cd || null; if (selectedLayerName === '하수관로') apiEndpoint = `v1/fcltppl/${fcltMngNo}/${mngInstCd}`; else if (selectedLayerName === '우수토실') apiEndpoint = `v1/fcltstofcbr/${fcltMngNo}/${mngInstCd}`; else if (selectedLayerName === '하수펌프장') apiEndpoint = `v1/fcltpump/${fcltMngNo}/${mngInstCd}`; else if (selectedLayerName === '하수맨홀') apiEndpoint = `v1/fcltmhl/${fcltMngNo}/${mngInstCd}`; // API에서 상세 데이터 가져오기 if (apiEndpoint) { try { console.log(`API 호출: ${apiEndpoint}`); const result = await getData(apiEndpoint); if (result) { console.log('API 데이터 로드 성공:', result); // ✅ codeMapper 사용하여 API 결과도 변환 const processedApiData = codeMapper({ layerName: selectedLayerName, data: { ...result, ...tableData } }); setFetchData(processedApiData); } } catch (apiError) { console.error('API 데이터 로딩 중 오류:', apiError); } } } catch (error) { console.error('데이터 로딩 중 오류:', error); } }; fetchData(); }, [featureId, processedData]); // 저장 시 모달 띄우기 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['fcltMngNo'] = featureData.values_.fclt_mng_no.toString() || null; bodyData['mngInstCd'] = featureData.values_.mng_inst_cd.toString() || 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;