Spaces:
Sleeping
Sleeping
| import React, { useCallback } from 'react'; | |
| import { Upload, FileText, Loader2 } from 'lucide-react'; | |
| import { motion } from 'framer-motion'; | |
| const FileUpload = ({ onFileUpload, loading = false }) => { | |
| const handleDrop = useCallback((e) => { | |
| if (loading) return; // Prevent upload while processing | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| const files = Array.from(e.dataTransfer.files); | |
| if (files.length > 0) { | |
| onFileUpload(files); | |
| } | |
| }, [onFileUpload, loading]); | |
| const handleDragOver = (e) => { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| }; | |
| const handleFileSelect = (e) => { | |
| if (loading) return; // Prevent upload while processing | |
| const files = Array.from(e.target.files); | |
| if (files.length > 0) { | |
| onFileUpload(files); | |
| } | |
| }; | |
| return ( | |
| <motion.div | |
| initial={{ opacity: 0, y: 20 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| transition={{ duration: 0.5 }} | |
| className="glass-panel" | |
| style={{ | |
| padding: '4rem', | |
| textAlign: 'center', | |
| borderStyle: 'dashed', | |
| borderWidth: '2px', | |
| borderColor: loading ? 'var(--accent-primary)' : 'var(--border-color)', | |
| cursor: loading ? 'not-allowed' : 'pointer', | |
| display: 'flex', | |
| flexDirection: 'column', | |
| alignItems: 'center', | |
| justifyContent: 'center', | |
| minHeight: '400px', | |
| opacity: loading ? 0.7 : 1, | |
| transition: 'all 0.3s ease' | |
| }} | |
| onDrop={handleDrop} | |
| onDragOver={handleDragOver} | |
| onClick={() => !loading && document.getElementById('fileInput').click()} | |
| > | |
| <input | |
| type="file" | |
| id="fileInput" | |
| multiple | |
| accept=".csv" | |
| style={{ display: 'none' }} | |
| onChange={handleFileSelect} | |
| disabled={loading} | |
| /> | |
| <div style={{ | |
| background: loading ? 'rgba(127, 90, 240, 0.2)' : 'rgba(127, 90, 240, 0.1)', | |
| padding: '1.5rem', | |
| borderRadius: '50%', | |
| marginBottom: '1.5rem', | |
| animation: loading ? 'pulse 2s infinite' : 'none' | |
| }}> | |
| {loading ? ( | |
| <Loader2 size={48} color="var(--accent-primary)" style={{ | |
| animation: 'spin 1s linear infinite' | |
| }} /> | |
| ) : ( | |
| <Upload size={48} color="var(--accent-primary)" /> | |
| )} | |
| </div> | |
| <h2 style={{ fontSize: '1.5rem', marginBottom: '0.5rem', fontWeight: 600 }}> | |
| {loading ? 'Processando arquivos...' : 'Arraste e solte seus arquivos CSV'} | |
| </h2> | |
| <p style={{ color: 'var(--text-secondary)', marginBottom: '2rem' }}> | |
| {loading ? 'Aguarde enquanto processamos seus dados' : 'ou clique para selecionar do computador'} | |
| </p> | |
| {!loading && ( | |
| <div style={{ display: 'flex', gap: '1rem', flexWrap: 'wrap', justifyContent: 'center' }}> | |
| <span style={{ | |
| background: 'var(--surface-hover)', | |
| padding: '0.5rem 1rem', | |
| borderRadius: '20px', | |
| fontSize: '0.875rem', | |
| display: 'flex', | |
| alignItems: 'center', | |
| gap: '0.5rem' | |
| }}> | |
| <FileText size={14} /> Google Maps Exports | |
| </span> | |
| </div> | |
| )} | |
| </motion.div> | |
| ); | |
| }; | |
| export default FileUpload; | |