import type { VocabularyEntry, OcrPrompts, IpaMode, SyllableMode } from './types' import { getApiBase } from './constants' /** * Process a single page and return vocabulary + optional scan quality info. */ export async function processSinglePage( sessionId: string, pageIndex: number, ipa: IpaMode, syllable: SyllableMode, ocrPrompts: OcrPrompts, ocrEnhance: boolean, ocrMaxCols: number, ocrMinConf: number, ): Promise<{ success: boolean; vocabulary: VocabularyEntry[]; error?: string; scanQuality?: any }> { const API_BASE = getApiBase() try { const params = new URLSearchParams({ ipa_mode: ipa, syllable_mode: syllable, enhance: String(ocrEnhance), max_cols: String(ocrMaxCols), min_conf: String(ocrMinConf), }) const res = await fetch(`${API_BASE}/api/v1/vocab/sessions/${sessionId}/process-single-page/${pageIndex}?${params}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ocr_prompts: ocrPrompts }), }) if (!res.ok) { const errBody = await res.json().catch(() => ({})) const detail = errBody.detail || `HTTP ${res.status}` return { success: false, vocabulary: [], error: `Seite ${pageIndex + 1}: ${detail}` } } const data = await res.json() if (!data.success) { return { success: false, vocabulary: [], error: data.error || `Seite ${pageIndex + 1}: Unbekannter Fehler` } } return { success: true, vocabulary: data.vocabulary || [], scanQuality: data.scan_quality } } catch (e) { return { success: false, vocabulary: [], error: `Seite ${pageIndex + 1}: ${e instanceof Error ? e.message : 'Netzwerkfehler'}` } } } /** * Reprocess pages with updated IPA/syllable settings. * Returns the new vocabulary array. */ export async function reprocessPagesFlow( sessionId: string, pagesToReprocess: number[], ipa: IpaMode, syllable: SyllableMode, ocrPrompts: OcrPrompts, ocrEnhance: boolean, ocrMaxCols: number, ocrMinConf: number, setExtractionStatus: (s: string) => void, ): Promise<{ vocabulary: VocabularyEntry[]; qualityInfo: string }> { const API_BASE = getApiBase() const allVocab: VocabularyEntry[] = [] let lastQuality: any = null for (const pageIndex of pagesToReprocess) { setExtractionStatus(`Verarbeite Seite ${pageIndex + 1}...`) try { const params = new URLSearchParams({ ipa_mode: ipa, syllable_mode: syllable, enhance: String(ocrEnhance), max_cols: String(ocrMaxCols), min_conf: String(ocrMinConf), }) const res = await fetch(`${API_BASE}/api/v1/vocab/sessions/${sessionId}/process-single-page/${pageIndex}?${params}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ocr_prompts: ocrPrompts }), }) if (res.ok) { const data = await res.json() if (data.vocabulary) allVocab.push(...data.vocabulary) if (data.scan_quality) lastQuality = data.scan_quality } } catch { /* ignore individual page failures */ } } const qualityInfo = lastQuality ? ` | Qualitaet: ${lastQuality.quality_pct}%${lastQuality.is_degraded ? ' (degradiert!)' : ''} | Blur: ${lastQuality.blur_score} | Kontrast: ${lastQuality.contrast_score}` : '' return { vocabulary: allVocab, qualityInfo } }