import { JSONPath as jsonpath } from "jsonpath-plus"; import React, { useMemo, useState } from "react"; import useTranslation from "next-translate/useTranslation"; import Link from "next/link"; import Dropzone from "react-dropzone"; import { deleteBlob, getFilesFromBlobHashed, uploadSingleFile, getFilesFromBlobproxy } from "../../../actions/services/documentService"; import { bytesToSize, getThumbnailIconByExtension } from "../../utils"; import { getDocumentTypePrefix, getThumbnailIconByMimeType, validateUploadFilename } from "../helpers/fileUploadHelpers"; const baseStyle = { display: "flex", flexDirection: "column", alignItems: "center", padding: "20px", borderWidth: 2, borderRadius: 2, borderColor: "#eeeeee", borderStyle: "dashed", backgroundColor: "#fafafa", color: "#bdbdbd", transition: "border .3s ease-in-out" }; const activeStyle = { borderColor: "#2196f3" }; const acceptStyle = { borderColor: "#00e676" }; const rejectStyle = { borderColor: "#ff1744" }; export const RenderFileUpload = (field) => { let files = field.input.value; let { t } = useTranslation(); const style = useMemo( () => ({ ...baseStyle // ...(isDragActive ? activeStyle : {}), // ...(isDragAccept ? acceptStyle : {}), // ...(isDragReject ? rejectStyle : {}), }), [] // [isDragActive, isDragReject, isDragAccept] ); const [filesList, setFilesList] = useState([]); const thumbs = filesList.map((file) => (
{file.name} -{" "} {file.name} ({file.size / 1024}kb)
)); const filelistObj = field.fileList || {}; const blobList = jsonpath({ path: "$..[?(@ && @.documentType=='" + field.documentTypeCode + "')]", json: filelistObj, eval: true }); //const blobList = filelistObj; const deleteThisBlob = async ( containerName, blobName, deleteblobhash, getblobshash, casefolderID ) => { //console.log(containerName, blobName, deleteblobhash); deleteBlob(containerName, blobName, deleteblobhash, casefolderID) .then((data) => data) .then(() => { getFilesFromBlobHashed( containerName, getblobshash, casefolderID ).then((newfilelist) => field.setFilesForAppeal(newfilelist)); }); }; const removeFile = (file) => { const newFilesArr = files.filter((user) => user.name != file.name); files == newFilesArr; field.input.onChange(newFilesArr); }; function removeEmptyObjects(arr) { return arr.filter((obj) => Object.keys(obj).length > 0); } const [errorMessage, setErrorMessage] = useState(null); const [rejectedFiles, setRejectedFiles] = useState([]); // Store rejected files const [completedUploadFiles, setCompletedUploadFiles] = useState(false); const [uploadCountMessage, setUploadCountMessage] = useState(""); const [totalUploadFiles, setTotalUploadFiles] = useState(0); const handleDropRejected = (fileRejections) => { const errors = fileRejections .map(({ file, errors }) => { return errors.map((error) => { if (error.code === "file-too-large") { return `${file.name} ${t( "newappeal:new-appeal-fileupload-file-error-filesize-label" )}`; } if (error.code === "file-invalid-type") { return `${file.name} ${t( "newappeal:new-appeal-fileupload-file-error-invalid-type-label" )}`; } if (error.code === "filename-invalid-chars") { return ( error.message || `${file.name} ${t( "newappeal:new-appeal-fileupload-file-error-invalid-filename-label" )}` ); } return `${file.name} ${t( "newappeal:new-appeal-fileupload-file-error-invalid-label" )}`; }); }) .flat(); // Flatten the errors array setRejectedFiles(errors); // Store the error messages for rejected files }; // Handle accepted files (clear error message when files are accepted) const handleDropAccepted = () => { setErrorMessage(null); // Clear any previous error messages when files are accepted setRejectedFiles([]); // Clear any previously rejected file errorsss }; return ( <> validateUploadFilename(file, t)} onDrop={(acceptedFiles, fileRejections, e) => { // build + display rejected messages (ALWAYS, even if some accepted) if (fileRejections?.length) { handleDropRejected(fileRejections); } else { // only clear rejections when nothing was rejected on this drop setRejectedFiles([]); setErrorMessage(null); } // if nothing accepted, stop (prevents showing only "uploading" when all invalid) if (!acceptedFiles || acceptedFiles.length === 0) { setCompletedUploadFiles(true); // optional: depends on your UX setUploadCountMessage(0); setTotalUploadFiles(0); return; } // continue with your existing upload logic for accepted files setCompletedUploadFiles(false); const renamedAcceptedFiles = acceptedFiles.map( (file) => new File( [file], `${getDocumentTypePrefix(field.documentTypeCode)}_-_${ file.name }`, { type: file.type } ) ); field.input.onChange(renamedAcceptedFiles); if (typeof field.setFileCount === "function") { field.setFileCount( (field.uploadCount || 0) + renamedAcceptedFiles.length ); } setUploadCountMessage(0); setTotalUploadFiles(renamedAcceptedFiles.length); uploadSingleFile( renamedAcceptedFiles, field.containerID, field.ticketnumber, { onChunkComplete: ({ cumulativeUploaded }) => { setUploadCountMessage(cumulativeUploaded); } } ) .then((data) => { let buildAppealFilesArray = []; let values = field.form.appealForm.values; let filesUploadObj = renamedAcceptedFiles; for (let key in filesUploadObj) { typeof filesUploadObj[key].name !== "undefined" && buildAppealFilesArray.push({ name: filesUploadObj[key].name, size: filesUploadObj[key].size }); } function removeDuplicates(arr, key) { const seen = new Set(); return arr.filter((item) => { const value = item[key]; if (seen.has(value)) return false; seen.add(value); return true; }); } buildAppealFilesArray = values.hasOwnProperty( "filesList" ) ? buildAppealFilesArray.concat(values.filesList) : buildAppealFilesArray; buildAppealFilesArray = removeDuplicates( buildAppealFilesArray, "name" ); Object.assign(values, { filesList: buildAppealFilesArray }); // keep your existing server-side invalid handling if (data.invalidFiles?.length > 0) { setRejectedFiles((prev) => [ ...prev, ...data.invalidFiles ]); setUploadCountMessage( renamedAcceptedFiles.length - data.invalidFiles.length ); } return getFilesFromBlobproxy( field.containerID, field.ticketnumber ); }) .then((data) => { field.setFilesForAppeal(data); setCompletedUploadFiles(true); }); }} > {({ getRootProps, getInputProps }) => ( <>
{" "}
{t( "newappeal:new-appeal-fileupload-drop-label" )}{" "} (Max 50 MB)
( {t( "newappeal:new-appeal-fileupload-file-list-label" )} )
{/* */}
)}
{rejectedFiles.length > 0 && (
)} {totalUploadFiles > 0 && completedUploadFiles == false && (
{t("home:uploading-files-label", { number: totalUploadFiles > 0 ? `${uploadCountMessage} of ${totalUploadFiles}` : uploadCountMessage })}
)} {completedUploadFiles > 0 && uploadCountMessage >= 0 && (
{t("home:completed-uploading-files-label", { number: uploadCountMessage })}
)} {field.meta.touched && field.meta.error && ( {field.meta.error} )} {files && Array.isArray(files) && ( <> {/* {(files = removeEmptyObjects(files))} */} {!completedUploadFiles && files.map( (file, i) => typeof file.name != "undefined" && (
{" "} {/* removeFile(file)} > − */} {file.name} {file.name} ( {bytesToSize(file.size)})
{completedUploadFiles ? (

Upload complete

) : (

{t( "home:uploading-files-progress-label" )}{" "}

)}
) )} )} {blobList.length > 0 && (

{t("newappeal:previously-added-files")}

)} {blobList.map( (blob, i) => blob.documentType == field.documentTypeCode && (
{ setUploadCountMessage( uploadCountMessage - 1 ); deleteThisBlob( field.containerID, blob.name, blob.hasheddeletepath, blob.hashgetblobs, field.ticketnumber ); }} title={t("home:remove-this-file-label")} > −
{blob.name} {blob.name} ({bytesToSize(blob.contentLength)})
) )}{" "} ); };