import { gothampro, fluxgore } from "@/utils/fonts"; import React, { useState, useRef, DragEvent, ChangeEvent } from "react"; interface FileUploadProps { label?: string; onFileSelect?: (files: File[]) => void; acceptedTypes?: string[]; maxFileSize?: number; // in MB maxFiles?: number; // maximum number of files multiple?: boolean; disabled?: boolean; placeholder?: string; id?: string; name?: string; required?: boolean; } function Fileupload({ label, onFileSelect, acceptedTypes = ["image/*", "application/pdf", ".doc", ".docx"], maxFileSize = 10, maxFiles = 5, multiple = false, disabled = false, placeholder = "Файл в формате jpg или png до N мб", id, name, required = false, }: FileUploadProps) { const [dragActive, setDragActive] = useState(false); const [selectedFiles, setSelectedFiles] = useState([]); const [errors, setErrors] = useState([]); const fileInputRef = useRef(null); const validateFiles = ( files: File[] ): { valid: File[]; errors: string[] } => { const validFiles: File[] = []; const fileErrors: string[] = []; files.forEach((file) => { // Check file size if (file.size > maxFileSize * 1024 * 1024) { fileErrors.push(`${file.name} is too large (max ${maxFileSize}MB)`); return; } // Check file type const isValidType = acceptedTypes.some((type) => { if (type.includes("*")) { return file.type.startsWith(type.split("*")[0]); } return file.type === type || file.name.toLowerCase().endsWith(type); }); if (!isValidType) { fileErrors.push(`${file.name} is not a supported file type`); return; } validFiles.push(file); }); return { valid: validFiles, errors: fileErrors }; }; const handleFiles = (files: FileList | null) => { if (!files) return; const fileArray = Array.from(files); const { valid, errors: validationErrors } = validateFiles(fileArray); const allErrors = [...validationErrors]; if (valid.length > 0) { let newFiles: File[]; if (multiple) { // Check if adding new files would exceed maxFiles limit const totalFiles = selectedFiles.length + valid.length; if (totalFiles > maxFiles) { const allowedCount = maxFiles - selectedFiles.length; if (allowedCount <= 0) { allErrors.push( `Maximum ${maxFiles} files allowed. Remove some files first.` ); setErrors(allErrors); return; } else { allErrors.push( `Only ${allowedCount} more files can be added (max ${maxFiles} total).` ); newFiles = [...selectedFiles, ...valid.slice(0, allowedCount)]; } } else { newFiles = [...selectedFiles, ...valid]; } } else { newFiles = valid; } setSelectedFiles(newFiles); onFileSelect?.(newFiles); } setErrors(allErrors); }; const handleDrag = (e: DragEvent) => { e.preventDefault(); e.stopPropagation(); if (e.type === "dragenter" || e.type === "dragover") { setDragActive(true); } else if (e.type === "dragleave") { setDragActive(false); } }; const handleDrop = (e: DragEvent) => { e.preventDefault(); e.stopPropagation(); setDragActive(false); if (disabled) return; if (e.dataTransfer.files) { handleFiles(e.dataTransfer.files); } }; const handleInputChange = (e: ChangeEvent) => { handleFiles(e.target.files); }; const removeFile = (index: number) => { const updatedFiles = selectedFiles.filter((_, i) => i !== index); setSelectedFiles(updatedFiles); onFileSelect?.(updatedFiles); }; const openFileDialog = () => { if (!disabled && fileInputRef.current) { fileInputRef.current.click(); } }; // Check if upload button should be disabled const isUploadDisabled = disabled || (multiple && selectedFiles.length >= maxFiles); return (
{label && ( )} {/* Upload Area */}
{/* Upload Button */} {/* File Display Area */}
{selectedFiles.length > 0 ? (
{selectedFiles[0].name} {multiple && selectedFiles.length > 1 && ( and {selectedFiles.length - 1} more )}
) : ( {placeholder.replace("N", maxFileSize.toString())} )}
{/* File count indicator for multiple files */} {multiple && selectedFiles.length > 0 && (
{selectedFiles.length} of {maxFiles} files selected
)} {/* Error Messages */} {errors.length > 0 && (
{errors.map((error, index) => (
{error}
))}
)} {/* Additional Files (if multiple) */} {multiple && selectedFiles.length > 1 && (
{selectedFiles.slice(1).map((file, index) => (
{file.name}
))}
)}
); } export default Fileupload;