From ae0384af83a1306c90c965f59bfb97d39c649ae9 Mon Sep 17 00:00:00 2001 From: swcho Date: Tue, 15 Jul 2025 15:38:42 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=83=81=EC=84=B8=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=A4=91=EB=B6=84=EB=A5=98=20?= =?UTF-8?q?=ED=91=9C=EC=8B=9C,=20=EA=B4=80=EB=A6=AC=EB=B2=88=ED=98=B8=20?= =?UTF-8?q?=ED=91=9C=EC=8B=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../map/components/common/codeMapper.tsx | 155 ++++++++++++++++++ .../map/featureClickEventPopup.tsx | 138 ++++++++-------- 2 files changed, 229 insertions(+), 64 deletions(-) create mode 100644 apps/sn/app/(map-layout)/map/components/common/codeMapper.tsx diff --git a/apps/sn/app/(map-layout)/map/components/common/codeMapper.tsx b/apps/sn/app/(map-layout)/map/components/common/codeMapper.tsx new file mode 100644 index 000000000..61a11c8a8 --- /dev/null +++ b/apps/sn/app/(map-layout)/map/components/common/codeMapper.tsx @@ -0,0 +1,155 @@ +import { MS_SWAGE_PPL_USE_CODES, MS_SWAGE_PPL_CODES, MS_SWAGE_MHL_CODES, MS_SWAGE_MHL_USE_CODES, DRTW_SEWAGE_PUMP_USE_CODES } from './table'; + +interface CodeMapperProps { + layerName: string; + data: any; +} + +/** + * 레이어별 코드 변환 함수 + * @param layerName - 레이어 이름 + * @param data - 변환할 데이터 객체 + * @returns 변환된 데이터 객체 + */ +export const codeMapper = ({ layerName, data }: CodeMapperProps): any => { + if (!data) return data; + + const processedData = { ...data }; + + switch (layerName) { + case '하수관로': + // usg_cd 값 변환 (용도코드) + if (processedData.usg_cd) { + const usageCodeItem = MS_SWAGE_PPL_USE_CODES.find( + code => code.val === processedData.usg_cd.trim() + ); + if (usageCodeItem) { + processedData.usg_cd = usageCodeItem.text; + } + } + + // mqlt_cd 값 변환 (재질코드) + if (processedData.mqlt_cd) { + const materialCodeItem = MS_SWAGE_PPL_CODES.find( + code => code.val === processedData.mqlt_cd.trim() + ); + if (materialCodeItem) { + processedData.mqlt_cd = materialCodeItem.text; + } + } + break; + + case '하수맨홀': + // usg_cd 값 변환 (용도코드) + if (processedData.usg_cd) { + const usageCodeItem = MS_SWAGE_MHL_USE_CODES.find( + code => code.val === processedData.usg_cd.trim() + ); + if (usageCodeItem) { + processedData.usg_cd = usageCodeItem.text; + } + } + + // 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; + } + } + break; + + case '하수펌프장': + // usg_cd 값 변환 (용도코드) + if (processedData.usg_cd) { + const usageCodeItem = DRTW_SEWAGE_PUMP_USE_CODES.find( + code => code.val === processedData.usg_cd.trim() + ); + if (usageCodeItem) { + processedData.usg_cd = usageCodeItem.text; + } + } + break; + + case '우수토실': + // prrtymngYn 값 변환 (중점여부) + if (processedData.prrtymngYn) { + if (processedData.prrtymngYn === 'Y') { + processedData.prrtymngYn = '중점우수토실'; + } else if (processedData.prrtymngYn === 'N') { + processedData.prrtymngYn = '우수토실'; + } + } + break; + case '중점우수토실': + if (processedData.manage_no) { + processedData.mqlt_cd = processedData.manage_no; + } + break; + + default: + // 다른 레이어는 변환하지 않음 + break; + } + + return processedData; +}; + +/** + * 저장 시 코드 역변환 함수 (한글 → 코드) + * @param layerName - 레이어 이름 + * @param data - 역변환할 데이터 객체 + * @returns 역변환된 데이터 객체 + */ +export const reverseCodeMapper = ({ layerName, data }: CodeMapperProps): any => { + if (!data) return data; + + const processedData = { ...data }; + + switch (layerName) { + case '하수맨홀': + // mqlt_cd 값 역변환 (텍스트 → 코드) + if (processedData.mqlt_cd && typeof processedData.mqlt_cd === 'string') { + const materialCodeItem = MS_SWAGE_MHL_CODES.find( + code => code.text === processedData.mqlt_cd.trim() + ); + if (materialCodeItem) { + processedData.mqlt_cd = materialCodeItem.val; + } + } + break; + + case '우수토실': + // prrtymngYn 값 역변환 (텍스트 → Y/N) + if (processedData.prrtymngYn) { + if (processedData.prrtymngYn === '중점우수토실') { + processedData.prrtymngYn = 'Y'; + } else if (processedData.prrtymngYn === '우수토실') { + processedData.prrtymngYn = 'N'; + } + } + break; + + case '하수펌프장': + // usg_cd 값 역변환 (텍스트 → 코드) + if (processedData.usg_cd && typeof processedData.usg_cd === 'string') { + const usageCodeItem = DRTW_SEWAGE_PUMP_USE_CODES.find( + code => code.text === processedData.usg_cd.trim() + ); + if (usageCodeItem) { + processedData.usg_cd = usageCodeItem.val; + } + } + break; + + default: + break; + } + + return processedData; +}; + +// 기본 내보내기 +export default { codeMapper, reverseCodeMapper }; \ No newline at end of file diff --git a/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx b/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx index e2cfa0115..036b358bf 100644 --- a/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx +++ b/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx @@ -11,18 +11,20 @@ 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'; +import { codeMapper } from "./components/common/codeMapper"; // 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 [layerSpecificNm, setLayerSpecificNm] = 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 [fetchData, setFetchData] = useState(); // api 호출여부 const contentRef = useRef(null); const [isModalOpen, setIsModalOpen] = useState(false); // 모달 열기 상태 const [isMainSsc, setIsMainSsc] = useState(false); // 중점우수토실 여부 @@ -133,10 +135,47 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, // 🎯 기본 데이터 포맷팅 const formattedData = formatDisplayData(data); - setfetchData(formattedData); + setLayerSpecificNm(featureData.values_.fclt_mng_no); + setFetchData(formattedData); setTableData(formattedData); switch (selectedLayerName) { + case '하수관로': + setHeadlist(MsSwagePplCol) + setButtonChk(true) + + // ✅ codeMapper 사용하여 API 결과도 변환 + setTableData(codeMapper({ + layerName: selectedLayerName, + data: { ...formattedData } + })); + // setFetchData(mappedData); + // setTableData(mappedData); + break; + case '하수맨홀': + setHeadlist(MsSwageMhlCol) + setButtonChk(true) + + // ✅ codeMapper 사용하여 API 결과도 변환 + setTableData(codeMapper({ + layerName: selectedLayerName, + data: { ...formattedData } + })); + // setFetchData(mappedData); + // setTableData(mappedData); + break; + case '하수펌프장': + setHeadlist(ExclnSewagePumpCol) + setButtonChk(true) + + setTableData(codeMapper({ + layerName: selectedLayerName, + data: { ...formattedData } + })); + setLayerSpecificNm(tableData.mqlt_cd); + // setFetchData(mappedData); + // setTableData(mappedData); + break; case '하수처리시설': setHeadlist(SwtrmtFcltCol); setButtonChk(false) @@ -145,6 +184,11 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, setHeadlist(SwtrmtPrcsZoneCol) setButtonChk(false) break; + case '우수토실': + setHeadlist(stofcbrCol) + setButtonChk(true) + setIsMainSsc(false) + break; case '중점우수토실': setHeadlist(untrtSwgRainCol1) setHeadlist2(untrtSwgRainCol2) @@ -153,51 +197,34 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, // 🎯 processedData도 포맷팅하여 설정 const processedFormattedData = formatDisplayData(processedData); - setfetchData([processedFormattedData]) + setFetchData([processedFormattedData]) setTableData(processedFormattedData); // setIsLoading(false); // 기본 렌더링 완료 + setTableData(codeMapper({ + layerName: selectedLayerName, + data: { ...processedFormattedData } + })); + setLayerSpecificNm(tableData.mqlt_cd); + // 강우/측정 정보 데이터 호출 - if (data?.chmbr_xcnts && data?.chmbr_ydnts) { - fetchRainMeasureData(data.chmbr_xcnts, data.chmbr_ydnts) + if (tableData?.chmbr_xcnts && tableData?.chmbr_ydnts) { + fetchRainMeasureData(tableData.chmbr_xcnts, tableData.chmbr_ydnts) .then(response => { console.log('additionalResponse', response); setRainMeasureData(response || []); }) .catch(error => { console.error('추가 데이터 로딩 실패:', error); - setRainMeasureData(false); + setRainMeasureData([]); }); } 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 엔드포인트 선택 + // 자체입력정보 API 엔드포인트 선택 let apiEndpoint = ''; const getFeatureId = featureId.toString().split('.').pop() || null; if (selectedLayerName === '하수관로') apiEndpoint = `v1/fcltppl/${getFeatureId}`; @@ -214,35 +241,13 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, if (result) { console.log('API 데이터 로드 성공:', result); - // 하수맨홀인 경우 용도코드를 텍스트로 변환 - if (selectedLayerName === '하수맨홀') { - const processedData = { ...result }; + // ✅ codeMapper 사용하여 API 결과도 변환 + const processedApiData = codeMapper({ + layerName: selectedLayerName, + data: { ...result, ...tableData } + }); - // 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); - } + setFetchData(processedApiData); } } catch (apiError) { console.error('API 데이터 로딩 중 오류:', apiError); @@ -256,7 +261,7 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, fetchData(); }, [featureId, processedData]); - // 🎯 추가 데이터 API 호출 함수 (독립적으로 실행) + // 🎯 추가 데이터 API 호출 함수 const fetchRainMeasureData = useCallback(async (chmbrXcnts: string, chmbrYdnts: string) => { if (!chmbrXcnts || !chmbrYdnts) { console.warn('추가 데이터 호출 실패: 필수 매개변수 누락', { chmbrXcnts, chmbrYdnts }); @@ -320,7 +325,7 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, }) .catch(error => { console.error('추가 데이터 최종 로딩 실패:', error); - setRainMeasureData(false); + setRainMeasureData([]); }); } } @@ -394,7 +399,7 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, if (result) { alert('저장되었습니다'); - setfetchData(result.data || result); + setFetchData(result.data || result); } else { alert('저장에 실패했습니다'); console.error('API 응답 오류:', result); @@ -413,8 +418,13 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,