Files
frontend/apps/sn/app/(map-layout)/map/searchModal/searchModal.tsx
T

828 lines
30 KiB
TypeScript

import React, { useEffect, useState, useMemo } from 'react';
import axios from 'axios';
import { UiModal, UiTable, SelectBox, UITab } from '@common/business_components/ui';
import { Button, Input, Label } from '@common/components';
import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox';
import { SidoSigunguSelectBox } from '@/components/ui/SidoSigunguSelectBox';
import { MsSwagePplCol2, SwtrmtFcltCol2, SwtrmtPrcsZoneCol2, MsSwageMhlCol2, ExclnSewagePumpCol2, stofcbrCol2 } from '../components/common/table';
import LoadingOverlay from '@/components/ui/LoadingBar';
//import { useDcTree, flattenFolders, useSggCd, useCityCd } from './components/searchModalReportApi';
import { useDcTree, flattenFolders, useSggCd, useCityCd, addFileName, getFileDownload } from '../components/searchModalReportApi';
import { useCityCdStore, type SelectDataType } from '../commonStore';
import { MS_SWAGE_PPL_USE_CODES, MS_SWAGE_PPL_CODES, MS_SWAGE_MHL_USE_CODES } from '../components/common/table';
// import { useBizByFcltStore } from "../../../store/StoreProvider";
import { getData } from "@/components/lib/api";
import BasicTab, { BASIC_TYPES } from './basicTab';
import OperationTab, { WORK_TYPES, BIZ_SE_CD, BIZ_TY_CD, BIZ_TY_CD_SELECT_ARRAY } from './operationTab';
const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}`;
// 탭
const TABS = [
{ val: "basic", text: "기본정보" },
{ val: "operation", text: "운영정보" },
{ val: "report", text: "하수도정비기본계획보고서" },
];
// 운영정보 - 사업 현황
const operationTableHeadlist = [
{ id: "bizNm", title: "사업명" },
{ id: "flfmtBgngYmd", title: "수행시작일자" },
{ id: "flfmtEndYmd", title: "수행종료일자" },
{ id: "flfmtYr", title: "수행년도" },
{ id: "bizTyCd", title: "사업유형" },
{ id: "bizAmt", title: "사업금액" },
];
// 운영정보 - 보수 및 갱신 결과표
const operationMaintenanceTableHeadlist = [
{ id: "fcltMngNo", title: "관리번호" },
{ id: "usgCd", title: "용도" },
{ id: "mqltCd", title: "재질" },
{ id: "pdmt", title: "관경(mm)" },
{ id: "prlg", title: "연장(m)" },
{ id: "instlYmd", title: "설치일자" },
// { id: "instlYmd", title: "사업구분" },
];
// 운영정보 - 청소 및 준설 결과표
const operationCleaningTableHeadlist = [
{ id: "fcltMngNo", title: "관리번호" },
{ id: "usgCd", title: "용도" },
{ id: "mqltCd", title: "재질" },
{ id: "pdmt", title: "관경(mm)" },
{ id: "prlg", title: "연장(m)" },
{ id: "instlYmd", title: "설치일자" },
];
// 운영정보 - 점검 및 진단 결과표
const operationInspectionTableHeadlist = [
{ id: "fcltMngNo", title: "관리번호" },
{ id: "usgCd", title: "용도" },
{ id: "mqltCd", title: "재질" },
{ id: "pdmt", title: "관경(mm)" },
{ id: "prlg", title: "연장(m)" },
{ id: "instlYmd", title: "설치일자" },
{ id: "strct_stat_grd", title: "구조적 상태등급" },
{ id: "oper_stat_grd", title: "운영적 상태등급" },
];
// 하수도정비 기본계획 보고서
const reportTableHeadlist = [
{ id: "no", title: "NO" },
{ id: "sido", title: "시도" },
{ id: "sigungu", title: "시군구" },
{ id: "approvalYear", title: "승인년도" },
{ id: "plantZoneGugun", title: "구분" },
{ id: "reportGubun", title: "보고서구분" },
{ id: "fileName", title: "파일명" },
{ id: "regDate", title: "등록일자" },
];
// 날짜 조합 함수
const getDateString = (
year: string,
month: string,
day: string,
defaultDate: string,
) => {
if (!year && !month && !day) return defaultDate;
const y = year || defaultDate.slice(0, 4);
const m = month || defaultDate.slice(4, 6);
const d = day || defaultDate.slice(6, 8);
return `${y}${m}${d}`;
};
interface SearchModalProps {
open: boolean;
onOpenChange: (open: boolean) => void;
onFeatureSelect: (row: any) => void;
}
const SearchModal: React.FC<SearchModalProps> = ({
open,
onOpenChange,
onFeatureSelect,
}) => {
const [activeTab, setActiveTab] = useState(TABS[0]?.val ?? "basic");
const [basicType, setBasicType] = useState(BASIC_TYPES[0]?.val ?? "");
const [workType, setWorkType] = useState(WORK_TYPES[0]?.val ?? "");
const [showTable, setShowTable] = useState(false);
const [tableData, setTableData] = useState<any[]>([]);
const [detailTableData, setDetailTableData] = useState<any[]>([]);
const [tableCount, setTableCount] = useState(0);
const [detailTableCount, setDetailTableCount] = useState(0);
const [curPage, setCurPage] = useState(1);
const [detailCurPage, setDetailCurPage] = useState(1);
const [detailBizId, setDetailBizId] = useState(0);
const [city, setCity] = useState(0);
const [sgg, setSgg] = useState(0);
const [ctpvCd, setCtpvCd] = useState('0');
const [sigungu, setSigungu] = useState('0');
//const [swageProcessingZone, set처리구역] = useState("");
const [gubun, setGubun] = useState(""); // 하수정비기본계획 report
// 날짜 상태 선언
const [start1, setStart1] = useState("");
const [start2, setStart2] = useState("");
const [end1, setEnd1] = useState("");
const [end2, setEnd2] = useState("");
const [var1, setVar1] = useState("");
const [var2, setVar2] = useState("");
const [var3, setVar3] = useState("");
const [var4, setVar4] = useState("");
// 시작, 종료
const [yearFilter, setYearFilter] = useState({ start: "", end: "" });
// const [fromDate, setFromDate] = useState(() => { const date = new Date(); date.setDate(date.getDate() - 7); return date })
const [toDate, setToDate] = useState(new Date())
const [filteredSiguns, setFilteredSiguns] = useState<SelectDataType[]>([{ val: '0', text: '전체', sido: '0' }]);
// const [dynamicHeadlist, setDynamicHeadlist] = useState<{ id: string, title: string }[]>([]);
// const [dynamicHeadlist2, setDynamicHeadlist2] = useState<{ id: string, title: string }[]>([]);
// 로딩바
const [isLoading, setIsLoading] = useState(false);
const [isDetailLoading, setIsDetailLoading] = useState(false);
const sidos = useCityCd();
const siguns = useSggCd();
const reportOriginData = useDcTree(""); //:Folder[]
// 오늘 날짜 구하기
const today = new Date();
const todayYear = today.getFullYear().toString();
const todayMonth = (today.getMonth() + 1).toString().padStart(2, "0");
const todayDate = today.getDate().toString().padStart(2, "0");
// const isDateInRanges = (date: Date) => {
// const standYear = parseInt(fromDate.getFullYear().toString());
// const dateRanges = [];
// dateRanges.push({
// start: new Date(standYear, 0, 1),
// end: new Date(standYear, 11, 31)
// });
// return dateRanges.some(range => {
// const start = new Date(range.start);
// const end = new Date(range.end);
// return date >= start && date <= end;
// });
// };
const dynamicHeadlist: { id: string, title: string }[] = useMemo(() => {
if (activeTab === 'basic') {
if (basicType === 'tb_ms_swage_ppl') return MsSwagePplCol2;
if (basicType === 'tb_il_swage_prcs_fclt') return SwtrmtFcltCol2;
if (basicType === 'tb_ms_swage_prcs_zone') return SwtrmtPrcsZoneCol2;
if (basicType === 'tb_ms_swage_mhl') return MsSwageMhlCol2;
if (basicType === 'tb_ms_swage_pmstn') return ExclnSewagePumpCol2;
if (basicType === 'tb_ms_stofcbr') return stofcbrCol2;
return [];
}
if (activeTab === 'operation') return operationTableHeadlist;
if (activeTab === 'report') return reportTableHeadlist;
return [];
}, [activeTab, basicType, workType]);
const dynamicHeadlist2 = useMemo(() => {
if (activeTab === 'operation') {
if (workType === '200') return operationMaintenanceTableHeadlist;
if (workType === '201') return operationMaintenanceTableHeadlist;
if (workType === '204') return operationMaintenanceTableHeadlist;
if (workType === '100') return operationCleaningTableHeadlist;
if (workType === '203') return operationInspectionTableHeadlist;
}
return [];
}, [activeTab, workType]);
useEffect(() => {
// filterParams 초기화
setStart1("");
setStart2("");
setEnd1("");
setEnd2("");
setVar1("");
setVar2("");
setVar3("");
setVar4("");
setCity(0);
setSgg(0);
setCtpvCd('0');
setSigungu('0');
setYearFilter({
start: "",
end: "",
});
setShowTable(false);
setTableCount(0);
setTableData([]);
// queryParams는 fetchFilteredData 내에서 매번 새로 생성되므로 별도 상태 초기화는 필요 없음
}, [activeTab, basicType, open]);
useEffect(() => {
setActiveTab(TABS[0]?.val ?? "basic");
setBasicType(BASIC_TYPES[0]?.val ?? "");
setWorkType(WORK_TYPES[0]?.val ?? "");
setTableCount(0);
setTableData([]);
setDetailTableCount(0);
setDetailTableData([]);
}, [open]);
// 페이지 변경 시마다 데이터 fetch
useEffect(() => {
// showTable이 true일 때만 fetch (최초 렌더 방지)
if (showTable) fetchFilteredData();
}, [curPage]);
// 페이지 변경 시마다 데이터 fetch
useEffect(() => {
// showTable이 true일 때만 fetch (최초 렌더 방지)
if (showTable) handleOperationPageNation(Number(detailBizId));
}, [detailCurPage]);
// 검색 API 호출 함수
const fetchFilteredData = async () => {
setIsLoading(true); // 로딩 시작
try {
let cqlFilters: string[] = [];
if (activeTab === 'basic') {
const queryParams = new URLSearchParams({
lyrTypeNm: basicType,
page: `${curPage - 1}`,
size: '10',
sort: 'string',
});
console.log('basicType', basicType);
if (basicType === 'tb_ms_swage_prcs_zone') cqlFilters = zoneCqlFilters(); // 하수처리구역
else if (basicType === 'tb_il_swage_prcs_fclt') cqlFilters = facilityCqlFilters(); // 하수처리시설
else if (basicType === 'tb_ms_swage_ppl') cqlFilters = pplCqlFilters(); // 하수관로
else if (basicType === 'tb_ms_swage_mhl') cqlFilters = mhCqlFilters(); // 하수맨홀
else if (basicType === 'tb_ms_swage_pmstn') cqlFilters = psmtnCqlFilters(); // 하수펌프장
else if (basicType === 'tb_ms_stofcbr') cqlFilters = otflCqlFilters(); // 우수토실
if (cqlFilters.length > 0) queryParams.append('cqlFiter', cqlFilters.join(' and '));
console.log('API URL:', `${API_URL}/v1/fclts?${queryParams.toString()}`);
const res = await axios.get(`${API_URL}/v1/fclts?${queryParams.toString()}`);
console.log('필터링된 API 결과(개수):', res.data.count);
console.log('필터링된 API 결과(데이터):', res.data.data);
setTableData(res.data.data || []);
setTableCount(res.data.count || []);
console.log('tableCount 상태 업데이트 후:', res.data.count); // tableCount 로그 추가
} else if (activeTab === 'operation') {
const RequestDTO: Record<string, string> = {
page: `${curPage - 1}`,
size: '5',
};
if (var1) RequestDTO.bizNm = var1;
if (var2 != '0' && var2) RequestDTO.bizTyCd = var2;
// 수행기간 범위
const startDate = getDateString(
yearFilter.start,
'',
'',
"19000101",
);
const endDate = getDateString(
yearFilter.end,
'',
'',
`${todayYear}${todayMonth}${todayDate}`,
);
RequestDTO.fromflfmtEndYmd = startDate;
RequestDTO.toflfmtEndYmd = endDate;
RequestDTO.bizSeCd = workType;
const params = new URLSearchParams(RequestDTO).toString();
console.log('API URL:', `/v1/bizInfo?${params}`);
const res = await getData(`v1/bizInfo?${params}`);
console.log('필터링된 API 결과(개수):', res.totalElements);
console.log('필터링된 API 결과(데이터):', res.content);
const mappedContent = (res.content || []).map((item: any) => {
const matched = BIZ_TY_CD.find(code => code.lwpoCd === item.bizTyCd);
return {
...item,
bizTyCd: matched ? matched.lwpoCdNm : item.bizTyCd,
};
});
setTableData(mappedContent || []);
setTableCount(res.totalElements || 0);
setDetailTableData([]);
setDetailTableCount(0);
} else if (activeTab === 'report') {
//const reportOriginData = await getDcTree('경기도');
const reportData = flattenFolders(reportOriginData);
let filterReportData = reportData;
if (ctpvCd !== "0") { // 시도검색
const sidoOption = sidos.find((n) => n.val === ctpvCd);
filterReportData = filterReportData.filter(item => item.sido === sidoOption?.text);
}
if (sigungu !== "0") { // 시군구검색
const sigunguOption = filteredSiguns.find((n) => n.val === sigungu);
filterReportData = filterReportData.filter(item => item.sigungu === sigunguOption?.text);
}
if (yearFilter.start != "" && yearFilter.end == "") //승인년도검색
filterReportData = filterReportData.filter(item => (item.approvalYear) ? item.approvalYear >= yearFilter.start + "년" : null);
if (yearFilter.start == "" && yearFilter.end != "")
filterReportData = filterReportData.filter(item => (item.approvalYear) ? item.approvalYear <= yearFilter.end + "년" : null);
if (yearFilter.start != "" && yearFilter.end != "") {
filterReportData = filterReportData.filter(item => {
return (item.approvalYear) ? item.approvalYear >= yearFilter.start + "년" && item.approvalYear <= yearFilter.end + "년" : null;
});
}
if (gubun !== "") { // 구분검색
filterReportData = filterReportData.filter(item => (item.plantZoneGugun) ? String(item.plantZoneGugun).includes(String(gubun)) : null);
}
console.log('report count:', filterReportData.length);
setTableCount(filterReportData.length || 0);
filterReportData = filterReportData.slice((curPage - 1) * 10, curPage * 10); // paging
filterReportData = filterReportData?.map((item, index) => ({ ...item, no: (curPage - 1) * 10 + index + 1 }));
//const fileList = await getDcFile("CLS20250530000041");
addFileName(filterReportData).then(data => {
filterReportData = data;
setTableData(filterReportData || []);
});
setTableData(filterReportData || []);
}
setShowTable(true);
} catch (err) {
console.error('API ERROR:', err);
setTableData([]);
} finally {
setIsLoading(false); // 로딩 종료
}
};
// 하수관로용 CQL 필터 생성
const pplCqlFilters = () => {
const cqlFilters: string[] = [];
// 추후 작성 예정
if (var1) cqlFilters.push(`usg_cd='${var1}'`);
if (var2) cqlFilters.push(`mqlt_cd='${var2}'`);
if (var3) cqlFilters.push(`pbadms_emd_cd='${var3}'`);
// 설치년도 범위
const startDate = getDateString(
yearFilter.start,
'',
'',
"19000101",
);
const endDate = getDateString(
yearFilter.end,
'',
'',
`${todayYear}${todayMonth}${todayDate}`,
);
cqlFilters.push(
`instl_ymd >= '${startDate}' and instl_ymd <= '${endDate}'`,
);
// 관경(mm) 범위
if (start1 && end1) cqlFilters.push(`pdmt BETWEEN ${start1} AND ${end1}`);
else if (start1) cqlFilters.push(`pdmt >= ${start1}`);
else if (end1) cqlFilters.push(`pdmt <= ${end1}`);
// 연장(m) 범위
if (start2 && end2) cqlFilters.push(`prlg BETWEEN ${start2} AND ${end2}`);
else if (start2) cqlFilters.push(`prlg >= ${start2}`);
else if (end2) cqlFilters.push(`prlg <= ${end2}`);
return cqlFilters;
};
// 하수처리시설용 CQL 필터 생성
const facilityCqlFilters = () => {
const cqlFilters: string[] = [];
// 가동개시일자 범위
const startDate = getDateString(
yearFilter.start,
'',
'',
"19000101",
);
const endDate = getDateString(
yearFilter.end,
'',
'',
`${todayYear}${todayMonth}${todayDate}`,
);
cqlFilters.push(
`oprtng_strt_ymd >= '${startDate}' and oprtng_strt_ymd <= '${endDate}'`,
);
// 시설용량 범위
if (start1 && end1)
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}%'`);
return cqlFilters;
};
// 하수처리구역용 CQL 필터 생성
const zoneCqlFilters = () => {
const cqlFilters: string[] = [];
if (city) cqlFilters.push(`ctpv_cd='${city}'`);
if (sgg) cqlFilters.push(`sgg_cd='${sgg}'`);
if (var1) cqlFilters.push(`swtrmt_zone_nm ILIKE '%${var1}%'`);
if (var2) cqlFilters.push(`swtrmt_fclt_nm ILIKE '%${var2}%'`);
return cqlFilters;
};
// 하수맨홀용 CQL 필터 생성
const mhCqlFilters = () => {
const cqlFilters: string[] = [];
// // 설치년도 범위
const startDate = getDateString(
yearFilter.start,
'',
'',
"19000101",
);
const endDate = getDateString(
yearFilter.end,
'',
'',
`${todayYear}${todayMonth}${todayDate}`,
);
cqlFilters.push(
`instl_ymd >= '${startDate}' and instl_ymd <= '${endDate}'`,
);
if (var1) cqlFilters.push(`usg_cd='${var1}'`);
// 구경(mm) 범위
if (start1 && end1) cqlFilters.push(`swage_mh_diam BETWEEN ${start1} AND ${end1}`);
else if (start1) cqlFilters.push(`swage_mh_diam >= ${start1}`);
else if (end1) cqlFilters.push(`swage_mh_diam <= ${end1}`);
return cqlFilters;
};
// 하수펌프장용 CQL 필터 생성
const psmtnCqlFilters = () => {
const cqlFilters: string[] = [];
// 설치년도 범위
const startDate = getDateString(
yearFilter.start,
'',
'',
"19000101",
);
const endDate = getDateString(
yearFilter.end,
'',
'',
`${todayYear}${todayMonth}${todayDate}`,
);
cqlFilters.push(
`instl_ymd >= '${startDate}' and instl_ymd <= '${endDate}'`,
);
// 일일처리용량 범위
if (start1 && end1)
cqlFilters.push(`daily_prcs_cpct BETWEEN ${start1} AND ${end1}`);
else if (start1) cqlFilters.push(`daily_prcs_cpct >= ${start1}`);
else if (end1) cqlFilters.push(`daily_prcs_cpct <= ${end1}`);
// 양수능력 범위
if (start2 && end2)
cqlFilters.push(`excln_wpmp_ablt BETWEEN ${start2} AND ${end2}`);
else if (start2) cqlFilters.push(`excln_wpmp_ablt >= ${start2}`);
else if (end2) cqlFilters.push(`excln_wpmp_ablt <= ${end2}`);
return cqlFilters;
};
// 우수토실용 CQL 필터 생성
const otflCqlFilters = () => {
const cqlFilters: string[] = [];
// 설치년도 범위
const startDate = getDateString(
yearFilter.start,
'',
'',
"19000101",
);
const endDate = getDateString(
yearFilter.end,
'',
'',
`${todayYear}${todayMonth}${todayDate}`,
);
cqlFilters.push(
`instl_ymd >= '${startDate}' and instl_ymd <= '${endDate}'`,
);
return cqlFilters;
};
// 조회 버튼 클릭 시 1페이지로 이동 및 데이터 초기화
const handleSearch = () => {
setCurPage(1); // 페이지를 1로 초기화
setDetailCurPage(1); // 페이지를 1로 초기화
fetchFilteredData();
setShowTable(true);
};
// 기본정보 테이블 cellClick 핸들러
const handleBasicCellClick = (index?: number | undefined, headId?: String) => {
if (typeof index === "number") {
onFeatureSelect(tableData[index % 10]); // 10은 page size 하드 코딩한 숫자
onOpenChange(false); // SearchModal 닫기
}
};
// 운영정보 테이블 cellClick 핸들러
const handleOperationCellClick = async (index?: number | undefined, headId?: String) => {
if (typeof index === "number") {
setIsDetailLoading(true);
setDetailBizId(tableData[index].bizId);
setDetailCurPage(1); // 상세 페이지 초기화
try {
const RequestDTO: Record<string, string> = {
page: `${detailCurPage - 1}`,
size: '5',
bizId: tableData[index % 5].bizId,
};
const res = await getData(`v1/bizInfo/fclts?${new URLSearchParams(RequestDTO).toString()}`);
console.log('운영정보 cellClick 데이터:', res);
console.log('운영정보 length:', res.data.length);
const mappedData = (res.data || []).map((item: any) => {
const usgCdObj = MS_SWAGE_PPL_USE_CODES.find(code => code.val === item.usgCd.trim());
const mqltCdObj = MS_SWAGE_PPL_CODES.find(code => code.val === item.mqltCd.trim());
return {
...item,
usgCd: usgCdObj ? usgCdObj.text : item.usgCd,
mqltCd: mqltCdObj ? mqltCdObj.text : item.mqltCd,
};
});
setDetailTableData(mappedData);
setDetailTableCount(res.count || 0);
} catch (error) {
console.error('운영정보 cellClick 에러:', error);
} finally {
setIsDetailLoading(false);
}
}
};
// 운영정보 디테일 테이블 페이지네이션 핸들러
const handleOperationPageNation = async (index?: number | undefined) => {
if (typeof index === "number") {
setIsDetailLoading(true);
try {
const RequestDTO: Record<string, string> = {
page: `${detailCurPage - 1}`,
size: '5',
bizId: String(detailBizId),
};
const res = await getData(`v1/bizInfo/fclts?${new URLSearchParams(RequestDTO).toString()}`);
console.log('운영정보 페이지네이션 데이터:', res);
console.log('운영정보 페이지네이션 length:', res.data.length);
const mappedData = (res.data || []).map((item: any) => {
const usgCdObj = MS_SWAGE_PPL_USE_CODES.find(code => code.val === item.usgCd.trim());
const mqltCdObj = MS_SWAGE_PPL_CODES.find(code => code.val === item.mqltCd.trim());
return {
...item,
usgCd: usgCdObj ? usgCdObj.text : item.usgCd,
mqltCd: mqltCdObj ? mqltCdObj.text : item.mqltCd,
};
});
setDetailTableData(mappedData);
setDetailTableCount(res.count || 0);
} catch (error) {
console.error('운영정보 페이지네이션 에러:', error);
} finally {
setIsDetailLoading(false);
}
}
};
// 하수도정비기본계획 테이블 cellClick 핸들러
const handleReportCellClick = (index: number | undefined, headId?: String) => {
console.log(index);
if (typeof index === "number" && tableData[index]) {
const reportData = tableData[index];
const fileName = reportData.fileName;
const filePath = reportData.filePath;
if (reportData.fileSn !== "") {
getFileDownload(reportData.fileSn, fileName, filePath);
}
}
};
const handleCtpvCdChange = (val: string | number) => { // 하수도정비기본계획.시도
const sidoOption = sidos.find((n) => n.val === val);
setCtpvCd(String(val));
if (val !== '0') {
const filterSiguns = siguns.filter(item => item.sido === sidoOption?.text);
filterSiguns.unshift({ val: '0', text: '전체', sido: '0' });
setFilteredSiguns(filterSiguns);
}
setSigungu("0");
setGubun("");
setYearFilter({ start: "", end: "", });
}
const renderBody = () => (
<>
{/* 탭 영역 */}
<UITab
defaultValue={TABS[0]?.val}
tabList={TABS.map((tab) => ({
value: tab.val,
label: tab.text
}))}
onValueChange={(value: string) => setActiveTab(value)}
>
{/* 각각의 탭 영역 */}
{/* 기본정보 탭 */}
{activeTab === 'basic' && (
<BasicTab
open={open}
basicType={basicType}
city={city}
sgg={sgg}
start1={start1}
start2={start2}
end1={end1}
end2={end2}
var1={var1}
var2={var2}
yearFilter={yearFilter}
handleSearch={handleSearch}
setBasicType={setBasicType}
setCity={setCity}
setSgg={setSgg}
setYearFilter={setYearFilter}
setStart1={setStart1}
setStart2={setStart2}
setEnd1={setEnd1}
setEnd2={setEnd2}
setVar1={setVar1}
setVar2={setVar2}
/>
)}
{/* 운영정보 탭 */}
{activeTab === 'operation' && (
<OperationTab
open={open}
workType={workType}
var1={var1}
var2={var2}
yearFilter={yearFilter}
handleSearch={handleSearch}
setWorkType={setWorkType}
setVar1={setVar1}
setVar2={setVar2}
setYearFilter={setYearFilter}
/>
)}
{/* 하수도정비기본계획보고서 탭 */}
{activeTab === 'report' && (
<div className="relative flex flex-col border rounded-lg p-6 mt-4 w-full h-[10vh]">
<div className="flex items-center mb-3">
<SelectBox
className="w-[150px] mr-8"
selectClass="rounded-lg bg-white"
label="시도"
selectArray={sidos}
value={ctpvCd}
onSelectValue={handleCtpvCdChange}
selectContentClass="z-[101]"
/>
<SelectBox
className="w-48"
selectClass="w-48 rounded-lg bg-white truncate"
label="시군구"
selectArray={filteredSiguns}
value={sigungu}
onSelectValue={val => setSigungu(String(val))}
selectContentClass="z-[101]"
/>
</div>
<div className="flex items-center mb-6">
<label className="inline-block w-auto whitespace-nowrap text-xl text-gray-600 mr-2">구분</label>
<Input
className='!text-xl w-[100px] placeholder:text-center mr-8'
placeholder="입력"
value={gubun}
onChange={(e) => { setGubun(e.target.value); }}
/>
<YearRangeSelectBox
start={yearFilter.start}
end={yearFilter.end}
onChange={range => setYearFilter({ ...yearFilter, start: range.start, end: range.end })}
startLabel="승인년도"
endLabel=""
/>
{/* 조회 버튼 */}
<div className="flex-1 flex justify-end">
<Button className="text-base py-2" onClick={handleSearch}>조회</Button>
</div>
</div>
</div>
)}
{/* </UITab2> */}
</UITab>
{/* 📋 결과 리스트 */}
{/* 기본정보 탭, 하수도정비기본계획보고서 탭 */}
{(activeTab === 'basic' || activeTab === 'report') && (
<div className="h-[80vh] w-full overflow-hidden rounded-lg border">
{/* 테이블2 영역 (가로/세로 스크롤 가능) */}
<div className="flex-1 px-2 pb-2">
<LoadingOverlay isLoading={isLoading} />
<UiTable
headName={(() => {
const label = BASIC_TYPES.find((type) => type.val === basicType)?.text
return (<>{label} 조회 결과 ({tableCount})건</>);
})()
}
tableData={tableData}
headlist={dynamicHeadlist}
pageSize={10}
total={tableCount}
cellClick={activeTab === 'report' ? handleReportCellClick : handleBasicCellClick}
onPageChange={setCurPage}
resetPageNo={false}
/>
</div>
</div>
)}
{/* 운영정보 탭 */}
{activeTab === 'operation' && (
<>
<div className="h-[35vh] w-full overflow-hidden rounded-lg border">
<div className="flex-1 px-2 pb-2">
<LoadingOverlay isLoading={isLoading} />
<UiTable
headName={
(() => {
const label = WORK_TYPES.find((type) => type.val === workType)?.text
return (<>{label} 사업 현황 ({tableCount})건</>);
})()
}
tableData={tableData}
headlist={dynamicHeadlist}
pageSize={5}
total={tableCount}
cellClick={handleOperationCellClick}
onPageChange={setCurPage}
resetPageNo={false}
/>
</div>
</div>
<div className="h-[35vh] w-full overflow-hidden rounded-lg border">
<div className="flex-1 px-2 pb-2">
<LoadingOverlay isLoading={isDetailLoading} />
<UiTable
headName={
(() => {
const label = WORK_TYPES.find((type) => type.val === workType)?.text
return (<>{label} 결과표 ({detailTableCount})건</>);
})()
}
tableData={detailTableData}
headlist={dynamicHeadlist2}
pageSize={5}
total={detailTableCount}
cellClick={undefined}
onPageChange={setDetailCurPage}
resetPageNo={false}
/>
</div>
</div>
</>
)}
</>
);
return (
<UiModal
open={open}
onOpenChange={onOpenChange}
bodyClass={`
h-[100vh]
w-[60vw]
max-w-[60vw]
max-h-[100vh]
overflow-hidden
z-[101]
`}
body={renderBody()}
useDirectRender={true}
/>
);
};
export default React.memo(SearchModal);