"use client"; import React, { FC, useState } 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 { Badge } from "@/components/ui/badge"; import { DialogFooter } from "@/components/ui/dialog"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; 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 { uploadReportTemp } from "@/lib/forms-plant/services"; // 최대 파일 크기 설정 (3000MB) const MAX_FILE_SIZE = 3000000; interface FormDataReportTempUploadTabProps { packageId: number; formId: number; uploaderType: string; } export const FormDataReportTempUploadTab: FC< FormDataReportTempUploadTabProps > = ({ packageId, formId, uploaderType }) => { const { toast } = useToast(); const params = useParams(); const lng = (params?.lng as string) || "ko"; const { t } = useTranslation(lng, "engineering"); const [selectedFiles, setSelectedFiles] = useState([]); const [isUploading, setIsUploading] = useState(false); const [uploadProgress, setUploadProgress] = useState(0); // 드롭존 - 파일 드랍 처리 const handleDropAccepted = (acceptedFiles: File[]) => { const newFiles = [...selectedFiles, ...acceptedFiles]; setSelectedFiles(newFiles); }; // 드롭존 - 파일 거부(에러) 처리 const handleDropRejected = (fileRejections: any[]) => { fileRejections.forEach((rejection) => { toast({ variant: "destructive", title: t("templateUploadTab.fileError"), description: `${rejection.file.name}: ${ rejection.errors[0]?.message || t("templateUploadTab.uploadFailed") }`, }); }); }; // 파일 제거 핸들러 const removeFile = (index: number) => { const updatedFiles = [...selectedFiles]; updatedFiles.splice(index, 1); setSelectedFiles(updatedFiles); }; const submitData = async () => { setIsUploading(true); setUploadProgress(0); try { const totalFiles = selectedFiles.length; let successCount = 0; for (let i = 0; i < totalFiles; i++) { const file = selectedFiles[i]; const formData = new FormData(); formData.append("file", file); formData.append("customFileName", file.name); formData.append("uploaderType", uploaderType); await uploadReportTemp(packageId, formId, formData); successCount++; setUploadProgress(Math.round((successCount / totalFiles) * 100)); } toastMessage.success(t("templateUploadTab.uploadComplete")); } catch (err) { console.error(err); toast({ title: t("templateUploadTab.error"), description: t("templateUploadTab.uploadError"), variant: "destructive", }); } finally { setIsUploading(false); setUploadProgress(0); setSelectedFiles([]) } }; return (
{({ maxSize }) => ( <>
{t("templateUploadTab.dropFileHere")} {t("templateUploadTab.orClickToSelect", { maxSize: maxSize ? prettyBytes(maxSize) : t("templateUploadTab.unlimited") })}
)}
{selectedFiles.length > 0 && (
{t("templateUploadTab.selectedFiles", { count: selectedFiles.length })}
{t("templateUploadTab.fileCount", { count: selectedFiles.length })}
)} {isUploading && }
); }; 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("templateUploadTab.remove")} ))} ); }; const UploadProgressBox: FC<{ uploadProgress: number; t: (key: string, options?: any) => string; }> = ({ uploadProgress, t }) => { return (
{t("templateUploadTab.uploadingProgress", { progress: uploadProgress })}
); };