import { useState, useCallback } from 'react' import { motion, AnimatePresence } from 'framer-motion' import { FileText, Download, Loader2, CheckCircle2, AlertCircle } from 'lucide-react' import axios from 'axios' const API_BASE = import.meta.env.VITE_API_URL || '/api' function PDFProcessor({ pdfFile, mode, prompt, advancedSettings, includeCaption }) { const [processing, setProcessing] = useState(false) const [progress, setProgress] = useState(0) const [result, setResult] = useState(null) const [error, setError] = useState(null) const [outputFormat, setOutputFormat] = useState('markdown') const formats = [ { value: 'markdown', label: 'Markdown', ext: 'md', icon: '📝' }, { value: 'html', label: 'HTML', ext: 'html', icon: '🌐' }, { value: 'docx', label: 'Word', ext: 'docx', icon: '📄' }, { value: 'json', label: 'JSON', ext: 'json', icon: '📊' } ] const handleProcess = useCallback(async () => { if (!pdfFile) return setProcessing(true) setError(null) setProgress(0) try { const formData = new FormData() formData.append('pdf_file', pdfFile) formData.append('mode', mode) formData.append('prompt', prompt) formData.append('output_format', outputFormat) formData.append('grounding', mode === 'find_ref') formData.append('include_caption', includeCaption) formData.append('extract_images', true) formData.append('dpi', 144) formData.append('base_size', advancedSettings.base_size) formData.append('image_size', advancedSettings.image_size) formData.append('crop_mode', advancedSettings.crop_mode) const response = await axios.post(`${API_BASE}/process-pdf`, formData, { headers: { 'Content-Type': 'multipart/form-data', }, responseType: outputFormat === 'json' ? 'json' : 'blob', onUploadProgress: (progressEvent) => { const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total) setProgress(percentCompleted) } }) if (outputFormat === 'json') { setResult(response.data) } else { // For file downloads (markdown, html, docx) const format = formats.find(f => f.value === outputFormat) const blob = new Blob([response.data], { type: response.headers['content-type'] }) const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = `ocr_result.${format.ext}` a.click() URL.revokeObjectURL(url) setResult({ success: true, message: `Document downloaded as ${format.label}`, format: outputFormat }) } setProgress(100) } catch (err) { console.error('PDF processing error:', err) setError(err.response?.data?.detail || err.message || 'Failed to process PDF') } finally { setProcessing(false) } }, [pdfFile, mode, prompt, outputFormat, includeCaption, advancedSettings]) const handleDownloadJSON = useCallback(() => { if (!result || outputFormat !== 'json') return const blob = new Blob([JSON.stringify(result, null, 2)], { type: 'application/json' }) const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = 'ocr_result.json' a.click() URL.revokeObjectURL(url) }, [result, outputFormat]) return (
{/* Format Selector */}
{formats.map((format) => ( setOutputFormat(format.value)} className={`p-3 rounded-xl text-sm font-medium transition-all ${ outputFormat === format.value ? 'bg-gradient-to-r from-purple-600 to-cyan-600 text-white' : 'glass text-gray-400 hover:bg-white/5' }`} whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} > {format.icon} {format.label} ))}
{/* Process Button */}
{processing ? ( <> Processing PDF... ) : ( <> Process PDF )}
{/* Progress Bar */} {processing && progress > 0 && (
Processing... {progress}%
)}
{/* Error Display */} {error && (

Processing Failed

{error}

)}
{/* Success Display */} {result && !error && (

{result.message || 'PDF processed successfully!'}

{outputFormat === 'json' && result.pages && (

Processed {result.total_pages} page{result.total_pages > 1 ? 's' : ''}

Download JSON
)}
)}
) } export default PDFProcessor