@@ -12,7 +12,7 @@ import {
1212 Trash2 ,
1313 X ,
1414} from 'lucide-react'
15- import { useParams } from 'next/navigation'
15+ import { useParams , useRouter , useSearchParams } from 'next/navigation'
1616import { Button } from '@/components/ui/button'
1717import { Checkbox } from '@/components/ui/checkbox'
1818import { Tooltip , TooltipContent , TooltipTrigger } from '@/components/ui/tooltip'
@@ -57,11 +57,37 @@ export function Document({
5757 const { mode, isExpanded } = useSidebarStore ( )
5858 const { getCachedKnowledgeBase, getCachedDocuments } = useKnowledgeStore ( )
5959 const { workspaceId } = useParams ( )
60+ const router = useRouter ( )
61+ const searchParams = useSearchParams ( )
6062
6163 const isSidebarCollapsed =
6264 mode === 'expanded' ? ! isExpanded : mode === 'collapsed' || mode === 'hover'
6365
64- const [ searchQuery , setSearchQuery ] = useState ( '' )
66+ const currentPageFromURL = parseInt ( searchParams . get ( 'page' ) || '1' , 10 )
67+ const searchQueryFromURL = searchParams . get ( 'search' ) || ''
68+
69+ const [ searchQuery , setSearchQuery ] = useState ( searchQueryFromURL )
70+
71+ const debouncedSearchQuery = useDebounce ( searchQuery , 800 )
72+
73+ const updateURL = useCallback ( ( newSearch : string , newPage : number = 1 ) => {
74+ const params = new URLSearchParams ( searchParams )
75+
76+ if ( newSearch ) {
77+ params . set ( 'search' , newSearch )
78+ } else {
79+ params . delete ( 'search' )
80+ }
81+
82+ if ( newPage > 1 ) {
83+ params . set ( 'page' , newPage . toString ( ) )
84+ } else {
85+ params . delete ( 'page' )
86+ }
87+
88+ router . replace ( `?${ params . toString ( ) } ` , { scroll : false } )
89+ } , [ router , searchParams ] )
90+
6591 const [ selectedChunks , setSelectedChunks ] = useState < Set < string > > ( new Set ( ) )
6692 const [ selectedChunk , setSelectedChunk ] = useState < ChunkData | null > ( null )
6793 const [ isModalOpen , setIsModalOpen ] = useState ( false )
@@ -70,16 +96,11 @@ export function Document({
7096 const [ isDeleteModalOpen , setIsDeleteModalOpen ] = useState ( false )
7197 const [ isBulkOperating , setIsBulkOperating ] = useState ( false )
7298 const [ pageBeforeSearch , setPageBeforeSearch ] = useState ( 1 )
73- const [ previousSearchQuery , setPreviousSearchQuery ] = useState ( '' )
7499
75100 const [ document , setDocument ] = useState < DocumentData | null > ( null )
76101 const [ isLoadingDocument , setIsLoadingDocument ] = useState ( true )
77102 const [ error , setError ] = useState < string | null > ( null )
78103
79- // Debounce the search query to avoid excessive API calls
80- const debouncedSearchQuery = useDebounce ( searchQuery , 500 )
81-
82- // Use the updated chunks hook with pagination
83104 const {
84105 chunks,
85106 isLoading : isLoadingChunks ,
@@ -94,81 +115,60 @@ export function Document({
94115 refreshChunks,
95116 updateChunk,
96117 searchChunks,
97- clearSearchAndGoToPage,
98- } = useDocumentChunks ( knowledgeBaseId , documentId )
118+ } = useDocumentChunks ( knowledgeBaseId , documentId , currentPageFromURL , searchQueryFromURL )
99119
100- // Combine errors
101120 const combinedError = error || chunksError
102121
103- // Handle search functionality with debounce
104122 useEffect ( ( ) => {
105123 if ( ! knowledgeBaseId || ! documentId ) return
106-
107- const handleSearch = async ( ) => {
108- try {
109- if ( debouncedSearchQuery . trim ( ) ) {
110- // Perform the search
111- await searchChunks ( debouncedSearchQuery . trim ( ) )
112- } else {
113- // If clearing search, return to the page we were on before searching
114- await clearSearchAndGoToPage ( pageBeforeSearch )
115- }
116- } catch ( err ) {
117- logger . error ( 'Search failed:' , err )
124+
125+ if ( debouncedSearchQuery !== searchQueryFromURL ) {
126+ if ( debouncedSearchQuery . trim ( ) . length >= 2 ) {
127+ // Starting a search - go to page 1
128+ updateURL ( debouncedSearchQuery , 1 )
129+ } else if ( debouncedSearchQuery . trim ( ) === '' ) {
130+ // Clearing search - return to page before search
131+ updateURL ( debouncedSearchQuery , pageBeforeSearch )
118132 }
119133 }
134+ } , [ debouncedSearchQuery , searchQueryFromURL , updateURL , knowledgeBaseId , documentId , pageBeforeSearch ] )
120135
121- handleSearch ( )
122- } , [ debouncedSearchQuery , knowledgeBaseId , documentId , pageBeforeSearch ] )
136+ useEffect ( ( ) => {
137+ setSearchQuery ( searchQueryFromURL )
138+ } , [ searchQueryFromURL ] )
123139
124- // Track search state changes and save page when starting search
140+ // Track when search starts to save current page
125141 useEffect ( ( ) => {
126- const isStartingSearch = ! previousSearchQuery . trim ( ) && searchQuery . trim ( )
142+ const isStartingSearch = ! searchQueryFromURL && searchQuery . trim ( )
127143
128144 if ( isStartingSearch ) {
129- setPageBeforeSearch ( currentPage )
145+ // User just started typing, save current page
146+ setPageBeforeSearch ( currentPageFromURL )
130147 }
131-
132- // Always update the previous search query for next comparison
133- setPreviousSearchQuery ( searchQuery )
134- } , [ searchQuery , previousSearchQuery ] )
148+ } , [ searchQuery , searchQueryFromURL , currentPageFromURL ] )
135149
136- // Handle pagination navigation
137150 const handlePrevPage = useCallback ( ( ) => {
138- if ( hasPrevPage && ! isLoadingChunks ) {
139- prevPage ( ) ?. catch ( ( err ) => {
140- logger . error ( 'Previous page failed:' , err )
141- } )
151+ if ( hasPrevPage ) {
152+ updateURL ( searchQuery , currentPageFromURL - 1 )
142153 }
143- } , [ hasPrevPage , isLoadingChunks , prevPage ] )
154+ } , [ hasPrevPage , updateURL , searchQuery , currentPageFromURL ] )
144155
145156 const handleNextPage = useCallback ( ( ) => {
146- if ( hasNextPage && ! isLoadingChunks ) {
147- nextPage ( ) ?. catch ( ( err ) => {
148- logger . error ( 'Next page failed:' , err )
149- } )
157+ if ( hasNextPage ) {
158+ updateURL ( searchQuery , currentPageFromURL + 1 )
150159 }
151- } , [ hasNextPage , isLoadingChunks , nextPage ] )
152-
153- const handleGoToPage = useCallback (
154- ( page : number ) => {
155- if ( page !== currentPage && ! isLoadingChunks ) {
156- goToPage ( page ) ?. catch ( ( err ) => {
157- logger . error ( 'Go to page failed:' , err )
158- } )
159- }
160- } ,
161- [ currentPage , isLoadingChunks , goToPage ]
162- )
160+ } , [ hasNextPage , updateURL , searchQuery , currentPageFromURL ] )
161+
162+ const handleGoToPage = useCallback ( ( page : number ) => {
163+ updateURL ( searchQuery , page )
164+ } , [ updateURL , searchQuery ] )
163165
164- // Try to get document from store cache first, then fetch if needed
165166 useEffect ( ( ) => {
166167 const fetchDocument = async ( ) => {
167168 try {
168169 setIsLoadingDocument ( true )
169170 setError ( null )
170171
171- // First try to get from cached documents in the store
172172 const cachedDocuments = getCachedDocuments ( knowledgeBaseId )
173173 const cachedDoc = cachedDocuments ?. find ( ( d ) => d . id === documentId )
174174
@@ -178,7 +178,6 @@ export function Document({
178178 return
179179 }
180180
181- // If not in cache, fetch from API
182181 const response = await fetch ( `/api/knowledge/${ knowledgeBaseId } /documents/${ documentId } ` )
183182
184183 if ( ! response . ok ) {
0 commit comments