Rag-Assistant / frontend /src /components /FileUpload.jsx
AsrorAsr's picture
Upload folder using huggingface_hub
9330b9f verified
Raw
History Blame Contribute Delete
3.94 kB
import { useState, useRef } from 'react';
import { uploadDocument } from '../services/api';
export default function FileUpload({ onUploadSuccess, documentCount }) {
const [isDragging, setIsDragging] = useState(false);
const [isUploading, setIsUploading] = useState(false);
const [progress, setProgress] = useState('');
const [error, setError] = useState('');
const fileInputRef = useRef(null);
const isLimitReached = typeof documentCount === 'number' && documentCount >= 3;
const handleDragOver = (e) => {
e.preventDefault();
if (!isLimitReached) setIsDragging(true);
};
const handleDragLeave = (e) => {
e.preventDefault();
setIsDragging(false);
};
const handleDrop = (e) => {
e.preventDefault();
setIsDragging(false);
if (!isLimitReached) {
const files = e.dataTransfer.files;
if (files.length > 0) handleFile(files[0]);
}
};
const handleFileSelect = (e) => {
if (!isLimitReached && e.target.files.length > 0) handleFile(e.target.files[0]);
};
const handleFile = async (file) => {
if (isLimitReached) {
setError('Maximum limit of 3 documents reached.');
return;
}
if (!file.name.toLowerCase().endsWith('.pdf')) {
setError('Only PDF files are supported');
return;
}
if (file.size > 50 * 1024 * 1024) {
setError('File size must be under 50MB');
return;
}
setError('');
setIsUploading(true);
setProgress('Uploading and processing...');
try {
const result = await uploadDocument(file);
setProgress(`✅ ${result.message}`);
onUploadSuccess?.(result.document);
setTimeout(() => setProgress(''), 3000);
} catch (err) {
setError(err.message);
} finally {
setIsUploading(false);
if (fileInputRef.current) fileInputRef.current.value = '';
}
};
return (
<div className="file-upload-container">
<div
className={`drop-zone ${isDragging && !isLimitReached ? 'dragging' : ''} ${isUploading ? 'uploading' : ''} ${isLimitReached ? 'disabled' : ''}`}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
onClick={() => !isUploading && !isLimitReached && fileInputRef.current?.click()}
style={isLimitReached ? { opacity: 0.5, cursor: 'not-allowed', borderColor: 'var(--border)' } : {}}
>
<input
ref={fileInputRef}
type="file"
accept=".pdf"
onChange={handleFileSelect}
style={{ display: 'none' }}
disabled={isLimitReached}
/>
<div className="drop-zone-content">
{isUploading ? (
<>
<div className="upload-spinner"></div>
<p className="upload-status">{progress}</p>
</>
) : (
<>
<div className="upload-icon">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
<polyline points="17 8 12 3 7 8" />
<line x1="12" y1="3" x2="12" y2="15" />
</svg>
</div>
<p className="drop-zone-text">
{isLimitReached ? (
<span style={{color: 'salmon'}}>Limit reached (3 max). Delete a file to upload.</span>
) : (
<>Drop your PDF here or <span className="browse-link">browse</span></>
)}
</p>
<p className="drop-zone-hint">Supports PDF up to 50MB</p>
</>
)}
</div>
</div>
{error && (
<div className="upload-error">
<span>⚠️</span> {error}
</div>
)}
{progress && !isUploading && (
<div className="upload-success">{progress}</div>
)}
</div>
);
}