diff --git a/apps/remix/app/components/general/document/document-drop-zone-wrapper.tsx b/apps/remix/app/components/general/document/document-drop-zone-wrapper.tsx index e5fe18636..84b1dfc4a 100644 --- a/apps/remix/app/components/general/document/document-drop-zone-wrapper.tsx +++ b/apps/remix/app/components/general/document/document-drop-zone-wrapper.tsx @@ -4,7 +4,7 @@ import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; import { Trans } from '@lingui/react/macro'; import { Loader } from 'lucide-react'; -import { useDropzone } from 'react-dropzone'; +import { ErrorCode, type FileRejection, useDropzone } from 'react-dropzone'; import { Link, useNavigate, useParams } from 'react-router'; import { match } from 'ts-pattern'; @@ -108,15 +108,51 @@ export const DocumentDropZoneWrapper = ({ children, className }: DocumentDropZon } }; - const onFileDropRejected = () => { + const onFileDropRejected = (fileRejections: FileRejection[]) => { + if (!fileRejections.length) { + return; + } + + // Since users can only upload only one file (no multi-upload), we only handle the first file rejection + const { file, errors } = fileRejections[0]; + + if (!errors.length) { + return; + } + + const errorNodes = errors.map((error, index) => ( + + {match(error.code) + .with(ErrorCode.FileTooLarge, () => ( + File is larger than {APP_DOCUMENT_UPLOAD_SIZE_LIMIT}MB + )) + .with(ErrorCode.FileInvalidType, () => Only PDF files are allowed) + .with(ErrorCode.FileTooSmall, () => File is too small) + .with(ErrorCode.TooManyFiles, () => ( + Only one file can be uploaded at a time + )) + .otherwise(() => ( + Unknown error + ))} + + )); + + const description = ( + <> + + {file.name} couldn't be uploaded: + + {errorNodes} + + ); + toast({ - title: _(msg`Your document failed to upload.`), - description: _(msg`File cannot be larger than ${APP_DOCUMENT_UPLOAD_SIZE_LIMIT}MB`), + title: _(msg`Upload failed`), + description, duration: 5000, variant: 'destructive', }); }; - const { getRootProps, getInputProps, isDragActive } = useDropzone({ accept: { 'application/pdf': ['.pdf'], @@ -129,8 +165,8 @@ export const DocumentDropZoneWrapper = ({ children, className }: DocumentDropZon void onFileDrop(acceptedFile); } }, - onDropRejected: () => { - void onFileDropRejected(); + onDropRejected: (fileRejections) => { + onFileDropRejected(fileRejections); }, noClick: true, noDragEventsBubbling: true, diff --git a/apps/remix/app/components/general/template/template-drop-zone-wrapper.tsx b/apps/remix/app/components/general/template/template-drop-zone-wrapper.tsx index 0d9c3fc9e..dbca5a8ea 100644 --- a/apps/remix/app/components/general/template/template-drop-zone-wrapper.tsx +++ b/apps/remix/app/components/general/template/template-drop-zone-wrapper.tsx @@ -4,8 +4,9 @@ import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; import { Trans } from '@lingui/react/macro'; import { Loader } from 'lucide-react'; -import { useDropzone } from 'react-dropzone'; +import { ErrorCode, type FileRejection, useDropzone } from 'react-dropzone'; import { useNavigate, useParams } from 'react-router'; +import { match } from 'ts-pattern'; import { APP_DOCUMENT_UPLOAD_SIZE_LIMIT } from '@documenso/lib/constants/app'; import { megabytesToBytes } from '@documenso/lib/universal/unit-convertions'; @@ -67,10 +68,47 @@ export const TemplateDropZoneWrapper = ({ children, className }: TemplateDropZon } }; - const onFileDropRejected = () => { + const onFileDropRejected = (fileRejections: FileRejection[]) => { + if (!fileRejections.length) { + return; + } + + // Since users can only upload only one file (no multi-upload), we only handle the first file rejection + const { file, errors } = fileRejections[0]; + + if (!errors.length) { + return; + } + + const errorNodes = errors.map((error, index) => ( + + {match(error.code) + .with(ErrorCode.FileTooLarge, () => ( + File is larger than {APP_DOCUMENT_UPLOAD_SIZE_LIMIT}MB + )) + .with(ErrorCode.FileInvalidType, () => Only PDF files are allowed) + .with(ErrorCode.FileTooSmall, () => File is too small) + .with(ErrorCode.TooManyFiles, () => ( + Only one file can be uploaded at a time + )) + .otherwise(() => ( + Unknown error + ))} + + )); + + const description = ( + <> + + {file.name} couldn't be uploaded: + + {errorNodes} + + ); + toast({ - title: _(msg`Your template failed to upload.`), - description: _(msg`File cannot be larger than ${APP_DOCUMENT_UPLOAD_SIZE_LIMIT}MB`), + title: _(msg`Upload failed`), + description, duration: 5000, variant: 'destructive', }); @@ -88,8 +126,8 @@ export const TemplateDropZoneWrapper = ({ children, className }: TemplateDropZon void onFileDrop(acceptedFile); } }, - onDropRejected: () => { - void onFileDropRejected(); + onDropRejected: (fileRejections) => { + onFileDropRejected(fileRejections); }, noClick: true, noDragEventsBubbling: true,