diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index fccf633..f1571c5 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -5,7 +5,7 @@ import { PDFViewer } from './viewer/PDFViewer'; import type { PDFViewerRef } from './viewer/PDFViewer'; import type { Annotation } from './viewer/AnnotationLayer'; import { gatewayService } from './lib/gatewayService'; -import type { DocumentInfo } from './lib/gatewayService'; +import type { DocumentInfo, SearchResult } from './lib/gatewayService'; import { wasmLoader } from './lib/wasmLoader'; import './App.css'; @@ -28,16 +28,30 @@ function App() { // Search State const [searchQuery, setSearchQuery] = useState(''); + const [searchResults, setSearchResults] = useState([]); const [searchResultCount, setSearchResultCount] = useState(0); const [searchCurrentMatch, setSearchCurrentMatch] = useState(0); - const handleSearch = (query: string) => { + const handleSearch = async (query: string) => { setSearchQuery(query); - // Mock search results for Phase 0 - if (query) { - setSearchResultCount(5); + if (!query || !selectedDocId) { + setSearchResults([]); + setSearchResultCount(0); setSearchCurrentMatch(0); - } else { + return; + } + + try { + const results = await gatewayService.searchDocument(selectedDocId, query); + setSearchResults(results); + setSearchResultCount(results.length); + setSearchCurrentMatch(0); + if (results.length > 0) { + viewerRef.current?.scrollToPage(results[0].pageIndex); + } + } catch (err) { + console.error("Search failed", err); + setSearchResults([]); setSearchResultCount(0); setSearchCurrentMatch(0); } @@ -45,13 +59,17 @@ function App() { const handleSearchNext = () => { if (searchResultCount > 0) { - setSearchCurrentMatch((prev) => (prev + 1) % searchResultCount); + const nextMatch = (searchCurrentMatch + 1) % searchResultCount; + setSearchCurrentMatch(nextMatch); + viewerRef.current?.scrollToPage(searchResults[nextMatch].pageIndex); } }; const handleSearchPrev = () => { if (searchResultCount > 0) { - setSearchCurrentMatch((prev) => (prev - 1 + searchResultCount) % searchResultCount); + const prevMatch = (searchCurrentMatch - 1 + searchResultCount) % searchResultCount; + setSearchCurrentMatch(prevMatch); + viewerRef.current?.scrollToPage(searchResults[prevMatch].pageIndex); } }; @@ -310,11 +328,15 @@ function App() { ref={viewerRef} documentId={activeDoc.id} totalPages={activeDoc.totalPages} + pageWidth={activeDoc.pageWidth} + pageHeight={activeDoc.pageHeight} zoom={zoom} pagesInfo={activeDoc.pages} activeTool={activeTool} annotations={annotations} searchQuery={searchQuery} + searchResults={searchResults} + searchCurrentMatch={searchCurrentMatch} onAnnotationAdded={handleAnnotationAdded} onPageVisible={setCurrentPage} /> diff --git a/frontend/src/components/Toolbar.tsx b/frontend/src/components/Toolbar.tsx index 943d30f..ceca69f 100644 --- a/frontend/src/components/Toolbar.tsx +++ b/frontend/src/components/Toolbar.tsx @@ -160,6 +160,14 @@ export const Toolbar: React.FC = ({ Highlight + +