Spaces:
Sleeping
Sleeping
| import React, { useCallback, useState } from 'react'; | |
| import { useDropzone } from 'react-dropzone'; | |
| import { | |
| Box, | |
| Paper, | |
| Typography, | |
| CircularProgress, | |
| Alert, | |
| Button | |
| } from '@mui/material'; | |
| import CloudUploadIcon from '@mui/icons-material/CloudUpload'; | |
| import axios from 'axios'; | |
| const FileUpload = ({ onUploadSuccess, onProcessingStart, onProcessingEnd }) => { | |
| const [uploading, setUploading] = useState(false); | |
| const [error, setError] = useState(null); | |
| const [success, setSuccess] = useState(false); | |
| const onDrop = useCallback(async (acceptedFiles) => { | |
| if (acceptedFiles.length === 0) return; | |
| const file = acceptedFiles[0]; | |
| // Check file type | |
| if (!file.name.toLowerCase().endsWith('.txt') && !file.name.toLowerCase().endsWith('.pdf')) { | |
| setError('Only .txt and .pdf files are allowed'); | |
| return; | |
| } | |
| // Check file size (2MB limit) | |
| if (file.size > 2 * 1024 * 1024) { | |
| setError('File size exceeds 2MB limit'); | |
| return; | |
| } | |
| setUploading(true); | |
| setError(null); | |
| setSuccess(false); | |
| onProcessingStart(); | |
| const formData = new FormData(); | |
| formData.append('file', file); | |
| try { | |
| const response = await axios.post('http://localhost:8000/upload', formData, { | |
| headers: { | |
| 'Content-Type': 'multipart/form-data', | |
| }, | |
| }); | |
| setSuccess(true); | |
| onUploadSuccess(file.name); | |
| } catch (err) { | |
| console.error('Upload error:', err); | |
| setError(err.response?.data?.detail || 'Error uploading file. Please try again.'); | |
| } finally { | |
| setUploading(false); | |
| onProcessingEnd(); | |
| } | |
| }, [onUploadSuccess, onProcessingStart, onProcessingEnd]); | |
| const { getRootProps, getInputProps, isDragActive } = useDropzone({ | |
| onDrop, | |
| accept: { | |
| 'text/plain': ['.txt'], | |
| 'application/pdf': ['.pdf'], | |
| }, | |
| maxSize: 2 * 1024 * 1024, // 2MB | |
| multiple: false, | |
| }); | |
| return ( | |
| <Paper | |
| elevation={2} | |
| sx={{ | |
| p: 3, | |
| mb: 4, | |
| border: '2px dashed', | |
| borderColor: isDragActive ? 'primary.main' : 'grey.300', | |
| backgroundColor: isDragActive ? 'action.hover' : 'background.paper', | |
| transition: 'all 0.2s ease', | |
| }} | |
| > | |
| <Box | |
| {...getRootProps()} | |
| sx={{ | |
| display: 'flex', | |
| flexDirection: 'column', | |
| alignItems: 'center', | |
| justifyContent: 'center', | |
| cursor: 'pointer', | |
| minHeight: '200px', | |
| }} | |
| > | |
| <input {...getInputProps()} /> | |
| {uploading ? ( | |
| <Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}> | |
| <CircularProgress size={60} sx={{ mb: 2 }} /> | |
| <Typography variant="body1">Processing your file...</Typography> | |
| </Box> | |
| ) : ( | |
| <> | |
| <CloudUploadIcon sx={{ fontSize: 60, color: 'primary.main', mb: 2 }} /> | |
| <Typography variant="h6" gutterBottom> | |
| {isDragActive ? 'Drop the file here' : 'Drag & drop a file here, or click to select'} | |
| </Typography> | |
| <Typography variant="body2" color="text.secondary" align="center" sx={{ mb: 2 }}> | |
| Supported formats: .txt, .pdf (max 2MB) | |
| </Typography> | |
| <Button variant="contained" color="primary"> | |
| Select File | |
| </Button> | |
| </> | |
| )} | |
| </Box> | |
| {error && ( | |
| <Alert severity="error" sx={{ mt: 2 }}> | |
| {error} | |
| </Alert> | |
| )} | |
| {success && ( | |
| <Alert severity="success" sx={{ mt: 2 }}> | |
| File uploaded successfully! You can now ask questions about the document. | |
| </Alert> | |
| )} | |
| </Paper> | |
| ); | |
| }; | |
| export default FileUpload; |