/** * ➡️ 경로 : 하수관망도 메인 페이지 (오른쪽 돋보기 모양 클릭) - 검색 모달 창 내 하수도정비기본계획보고서 탭 * * 📄 Report Tab * Next.js App Router (app/) 기반 검색 모달 보고서 탭 컴포넌트 * * - 하수도정비 기본계획 보고서 목록 표시 및 필터링 * - 시도/시군구/보고서 구분/승인년도 기반 검색 기능 * - 테이블 데이터 표시 및 페이지네이션 지원 * - 보고서 클릭 시 파일 목록 모달 열기 * - Zustand를 통한 모달 상태 및 데이터 관리 * - 로딩 오버레이 및 선택 초기화 기능 */ 'use client'; import React, { useEffect, useState } from 'react'; import { Button, Label } from '@common/components'; import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox'; import { SelectBox, UiTable } from '@common/business_components/ui'; import LoadingOverlay from '@/components/ui/LoadingBar'; import useReportTab from './useReportTab'; import useStore from '@/store/useStore'; import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox'; import useSearchModalStore from '@/store/useSearchModalStore'; import { useReportTabStore } from '@/store/useReportTabStore'; import ReportFilesModal from './reportFilesModal'; // 파일목록모달 // 하수도정비 기본계획 보고서 export const reportTableHeadlist = [ { id: "no", title: "NO" }, { id: "sido", title: "시도" }, { id: "sigungu", title: "시군구" }, { id: "approvalYear", title: "승인년도" }, { id: "plantZoneGubun", title: "구분" }, { id: "reportGubun", title: "보고서구분" }, { id: "fileName", title: "파일명" }, { id: "regDate", title: "등록일자" }, ]; interface ReportTabProps { open?: boolean; isSearch?: boolean; ctpvNm?: string; sggNm?: string; } const ReportTab: React.FC = ({ open, isSearch = true, ctpvNm, sggNm }) => { // const [isLoading, setIsLoading] = useState(false); const [isResetPage, setIsResetPage] = useState(false); const [isResetSelection, setIsResetSelection] = useState(false); const [showTable, setShowTable] = useState(false); // const [tableData, setTableData] = useState([]); // const [tableCount, setTableCount] = useState(0); // const [curPage, setCurPage] = useState(1); // const [yearFilter, setYearFilter] = useState({ start: "", end: "" }); const [ctpvCd, setCtpvCd] = useState('0'); const [sggCd, setSggCd] = useState('0'); const [reportGubun, setReportGubun] = useState("0"); const [clsfSystmSn, setClsfSystmSn] = useState(''); // 자료관 기본계획 일련번호 const { tableData, tableCount, isLoading, yearFilter, curPage, setTableData, setTableCount, setIsLoading, setYearFilter, setCurPage } = useSearchModalStore(); const { ctpv, sgg } = useStore(); const { isOpen: isReportFilesModalOpen, setIsOpen: setIsReportFilesModalOpen, dcTree: reportOriginData, fetchDcTree } = useReportTabStore(); // 모달 상태 관리 스토어 const { REPORT_TYPES, flattenFolders, addFileName } = useReportTab(); useEffect(() => { fetchDcTree("기본계획"); // 하수정비기본계획 report }, []); useEffect(() => { // filterParams 초기화 setCtpvCd('0'); setSggCd('0'); setReportGubun('0'); setYearFilter({ start: "", end: "" }); setShowTable(false); setTableData([]); setTableCount(0); setCurPage(1); // 페이지를 1로 초기화 setIsResetPage(true); // 페이지를 초기화 setIsResetSelection(true); // 선택 초기화 }, [open]); useEffect(() => { const newCtpvCd = ctpv.find((n) => n.text === ctpvNm)?.val || '0'; const newSggCd = sgg.find((n) => n.text === sggNm)?.val || '0'; setCtpvCd(newCtpvCd); setSggCd(newSggCd); }, [ctpvNm, sggNm]); // ctpvCd, sggCd가 업데이트된 후에 fetchFilteredData 실행 useEffect(() => { if (!isSearch && ctpvCd && sggCd) { fetchFilteredData(); } }, [reportOriginData, ctpvCd, sggCd, isSearch]); // 페이지 변경 시마다 데이터 fetch useEffect(() => { // showTable이 true일 때만 fetch (최초 렌더 방지) setIsResetPage(false); if (showTable) fetchFilteredData(); }, [curPage]); const handleCtpvCdChange = (sidoId: string) => { setCtpvCd(sidoId); setSggCd('0'); } // 조회 버튼 클릭 시 1페이지로 이동 및 데이터 초기화 const handleSearch = () => { setCurPage(1); // 페이지를 1로 초기화 fetchFilteredData(); setIsResetPage(true); // 페이지를 초기화 setIsResetSelection(false); // 선택 초기화 setShowTable(true); }; // 하수도정비기본계획 테이블 cellClick 핸들러 const handleReportCellClick = (index: number | undefined) => { if (typeof index === "number" && tableData[index]) { const reportData = tableData[index]; if (reportData.fileSn !== "") { setClsfSystmSn(reportData.clsfSystmSn); // 자료관 기본계획 일련번호 설정 setIsReportFilesModalOpen(true); // 모달 열기 } } }; // 검색 API 호출 함수 const fetchFilteredData = async () => { setIsLoading(true); // 로딩 시작 setIsResetSelection(true); // 선택 초기화 try { const reportData = flattenFolders(reportOriginData); let filterReportData = reportData; if (ctpvCd !== '0') { // 시도검색 const sidoOption = ctpv.find((n) => n.val.trim() === ctpvCd.trim()); filterReportData = filterReportData.filter(item => item.sido === sidoOption?.text); } if (sggCd !== '0') { // 시군구검색 const sigunguOption = sgg.find((n) => String(n.val) === String(sggCd)); filterReportData = filterReportData.filter(item => item.sigungu === sigunguOption?.text); } if (reportGubun !== "0") { // 보고서구분검색 const reportGubunOption = REPORT_TYPES.find((n) => n.val === reportGubun); filterReportData = filterReportData.filter(item => item.reportGubun === reportGubunOption?.text); } const { start, end } = yearFilter; if (start && !end) //승인년도검색 filterReportData = filterReportData.filter(item => (item.approvalYear) ? item.approvalYear >= yearFilter.start + "년" : null); else if (!start && end) filterReportData = filterReportData.filter(item => (item.approvalYear) ? item.approvalYear <= yearFilter.end + "년" : null); else if (start && end) { filterReportData = filterReportData.filter(item => { return (item.approvalYear) ? item.approvalYear >= yearFilter.start + "년" && item.approvalYear <= yearFilter.end + "년" : null; }); } // if (gubun !== "") { // 구분검색 (추후 사용할 수도 있을 것 같아 남겨둠) // filterReportData = filterReportData.filter(item => (item.plantZoneGubun) ? String(item.plantZoneGubun).includes(String(gubun)) : null); // } 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 })); addFileName(filterReportData).then(data => { filterReportData = data; setTableData(filterReportData || []); setIsResetSelection(false); // 데이터 설정 후 선택 초기화 해제 }); setTableData(filterReportData || []); setShowTable(true); } catch (err) { console.error('API ERROR:', err); setTableData([]); setIsResetSelection(false); // 에러 시에도 선택 초기화 해제 } finally { setIsLoading(false); // 로딩 종료 } }; return ( <>
{isSearch && ( <>
{ handleCtpvCdChange(sidoId) }} onSigunguChange={setSggCd} setIsLoading={setIsLoading} />
)}
setReportGubun(String(val))} selectContentClass="z-[101]" labelClass='whitespace-nowrap text-xl text-gray-600 pr-2' /> {/* 승인년도 필터 */} setYearFilter({ ...yearFilter, start: range.start, end: range.end })} startLabel="승인년도" endLabel="" /> {/* 조회 버튼 */}
{/* 테이블2 영역 (가로/세로 스크롤 가능) */}
{ return (<>조회 결과 ({tableCount.toLocaleString('ko-KR')})건); })() } tableData={tableData} headlist={reportTableHeadlist} pageSize={10} total={tableCount} cellClick={handleReportCellClick} onPageChange={setCurPage} resetPageNo={isResetPage} resetSelection={isResetSelection} />
{/* 모달 컴포넌트 */} {isReportFilesModalOpen && } ); }; export default React.memo(ReportTab);