Dr. Abdulmalek
deploy: OmniFile AI Processor v4.3.0
900df0b
import React, { useState, useCallback } from 'react';
import { Upload, File, X, AlertCircle } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card';
const FileUpload = ({ onFileSelect, acceptedTypes = '.pdf,.png,.jpg,.jpeg,.tiff,.tif,.txt' }) => {
const [dragActive, setDragActive] = useState(false);
const [selectedFile, setSelectedFile] = useState(null);
const [error, setError] = useState('');
const handleDrag = useCallback((e) => {
e.preventDefault();
e.stopPropagation();
if (e.type === 'dragenter' || e.type === 'dragover') {
setDragActive(true);
} else if (e.type === 'dragleave') {
setDragActive(false);
}
}, []);
const handleDrop = useCallback((e) => {
e.preventDefault();
e.stopPropagation();
setDragActive(false);
if (e.dataTransfer.files && e.dataTransfer.files[0]) {
handleFileSelection(e.dataTransfer.files[0]);
}
}, []);
const handleFileSelection = (file) => {
setError('');
// Check file size (50MB limit)
if (file.size > 50 * 1024 * 1024) {
setError('File size must be less than 50MB');
return;
}
// Check file type
const allowedTypes = acceptedTypes.split(',').map(type => type.trim().toLowerCase());
const fileExtension = '.' + file.name.split('.').pop().toLowerCase();
if (!allowedTypes.includes(fileExtension)) {
setError(`File type not supported. Allowed types: ${acceptedTypes}`);
return;
}
setSelectedFile(file);
onFileSelect(file);
};
const handleFileInput = (e) => {
if (e.target.files && e.target.files[0]) {
handleFileSelection(e.target.files[0]);
}
};
const removeFile = () => {
setSelectedFile(null);
setError('');
onFileSelect(null);
};
const formatFileSize = (bytes) => {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};
return (
<Card className="w-full">
<CardContent className="p-6">
<div className="space-y-4">
{!selectedFile ? (
<div
className={`relative border-2 border-dashed rounded-lg p-8 text-center transition-colors ${
dragActive
? 'border-blue-500 bg-blue-50'
: 'border-gray-300 hover:border-gray-400'
}`}
onDragEnter={handleDrag}
onDragLeave={handleDrag}
onDragOver={handleDrag}
onDrop={handleDrop}
>
<input
type="file"
accept={acceptedTypes}
onChange={handleFileInput}
className="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
/>
<div className="space-y-4">
<Upload className="mx-auto h-12 w-12 text-gray-400" />
<div>
<p className="text-lg font-medium text-gray-900">
Drop your file here, or{' '}
<span className="text-blue-600 hover:text-blue-500">browse</span>
</p>
<p className="text-sm text-gray-500 mt-2">
Supports: PDF, PNG, JPG, TIFF, TXT (max 50MB)
</p>
</div>
</div>
</div>
) : (
<div className="flex items-center justify-between p-4 bg-gray-50 rounded-lg">
<div className="flex items-center space-x-3">
<File className="h-8 w-8 text-blue-600" />
<div>
<p className="font-medium text-gray-900">{selectedFile.name}</p>
<p className="text-sm text-gray-500">{formatFileSize(selectedFile.size)}</p>
</div>
</div>
<Button
variant="ghost"
size="sm"
onClick={removeFile}
className="text-gray-500 hover:text-red-600"
>
<X className="h-4 w-4" />
</Button>
</div>
)}
{error && (
<div className="flex items-center space-x-2 text-red-600 bg-red-50 p-3 rounded-lg">
<AlertCircle className="h-4 w-4" />
<span className="text-sm">{error}</span>
</div>
)}
</div>
</CardContent>
</Card>
);
};
export default FileUpload;