Merge remote-tracking branch 'origin/iipbs/sn/dev'
This commit is contained in:
@@ -28,20 +28,20 @@ export const MsSwagePplCol = [
|
||||
// { id: 'lyrTypeNm', title: '레이어타입명' },
|
||||
]
|
||||
export const MsSwagePplCol2 = [
|
||||
{ id: 'rowNumber', title: '일련번호' },
|
||||
{ id: 'fcltMngNo', title: '시설 관리번호' },
|
||||
{ id: 'instMngNo', title: '기관 관리번호' },
|
||||
{ id: 'rowNumber', title: '일련\n번호' },
|
||||
{ id: 'fcltMngNo', title: '시설\n관리번호' },
|
||||
{ id: 'instMngNo', title: '기관\n관리번호' },
|
||||
{ id: 'instlYmd', title: '설치일자' },
|
||||
// { id: 'mapshtNo', title: '도엽번호' },
|
||||
{ id: 'pdmt', title: '관경(mm)' },
|
||||
{ id: 'prlg', title: '연장(m)' },
|
||||
{ id: 'avgGrdn', title: '평균구배(m/m)' },
|
||||
{ id: 'tmptDpth', title: '시점깊이(m)' },
|
||||
{ id: 'tmptMhlMngNo', title: '시점맨홀 관리번호' },
|
||||
{ id: 'scendDpth', title: '종점깊이(m)' },
|
||||
{ id: 'scendMhlMngNo', title: '종점맨홀 관리번호' },
|
||||
{ id: 'vrtcLen', title: '세로길이(m)' },
|
||||
{ id: 'wdthLen', title: '가로길이(m)' },
|
||||
{ id: 'pdmt', title: '관경\n(mm)' },
|
||||
{ id: 'prlg', title: '연장\n(m)' },
|
||||
{ id: 'avgGrdn', title: '평균구배\n(m/m)' },
|
||||
{ id: 'tmptDpth', title: '시점깊이\n(m)' },
|
||||
{ id: 'tmptMhlMngNo', title: '시점맨홀\n관리번호' },
|
||||
{ id: 'scendDpth', title: '종점깊이\n(m)' },
|
||||
{ id: 'scendMhlMngNo', title: '종점맨홀\n관리번호' },
|
||||
{ id: 'vrtcLen', title: '세로길이\n(m)' },
|
||||
{ id: 'wdthLen', title: '가로길이\n(m)' },
|
||||
// { id: 'fcltyShpCd', title: '시설물형태코드' },
|
||||
// { id: 'fid', title: 'FID' },
|
||||
// { id: 'ftreSmbolCd', title: '지형지물부호코드' },
|
||||
@@ -297,9 +297,9 @@ export const SwtrmtFcltCol = [
|
||||
// { id: 'obsrvnSptCd', title: '관측지점코드' },
|
||||
];
|
||||
export const SwtrmtFcltCol2 = [
|
||||
{ id: 'rowNumber', title: '일련번호' },
|
||||
{ id: 'swtrmtFcltNm', title: '하수처리시설명' },
|
||||
{ id: 'fcltCpct', title: '시설용량(㎥/d)' },
|
||||
{ id: 'rowNumber', title: '일련\n번호' },
|
||||
{ id: 'swtrmtFcltNm', title: '하수처리\n시설명' },
|
||||
{ id: 'fcltCpct', title: '시설\n용량\n(㎥/d)' },
|
||||
{ id: 'rgnExpln', title: '지역설명' },
|
||||
// { id: 'cmcnYmd', title: '준공일자' },
|
||||
{ id: 'oprtngStrtYmd', title: '가동개시일자' },
|
||||
@@ -311,7 +311,7 @@ export const SwtrmtFcltCol2 = [
|
||||
// { id: 'sggNm', title: '시군구명' },
|
||||
// { id: 'sareaCd', title: '권역코드' },
|
||||
{ id: 'sareaNm', title: '권역명' },
|
||||
{ id: 'lrgeSareaNm', title: '대권역명' },
|
||||
// { id: 'lrgeSareaNm', title: '대권역명' },
|
||||
{ id: 'rvrNm', title: '하천명' },
|
||||
// { id: 'addr', title: '주소' },
|
||||
// { id: 'dtlAddr', title: '상세주소' },
|
||||
@@ -320,19 +320,19 @@ export const SwtrmtFcltCol2 = [
|
||||
{ id: 'dschgWtstNm', title: '방류수계명' },
|
||||
// { id: 'pllnArea', title: '부지면적(m²)' },
|
||||
// { id: 'mngRprtvBzentyNm', title: '관리대행업체명' },
|
||||
{ id: 'swtrmtPpltnCnt', title: '하수처리인구수(인)' },
|
||||
{ id: 'swtrmtPpltnCnt', title: '하수\n처리\n인구수\n(인)' },
|
||||
// { id: 'prcsZoneAreaSum', title: '처리구역면적합계(m²)' },
|
||||
// { id: 'xcrd', title: 'X좌표' },
|
||||
// { id: 'ycrd', title: 'Y좌표' },
|
||||
// { id: 'oprtngSttsCd', title: '가동상태코드' },
|
||||
{ id: 'rprsMsrcCn', title: '대표공법내용' },
|
||||
{ id: 'rprsMsrcCn', title: '대표\n공법\n내용' },
|
||||
// { id: 'sttyCrtrBod', title: '법정기준생물화학적산소요구량(mg/L)' },
|
||||
// { id: 'sttyCrtrToc', title: '법정기준TOC(mg/L)' },
|
||||
// { id: 'sttyCrtrSs', title: '법정기준SS(mg/L)' },
|
||||
// { id: 'sttyCrtrTn', title: '법정기준총질소(mg/L)' },
|
||||
// { id: 'sttyCrtrTph', title: '법정기준총인(mg/L)' },
|
||||
// { id: 'sttyCrtrClbclCnt', title: '법정기준대장균수(군수/100mL)' },
|
||||
{ id: 'bsnNm', title: '유역명' },
|
||||
// { id: 'bsnNm', title: '유역명' },
|
||||
// { id: 'obsrvnSptCd', title: '관측지점코드' },
|
||||
];
|
||||
|
||||
@@ -353,9 +353,9 @@ export const SwtrmtPrcsZoneCol2 = [
|
||||
{ id: 'swtrmtZoneNm', title: '하수처리구역명' },
|
||||
// { id: 'swtrmt_fclt_cd', title: '하수처리시설코드' },
|
||||
// { id: 'ctpv_cd', title: '시도코드' },
|
||||
{ id: 'ctpvNm', title: '시도명' },
|
||||
{ id: 'ctpvNm', title: '시도' },
|
||||
// { id: 'sgg_cd', title: '시군구코드' },
|
||||
{ id: 'sggNm', title: '시군구명' },
|
||||
{ id: 'sggNm', title: '시군구' },
|
||||
{ id: 'swtrmtFcltNm', title: '하수처리시설명' },
|
||||
];
|
||||
|
||||
|
||||
@@ -12,20 +12,114 @@ const inputColumn = [
|
||||
{ id: "swtrmtZoneCd", title: "처리구역", type: "input" },
|
||||
];
|
||||
|
||||
const Ssc = ({ featureData, isMainSsc, rainMeasureData, onSaveClick }: {
|
||||
const Ssc = ({ featureData, isMainSsc, chmbrXcnts, chmbrYdnts, onSaveClick }: {
|
||||
featureData: any,
|
||||
isMainSsc?: boolean,
|
||||
rainMeasureData?: any,
|
||||
chmbrXcnts?: string,
|
||||
chmbrYdnts?: string,
|
||||
onSaveClick?: () => void
|
||||
}) => {
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [isDataLoaded, setIsDataLoaded] = useState(false);
|
||||
const [formData, setFormData] = useState<any>({});
|
||||
const [mntrngsData, setMntrngsData] = useState<any[]>([]); // 수량/수질 측정 정보
|
||||
const [rainMeasureData, setRainMeasureData] = useState<any>({}); // 강우, 측정 정보
|
||||
const [mntrngsData, setMntrngsData] = useState<any[]>([]); // 수량/수질측정 정보
|
||||
const [totalCount, setTotalCount] = useState<number>(0);
|
||||
const [totalDetailCount, setTotalDetailCount] = useState<number>(0);
|
||||
const [selectedRowIndex, setSelectedRowIndex] = useState<number>(-1);
|
||||
const [curPage, setCurPage] = useState<number>(1);
|
||||
const [curDetailPage, setCurDetailPage] = useState<number>(1);
|
||||
const [isResetPage, setIsResetPage] = useState<boolean>(false);
|
||||
const [isResetDetailPage, setIsResetDetailPage] = useState<boolean>(false);
|
||||
const [isResetSelection, setIsResetSelection] = useState<boolean>(false);
|
||||
const [curIdx, setCurIdx] = useState<number>(0);
|
||||
|
||||
// console.log('featureData data received:', featureData); // 추가 데이터 확인용
|
||||
// console.log('rainMeasureData received:', rainMeasureData); // 추가 데이터 확인용
|
||||
// 강우, 측정 정보 API 호출 함수
|
||||
const fetchRainMeasureData = async (chmbrXcnts: string, chmbrYdnts: string) => {
|
||||
if (!chmbrXcnts || !chmbrYdnts) {
|
||||
console.warn('추가 데이터 호출 실패: 필수 매개변수 누락', { chmbrXcnts, chmbrYdnts });
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
const queryParams = new URLSearchParams({
|
||||
chmbrXcnts: chmbrXcnts,
|
||||
chmbrYdnts: chmbrYdnts,
|
||||
page: `${curPage - 1}`,
|
||||
size: '3',
|
||||
});
|
||||
|
||||
console.log('queryParams', queryParams.toString());
|
||||
console.log(`추가 데이터 API 호출 시작: v1/onsemiro/getSwgRainsByGeomety?${queryParams.toString()}`);
|
||||
|
||||
const result = await getData(`v1/onsemiro/getSwgRainsByGeomety?${queryParams.toString()}`);
|
||||
|
||||
console.log('추가 데이터 API 호출 성공:', result);
|
||||
|
||||
const processedDataArray: any[] = result.content.map((data: any) => {
|
||||
// 🎯 formatDisplayData로 기본 포맷팅 적용
|
||||
const formattedItem = formatDisplayData(data);
|
||||
|
||||
// 🎯 추가 데이터 조합
|
||||
return {
|
||||
...formattedItem,
|
||||
flwmtrCombined: `${data.flwmtrMesureTpEtc || '-'} / ${data.flwmtrKnd || '-'}`,
|
||||
};
|
||||
});
|
||||
setRainMeasureData(processedDataArray);
|
||||
setTotalCount(result?.totalElements || 0);
|
||||
} catch (error) {
|
||||
console.error('추가 데이터 로딩 실패:', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
// 수량/수질측정 정보 API 호출 함수
|
||||
const fetchMntrngsData = async (adstDstrCd: string, manageNo: string) => {
|
||||
if (!adstDstrCd || !manageNo) {
|
||||
console.warn('추가 데이터 호출 실패: 필수 매개변수 누락', { adstDstrCd, manageNo });
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
const queryParams = new URLSearchParams({
|
||||
page: `${curDetailPage - 1}`,
|
||||
size: '3',
|
||||
});
|
||||
|
||||
console.log(`SSC 추가 데이터 API 호출 시작: v1/onsemiro/swgRain?${queryParams.toString()}`);
|
||||
|
||||
const result = await getData(`v1/onsemiro/swgRain/${adstDstrCd}/${manageNo}/mntrngs?${queryParams.toString()}`);
|
||||
|
||||
console.log('SSC 추가 데이터 API 호출 성공:', result);
|
||||
|
||||
// 각 아이템 전처리
|
||||
const processedDataArray = result.content.map((data: any) => {
|
||||
// 기본 포맷팅 적용
|
||||
const formattedItem = formatDisplayData(data);
|
||||
return {
|
||||
...formattedItem,
|
||||
};
|
||||
});
|
||||
|
||||
console.log('processedDataArray', processedDataArray);
|
||||
|
||||
setMntrngsData(processedDataArray);
|
||||
setTotalDetailCount(result?.totalElements || 0);
|
||||
} catch (error) {
|
||||
console.error('추가 데이터 로딩 실패:', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 🎯 추가 데이터는 별도 useEffect로 비동기 로딩
|
||||
useEffect(() => {
|
||||
// 강우/측정 정보 데이터 호출
|
||||
if (isMainSsc && chmbrXcnts && chmbrYdnts) {
|
||||
fetchRainMeasureData(chmbrXcnts, chmbrYdnts)
|
||||
}
|
||||
}, [chmbrXcnts, chmbrYdnts]);
|
||||
|
||||
const openModal = () => {
|
||||
setIsModalOpen(true);
|
||||
@@ -46,6 +140,19 @@ const Ssc = ({ featureData, isMainSsc, rainMeasureData, onSaveClick }: {
|
||||
}
|
||||
}, [featureData]);
|
||||
|
||||
// featureData가 변경될 때 formData 초기화
|
||||
useEffect(() => {
|
||||
// showTable이 true일 때만 fetch (최초 렌더 방지)
|
||||
setIsResetPage(false);
|
||||
setIsResetDetailPage(true);
|
||||
if (chmbrXcnts && chmbrYdnts) fetchRainMeasureData(chmbrXcnts, chmbrYdnts);
|
||||
}, [curPage]);
|
||||
|
||||
// 페이지 변경 시마다 데이터 fetch
|
||||
useEffect(() => {
|
||||
if (chmbrXcnts && chmbrYdnts) fetchMntrngsData(chmbrXcnts, chmbrYdnts);
|
||||
}, [curDetailPage]);
|
||||
|
||||
// 폼 데이터가 변경될 때 호출될 핸들러
|
||||
const handleFormDataChange = (newFormData: any) => {
|
||||
setFormData(newFormData);
|
||||
@@ -62,91 +169,39 @@ const Ssc = ({ featureData, isMainSsc, rainMeasureData, onSaveClick }: {
|
||||
// 테이블 셀 클릭 핸들러 추가
|
||||
const handleCellClick = async (index: number | undefined, headId: string) => {
|
||||
if (index !== undefined && rainMeasureData) {
|
||||
const data = await fetchMntrngsData(rainMeasureData[index].adstDstrCd, rainMeasureData[index].manageNo);
|
||||
|
||||
setMntrngsData(data);
|
||||
await fetchMntrngsData(rainMeasureData[index].adstDstrCd, rainMeasureData[index].manageNo);
|
||||
setSelectedRowIndex(index);
|
||||
}
|
||||
};
|
||||
|
||||
// 🎯 추가 데이터 API 호출 함수 (독립적으로 실행)
|
||||
const fetchMntrngsData = useCallback(async (adstDstrCd: string, manageNo: string) => {
|
||||
if (!adstDstrCd || !manageNo) {
|
||||
console.warn('추가 데이터 호출 실패: 필수 매개변수 누락', { adstDstrCd, manageNo });
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
const queryParams = new URLSearchParams({
|
||||
pageable: `{}`,
|
||||
});
|
||||
|
||||
console.log(`SSC 추가 데이터 API 호출 시작: v1/onsemiro/swgRain?${queryParams.toString()}`);
|
||||
|
||||
const result = await getData(`v1/onsemiro/swgRain/${adstDstrCd}/${manageNo}/mntrngs?${queryParams.toString()}`);
|
||||
|
||||
console.log('SSC 추가 데이터 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,
|
||||
};
|
||||
});
|
||||
|
||||
console.log('processedDataArray', processedDataArray);
|
||||
|
||||
return processedDataArray;
|
||||
} catch (error) {
|
||||
console.error('추가 데이터 로딩 실패:', error);
|
||||
return [];
|
||||
}
|
||||
}, []);
|
||||
|
||||
const renderModalBody = () => (
|
||||
<div className='grid grid-cols-1 gap-4 p-4'>
|
||||
{/* 강우정보 테이블 */}
|
||||
<UiTable
|
||||
headName='강우정보'
|
||||
tableData={Array.isArray(rainMeasureData) ? rainMeasureData : []}
|
||||
tableData={rainMeasureData}
|
||||
headlist={untrtSwgRainCol3}
|
||||
pageSize={10}
|
||||
total={Array.isArray(rainMeasureData) ? rainMeasureData.length : 0}
|
||||
pageSize={3}
|
||||
total={0}
|
||||
cellClick={handleCellClick}
|
||||
onPageChange={function (page: number): void {
|
||||
console.log('Rain data page change:', page);
|
||||
}}
|
||||
onPageChange={setCurPage}
|
||||
resetPageNo={isResetPage}
|
||||
resetSelection={isResetSelection}
|
||||
index={curIdx}
|
||||
/>
|
||||
|
||||
{/* 측정정보 테이블 */}
|
||||
<UiTable
|
||||
headName='측정정보'
|
||||
tableData={Array.isArray(rainMeasureData) ? rainMeasureData : []}
|
||||
tableData={rainMeasureData}
|
||||
headlist={untrtSwgRainCol4}
|
||||
pageSize={10}
|
||||
total={Array.isArray(rainMeasureData) ? rainMeasureData.length : 0}
|
||||
pageSize={3}
|
||||
total={totalCount}
|
||||
cellClick={handleCellClick}
|
||||
// onPageChange={setCurPage}
|
||||
onPageChange={function (page: number): void {
|
||||
console.log('Rain data page change:', page);
|
||||
}}
|
||||
resetPageNo={false}
|
||||
// index={curPage}
|
||||
onPageChange={setCurPage}
|
||||
resetPageNo={isResetPage}
|
||||
resetSelection={isResetSelection}
|
||||
index={curIdx}
|
||||
>
|
||||
{/* 커스텀 헤더 */}
|
||||
<TableRow>
|
||||
@@ -168,14 +223,12 @@ const Ssc = ({ featureData, isMainSsc, rainMeasureData, onSaveClick }: {
|
||||
{/* 수량/수질측정 정보 테이블 */}
|
||||
<UiTable
|
||||
headName='수량/수질측정 정보'
|
||||
tableData={Array.isArray(mntrngsData) ? mntrngsData : []}
|
||||
tableData={mntrngsData}
|
||||
headlist={untrtSwgRainCol5}
|
||||
pageSize={10}
|
||||
total={Array.isArray(mntrngsData) ? mntrngsData.length : 0}
|
||||
pageSize={3}
|
||||
total={totalDetailCount}
|
||||
cellClick={undefined}
|
||||
onPageChange={function (page: number): void {
|
||||
console.log('Quality data page change:', page);
|
||||
}}
|
||||
onPageChange={setCurDetailPage}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
+14
-90
@@ -5,13 +5,13 @@ 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, 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 "./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 { 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 "./components/common/codeMapper";
|
||||
import { codeMapper } from "../common/codeMapper";
|
||||
import { searchUpperPpls } from '@common/business_components/ui/map/Gis';
|
||||
import LoadingOverlay from '@/components/ui/LoadingBar';
|
||||
|
||||
@@ -33,9 +33,10 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
|
||||
// 🎯 InfilChart 및 RdiiChart 관련 상태 추가
|
||||
const { setIsOpen: setIsModalInfil } = useInfilChartModalStore();
|
||||
const { setIsOpen: setIsModalRdii } = useRdiiChartModalStore();
|
||||
const [curPage, setCurPage] = useState(1); // 현재 페이지 상태
|
||||
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 || "";
|
||||
@@ -263,18 +264,9 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
|
||||
data: { ...processedFormattedData }
|
||||
}));
|
||||
|
||||
// 강우/측정 정보 데이터 호출
|
||||
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([]);
|
||||
});
|
||||
}
|
||||
setChmbrXcnts(data.chmbr_xcnts);
|
||||
setChmbrYdnts(data.chmbr_ydnts);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -317,76 +309,6 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
|
||||
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([]);
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [layerNm, featureData?.values_, fetchRainMeasureData]);
|
||||
|
||||
// 저장 시 모달 띄우기
|
||||
const handleSaveClick = () => {
|
||||
setIsModalOpen(true); // 모달 열기
|
||||
@@ -555,8 +477,10 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void,
|
||||
featureData={fetchData}
|
||||
isMainSsc={isMainSsc}
|
||||
isDrtwSewagePump={isDrtwSewagePump}
|
||||
rainMeasureData={rainMeasureData}
|
||||
// rainMeasureData={rainMeasureData}
|
||||
onSaveClick={handleSaveClick}
|
||||
chmbrXcnts={chmbrXcnts}
|
||||
chmbrYdnts={chmbrYdnts}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
@@ -5,7 +5,8 @@ import { getData } from "../../components/lib/api";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import GisApp from "@common/business_components/ui/map/lib/gis.core";
|
||||
import SearchModal from "./searchModal/searchModal";
|
||||
import FeatureClickEventPopup from "./featureClickEventPopup";
|
||||
import FeatureClickEventPopup from "./components/popupComponent/featureClickEventPopup";
|
||||
import useStore from "../../store/useStore";
|
||||
import { SearchBar } from "./searchBar/searchBar";
|
||||
|
||||
// 타입 정의 추가
|
||||
@@ -39,6 +40,13 @@ const Map = () => {
|
||||
const [isOpen, setIsOpen] = useState(false); // 팝업 열기/닫기 상태
|
||||
const [isSearchModalOpen, setIsSearchModalOpen] = useState(false); // SearchModal 열림 상태
|
||||
const [featureData, setFeatureData] = useState(null); // 선택된 피쳐 데이터
|
||||
const { fetchCtpvData, fetchSggData } = useStore();
|
||||
|
||||
// 시도, 시군구 호출
|
||||
useEffect(() => {
|
||||
fetchCtpvData();
|
||||
fetchSggData();
|
||||
}, [fetchCtpvData, fetchSggData]);
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
|
||||
@@ -39,7 +39,9 @@ interface BasicTabProps {
|
||||
// setTableCount?: (count: number) => void;
|
||||
setBasicType: (type: string) => void;
|
||||
setCity: (city: number) => void;
|
||||
setCtpvName: (name: string) => void;
|
||||
setSgg: (sgg: number) => void;
|
||||
setSggName: (name: string) => void;
|
||||
setYearFilter: (filter: { start: string; end: string }) => void;
|
||||
setStart1: (value: string) => void;
|
||||
setStart2: (value: string) => void;
|
||||
@@ -68,7 +70,9 @@ const BasicTab: React.FC<BasicTabProps> = ({
|
||||
// setTableCount,
|
||||
setBasicType,
|
||||
setCity,
|
||||
setCtpvName,
|
||||
setSgg,
|
||||
setSggName,
|
||||
setYearFilter,
|
||||
setStart1,
|
||||
setStart2,
|
||||
@@ -78,7 +82,7 @@ const BasicTab: React.FC<BasicTabProps> = ({
|
||||
setVar2,
|
||||
}) => {
|
||||
return (
|
||||
<div className="relative border rounded-lg p-6 w-full h-[10vh]">
|
||||
<div className="relative border rounded-lg p-5 w-full h-[10vh]">
|
||||
{/* 구분 */}
|
||||
<div className="mb-3 flex items-center justify-between gap-4">
|
||||
<div className="flex items-center">
|
||||
@@ -124,12 +128,18 @@ const BasicTab: React.FC<BasicTabProps> = ({
|
||||
start2={start2}
|
||||
end1={end1}
|
||||
end2={end2}
|
||||
city={city}
|
||||
sgg={sgg}
|
||||
yearFilter={yearFilter}
|
||||
setVar1={setVar1}
|
||||
setStart1={setStart1}
|
||||
setStart2={setStart2}
|
||||
setEnd1={setEnd1}
|
||||
setEnd2={setEnd2}
|
||||
setCity={setCity}
|
||||
setCtpvName={setCtpvName}
|
||||
setSgg={setSgg}
|
||||
setSggName={setSggName}
|
||||
setYearFilter={setYearFilter}
|
||||
handleSearch={handleSearch}
|
||||
/>
|
||||
|
||||
@@ -111,7 +111,7 @@ const OperationTab: React.FC<OperationTabProps> = ({
|
||||
setYearFilter,
|
||||
}) => {
|
||||
return (
|
||||
<div className="relative flex flex-col border rounded-lg p-6 w-full h-[10vh]">
|
||||
<div className="relative flex flex-col border rounded-lg p-5 w-full h-[10vh]">
|
||||
<div className="flex items-center mb-3">
|
||||
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">업무구분</Label>
|
||||
<SelectBox
|
||||
|
||||
@@ -165,7 +165,7 @@ const ReportTab: React.FC<BasicTabProps> = ({ open }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="relative flex flex-col border rounded-lg p-6 w-full h-[10vh]">
|
||||
<div className="relative flex flex-col border rounded-lg p-5 w-full h-[10vh]">
|
||||
<div className="flex items-center mb-3">
|
||||
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">시도</Label>
|
||||
<SelectBox className="w-60 mr-8"
|
||||
|
||||
@@ -63,8 +63,10 @@ const SearchModal: React.FC<SearchModalProps> = ({
|
||||
const [isResetSelection, setIsResetSelection] = useState<boolean>(false);
|
||||
const [isResetDetailSelection, setIsResetDetailSelection] = useState<boolean>(false);
|
||||
const [detailBizId, setDetailBizId] = useState(0);
|
||||
const [city, setCity] = useState(0);
|
||||
const [sgg, setSgg] = useState(0);
|
||||
const [city, setCity] = useState<number>(0);
|
||||
const [ctpvName, setCtpvName] = useState<string>('');
|
||||
const [sgg, setSgg] = useState<number>(0);
|
||||
const [sggName, setSggName] = useState<string>('');
|
||||
const [ctpvCd, setCtpvCd] = useState('0'); // 하수정비기본계획 report
|
||||
const [sigungu, setSigungu] = useState('0'); // 하수정비기본계획 report
|
||||
const [gubun, setGubun] = useState(""); // 하수정비기본계획 report
|
||||
@@ -341,13 +343,17 @@ const SearchModal: React.FC<SearchModalProps> = ({
|
||||
cqlFilters.push(`fclt_cpct BETWEEN ${start1} AND ${end1}`);
|
||||
else if (start1) cqlFilters.push(`fclt_cpct >= ${start1}`);
|
||||
else if (end1) cqlFilters.push(`fclt_cpct <= ${end1}`);
|
||||
// 처리구역 면적
|
||||
if (start2 && end2)
|
||||
cqlFilters.push(`prcsZoneAreaSum BETWEEN ${start2} AND ${end2}`);
|
||||
else if (start2) cqlFilters.push(`prcsZoneAreaSum >= ${start2}`);
|
||||
else if (end2) cqlFilters.push(`prcsZoneAreaSum <= ${end2}`);
|
||||
// 하수처리시설명
|
||||
if (var1) cqlFilters.push(`swtrmt_fclt_nm ILIKE '%${var1}%'`);
|
||||
|
||||
// 시도
|
||||
if (ctpvName) cqlFilters.push(`ctpv_nm ILIKE '%${ctpvName}%'`);
|
||||
if (sggName) cqlFilters.push(`sgg_nm ILIKE '%${sggName}%'`);
|
||||
// // 처리구역 면적
|
||||
// if (start2 && end2)
|
||||
// cqlFilters.push(`prcsZoneAreaSum BETWEEN ${start2} AND ${end2}`);
|
||||
// else if (start2) cqlFilters.push(`prcsZoneAreaSum >= ${start2}`);
|
||||
// else if (end2) cqlFilters.push(`prcsZoneAreaSum <= ${end2}`);
|
||||
// // 하수처리시설명
|
||||
// if (var1) cqlFilters.push(`swtrmt_fclt_nm ILIKE '%${var1}%'`);
|
||||
return cqlFilters;
|
||||
};
|
||||
// 하수처리구역용 CQL 필터 생성
|
||||
@@ -575,7 +581,9 @@ const SearchModal: React.FC<SearchModalProps> = ({
|
||||
handleSearch={handleSearch}
|
||||
setBasicType={setBasicType}
|
||||
setCity={setCity}
|
||||
setCtpvName={setCtpvName}
|
||||
setSgg={setSgg}
|
||||
setSggName={setSggName}
|
||||
setYearFilter={setYearFilter}
|
||||
setStart1={setStart1}
|
||||
setStart2={setStart2}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// 하수처리시설
|
||||
|
||||
import React from 'react';
|
||||
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
|
||||
import { Button, Input, Label } from '@common/components';
|
||||
import React from 'react';
|
||||
import { SidoSigunguSelectBox } from '@/components/ui/SidoSigunguSelectBox';
|
||||
|
||||
|
||||
interface SwagePrcsFcltProps {
|
||||
var1: string;
|
||||
@@ -10,36 +12,53 @@ interface SwagePrcsFcltProps {
|
||||
start2: string;
|
||||
end1: string;
|
||||
end2: string;
|
||||
city: number;
|
||||
sgg: number;
|
||||
yearFilter: { start: string; end: string };
|
||||
setVar1: (value: string) => void;
|
||||
setStart1: (value: string) => void;
|
||||
setStart2: (value: string) => void;
|
||||
setEnd1: (value: string) => void;
|
||||
setEnd2: (value: string) => void;
|
||||
setCity: (value: number) => void;
|
||||
setCtpvName: (name: string) => void;
|
||||
setSgg: (value: number) => void;
|
||||
setSggName: (name: string) => void;
|
||||
setYearFilter: (filter: { start: string; end: string }) => void;
|
||||
handleSearch: () => void;
|
||||
}
|
||||
|
||||
const SwagePrcsFclt: React.FC<SwagePrcsFcltProps> = ({
|
||||
var1,
|
||||
start1,
|
||||
start2,
|
||||
end1,
|
||||
end2,
|
||||
city,
|
||||
sgg,
|
||||
yearFilter,
|
||||
setVar1,
|
||||
setStart1,
|
||||
setStart2,
|
||||
setEnd1,
|
||||
setEnd2,
|
||||
setCity,
|
||||
setCtpvName,
|
||||
setSgg,
|
||||
setSggName,
|
||||
setYearFilter,
|
||||
handleSearch,
|
||||
}) => {
|
||||
|
||||
return (
|
||||
<div className="mb-3">
|
||||
{/* 가동개시일자 */}
|
||||
<div className="mb-2 flex items-center">
|
||||
<SidoSigunguSelectBox
|
||||
sido={city}
|
||||
sigungu={sgg}
|
||||
onSidoChange={(sidoId) => {
|
||||
setCity(sidoId);
|
||||
setSgg(0);
|
||||
}}
|
||||
onSigunguChange={setSgg}
|
||||
setCtpvName={setCtpvName}
|
||||
setSggName={setSggName}
|
||||
/>
|
||||
{/* 가동개시일자 */}
|
||||
<Label className="mr-2 w-auto text-xl text-gray-600">가동개시일자</Label>
|
||||
<YearRangeSelectBox
|
||||
start={yearFilter.start}
|
||||
@@ -89,57 +108,6 @@ const SwagePrcsFclt: React.FC<SwagePrcsFcltProps> = ({
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{/* 처리구역 면적 */}
|
||||
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">처리구역 면적(m²)</Label>
|
||||
<Input
|
||||
className="w-[60px] !text-xl placeholder:text-center"
|
||||
placeholder="입력"
|
||||
value={start2}
|
||||
onChange={(e) => {
|
||||
// 숫자만 입력 허용
|
||||
const val = e.target.value.replace(/[^0-9]/g, "");
|
||||
setStart2(val);
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault(); // Enter 키 기본 동작 방지
|
||||
handleSearch();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<span className="mx-2 text-xl font-semibold">~</span>
|
||||
<Input
|
||||
className="mr-8 w-[60px] !text-xl placeholder:text-center"
|
||||
placeholder="입력"
|
||||
value={end2}
|
||||
onChange={(e) => {
|
||||
// 숫자만 입력 허용
|
||||
const val = e.target.value.replace(/[^0-9]/g, "");
|
||||
setEnd2(val);
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault(); // Enter 키 기본 동작 방지
|
||||
handleSearch();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{/* 하수처리시설명 */}
|
||||
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">하수처리시설명</Label>
|
||||
<Input
|
||||
className="mr-8 w-[100px] !text-xl placeholder:text-center"
|
||||
placeholder="입력"
|
||||
value={var1}
|
||||
onChange={(e) => {
|
||||
setVar1(e.target.value);
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault(); // Enter 키 기본 동작 방지
|
||||
handleSearch();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{/* 조회 버튼 */}
|
||||
<div className="flex-1 flex justify-end">
|
||||
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
|
||||
|
||||
@@ -40,13 +40,13 @@ const swagePrcsZone: React.FC<swagePrcsZoneProps> = ({
|
||||
}}
|
||||
onSigunguChange={setSgg}
|
||||
/>
|
||||
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">하수처리구역명</Label>
|
||||
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">하수처리시설명</Label>
|
||||
<Input
|
||||
className="mr-8 w-[100px] !text-xl placeholder:text-center"
|
||||
className='!text-xl w-[120px] placeholder:text-center mr-8'
|
||||
placeholder="입력"
|
||||
value={var1}
|
||||
value={var2}
|
||||
onChange={(e) => {
|
||||
setVar1(e.target.value);
|
||||
setVar2(e.target.value);
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
@@ -55,13 +55,13 @@ const swagePrcsZone: React.FC<swagePrcsZoneProps> = ({
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">하수처리시설명</Label>
|
||||
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">하수처리구역명</Label>
|
||||
<Input
|
||||
className='!text-xl w-[120px] placeholder:text-center mr-8'
|
||||
className="mr-8 w-[100px] !text-xl placeholder:text-center"
|
||||
placeholder="입력"
|
||||
value={var2}
|
||||
value={var1}
|
||||
onChange={(e) => {
|
||||
setVar2(e.target.value);
|
||||
setVar1(e.target.value);
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
|
||||
@@ -47,7 +47,7 @@ interface ApiSelectOption {
|
||||
}
|
||||
|
||||
const IrSetting = () => {
|
||||
const [input1, setInput1] = useState('');
|
||||
const [input1, setInput1] = useState('0.8'); // 오수전환율 초기값
|
||||
const [input2, setInput2] = useState('');
|
||||
const [select1, setSelect1] = useState('0'); // 환경청코드
|
||||
const [select2, setSelect2] = useState('0'); // 시도코드
|
||||
@@ -387,10 +387,7 @@ const IrSetting = () => {
|
||||
accept={".xls, .xlsx, .xlsm, .xltx"}
|
||||
fileIdx={2} />
|
||||
</FormSection>
|
||||
<FormSection
|
||||
name='inputdate'
|
||||
form={form}
|
||||
titleNm='▷ 상수사용량 적용월'>
|
||||
<FormSection name='inputdate' form={form} titleNm='▷ 상수사용량 적용월'>
|
||||
{/* 연월 선택 라이브러리로 수정 필요 */}
|
||||
<DateMonthPicker
|
||||
field={{
|
||||
@@ -403,10 +400,7 @@ const IrSetting = () => {
|
||||
startYear={1900} // 시작 연도 설정
|
||||
/>
|
||||
</FormSection>
|
||||
<FormSection
|
||||
name='rtkSource'
|
||||
form={form}
|
||||
titleNm='▷ 오수전환율'>
|
||||
<FormSection name='rtkSource' form={form} titleNm='▷ 오수전환율'>
|
||||
<Input
|
||||
value={input1}
|
||||
onChange={(e) => {
|
||||
@@ -434,10 +428,7 @@ const IrSetting = () => {
|
||||
placeholder="예: 0.75"
|
||||
/>
|
||||
</FormSection>
|
||||
<FormSection
|
||||
name='analysis information'
|
||||
form={form}
|
||||
titleNm='▷ 분석 정보'>
|
||||
<FormSection name='analysis information' form={form} titleNm='▷ 분석 정보'>
|
||||
<Input
|
||||
value={input2}
|
||||
onChange={(e) => setInput2(e.target.value)}
|
||||
|
||||
@@ -85,7 +85,7 @@ export const deleteData = async (url: string, data?: object): Promise<any> => {
|
||||
return res;
|
||||
};
|
||||
|
||||
// RSONE DC API 호출
|
||||
// DC API 호출
|
||||
export const getDcData = async (url: string, data?: object): Promise<any> => {
|
||||
const res = await fetch('/dc-service' + url, {
|
||||
method: "GET",
|
||||
@@ -97,7 +97,7 @@ export const getDcData = async (url: string, data?: object): Promise<any> => {
|
||||
throw new Error('Failed to fetch data');
|
||||
};
|
||||
|
||||
// RSONE DC API 호출
|
||||
// CMS API 호출
|
||||
export const getCmsData = async (url: string, data?: object): Promise<any> => {
|
||||
console.log(url);
|
||||
const res = await fetch('/cms-service' + url, {
|
||||
@@ -110,6 +110,18 @@ export const getCmsData = async (url: string, data?: object): Promise<any> => {
|
||||
throw new Error('Failed to fetch data');
|
||||
};
|
||||
|
||||
// GeoServer API 호출
|
||||
export const getGeoData = async (url: string, data?: object): Promise<any> => {
|
||||
const res = await fetch('/geoserver' + url, {
|
||||
method: "GET",
|
||||
});
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
return data;
|
||||
}
|
||||
throw new Error('Failed to fetch data');
|
||||
};
|
||||
|
||||
export function getCookie(name: string) {
|
||||
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
|
||||
if (match && match[2]) {
|
||||
|
||||
@@ -103,8 +103,10 @@ export const formatDateString = (dateStr: string): string => {
|
||||
}
|
||||
|
||||
const year = cleanStr.substring(0, 4);
|
||||
const month = parseInt(cleanStr.substring(4, 6)); // parseInt로 앞의 0 제거
|
||||
const day = parseInt(cleanStr.substring(6, 8)); // parseInt로 앞의 0 제거
|
||||
const month = cleanStr.substring(4, 6); // parseInt로 앞의 0 제거
|
||||
// const month = parseInt(cleanStr.substring(4, 6)); // parseInt로 앞의 0 제거
|
||||
// const day = parseInt(cleanStr.substring(6, 8)); // parseInt로 앞의 0 제거
|
||||
const day = cleanStr.substring(6, 8); // parseInt로 앞의 0 제거
|
||||
|
||||
return `${year}년 ${month}월 ${day}일`;
|
||||
return `${year}-${month}-${day}`;
|
||||
};
|
||||
@@ -21,7 +21,7 @@ export const formatDisplayData = (data: { [key: string]: any }): { [key: string]
|
||||
if (/^\d{6}$/.test(dateStr)) {
|
||||
const year = dateStr.substring(0, 4);
|
||||
const month = parseInt(dateStr.substring(4, 6));
|
||||
formattedData[fieldId] = `${year}년 ${month}월`;
|
||||
formattedData[fieldId] = `${year}-${month}`;
|
||||
} else {
|
||||
formattedData[fieldId] = String(value);
|
||||
}
|
||||
@@ -45,9 +45,10 @@ export const formatDisplayData = (data: { [key: string]: any }): { [key: string]
|
||||
|
||||
// 🎯 undefined 체크 후 parseInt 적용
|
||||
if (year && month && day && hour && minute) {
|
||||
const formattedMonth = parseInt(month);
|
||||
const formattedDay = parseInt(day);
|
||||
formattedData[fieldId] = `${year}년 ${formattedMonth}월 ${formattedDay}일 ${hour}시 ${minute}분 ${second}초`;
|
||||
// const formattedMonth = parseInt(month);
|
||||
// const formattedDay = parseInt(day);
|
||||
// formattedData[fieldId] = `${year}-${formattedMonth}-${formattedDay} ${hour}:${minute}:${second}`;
|
||||
formattedData[fieldId] = `${year}-${month}-${day} ${hour}:${minute}:${second}`;
|
||||
} else {
|
||||
formattedData[fieldId] = String(value);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useMemo } from "react";
|
||||
import React, { useState, useMemo, useEffect } from "react";
|
||||
import { SelectBox } from '@common/business_components/ui'
|
||||
import { Label } from '@common/components';
|
||||
import useStore from '../../store/useStore';
|
||||
|
||||
interface Option {
|
||||
id: number;
|
||||
@@ -11,131 +12,35 @@ interface SidoSigunguSelectBoxProps {
|
||||
sido: number;
|
||||
sigungu: number;
|
||||
onSidoChange: (id: number) => void;
|
||||
setCtpvName?: (name: string) => void;
|
||||
onSigunguChange: (id: number) => void;
|
||||
setSggName?: (name: string) => void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const sidoList: { id: number, name: string }[] = [
|
||||
{ id: 0, name: '전체' },
|
||||
{ id: 26, name: '부산광역시' },
|
||||
{ id: 28, name: '인천광역시' },
|
||||
{ id: 30, name: '대전광역시' },
|
||||
{ id: 41, name: '경기도' },
|
||||
{ id: 42, name: '강원도' },
|
||||
{ id: 44, name: '충청남도' },
|
||||
{ id: 45, name: '전라북도' },
|
||||
{ id: 46, name: '전라남도' },
|
||||
{ id: 47, name: '경상북도' },
|
||||
{ id: 48, name: '경상남도' },
|
||||
];
|
||||
const sigunguMap: Record<number, { id: number; name: string }[]> = {
|
||||
26: [
|
||||
{ id: 0, name: '전체' },
|
||||
// ...부산산광역시의 시군구 추가
|
||||
],
|
||||
28: [
|
||||
{ id: 0, name: '전체' },
|
||||
// ...인천광역시의 시군구 추가
|
||||
],
|
||||
30: [
|
||||
{ id: 0, name: '전체' },
|
||||
// ...대전광역시의 시군구 추가
|
||||
],
|
||||
41: [
|
||||
{ id: 0, name: '전체' },
|
||||
{ id: 41820, name: '가평군' },
|
||||
{ id: 41550, name: '안성시' },
|
||||
{ id: 41830, name: '양평군' },
|
||||
{ id: 41670, name: '여주시' },
|
||||
{ id: 41500, name: '이천시' },
|
||||
{ id: 41430, name: '의왕시' },
|
||||
{ id: 41150, name: '의정부시' },
|
||||
{ id: 41480, name: '파주시' },
|
||||
{ id: 41650, name: '포천시' },
|
||||
// ...경기도의 시군구 추가
|
||||
],
|
||||
42: [
|
||||
{ id: 0, name: '전체' },
|
||||
{ id: 42170, name: '동해시' },
|
||||
{ id: 42110, name: '춘천시' },
|
||||
{ id: 42720, name: '홍천군' },
|
||||
// ...강원도의 시군구 추가
|
||||
],
|
||||
44: [
|
||||
{ id: 0, name: '전체' },
|
||||
{ id: 44770, name: '서천군' },
|
||||
// ...충청남도의 시군구 추가
|
||||
],
|
||||
45: [
|
||||
{ id: 0, name: '전체' },
|
||||
{ id: 45130, name: '군산시' },
|
||||
{ id: 45190, name: '남원시' },
|
||||
{ id: 45730, name: '무주군' },
|
||||
{ id: 45800, name: '부안군' },
|
||||
{ id: 45770, name: '순창군' },
|
||||
{ id: 45140, name: '익산시' },
|
||||
{ id: 45750, name: '임실군' },
|
||||
{ id: 45710, name: '완주군' },
|
||||
{ id: 45110, name: '전주시' },
|
||||
// ...전라북도의 시군구 추가
|
||||
],
|
||||
46: [
|
||||
{ id: 0, name: '전체' },
|
||||
{ id: 46810, name: "강진군" },
|
||||
{ id: 46770, name: "고흥군" },
|
||||
{ id: 46720, name: "곡성군" },
|
||||
{ id: 46730, name: "구례군" },
|
||||
{ id: 46230, name: "광양시" },
|
||||
{ id: 46170, name: "나주시" },
|
||||
{ id: 46110, name: "목포시" },
|
||||
{ id: 46840, name: "무안군" },
|
||||
{ id: 46150, name: "순천시" },
|
||||
{ id: 46910, name: "신안군" },
|
||||
{ id: 46130, name: "여수시" },
|
||||
{ id: 46890, name: "완도군" },
|
||||
// ...전라남도의 시군구 추가
|
||||
],
|
||||
47: [
|
||||
{ id: 0, name: '전체' },
|
||||
{ id: 47130, name: "경주시" },
|
||||
{ id: 47830, name: "고령군" },
|
||||
{ id: 47190, name: "구미시" },
|
||||
{ id: 47720, name: "군위군" },
|
||||
{ id: 47150, name: "김천시" },
|
||||
{ id: 47280, name: "문경시" },
|
||||
{ id: 47920, name: "봉화군" },
|
||||
{ id: 47250, name: "상주시" },
|
||||
{ id: 47770, name: "영덕군" },
|
||||
{ id: 47760, name: "영양군" },
|
||||
{ id: 47210, name: "영주시" },
|
||||
{ id: 47900, name: "예천군" },
|
||||
{ id: 47930, name: "울진군" },
|
||||
{ id: 47730, name: "의성군" },
|
||||
{ id: 47750, name: "청송군" },
|
||||
{ id: 47850, name: "칠곡군" },
|
||||
{ id: 47110, name: "포항시" },
|
||||
// ...경상북도의 시군구 추가
|
||||
],
|
||||
48: [
|
||||
{ id: 0, name: '전체' },
|
||||
{ id: 48310, name: "거제시" },
|
||||
{ id: 48250, name: "김해시" },
|
||||
{ id: 48270, name: "밀양시" },
|
||||
{ id: 48220, name: "통영시" },
|
||||
// ...경상남도의 시군구 추가
|
||||
],
|
||||
// ...나머지 시도별 시군구 추가
|
||||
};
|
||||
|
||||
export function SidoSigunguSelectBox({
|
||||
sido,
|
||||
sigungu,
|
||||
onSidoChange,
|
||||
setCtpvName,
|
||||
onSigunguChange,
|
||||
setSggName,
|
||||
className = "",
|
||||
}: SidoSigunguSelectBoxProps) {
|
||||
// 선택된 시도에 따라 시군구 리스트를 가져옴
|
||||
const sigunguList = useMemo(() => sigunguMap[sido] || [{ id: 0, name: '전체' }], [sido]);
|
||||
|
||||
const { ctpv, sgg} = useStore();
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
onSidoChange(0);
|
||||
onSigunguChange(0);
|
||||
if (setCtpvName && setSggName) {
|
||||
setCtpvName("");
|
||||
setSggName("");
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
|
||||
|
||||
return (
|
||||
<div className={`flex items-center justify-center ${className} mr-8`}>
|
||||
@@ -144,9 +49,16 @@ export function SidoSigunguSelectBox({
|
||||
className="w-60 mr-8"
|
||||
selectClass="rounded-lg bg-white"
|
||||
label=""
|
||||
selectArray={sidoList.map(opt => ({ val: opt.id, text: opt.name }))}
|
||||
selectArray={
|
||||
[{ val: 0, text: '전체' },
|
||||
...ctpv.map(opt => ({ val: opt.id, text: opt.name }))
|
||||
]
|
||||
}
|
||||
value={sido}
|
||||
onSelectValue={val => onSidoChange(Number(val))}
|
||||
onSelectValue={val => {
|
||||
onSidoChange(Number(val));
|
||||
if (setCtpvName) setCtpvName(ctpv.find(opt => Number(opt.id) === Number(val))?.name || "");
|
||||
}}
|
||||
selectContentClass="z-[101]"
|
||||
/>
|
||||
<Label className="text-xl text-gray-600 font-medium whitespace-nowrap mr-2">시군구</Label>
|
||||
@@ -154,9 +66,18 @@ export function SidoSigunguSelectBox({
|
||||
className="w-48"
|
||||
selectClass="w-48 rounded-lg bg-white truncate"
|
||||
label=""
|
||||
selectArray={sigunguList.map(opt => ({ val: opt.id, text: opt.name }))}
|
||||
selectArray={
|
||||
[{ val: 0, text: '전체' },
|
||||
...sgg
|
||||
.filter(opt => String(opt.id).slice(0, 2) === String(sido))
|
||||
.map(opt => ({ val: opt.id, text: opt.name }))
|
||||
]
|
||||
}
|
||||
value={sigungu}
|
||||
onSelectValue={val => onSigunguChange(Number(val))}
|
||||
onSelectValue={val => {
|
||||
onSigunguChange(Number(val))
|
||||
if (setSggName) setSggName(sgg.find(opt => Number(opt.id) === Number(val))?.name || "");
|
||||
}}
|
||||
selectContentClass="z-[101]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { useMemo } from "react";
|
||||
import { create } from "zustand";
|
||||
import { getGeoData } from "@/components/lib/api";
|
||||
import { get } from "http";
|
||||
|
||||
interface Option { id: number, name: string }
|
||||
|
||||
interface SnStoreState {
|
||||
ctpv: Option[];
|
||||
sgg: Option[];
|
||||
fetchCtpvData: () => Promise<void>;
|
||||
fetchSggData: () => Promise<void>;
|
||||
}
|
||||
|
||||
const useStore = create<SnStoreState>((set) => ({
|
||||
// Define your store state and actions here
|
||||
ctpv: [],
|
||||
sgg: [],
|
||||
fetchCtpvData: async () => {
|
||||
const ctpvData = await getGeoData('/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo%3Atb_ms_ctpv&outputFormat=application%2Fjson');
|
||||
const ctpvList: Option[] = ctpvData.features
|
||||
.map((feature: any) => ({
|
||||
id: feature.properties.mctpv_cd.trim(),
|
||||
name: feature.properties.mctpv_korn_nm
|
||||
}))
|
||||
.sort((a: Option, b: Option) => a.name.localeCompare(b.name, 'ko'));
|
||||
set({ ctpv: ctpvList });
|
||||
},
|
||||
fetchSggData: async () => {
|
||||
const sggData = await getGeoData('/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo%3Atb_ms_sgg&outputFormat=application%2Fjson');
|
||||
const sggList: Option[] = sggData.features
|
||||
.map((feature: any) => ({
|
||||
id: feature.properties.sgg_cd,
|
||||
name: feature.properties.sgg_korn_nm
|
||||
}))
|
||||
.sort((a: Option, b: Option) => a.name.localeCompare(b.name, 'ko'));
|
||||
set({ sgg: sggList });
|
||||
}
|
||||
}));
|
||||
|
||||
export default useStore;
|
||||
Reference in New Issue
Block a user