import { useState, useRef, useCallback } from 'react'; import { toast } from 'sonner'; interface UseFileUploadOptions { acceptedTypes?: string[]; maxSizeMB?: number; onFileSelected?: (file: File) => void; } interface UseFileUploadResult { fileInputRef: React.RefObject; isSelecting: boolean; selectedFile: File | null; triggerFileSelect: () => void; handleFileChange: (event: React.ChangeEvent) => void; clearSelectedFile: () => void; } /** * A custom hook for handling file uploads with validation */ export function useFileUpload(options: UseFileUploadOptions = {}): UseFileUploadResult { const { acceptedTypes = ['.xlsx', '.xls', '.csv'], maxSizeMB = 10, onFileSelected } = options; const fileInputRef = useRef(null); const [isSelecting, setIsSelecting] = useState(false); const [selectedFile, setSelectedFile] = useState(null); const triggerFileSelect = useCallback(() => { if (fileInputRef.current) { fileInputRef.current.click(); } }, []); const clearSelectedFile = useCallback(() => { setSelectedFile(null); if (fileInputRef.current) { fileInputRef.current.value = ''; } }, []); const handleFileChange = useCallback((event: React.ChangeEvent) => { setIsSelecting(true); try { const file = event.target.files?.[0]; if (!file) { return; } // Validate file type const fileExtension = file.name.substring(file.name.lastIndexOf('.')).toLowerCase(); if (acceptedTypes.length > 0 && !acceptedTypes.includes(fileExtension)) { toast.error(`Invalid file type. Accepted types: ${acceptedTypes.join(', ')}`); return; } // Validate file size const maxSizeBytes = maxSizeMB * 1024 * 1024; if (file.size > maxSizeBytes) { toast.error(`File size too large. Maximum size is ${maxSizeMB}MB`); return; } // Set the selected file setSelectedFile(file); // Call the onFileSelected callback if provided if (onFileSelected) { onFileSelected(file); } // Reset input value event.target.value = ''; } catch (error) { console.error('Error selecting file:', error); toast.error('Error selecting file. Please try again.'); } finally { setIsSelecting(false); } }, [acceptedTypes, maxSizeMB, onFileSelected]); return { fileInputRef, isSelecting, selectedFile, triggerFileSelect, handleFileChange, clearSelectedFile, }; } export default useFileUpload;