파일목록 modal
This commit is contained in:
@@ -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 }),
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user