import React, { useCallback, useState } from 'react'; import { CsvInputRow, REQUIRED_CSV_HEADERS } from '../types'; import { UploadIcon } from './Icons'; // This tells TypeScript that `Papa` is available on the global window object. declare const Papa: any; interface FileUploadProps { onFileParsed: (data: CsvInputRow[], file: File) => void; onParseError: (message: string) => void; disabled: boolean; } const FileUpload: React.FC = ({ onFileParsed, onParseError, disabled }) => { const [isDragging, setIsDragging] = useState(false); const handleFile = useCallback((file: File) => { if (!file) { onParseError('No file selected.'); return; } if (file.type !== 'text/csv') { onParseError('Invalid file type. Please upload a CSV file.'); return; } Papa.parse(file, { header: true, skipEmptyLines: true, complete: (results: any) => { if (results.errors.length > 0) { console.error('CSV Parsing Errors:', results.errors); onParseError(`Error parsing CSV: ${results.errors[0].message}`); return; } const headers = results.meta.fields; const missingHeaders = REQUIRED_CSV_HEADERS.filter( (requiredHeader) => !headers.includes(requiredHeader) ); if (missingHeaders.length > 0) { onParseError(`Missing required CSV columns: ${missingHeaders.join(', ')}`); return; } onFileParsed(results.data as CsvInputRow[], file); }, error: (error: any) => { console.error('PapaParse Error:', error); onParseError('An unexpected error occurred while parsing the file.'); }, }); }, [onFileParsed, onParseError]); const handleDragEnter = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); if (!disabled) setIsDragging(true); }; const handleDragLeave = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); setIsDragging(false); }; const handleDragOver = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); }; const handleDrop = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); setIsDragging(false); if (disabled) return; if (e.dataTransfer.files && e.dataTransfer.files.length > 0) { handleFile(e.dataTransfer.files[0]); e.dataTransfer.clearData(); } }; const handleInputChange = (e: React.ChangeEvent) => { if (e.target.files && e.target.files.length > 0) { handleFile(e.target.files[0]); } }; const borderColor = isDragging ? 'border-blue-500' : 'border-gray-600'; const bgColor = isDragging ? 'bg-gray-700' : 'bg-gray-800'; return (
); }; export default FileUpload;