Spaces:
Sleeping
Sleeping
File size: 4,003 Bytes
2341446 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
"use client"
import { useState, useRef } from 'react'
import { Box, Typography, Button, CircularProgress, Chip, Stack } from '@mui/material'
import UploadFileIcon from '@mui/icons-material/UploadFile'
import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile'
interface FileUploadProps {
onDocumentsLoaded: (documents: { text: string }[]) => void;
}
export default function FileUpload({ onDocumentsLoaded }: FileUploadProps) {
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const [uploadedFiles, setUploadedFiles] = useState<string[]>([])
const fileInputRef = useRef<HTMLInputElement>(null)
const handleButtonClick = () => {
fileInputRef.current?.click()
}
const handleFileUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
const files = e.target.files
if (!files?.length) return
setLoading(true)
setError(null)
try {
const formData = new FormData()
const fileNames: string[] = []
Array.from(files).forEach(file => {
formData.append('files', file)
fileNames.push(file.name)
})
const response = await fetch('/api/upload', {
method: 'POST',
body: formData,
})
if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.error || 'Upload failed')
}
const data = await response.json()
setUploadedFiles(prev => [...prev, ...fileNames])
onDocumentsLoaded(data.documents)
} catch (err) {
console.error('Upload error:', err)
setError(err instanceof Error ? err.message : 'Failed to process files. Please try again.')
} finally {
setLoading(false)
if (fileInputRef.current) {
fileInputRef.current.value = ''
}
}
}
return (
<Box>
<Typography variant="subtitle1" sx={{ mb: 1, color: 'text.primary' }}>
Upload Documents
</Typography>
<Typography variant="body2" sx={{ mb: 2, color: 'text.secondary' }}>
You can upload multiple PDF and Word documents at once
</Typography>
{uploadedFiles.length > 0 && (
<Box sx={{ mb: 3 }}>
<Typography variant="body2" sx={{ mb: 1, color: 'text.secondary' }}>
{uploadedFiles.length} {uploadedFiles.length === 1 ? 'file' : 'files'} uploaded
</Typography>
<Stack direction="row" spacing={1} sx={{ flexWrap: 'wrap', gap: 1 }}>
{uploadedFiles.map((fileName, index) => (
<Chip
key={index}
icon={<InsertDriveFileIcon />}
label={fileName}
variant="outlined"
sx={{
backgroundColor: 'rgba(37, 99, 235, 0.1)',
borderColor: 'rgba(37, 99, 235, 0.2)',
'& .MuiChip-icon': {
color: 'primary.main',
}
}}
/>
))}
</Stack>
</Box>
)}
<input
ref={fileInputRef}
type="file"
onChange={handleFileUpload}
accept=".pdf,.doc,.docx"
multiple
style={{ display: 'none' }}
disabled={loading}
/>
<Button
variant="outlined"
fullWidth
onClick={handleButtonClick}
disabled={loading}
startIcon={loading ? <CircularProgress size={20} /> : <UploadFileIcon />}
sx={{
py: 3,
borderStyle: 'dashed',
borderWidth: 2,
backgroundColor: 'rgba(255, 255, 255, 0.8)',
'&:hover': {
borderColor: 'primary.main',
backgroundColor: 'rgba(37, 99, 235, 0.04)',
}
}}
>
{loading ? 'Processing...' : 'Click to upload PDF or Word documents'}
</Button>
{error && (
<Typography color="error" sx={{ mt: 2, fontSize: '0.875rem' }}>
{error}
</Typography>
)}
</Box>
)
} |