"use client"; import React, { FC, Dispatch, SetStateAction, useState, useEffect, } from "react"; import { useParams } from "next/navigation"; import { useTranslation } from "@/i18n/client"; import { useToast } from "@/hooks/use-toast"; import { toast as toastMessage } from "sonner"; import prettyBytes from "pretty-bytes"; import { X, Loader2 } from "lucide-react"; import { saveAs } from "file-saver"; import { Badge } from "@/components/ui/badge"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from "@/components/ui/dialog"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Dropzone, DropzoneDescription, DropzoneInput, DropzoneTitle, DropzoneUploadIcon, DropzoneZone, } from "@/components/ui/dropzone"; import { FileList, FileListAction, FileListDescription, FileListHeader, FileListIcon, FileListInfo, FileListItem, FileListName, } from "@/components/ui/file-list"; import { Button } from "@/components/ui/button"; import { getReportTempList, getOrigin } from "@/lib/forms/services"; import { DataTableColumnJSON } from "./form-data-table-columns"; import { PublishDialog } from "./publish-dialog"; const MAX_FILE_SIZE = 3000000; type ReportData = { [key: string]: any; }; interface tempFile { fileName: string; filePath: string; } interface FormDataReportBatchDialogProps { open: boolean; setOpen: Dispatch>; columnsJSON: DataTableColumnJSON[]; reportData: ReportData[]; packageId: number; formId: number; formCode: string; } export const FormDataReportBatchDialog: FC = ({ open, setOpen, columnsJSON, reportData, packageId, formId, formCode, }) => { const { toast } = useToast(); const params = useParams(); const lng = (params?.lng as string) || "ko"; const { t } = useTranslation(lng, "engineering"); const [tempList, setTempList] = useState([]); const [selectTemp, setSelectTemp] = useState(""); const [selectedFiles, setSelectedFiles] = useState([]); const [isUploading, setIsUploading] = useState(false); // Add new state for publish dialog const [publishDialogOpen, setPublishDialogOpen] = useState(false); const [generatedFileBlob, setGeneratedFileBlob] = useState(null); useEffect(() => { updateReportTempList(packageId, formId, setTempList); }, [packageId, formId]); const onClose = () => { if (isUploading) { return; } setOpen(false); }; // 드롭존 - 파일 드랍 처리 const handleDropAccepted = (acceptedFiles: File[]) => { const newFiles = [...acceptedFiles]; setSelectedFiles(newFiles); }; // 드롭존 - 파일 거부(에러) 처리 const handleDropRejected = (fileRejections: any[]) => { fileRejections.forEach((rejection) => { toast({ variant: "destructive", title: t("batchReport.fileError"), description: `${rejection.file.name}: ${ rejection.errors[0]?.message || t("batchReport.uploadFailed") }`, }); }); }; // 파일 제거 핸들러 const removeFile = (index: number) => { const updatedFiles = [...selectedFiles]; updatedFiles.splice(index, 1); setSelectedFiles(updatedFiles); }; // Create and download document const submitData = async () => { setIsUploading(true); try { const origin = await getOrigin(); const targetFiles = selectedFiles[0]; const reportDatas = reportData.map((c) => { const reportValue = stringifyAllValues(c); const reportValueMapping: { [key: string]: any } = {}; columnsJSON.forEach((c2) => { const { key } = c2; reportValueMapping[key] = reportValue?.[key] ?? ""; }); return reportValueMapping; }); const formData = new FormData(); formData.append("file", targetFiles); formData.append("customFileName", `${formCode}.pdf`); formData.append("reportDatas", JSON.stringify(reportDatas)); formData.append("reportTempPath", selectTemp); const requestCreateReport = await fetch( `${origin}/api/pdftron/createVendorDataReports`, { method: "POST", body: formData } ); if (requestCreateReport.ok) { const blob = await requestCreateReport.blob(); saveAs(blob, `${formCode}.pdf`); toastMessage.success(t("batchReport.downloadComplete")); } else { const err = await requestCreateReport.json(); console.error("에러:", err); throw new Error(err.message); } } catch (err) { console.error(err); toast({ title: t("batchReport.error"), description: t("batchReport.reportGenerationError"), variant: "destructive", }); } finally { setIsUploading(false); setSelectedFiles([]); setOpen(false); } }; // New function to prepare the file for publishing const prepareFileForPublishing = async () => { setIsUploading(true); try { const origin = await getOrigin(); const targetFiles = selectedFiles[0]; const reportDatas = reportData.map((c) => { const reportValue = stringifyAllValues(c); const reportValueMapping: { [key: string]: any } = {}; columnsJSON.forEach((c2) => { const { key } = c2; reportValueMapping[key] = reportValue?.[key] ?? ""; }); return reportValueMapping; }); const formData = new FormData(); formData.append("file", targetFiles); formData.append("customFileName", `${formCode}.pdf`); formData.append("reportDatas", JSON.stringify(reportDatas)); formData.append("reportTempPath", selectTemp); const requestCreateReport = await fetch( `${origin}/api/pdftron/createVendorDataReports`, { method: "POST", body: formData } ); if (requestCreateReport.ok) { const blob = await requestCreateReport.blob(); setGeneratedFileBlob(blob); setPublishDialogOpen(true); toastMessage.success(t("batchReport.documentGenerated")); } else { const err = await requestCreateReport.json(); console.error("에러:", err); throw new Error(err.message); } } catch (err) { console.error(err); toast({ title: t("batchReport.error"), description: t("batchReport.documentGenerationError"), variant: "destructive", }); } finally { setIsUploading(false); } }; return ( <> {t("batchReport.dialogTitle")} {t("batchReport.dialogDescription")}
{({ maxSize }) => ( <>
{t("batchReport.dropFileHere")} {t("batchReport.orClickToSelect", { maxSize: maxSize ? prettyBytes(maxSize) : t("batchReport.unlimited") })}
)}
{selectedFiles.length > 0 && (
{t("batchReport.selectedFiles", { count: selectedFiles.length })}
{t("batchReport.fileCount", { count: selectedFiles.length })}
)} {/* Add the new Publish button */}
{/* Add the PublishDialog component */} ); }; interface UploadFileItemProps { selectedFiles: File[]; removeFile: (index: number) => void; isUploading: boolean; t: (key: string, options?: any) => string; } const UploadFileItem: FC = ({ selectedFiles, removeFile, isUploading, t, }) => { return ( {selectedFiles.map((file, index) => ( {file.name} {prettyBytes(file.size)} removeFile(index)} disabled={isUploading} > {t("batchReport.remove")} ))} ); }; type UpdateReportTempList = ( packageId: number, formId: number, setPrevReportTemp: Dispatch> ) => void; const updateReportTempList: UpdateReportTempList = async ( packageId, formId, setTempList ) => { const tempList = await getReportTempList(packageId, formId); setTempList( tempList.map((c) => { const { fileName, filePath } = c; return { fileName, filePath }; }) ); }; const stringifyAllValues = (obj: any): any => { if (Array.isArray(obj)) { return obj.map((item) => stringifyAllValues(item)); } else if (typeof obj === "object" && obj !== null) { const result: any = {}; for (const key in obj) { result[key] = stringifyAllValues(obj[key]); } return result; } else { return obj !== null && obj !== undefined ? String(obj) : ""; } };