diff --git a/admin-lehrer/app/(admin)/ai/ocr-pipeline/types.ts b/admin-lehrer/app/(admin)/ai/ocr-pipeline/types.ts index da938c4..1f7bd3d 100644 --- a/admin-lehrer/app/(admin)/ai/ocr-pipeline/types.ts +++ b/admin-lehrer/app/(admin)/ai/ocr-pipeline/types.ts @@ -227,6 +227,9 @@ export interface OcrWordBox { width: number // px height: number // px conf: number + color?: string // hex color of detected text, e.g. '#dc2626' + color_name?: string // 'black' | 'red' | 'blue' | 'green' | 'orange' | 'purple' | 'yellow' + recovered?: boolean // true if this word was recovered via color detection } export interface GridCell { diff --git a/admin-lehrer/components/grid-editor/GridEditor.tsx b/admin-lehrer/components/grid-editor/GridEditor.tsx index 18af07e..e159e9a 100644 --- a/admin-lehrer/components/grid-editor/GridEditor.tsx +++ b/admin-lehrer/components/grid-editor/GridEditor.tsx @@ -143,6 +143,23 @@ export function GridEditor({ sessionId, onNext }: GridEditorProps) { {grid.boxes_detected} Box(en) erkannt )} + {grid.summary.color_stats && Object.entries(grid.summary.color_stats) + .filter(([name]) => name !== 'black') + .map(([name, count]) => ( + + + {count} {name} + + )) + } + {(grid.summary.recovered_colored ?? 0) > 0 && ( + + +{grid.summary.recovered_colored} recovered + + )} {grid.duration_seconds.toFixed(1)}s diff --git a/admin-lehrer/components/grid-editor/GridTable.tsx b/admin-lehrer/components/grid-editor/GridTable.tsx index 106ed39..083bbad 100644 --- a/admin-lehrer/components/grid-editor/GridTable.tsx +++ b/admin-lehrer/components/grid-editor/GridTable.tsx @@ -51,6 +51,17 @@ export function GridTable({ cellMap.set(`${cell.row_index}_${cell.col_index}`, cell) } + /** Dominant non-black color from a cell's word_boxes, or null. */ + const getCellColor = (cell: (typeof zone.cells)[0] | undefined): string | null => { + if (!cell?.word_boxes?.length) return null + for (const wb of cell.word_boxes) { + if (wb.color_name && wb.color_name !== 'black' && wb.color) { + return wb.color + } + } + return null + } + const isBoxZone = zone.zone_type === 'box' return ( @@ -119,6 +130,7 @@ export function GridTable({ const isSelected = selectedCell === cellId const isBold = col.bold || cell?.is_bold const isLowConf = cell && cell.confidence > 0 && cell.confidence < 60 + const cellColor = getCellColor(cell) return ( - { - if (cell) onCellTextChange(cellId, e.target.value) - }} - onFocus={() => onSelectCell(cellId)} - onKeyDown={(e) => handleKeyDown(e, cellId)} - className={`w-full px-2 py-1.5 bg-transparent border-0 outline-none text-gray-800 dark:text-gray-200 ${ - isBold ? 'font-bold' : 'font-normal' - } ${row.is_header ? 'text-base' : 'text-sm'}`} - spellCheck={false} - /> +
+ {cellColor && ( + wb.color_name !== 'black')?.color_name}`} + /> + )} + { + if (cell) onCellTextChange(cellId, e.target.value) + }} + onFocus={() => onSelectCell(cellId)} + onKeyDown={(e) => handleKeyDown(e, cellId)} + className={`w-full px-2 py-1.5 bg-transparent border-0 outline-none ${ + isBold ? 'font-bold' : 'font-normal' + } ${row.is_header ? 'text-base' : 'text-sm'}`} + style={cellColor ? { color: cellColor } : undefined} + spellCheck={false} + /> +
) })} diff --git a/admin-lehrer/components/grid-editor/types.ts b/admin-lehrer/components/grid-editor/types.ts index fa596c5..4ebcc89 100644 --- a/admin-lehrer/components/grid-editor/types.ts +++ b/admin-lehrer/components/grid-editor/types.ts @@ -22,6 +22,8 @@ export interface GridSummary { total_rows: number total_cells: number total_words: number + recovered_colored?: number + color_stats?: Record } export interface GridFormatting {