파일목록 modal

This commit is contained in:
2025-08-13 15:17:45 +09:00
parent e4df3ac86c
commit 5e9a49abe8
3 changed files with 163 additions and 9 deletions
@@ -0,0 +1,108 @@
'use client'
import React, { useEffect, useState } from 'react';
import LoadingOverlay from '@/components/ui/LoadingBar';
import { getFileDownload, getDcFiles, useDcFiles } from './searchModalReportApi';
import { type ReportDataFile } from './searchModalReportApi';
import { useReportFileModalStore } from './searchModalReportApi'; // 모달 상태 관리 스토어
import { UiTable } from '@common/business_components/ui';
import { UiModal } from "@common/business_components";
type ModalOpenProp = {
clsfSystmSn: string, // 자료관 기본계획 일련번호
}
// 하수도정비 기본계획 보고서 파일목록
export const headlist = [
{ id: "no", title: "NO" },
{ id: "fileTitle", title: "파일명" },
{ id: "regDt", title: "등록일자" },
];
const ReportFiles: React.FC<ModalOpenProp> = ({ clsfSystmSn }: ModalOpenProp) => {
const [isLoading, setIsLoading] = useState(false);
const [isResetPage, setIsResetPage] = useState<boolean>(false);
const [isResetSelection, setIsResetSelection] = useState<boolean>(false);
const { isOpen: isModalOpen, setIsOpen: setIsModalOpen } = useReportFileModalStore(); // 모달 상태 관리 스토어
const [files, setFiles] = useState<ReportDataFile[]>([]);
const [curPage, setCurPage] = useState(1);
const filesOrigin = useDcFiles(clsfSystmSn); // 자료관 기본계획 일련번호에 해당하는 파일 목록을 가져오기 위한 훅
useEffect(() => {
if (isModalOpen === true) {
getFiles(); // 파일 목록 조회
} else {
setFiles([]); // 모달이 닫힐 때 파일 목록 초기화
setCurPage(1); // 페이지를 1로 초기화
setIsResetPage(true); // 페이지를 초기화
setIsResetSelection(true); // 선택 초기화
}
}, [filesOrigin, isModalOpen, curPage]);
// 파일 목록 조회
const getFiles = async () => {
setIsLoading(true); // 로딩 시작
try {
//let data = await getDcFiles(clsfSystmSn);
let data = filesOrigin;
data = data?.slice((curPage - 1) * 10, curPage * 10); // paging
data = data?.map((item, index) => ({ ...item, no: (curPage - 1) * 10 + index + 1 }));
setFiles(data);
} catch (error) {
console.error("파일 목록 조회 에러:", error);
} finally {
setIsLoading(false); // 로딩 종료
}
};
// cellClick 핸들러
const handleCellClick = (index: number|undefined) => {
if (typeof index === "number" && files[index]) {
const fileName = files[index].fileTitle;
const filePath = files[index].filePath;
if (files[index].fileSn !== "") {
getFileDownload(files[index].fileSn, fileName, filePath);
}
}
};
const renderBody = () => (
<>
<div className="flex-1 px-2 pb-2">
<LoadingOverlay isLoading={isLoading} />
<UiTable
headName={(() => {
return (<>조회 결과 ({filesOrigin.length.toLocaleString('ko-KR')})건</>);
})()
}
tableData={files}
headlist={headlist}
pageSize={10}
total={filesOrigin.length}
cellClick={handleCellClick}
onPageChange={setCurPage}
resetPageNo={isResetPage}
resetSelection={isResetSelection}
/>
</div>
</>
);
return (
<UiModal
open={isModalOpen}
onOpenChange={setIsModalOpen}
headerTitle=""
bodyClass={`
min-h-[50vh]
h-[580px]
min-w-[55vw]
max-w-none max-h-none
overflow-visible
z-[5000]
`}
body={renderBody()}
noFooterYn='Y'
/>
);
};
export default React.memo(ReportFiles);
@@ -7,6 +7,8 @@ import LoadingOverlay from '@/components/ui/LoadingBar';
import { addFileName, flattenFolders, getFileDownload, useDcTree, reportGubuns } from './searchModalReportApi';
import useStore from '../../../store/useStore';
import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox';
import { useReportFileModalStore } from './searchModalReportApi'; // 모달 상태 관리 스토어
import ReportFiles from './reportFiles'; // 파일목록모달
// 하수도정비 기본계획 보고서
@@ -41,7 +43,8 @@ const ReportTab: React.FC<ReportTabProps> = ({ open, isSearch = true, ctpvNm, sg
const [sggCd, setSggCd] = useState('0');
const [reportGubun, setReportGubun] = useState("0");
// const [gubun, setGubun] = useState("");
const { isOpen: isModalOpen, setIsOpen: setIsModalOpen } = useReportFileModalStore(); // 모달 상태 관리 스토어
const [clsfSystmSn, setClsfSystmSn] = useState(''); // 자료관 기본계획 일련번호
const { ctpv, sgg } = useStore();
// 하수정비기본계획 report
@@ -105,7 +108,9 @@ const ReportTab: React.FC<ReportTabProps> = ({ open, isSearch = true, ctpvNm, sg
const fileName = reportData.fileName;
const filePath = reportData.filePath;
if (reportData.fileSn !== "") {
getFileDownload(reportData.fileSn, fileName, filePath);
//getFileDownload(reportData.fileSn, fileName, filePath);
setIsModalOpen(true); // 모달 열기
setClsfSystmSn(reportData.clsfSystmSn); // 자료관 기본계획 일련번호 설정
}
}
};
@@ -228,6 +233,8 @@ const ReportTab: React.FC<ReportTabProps> = ({ open, isSearch = true, ctpvNm, sg
/>
</div>
</div>
{/* 모달 컴포넌트 */}
{isModalOpen && <ReportFiles clsfSystmSn={clsfSystmSn} />}
</>
);
};
@@ -1,6 +1,6 @@
import { useState, useEffect } from 'react';
import { getDcData } from '@/components/lib/api';
import { create } from 'zustand';
export type Folder = {
clsfSystmSn: string;
@@ -16,13 +16,14 @@ export type SelectDataType = {
val: string;
sido?: string; // 시도 코드 (선택 사항)
}
type ReportDataFile = {
export type ReportDataFile = {
no: number;
fileTitle: string;
regDt: string;
fileSn: string;
filePath: string;
}
const isYear = (value: string): boolean => {
return /^[0-9]{4}년$/.test(value);
};
@@ -107,23 +108,53 @@ export const useDcTree = (clsfSystmNm: string) => {
return data;
};
export const getDcFile = async (clsfSystmSn: string) => {
export const getDcFiles = async (clsfSystmSn: string) : Promise<ReportDataFile[]> => {
if (!clsfSystmSn) {
console.error("clsfSystmSn is required to get files.");
return [];
}
const queryString = 'clsfSystmSn=' + clsfSystmSn;
const result = await getDcData(`/api/v1/dc/file${queryString ? `?${queryString}` : ''}`);
return result;
};
export const useDcFiles = (clsfSystmNm: string) => {
const [data, setData] = useState<ReportDataFile[]>([]);
useEffect(() => {
const fetch = async () => {
const result = await getDcFiles(clsfSystmNm);
if (result) {
setData(result);
}
console.log("useDcFiles 호출");
console.log("clsfSystmNm:", clsfSystmNm, "data:", result);
};
fetch();
}, [clsfSystmNm]);
return data;
};
// 파일 이름 추가
export const addFileName = async (data: FlattenedFolder[]) => {
const fileReportData = await Promise.all(
data.map(async (item) => {
const filenameArr: ReportDataFile[] = await getDcFile(String(item.clsfSystmSn));
const f = filenameArr[0];
const result = { ...item, fileName: f?.fileTitle, regDate: f?.regDt, fileSn: f?.fileSn, filePath: f?.filePath };
const fileArr: ReportDataFile[] = await getDcFiles(String(item.clsfSystmSn));
let result:FlattenedFolder;
if (fileArr.length > 0) {
const f = fileArr[0];
const fCount = fileArr.length;
result = { ...item, fileName: f?.fileTitle+" 외 "+fCount+"건", regDate: f?.regDt, fileSn: f?.fileSn, filePath: f?.filePath };
} else {
result = { ...item, fileName: "", regDate: "", fileSn: "", filePath: "" };
}
return result;
})
);
return fileReportData;
};
export const getDcFileprcs = async (fileSn: string) => {
const queryString = 'fileSn=' + fileSn;
const result = await getDcData(`/api/v1/dc/fileprcs${queryString ? `?${queryString}` : ''}`);
@@ -157,3 +188,11 @@ export const getFileDownload = async (fileSn: string, fileName: string, filePath
fileDownload(blobData, fileName);
}
interface ModalStore {
isOpen: boolean;
setIsOpen: (open: boolean) => void;
}
export const useReportFileModalStore = create<ModalStore>((set) => ({
isOpen: false,
setIsOpen: (open: boolean) => set({ isOpen: open }),
}));