'use client' import { useState } from 'react'; import { Dropzone, MIME_TYPES, FileRejection } from '@mantine/dropzone'; import { Button, Box, Text, Stack, Group, ActionIcon, Paper, Alert } from '@pikku/mantine/core'; import { IconX, IconPlus } from '@tabler/icons-react'; import { useI18n } from '@/context/i18n-provider'; import { asI18n } from '@pikku/react'; type UploadedFile = { id: string fileName: string } export type UploadFile = (files: File[]) => Promise export type DeleteFile = (id: string) => Promise interface FileUploadProps { multiple?: boolean; accept?: string; maxFileSize?: number; chooseLabel?: string; className?: string; files: UploadedFile[] uploadFiles: UploadFile deleteFile: DeleteFile } export const FileUpload: React.FunctionComponent = ({ multiple = true, accept = ".pdf,.jpg,.jpeg,.png", maxFileSize = 210000000, chooseLabel, files = [], uploadFiles, deleteFile }) => { const t = useI18n() const [uploading, setUploading] = useState(false); const [rejectionError, setRejectionError] = useState(null); const defaultChooseLabel = chooseLabel ? asI18n(chooseLabel) : t('jobs.fileupload.choosefile') const handleUpload = async (files: File[]) => { setRejectionError(null); // Clear any previous errors setUploading(true); try { await uploadFiles(files) } catch (error) { console.error('Error uploading files:', error) } setUploading(false); } const handleReject = (rejectedFiles: FileRejection[]) => { if (rejectedFiles.length > 0) { const firstError = rejectedFiles[0].errors[0]; let errorMessage: string; switch (firstError.code) { case 'file-invalid-type': errorMessage = t('jobs.fileupload.error.file-invalid-type'); break; case 'file-too-large': errorMessage = t('jobs.fileupload.error.file-too-large'); break; case 'file-too-small': errorMessage = t('jobs.fileupload.error.file-too-small'); break; case 'too-many-files': errorMessage = t('jobs.fileupload.error.too-many-files'); break; default: errorMessage = firstError.message; } setRejectionError(errorMessage); } } const handleDelete = async (file: UploadedFile) => { try { await deleteFile(file.id) } catch (error) { console.error('Error deleting file:', error) } } const acceptTypes = accept.split(',').map(type => { switch (type.trim()) { case '.pdf': return MIME_TYPES.pdf; case '.jpg': case '.jpeg': return MIME_TYPES.jpeg; case '.png': return MIME_TYPES.png; default: return type.trim(); } }); return ( {!files || files.length === 0 ? ( {t('jobs.fileupload.dragdroptext')} {t('jobs.fileupload.acceptedformats')}
{t('jobs.fileupload.maxsize')}
) : null}
{files && files.length > 0 && ( {files.map((file) => ( {asI18n(file.fileName)} handleDelete(file)} aria-label={t('jobs.fileupload.delete')} > ))} )} {rejectionError && ( setRejectionError(null)} withCloseButton> {asI18n(rejectionError)} )}
); }