diff --git a/admin-lehrer/app/(admin)/ai/ocr-pipeline/types.ts b/admin-lehrer/app/(admin)/ai/ocr-pipeline/types.ts index e5d50d2..abe59f2 100644 --- a/admin-lehrer/app/(admin)/ai/ocr-pipeline/types.ts +++ b/admin-lehrer/app/(admin)/ai/ocr-pipeline/types.ts @@ -181,12 +181,14 @@ export interface WordEntry { german: string example: string source_page?: string + marker?: string confidence: number bbox: WordBbox bbox_en: WordBbox | null bbox_de: WordBbox | null bbox_ex: WordBbox | null bbox_ref?: WordBbox | null + bbox_marker?: WordBbox | null status?: 'pending' | 'confirmed' | 'edited' | 'skipped' } diff --git a/admin-lehrer/components/ocr-pipeline/StepLlmReview.tsx b/admin-lehrer/components/ocr-pipeline/StepLlmReview.tsx index 89640d5..7694217 100644 --- a/admin-lehrer/components/ocr-pipeline/StepLlmReview.tsx +++ b/admin-lehrer/components/ocr-pipeline/StepLlmReview.tsx @@ -1,7 +1,7 @@ 'use client' import { useCallback, useEffect, useRef, useState } from 'react' -import type { GridResult, WordEntry } from '@/app/(admin)/ai/ocr-pipeline/types' +import type { GridResult, WordEntry, ColumnMeta } from '@/app/(admin)/ai/ocr-pipeline/types' const KLAUSUR_API = '/klausur-api' @@ -34,6 +34,26 @@ const FIELD_LABELS: Record = { english: 'EN', german: 'DE', example: 'Beispiel', + source_page: 'Seite', + marker: 'Marker', +} + +/** Map column type to WordEntry field name */ +const COL_TYPE_TO_FIELD: Record = { + column_en: 'english', + column_de: 'german', + column_example: 'example', + page_ref: 'source_page', + column_marker: 'marker', +} + +/** Column type → color class */ +const COL_TYPE_COLOR: Record = { + column_en: 'text-blue-600 dark:text-blue-400', + column_de: 'text-green-600 dark:text-green-400', + column_example: 'text-orange-600 dark:text-orange-400', + page_ref: 'text-cyan-600 dark:text-cyan-400', + column_marker: 'text-gray-500 dark:text-gray-400', } type RowStatus = 'pending' | 'active' | 'reviewed' | 'corrected' | 'skipped' @@ -51,6 +71,7 @@ export function StepLlmReview({ sessionId, onNext }: StepLlmReviewProps) { // Full vocab table state const [vocabEntries, setVocabEntries] = useState([]) + const [columnsUsed, setColumnsUsed] = useState([]) const [activeRowIndices, setActiveRowIndices] = useState>(new Set()) const [reviewedRows, setReviewedRows] = useState>(new Set()) const [skippedRows, setSkippedRows] = useState>(new Set()) @@ -86,6 +107,7 @@ export function StepLlmReview({ sessionId, onNext }: StepLlmReviewProps) { const entries = wordResult.vocab_entries || wordResult.entries || [] setVocabEntries(entries) + setColumnsUsed(wordResult.columns_used || []) // Check if LLM review was already run const llmReview = wordResult.llm_review @@ -458,9 +480,23 @@ export function StepLlmReview({ sessionId, onNext }: StepLlmReviewProps) { # - EN - DE - Beispiel + {columnsUsed.length > 0 ? ( + columnsUsed.map((col, i) => { + const field = COL_TYPE_TO_FIELD[col.type] + if (!field) return null + return ( + + {FIELD_LABELS[field] || field} + + ) + }) + ) : ( + <> + EN + DE + Beispiel + + )} Status @@ -486,15 +522,30 @@ export function StepLlmReview({ sessionId, onNext }: StepLlmReviewProps) { }`} > {idx} - - - - - - - - - + {columnsUsed.length > 0 ? ( + columnsUsed.map((col, i) => { + const field = COL_TYPE_TO_FIELD[col.type] + if (!field) return null + const text = (entry as Record)[field] as string || '' + return ( + + + + ) + }) + ) : ( + <> + + + + + + + + + + + )} diff --git a/admin-lehrer/components/ocr-pipeline/StepReconstruction.tsx b/admin-lehrer/components/ocr-pipeline/StepReconstruction.tsx index b564818..32ff351 100644 --- a/admin-lehrer/components/ocr-pipeline/StepReconstruction.tsx +++ b/admin-lehrer/components/ocr-pipeline/StepReconstruction.tsx @@ -264,6 +264,8 @@ export function StepReconstruction({ sessionId, onNext }: StepReconstructionProp column_de: 'border-green-400/40 focus:border-green-500', column_example: 'border-orange-400/40 focus:border-orange-500', column_text: 'border-purple-400/40 focus:border-purple-500', + page_ref: 'border-cyan-400/40 focus:border-cyan-500', + column_marker: 'border-gray-400/40 focus:border-gray-500', } return colors[colType] || 'border-gray-400/40 focus:border-gray-500' }