Fix blank screen on Analyze; add mode selector to result view

showResultView now only activates after results exist (not during loading),
preventing AnimatePresence from blanking the screen mid-transition.
Adds a mode selector + Analyze button at the top of the result view so
additional modes can be run without leaving the page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Aaron Roberts
2026-06-10 21:55:23 +01:00
parent 07b2f2b6bc
commit a511db78cb

View File

@@ -54,10 +54,8 @@ function App() {
const COMMITTABLE_MODES = new Set(['plain_ocr', 'describe', 'freeform']) const COMMITTABLE_MODES = new Set(['plain_ocr', 'describe', 'freeform'])
const MODE_LABELS = { plain_ocr: 'OCR Text', describe: 'Description', freeform: 'Freeform' } const MODE_LABELS = { plain_ocr: 'OCR Text', describe: 'Description', freeform: 'Freeform' }
// Show the full-screen result view when any committable mode has a result (or is loading) // Show the full-screen result view once at least one committable mode has a result
const showResultView = view === 'new_job' && ( const showResultView = view === 'new_job' && Object.keys(modeResults).length > 0
Object.keys(modeResults).length > 0 || (loading && COMMITTABLE_MODES.has(mode))
)
const handleFileTypeChange = useCallback((newType) => { const handleFileTypeChange = useCallback((newType) => {
setImage(null) setImage(null)
@@ -254,7 +252,7 @@ function App() {
<main className="max-w-7xl mx-auto px-6 py-6"> <main className="max-w-7xl mx-auto px-6 py-6">
<AnimatePresence mode="wait"> <AnimatePresence mode="wait">
{/* ── Full-screen OCR result view (plain_ocr + result) ── */} {/* ── Full-screen OCR result view ── */}
{showResultView ? ( {showResultView ? (
<motion.div <motion.div
key="ocr_result" key="ocr_result"
@@ -263,6 +261,29 @@ function App() {
exit={{ opacity: 0, y: -20 }} exit={{ opacity: 0, y: -20 }}
className="flex flex-col gap-4" className="flex flex-col gap-4"
> >
{/* Run additional modes */}
<div className="glass p-4 rounded-2xl flex-shrink-0">
<ModeSelector
mode={mode} onModeChange={setMode}
prompt={prompt} onPromptChange={setPrompt}
findTerm={findTerm} onFindTermChange={setFindTerm}
/>
<div className="flex items-center gap-3 mt-3">
<motion.button
onClick={handleSubmit}
disabled={loading}
className={`flex items-center gap-2 px-5 py-2 rounded-xl font-medium text-sm transition-all ${loading ? 'opacity-50 cursor-not-allowed bg-white/5' : 'bg-gradient-to-r from-purple-600 to-cyan-600'}`}
whileHover={!loading ? { scale: 1.02 } : {}}
whileTap={!loading ? { scale: 0.98 } : {}}
>
{loading
? <><Loader2 className="w-4 h-4 animate-spin" /> Processing...</>
: <><Zap className="w-4 h-4" /> Analyze</>}
</motion.button>
{error && <p className="text-sm text-red-400">{error}</p>}
</div>
</div>
{/* Image + Text */} {/* Image + Text */}
<div className="grid gap-6" style={{ gridTemplateColumns: '1fr 1fr', height: '130vh' }}> <div className="grid gap-6" style={{ gridTemplateColumns: '1fr 1fr', height: '130vh' }}>
{imagePreview && typeof imagePreview === 'string' ? ( {imagePreview && typeof imagePreview === 'string' ? (