import React, { useEffect, useState } from 'react'; import { AppStatus, type FileData, type FormResponse } from './types'; import { FileUpload } from './components/FileUpload'; import { SourceInput } from './components/SourceInput'; import { ReviewPanel } from './components/ReviewPanel'; import { ThemeToggle } from './components/ThemeToggle'; import { ProcessingIndicator } from './components/ProcessingIndicator'; import { processDocuments } from './services/api'; import { getPdfFields, type PdfFieldInfo } from './services/pdfService'; import { AlertTriangle, ArrowRight, Bot, FileCheck2, ScanText, Sparkles, } from 'lucide-react'; const App: React.FC = () => { const [status, setStatus] = useState(AppStatus.IDLE); const [formFile, setFormFile] = useState(null); const [sourceFiles, setSourceFiles] = useState([]); const [sourceText, setSourceText] = useState(''); const [pdfFields, setPdfFields] = useState([]); const [pdfFieldsChecked, setPdfFieldsChecked] = useState(false); const [responseData, setResponseData] = useState(null); const [error, setError] = useState(null); useEffect(() => { const run = async () => { if (!formFile) { setPdfFields([]); setPdfFieldsChecked(false); return; } if (formFile.type !== 'application/pdf') { setPdfFields([]); setPdfFieldsChecked(true); return; } const fields = await getPdfFields(formFile.base64); setPdfFields(fields); setPdfFieldsChecked(true); }; run(); }, [formFile]); const noAcroForm = !!formFile && pdfFieldsChecked && pdfFields.length === 0; const hasAnySource = sourceFiles.length > 0 || sourceText.trim().length > 0; const handleAnalyze = async () => { if (!formFile || !hasAnySource) return; if (pdfFields.length === 0) { setError( 'Das Ziel-PDF enthält keine AcroForm-Felder. Bitte ein Formular mit interaktiven Feldern hochladen.' ); setStatus(AppStatus.ERROR); return; } setStatus(AppStatus.PROCESSING); setError(null); try { const data = await processDocuments( formFile, sourceFiles, sourceText, pdfFields ); setResponseData(data); setStatus(AppStatus.REVIEW); } catch (e: unknown) { const msg = e instanceof Error ? e.message : String(e); setError(msg || 'Während der Analyse ist etwas schiefgelaufen.'); setStatus(AppStatus.ERROR); } }; const reset = () => { if (formFile?.previewUrl?.startsWith('blob:')) { URL.revokeObjectURL(formFile.previewUrl); } for (const f of sourceFiles) { if (f.previewUrl?.startsWith('blob:')) URL.revokeObjectURL(f.previewUrl); } setStatus(AppStatus.IDLE); setFormFile(null); setSourceFiles([]); setSourceText(''); setResponseData(null); setError(null); setPdfFields([]); setPdfFieldsChecked(false); }; if (status === AppStatus.REVIEW && responseData && formFile) { return (
Rentenversicherer
); } const analyzeDisabled = !formFile || !hasAnySource || !pdfFieldsChecked || pdfFields.length === 0 || status === AppStatus.PROCESSING; return (

Rentenversicherer

AcroForm-PDFs halbautomatisch ausfüllen

1. Scan 2. Extract 3. Review
{status === AppStatus.IDLE || status === AppStatus.ERROR ? ( <>

PDF-Formular automatisch ausfüllen

Original-PDF (mit AcroForm-Feldern) und beliebig viele Quelldokumente hochladen. Claude extrahiert die Daten, du prüfst und lädst das ausgefüllte — weiterhin editierbare — PDF runter.

{error && (

{error}

)} {noAcroForm && !error && (

Das Ziel-PDF enthält keine AcroForm-Felder. Nur Formulare mit interaktiven Feldern werden unterstützt.

)}
1

Ziel-Formular

{pdfFields.length > 0 && ( {pdfFields.length} AcroForm-Felder erkannt )}
2

Quelldokumente

{sourceFiles.length > 0 && ( {sourceFiles.length}{' '} {sourceFiles.length === 1 ? 'Datei' : 'Dateien'} )}
) : ( )}
); }; export default App;