From 418eb48ee487ccd99285f78919ab57197a199fa7 Mon Sep 17 00:00:00 2001 From: perf3ct Date: Mon, 14 Jul 2025 21:44:29 +0000 Subject: [PATCH] feat(document_details): add "expand" to OCR text box --- frontend/src/pages/DocumentDetailsPage.tsx | 195 ++++++++++++++++++++- 1 file changed, 192 insertions(+), 3 deletions(-) diff --git a/frontend/src/pages/DocumentDetailsPage.tsx b/frontend/src/pages/DocumentDetailsPage.tsx index 611fea5..28fb5b8 100644 --- a/frontend/src/pages/DocumentDetailsPage.tsx +++ b/frontend/src/pages/DocumentDetailsPage.tsx @@ -21,6 +21,8 @@ import { Container, Fade, Skeleton, + TextField, + InputAdornment, } from '@mui/material'; import Grid from '@mui/material/GridLegacy'; import { @@ -46,6 +48,8 @@ import { History as HistoryIcon, Speed as SpeedIcon, MoreVert as MoreIcon, + OpenInFull as ExpandIcon, + Close as CloseIcon, } from '@mui/icons-material'; import { documentService, OcrResponse, type Document } from '../services/api'; import DocumentViewer from '../components/DocumentViewer'; @@ -77,6 +81,7 @@ const DocumentDetailsPage: React.FC = () => { const [processedImageLoading, setProcessedImageLoading] = useState(false); const [thumbnailUrl, setThumbnailUrl] = useState(null); const [documentLabels, setDocumentLabels] = useState([]); + const [ocrSearchTerm, setOcrSearchTerm] = useState(''); const [expandedOcrText, setExpandedOcrText] = useState(false); const [availableLabels, setAvailableLabels] = useState([]); const [showLabelDialog, setShowLabelDialog] = useState(false); const [labelsLoading, setLabelsLoading] = useState(false); @@ -723,9 +728,32 @@ const DocumentDetailsPage: React.FC = () => { }} > - - 🔍 Extracted Text (OCR) - + + + 🔍 Extracted Text (OCR) + + {ocrData?.ocr_text && ( + + setExpandedOcrText(true)} + sx={{ + backgroundColor: theme.palette.primary.main, + color: theme.palette.primary.contrastText, + '&:hover': { + backgroundColor: theme.palette.primary.dark, + }, + borderRadius: 2, + px: 2, + }} + > + + + Expand + + + + )} + {ocrLoading ? ( @@ -1071,6 +1099,167 @@ const DocumentDetailsPage: React.FC = () => { + {/* Expanded OCR Text Dialog with Search */} + { + setExpandedOcrText(false); + setOcrSearchTerm(''); + }} + maxWidth="lg" + fullWidth + PaperProps={{ + sx: { + height: '90vh', + backgroundColor: theme.palette.background.paper, + } + }} + > + + + + 🔍 Extracted Text (OCR) - Full View + + + {ocrData && ( + + {ocrData.ocr_confidence && ( + + )} + {ocrData.ocr_word_count && ( + + )} + + )} + { + setExpandedOcrText(false); + setOcrSearchTerm(''); + }} + sx={{ + backgroundColor: theme.palette.action.hover, + '&:hover': { + backgroundColor: theme.palette.action.selected, + }, + }} + > + + + + + + + {/* Search Bar */} + + setOcrSearchTerm(e.target.value)} + InputProps={{ + startAdornment: ( + + + + ), + endAdornment: ocrSearchTerm && ( + + setOcrSearchTerm('')} + > + + + + ), + }} + sx={{ + '& .MuiOutlinedInput-root': { + borderRadius: 2, + }, + }} + /> + {ocrSearchTerm && ( + + {(() => { + const text = ocrData?.ocr_text || ''; + const matches = text.toLowerCase().split(ocrSearchTerm.toLowerCase()).length - 1; + return matches > 0 ? `${matches} match${matches === 1 ? '' : 'es'} found` : 'No matches found'; + })()} + + )} + + + {/* OCR Text Content */} + + {ocrLoading ? ( + + + + Loading OCR text... + + + ) : ( + <> + {ocrData && ocrData.ocr_error && ( + + OCR Error: {ocrData.ocr_error} + + )} + + $1' + ) + : ocrData.ocr_text + ) : 'No OCR text available for this document.' + }} + /> + + {ocrData && (ocrData.ocr_processing_time_ms || ocrData.ocr_completed_at) && ( + + + {ocrData.ocr_processing_time_ms && `Processing time: ${ocrData.ocr_processing_time_ms}ms`} + {ocrData.ocr_processing_time_ms && ocrData.ocr_completed_at && ' • '} + {ocrData.ocr_completed_at && `Completed: ${new Date(ocrData.ocr_completed_at).toLocaleString()}`} + + + )} + + )} + + + + {/* Document View Dialog */}