210 lines
9.2 KiB
TypeScript
210 lines
9.2 KiB
TypeScript
'use client'
|
|
import { getData, putData } 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 } from "react";
|
|
import { getLayerContentComponent } from "./components/common";
|
|
import { SwtrmtFcltCol, SwtrmtPrcsZoneCol, untrtSwgRainCol1, untrtSwgRainCol2 } from "./components/common/table";
|
|
// TODO:
|
|
const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, featureData: any }) => {
|
|
const { gisMap } = useGisContext() as unknown as { checkedLayerIds: React.MutableRefObject<number[]>; treeData: { lyrSn: number }[] | null; gisCore: any; gisMap: any; };
|
|
// const featureId = featureData.getId(); // 피처의 id 가져오기
|
|
const featureId = typeof featureData.getId === 'function'
|
|
? featureData.getId()
|
|
: featureData.fid;
|
|
const [layerNm, setLayerNm] = useState<string>(""); // 레이어 이름 상태
|
|
const [tableData, setTableData] = useState<any>(null); // 피처 데이터
|
|
const [mntrngsData, setMntrngsData] = useState(false); // 수량/수질 측정 정보
|
|
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<any>(); // api 호출여부
|
|
const contentRef = useRef<HTMLDivElement>(null);
|
|
const [isModalOpen, setIsModalOpen] = useState(false); // 모달 열기 상태
|
|
const [chkMainSsc, setChkMainSsc] = useState(false); // 중점우수토실 여부
|
|
|
|
// 피쳐데이터의 현재 레이어 이름 가져오는 함수
|
|
const getSelectedLayers = () => {
|
|
let result = null;
|
|
const layers = gisMap.getLayers().getArray(); // gisMap에서 모든 레이어 가져오기
|
|
let featureLayer: { get: (key: string) => any } = { get: (key: string) => null }; // 피처가 속한 레이어를 찾기 위한 변수
|
|
layers.forEach((layer: any) => {
|
|
const source = layer.getSource();
|
|
if (source && source.hasFeature && featureData
|
|
&& typeof featureData.getId === 'function' && source.hasFeature(featureData)) {
|
|
featureLayer = layer; // 피처가 속한 레이어 찾기
|
|
}
|
|
});
|
|
// 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 === 'om_dt_untrt_swg_rain') result = '중점우수토실';
|
|
}
|
|
else result = featureLayer.get('lyrNm');
|
|
|
|
return result;
|
|
// return featureLayer.get('lyrNm'); // 레이어 이름 출력
|
|
};
|
|
|
|
useEffect(() => {
|
|
const fetchData = async () => {
|
|
if (featureId) {
|
|
const selectedLayerName = getSelectedLayers(); // 레이어 이름 가져오기
|
|
setLayerNm(selectedLayerName); // 상태 업데이트
|
|
const layerId = featureId.split('.')[0]
|
|
let data = await getData(`v1/fclts/${featureId}?lyrTypeNm=${layerId}`);
|
|
setfetchData(data)
|
|
switch (selectedLayerName) {
|
|
case '하수처리시설':
|
|
setHeadlist(SwtrmtFcltCol);
|
|
setButtonChk(false)
|
|
break;
|
|
case '하수처리구역':
|
|
setHeadlist(SwtrmtPrcsZoneCol)
|
|
setButtonChk(false)
|
|
break;
|
|
case '중점우수토실':
|
|
setHeadlist(untrtSwgRainCol1)
|
|
setHeadlist2(untrtSwgRainCol2)
|
|
setButtonChk(false)
|
|
setChkMainSsc(true)
|
|
|
|
// 데이터 전처리: 합쳐진 필드 추가
|
|
data = data ? {
|
|
...data,
|
|
discharge_pipe_spec: `직경: ${data.pipe_diameter || '-'} / 높이: ${data.pipe_hg || '-'} / 길이: ${data.pipe_lt || '-'}`
|
|
} : {};
|
|
|
|
// 수량/수질측정 정보 데이터 호출
|
|
const additionalResponse = await getData(`v1/onsemiro/swgRain/${data.adst_dstr_cd}/${data.manage_no}/mntrngs`);
|
|
setMntrngsData(additionalResponse.content);
|
|
break;
|
|
case '우수토실':
|
|
setButtonChk(true)
|
|
break;
|
|
case '하수관로':
|
|
setButtonChk(true)
|
|
break;
|
|
case '오수펌프':
|
|
setButtonChk(true)
|
|
break;
|
|
case '빗물펌프':
|
|
setButtonChk(true)
|
|
break;
|
|
case '하수맨홀':
|
|
setButtonChk(true)
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
setTableData(data);
|
|
};
|
|
}
|
|
fetchData();
|
|
}, [featureId]);
|
|
|
|
// 저장 시 모달 띄우기
|
|
const handleSaveClick = () => {
|
|
setIsModalOpen(true); // 모달 열기
|
|
};
|
|
|
|
const handleModalSave = () => {
|
|
setIsModalOpen(false); // 모달 닫기
|
|
btnClickEvent(); // 저장 이벤트 실행
|
|
};
|
|
|
|
const handleModalClose = () => {
|
|
setIsModalOpen(false); // 모달 닫기
|
|
};
|
|
|
|
const btnClickEvent = async () => {
|
|
const bodyData: Record<string, any> = {}
|
|
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;
|
|
});
|
|
if (layerNm === '하수관로') bodyData['lyrTypeNm'] = 'tb_ms_swage_ppl'
|
|
else if (layerNm === '우수토실') bodyData['lyrTypeNm'] = 'tb_ms_stofcbr'
|
|
else if (layerNm === '오수펌프') bodyData['lyrTypeNm'] = 'tb_ms_swage_pmstn'
|
|
else if (layerNm === '빗물펌프') bodyData['lyrTypeNm'] = 'tb_ms_swage_pmstn'
|
|
else if (layerNm === '하수맨홀') bodyData['lyrTypeNm'] = 'tb_ms_swage_mnhl'
|
|
bodyData['fid'] = featureId
|
|
const data = await putData(`v1/fclts/${featureId}`, bodyData);
|
|
if (data.status == 200) {
|
|
alert('저장되었습니다')
|
|
setTableData(data)
|
|
setfetchData(data)
|
|
}
|
|
}
|
|
}
|
|
const ContentComponent = layerNm ? getLayerContentComponent(layerNm) : null;
|
|
return (
|
|
<div id="popup" className="absolute top-0 right-0 w-[350px] h-[calc(100vh-10rem)] bg-white border-r border-gray-300 flex flex-col overflow-hidden transition-all duration-300 z-[50]">
|
|
<div className="card-header bg-primary flex items-center justify-between p-4">
|
|
<div className="flex mx-3 flex-col">
|
|
<h3 className="text-2xl font-medium text-white text-label">{layerNm} 정보</h3>
|
|
{/* <div className="font-medium text-white text-label">(00구 00리 하수관로)</div> */}
|
|
</div>
|
|
<button
|
|
onClick={onClose}
|
|
className="text-white hover:text-gray-700 focus:outline-none"
|
|
aria-label="닫기"
|
|
>
|
|
✕
|
|
</button>
|
|
</div>
|
|
<div className="overflow-y-auto overflow-x-hidden flex-1" ref={contentRef}>
|
|
<VerticalTable
|
|
headName='LX 연계정보'
|
|
tableName1={layerNm === '중점우수토실' ? "측정지점" : undefined}
|
|
tableData={[tableData]}
|
|
headlist={headlist}
|
|
pageSize={20}
|
|
total={0}
|
|
children={undefined}
|
|
cellClick={undefined}
|
|
onPageChange={function (page: number): void {
|
|
throw new Error("Function not implemented.");
|
|
}}
|
|
// 두 번째 테이블 조건부 props
|
|
showSecondTable={layerNm === '중점우수토실' ? true : false}
|
|
tableName2={layerNm === '중점우수토실' ? "시설현황" : undefined}
|
|
tableData2={layerNm === '중점우수토실' && tableData ? [tableData] : []}
|
|
headlist2={layerNm === '중점우수토실' ? headlist2 : undefined}
|
|
pageSize2={20}
|
|
total2={0}
|
|
isEditable2={buttonChk}
|
|
/>
|
|
<div className="w-full mx-5 flex items-center justify-end space-x-2">
|
|
{buttonChk ? <Button onClick={handleSaveClick} className="px-4 mr-5 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700">
|
|
저장
|
|
</Button> : null}
|
|
</div>
|
|
<Modal isModalOpen={isModalOpen} title="자체입력정보 저장" setIsModalOpen={setIsModalOpen} closeModal={handleModalClose} saveModal={handleModalSave}><div className="text-lg">정보를 저장하시겠습니까?</div></Modal>
|
|
{ContentComponent &&
|
|
<ContentComponent
|
|
featureData={fetchData}
|
|
chkMainSsc={chkMainSsc}
|
|
additionalData={mntrngsData}
|
|
/>
|
|
}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
export default FeatureClickEventPopup; |