No preview
OCR Text (edit before committing)
Job saved — ID: {commitResult.job?.id}
{commitResult.error}
{error}
import { useState, useCallback } from 'react' import { motion, AnimatePresence } from 'framer-motion' import { Sparkles, Zap, Loader2, Settings, Image as ImageIcon, FileText, Layers, ChevronLeft, CheckCircle2, Database, } from 'lucide-react' import ImageUpload from './components/ImageUpload' import ModeSelector from './components/ModeSelector' import ResultPanel from './components/ResultPanel' import AdvancedSettings from './components/AdvancedSettings' import PDFProcessor from './components/PDFProcessor' import MetadataForm from './components/MetadataForm' import JobsPanel from './components/JobsPanel' import axios from 'axios' const API_BASE = import.meta.env.VITE_API_URL || '/api' const INPUT_CLASS = 'w-full bg-white/5 border border-white/10 rounded-lg px-3 py-2 text-sm text-gray-200 ' + 'placeholder-gray-600 focus:outline-none focus:border-purple-500/50 transition-colors' function App() { const [view, setView] = useState('new_job') // OCR state const [mode, setMode] = useState('plain_ocr') const [fileType, setFileType] = useState('image') const [image, setImage] = useState(null) const [imagePreview, setImagePreview] = useState(null) const [result, setResult] = useState(null) const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const [showAdvanced, setShowAdvanced] = useState(false) const [includeCaption, setIncludeCaption] = useState(false) const [prompt, setPrompt] = useState('') const [findTerm, setFindTerm] = useState('') const [advancedSettings, setAdvancedSettings] = useState({ base_size: 1024, image_size: 640, crop_mode: true, test_compress: false, }) const [metadata, setMetadata] = useState({ author: '', book: '', chapter: '', page: '' }) const [editedOcrText, setEditedOcrText] = useState('') const [commitLoading, setCommitLoading] = useState(false) const [commitResult, setCommitResult] = useState(null) // Whether to show the full-screen result view const showResultView = view === 'new_job' && mode === 'plain_ocr' && !!result const handleFileTypeChange = useCallback((newType) => { setImage(null) if (imagePreview) URL.revokeObjectURL(imagePreview) setImagePreview(null) setError(null) setResult(null) setFileType(newType) }, [imagePreview]) const handleImageSelect = useCallback((file) => { if (file === null) { setImage(null) if (imagePreview && fileType === 'image') URL.revokeObjectURL(imagePreview) setImagePreview(null) setError(null) setResult(null) setEditedOcrText('') setCommitResult(null) } else { setImage(file) setImagePreview(fileType === 'image' ? URL.createObjectURL(file) : file) setError(null) setResult(null) setEditedOcrText('') setCommitResult(null) } }, [imagePreview, fileType]) const handleSubmit = async () => { if (!image) { setError('Please upload an image first'); return } setLoading(true) setError(null) setCommitResult(null) try { const formData = new FormData() formData.append('image', image) formData.append('mode', mode) formData.append('prompt', prompt) formData.append('grounding', mode === 'find_ref') formData.append('include_caption', includeCaption) formData.append('find_term', findTerm) formData.append('schema', '') formData.append('base_size', advancedSettings.base_size) formData.append('image_size', advancedSettings.image_size) formData.append('crop_mode', advancedSettings.crop_mode) formData.append('test_compress', advancedSettings.test_compress) const response = await axios.post(`${API_BASE}/ocr`, formData, { headers: { 'Content-Type': 'multipart/form-data' }, }) setResult(response.data) setEditedOcrText(response.data.text || '') setCommitResult(null) } catch (err) { setError(err.response?.data?.detail || err.message || 'An error occurred') } finally { setLoading(false) } } const handleNewAnalysis = () => { setResult(null) setEditedOcrText('') setCommitResult(null) } const handleCommitJob = useCallback(async () => { if (!image) return setCommitLoading(true) setCommitResult(null) try { const formData = new FormData() formData.append('image', image) formData.append('author', metadata.author) formData.append('book', metadata.book) formData.append('chapter', metadata.chapter) formData.append('page', metadata.page) formData.append('ocr_text', editedOcrText) formData.append('mode', mode) const response = await axios.post(`${API_BASE}/jobs`, formData, { headers: { 'Content-Type': 'multipart/form-data' }, }) setCommitResult({ success: true, job: response.data }) } catch (err) { setCommitResult({ success: false, error: err.response?.data?.detail || err.message }) } finally { setCommitLoading(false) } }, [image, editedOcrText, metadata, mode]) const handleCopy = useCallback(() => { const text = editedOcrText || result?.text if (text) navigator.clipboard.writeText(text) }, [editedOcrText, result]) const handleDownload = useCallback(() => { const text = editedOcrText || result?.text if (!text) return const ext = { plain_ocr: 'txt', describe: 'txt', find_ref: 'txt', freeform: 'txt' }[mode] || 'txt' const blob = new Blob([text], { type: 'text/plain' }) const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = `deepseek-ocr-result.${ext}` a.click() URL.revokeObjectURL(url) }, [editedOcrText, result, mode]) const metaField = (key) => (e) => setMetadata(m => ({ ...m, [key]: e.target.value })) return (
Next-Gen Vision AI
No preview
OCR Text (edit before committing)
Job saved — ID: {commitResult.job?.id}
{commitResult.error}
{error}