Merge remote-tracking branch 'origin/iipbs/sn/dev' into iipbs/sn/search
This commit is contained in:
@@ -7,20 +7,24 @@ interface ModalProps {
|
||||
title?: string;
|
||||
children: React.ReactNode;
|
||||
closeModal: () => void;
|
||||
saveModal?: () => void
|
||||
}
|
||||
|
||||
const Modal: React.FC<ModalProps> = ({ isModalOpen, setIsModalOpen, title, children, closeModal }) => {
|
||||
const Modal: React.FC<ModalProps> = ({ isModalOpen, setIsModalOpen, title, children, closeModal,saveModal }) => {
|
||||
return (
|
||||
<Dialog open={isModalOpen} onOpenChange={setIsModalOpen}>
|
||||
<DialogOverlay className='z-[200]'/>
|
||||
<DialogContent className="w-auto max-w-[1200px] min-w-[400px] min-h-[300px] h-auto max-h-[450px] overflow-auto z-[1000]">
|
||||
<DialogOverlay className='z-[200]' />
|
||||
<DialogContent className="w-auto max-w-[1200px] min-w-[400px] min-h-[150px] h-auto max-h-[450px] overflow-auto z-[1000]">
|
||||
{title ? <DialogHeader>
|
||||
<DialogTitle>{title}</DialogTitle>
|
||||
</DialogHeader> : null}
|
||||
{children}
|
||||
<DialogFooter>
|
||||
<DialogClose>
|
||||
<div className='flex justify-end gap-2'>
|
||||
{saveModal ? <button className="px-4 py-2 bg-primary text-white rounded" onClick={saveModal}>저장</button> : null}
|
||||
<button className="px-4 py-2 bg-gray-600 text-white rounded" onClick={closeModal}>닫기</button>
|
||||
</div>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
|
||||
@@ -17,9 +17,10 @@ type LayerContentMap = {
|
||||
const layerContentMap: LayerContentMap = {
|
||||
// TODO: gis데이터 추가되면 추가 작업 필요
|
||||
"하수처리시설": {
|
||||
component: StormWaterPump,
|
||||
component: SwtrmtFclt,
|
||||
},
|
||||
"하수처리구역": { },
|
||||
"우수토실":{component: Ssc,},
|
||||
"중점우수토실":{component: Ssc,},
|
||||
"하수관로":{component: MsSwagePpl,},
|
||||
"하수맨홀":{component: smh,},
|
||||
|
||||
@@ -5,7 +5,7 @@ import { UiTable } from '@common/business_components/ui';
|
||||
import { Button, TableHead, TableRow } from '@common/components/ui';
|
||||
import React from 'react'
|
||||
const inputColumn = [
|
||||
{ id: "guyeok", title: "처리구역", type: "select", options: ["구역1", "구역2"] },
|
||||
{ id: "swtrmt_zone_cd", title: "처리구역", type: "input" },
|
||||
{ id: "mainSscYn", title: "중점우수토실 대상여부", type: "select", options: ['Y', 'N'] },
|
||||
];
|
||||
const headlist = [
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { VerticalTable } from '@/components/ui/verticalTable';
|
||||
import React from 'react'
|
||||
const inputColumn = [
|
||||
{ id: "guyeok", title: "처리구역", type: "select", options: ["구역1", "구역2"] },
|
||||
{ id: "bungu", title: "배수분구", type: "input" },
|
||||
{ id: "swtrmt_zone_cd", title: "처리구역", type: "select", options: ["구역1", "구역2"] },
|
||||
{ id: "mltv_dtdv_nm", title: "배수분구", type: "input" },
|
||||
{ id: "freq", title: "설계빈도", type: "input" },
|
||||
]
|
||||
// 오수펌프
|
||||
|
||||
@@ -6,6 +6,7 @@ import { SwtrmtFcltCol, SwtrmtPrcsZoneCol } from "./components/common/table";
|
||||
import { useGisContext } from "@common/business_components/ui/map/Gis";
|
||||
import { getData, putData } from "@/components/lib/api";
|
||||
import { getLayerContentComponent } from "./components/common";
|
||||
import Modal from "@/components/ui/modal";
|
||||
// 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; };
|
||||
@@ -19,6 +20,7 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
|
||||
const [buttonChk, setButtonChk] = useState(true)
|
||||
const [fetchData, setfetchData] = useState<any>(); // api 호출여부
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false); // 모달 열기 상태
|
||||
// 피쳐데이터의 현재 레이어 이름 가져오는 함수
|
||||
const getSelectedLayers = () => {
|
||||
let result = null;
|
||||
@@ -46,8 +48,8 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
|
||||
if (featureId) {
|
||||
const selectedLayerName = getSelectedLayers(); // 레이어 이름 가져오기
|
||||
setLayerNm(selectedLayerName); // 상태 업데이트
|
||||
|
||||
const data = await getData(`v1/fclts/${featureId}`);
|
||||
const layerId = featureId.split('.')[0]
|
||||
const data = await getData(`v1/fclts/${featureId}?lyrTypeNm=${layerId}`);
|
||||
setfetchData(data)
|
||||
switch (selectedLayerName) {
|
||||
case '하수처리시설':
|
||||
@@ -73,6 +75,9 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
|
||||
case '빗물펌프':
|
||||
setButtonChk(true)
|
||||
break;
|
||||
case '하수맨홀':
|
||||
setButtonChk(true)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -81,34 +86,46 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
|
||||
}
|
||||
fetchData();
|
||||
}, [featureId]);
|
||||
// TODO: api 호출작업 필요(사용자 입력부분)
|
||||
// 저장 시 모달 띄우기
|
||||
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) => {
|
||||
bodyData[select.id] = select.value;
|
||||
const camelCaseId = toCamelCase(select.id);
|
||||
bodyData[camelCaseId] = select.value;
|
||||
});
|
||||
// input 태그의 값 가져오기
|
||||
inputElements.forEach((input) => {
|
||||
bodyData[input.id] = input.value;
|
||||
const camelCaseId = toCamelCase(input.id);
|
||||
bodyData[camelCaseId] = input.value;
|
||||
});
|
||||
if (layerNm === '하수관로' || 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'
|
||||
}
|
||||
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){
|
||||
console.log('저장완료', data);
|
||||
if(data.status==200){
|
||||
alert('저장되었습니다')
|
||||
setTableData(data)
|
||||
setfetchData(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,10 +150,11 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
|
||||
throw new Error("Function not implemented.");
|
||||
}}></VerticalTable>
|
||||
<div className="w-full mx-5 flex items-center justify-end space-x-2">
|
||||
{buttonChk ? <Button onClick={btnClickEvent} className="px-4 mr-5 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700">
|
||||
{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} />}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,6 +11,37 @@ const Page = () => {
|
||||
const [selectedDate, setSelectedDate] = useState(new Date())
|
||||
const [company, setCompany] = useState('')
|
||||
const [pjNm, setpjNm] = useState('')
|
||||
|
||||
|
||||
const handleDownload = async () => {
|
||||
try {
|
||||
const response = await fetch('/sn/attach-service/api/v1/download/6066b08c-2a55-438c-b8ff-2aed9739a0c6', {
|
||||
method: 'GET',
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('파일 다운로드 실패');
|
||||
}
|
||||
|
||||
const blob = await response.blob();
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
|
||||
// 다운로드를 트리거할 가짜 <a> 태그 생성
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = 'test.jpg'; // 원하는 파일명 지정
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
// 메모리 해제
|
||||
link.remove();
|
||||
window.URL.revokeObjectURL(url);
|
||||
} catch (error) {
|
||||
console.error('다운로드 중 오류 발생:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<ContentLayout title='도시침수 예방사업'>
|
||||
<SearchDiv>
|
||||
@@ -53,7 +84,7 @@ const Page = () => {
|
||||
<h3 className="text-2xl font-medium">사업정보 등록현황</h3>
|
||||
<div>
|
||||
<Button className="px-4 py-2 !mr-[1.2rem] bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700" size="sm" >파일 다운로드</Button>
|
||||
<Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700 !mr-[1.2rem]" size="sm" >삭제</Button>
|
||||
<Button className="px-4 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700 !mr-[1.2rem]" size="sm" onClick={handleDownload} >삭제</Button>
|
||||
</div>
|
||||
</div>
|
||||
<UiTable headName='' tableData={tableData} headlist={tableHeadlist} pageSize={10} total={20} children={undefined} cellClick={() => { }} onPageChange={function (page: number): void {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import type { NextConfig } from "next";
|
||||
import webpack from "webpack";
|
||||
|
||||
const geoserverUrl = process.env.NEXT_PUBLIC_GEOSERVER_URL?.replace(/\/$/, '') ?? '';
|
||||
const geoServerUrl = process.env.NEXT_PUBLIC_GEOSERVER_URL?.replace(/\/$/, '') ?? '';
|
||||
const cnServerUrl = process.env.NEXT_PUBLIC_SERVER_API_URL?.replace(/\/$/, '') ?? '';
|
||||
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
basePath: "/sn",
|
||||
@@ -46,7 +48,11 @@ const nextConfig: NextConfig = {
|
||||
return [
|
||||
{
|
||||
source: '/geoserver/:hasudo*',
|
||||
destination: `${geoserverUrl}/:hasudo*`,
|
||||
destination: `${geoServerUrl}/:hasudo*`,
|
||||
},
|
||||
{
|
||||
source: '/attach-service/:path*',
|
||||
destination: `${cnServerUrl}/attach-service/:path*`,
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user