@@ -9,10 +9,19 @@ export interface FilterState {
99 search : string | null ;
1010}
1111
12+ interface PaginatedResponse {
13+ items : Problem [ ] ;
14+ pagination : {
15+ page : number ;
16+ limit : number ;
17+ total : number ;
18+ totalPages : number ;
19+ } ;
20+ }
21+
1222const PAGE_SIZE = 20 ;
1323
1424export function useFilteredProblems ( ) {
15- // States for both filtering and pagination
1625 const [ problems , setProblems ] = useState < Problem [ ] > ( [ ] ) ;
1726 const [ filters , setFilters ] = useState < FilterState > ( {
1827 difficulty : null ,
@@ -21,59 +30,60 @@ export function useFilteredProblems() {
2130 search : null ,
2231 } ) ;
2332 const [ isLoading , setIsLoading ] = useState ( true ) ;
24- const [ page , setPage ] = useState ( 1 ) ;
2533 const [ hasMore , setHasMore ] = useState ( true ) ;
34+ const [ isEmpty , setIsEmpty ] = useState ( false ) ;
2635 const seenIds = useRef ( new Set < number > ( ) ) ;
36+ const currentPage = useRef ( 1 ) ;
2737
2838 const fetchProblems = useCallback (
29- async ( pageNum : number , isLoadingMore = false ) => {
39+ async ( isLoadingMore = false ) => {
3040 if ( ! isLoadingMore ) {
3141 seenIds . current . clear ( ) ;
42+ currentPage . current = 1 ;
43+ setIsEmpty ( false ) ;
3244 }
3345
3446 setIsLoading ( true ) ;
3547
3648 try {
3749 const params = new URLSearchParams ( ) ;
38- params . append ( 'page' , pageNum . toString ( ) ) ;
50+ params . append ( 'page' , currentPage . current . toString ( ) ) ;
3951 params . append ( 'limit' , PAGE_SIZE . toString ( ) ) ;
4052
41- // Apply filters to query
4253 if ( filters . difficulty ) params . append ( 'difficulty' , filters . difficulty ) ;
4354 if ( filters . status ) params . append ( 'status' , filters . status ) ;
4455 if ( filters . topics ?. length ) {
45- filters . topics . forEach ( ( topic ) => params . append ( 'topics' , topic ) ) ;
56+ params . append ( 'topics' , filters . topics . join ( ',' ) ) ;
4657 }
4758 if ( filters . search ) params . append ( 'search' , filters . search ) ;
4859
4960 const url = `/questions?${ params . toString ( ) } ` ;
50- const response = await axiosClient . get < Problem [ ] > ( url ) ;
51- const newProblems = response . data ;
61+ const response = await axiosClient . get < PaginatedResponse > ( url ) ;
62+ const { items : newProblems } = response . data ;
5263
53- if ( newProblems . length === 0 ) {
64+ if ( ! isLoadingMore && newProblems . length === 0 ) {
65+ setIsEmpty ( true ) ;
66+ setProblems ( [ ] ) ;
5467 setHasMore ( false ) ;
5568 return ;
5669 }
5770
5871 if ( isLoadingMore ) {
59- console . log ( 'Fetching a page of 20 items' ) ;
60- const uniqueNewProblems : Problem [ ] = [ ] ;
61- let foundDuplicate = false ;
62-
63- for ( const problem of newProblems ) {
72+ const uniqueNewProblems = newProblems . filter ( ( problem ) => {
6473 if ( seenIds . current . has ( problem . _id ) ) {
65- foundDuplicate = true ;
66- break ;
74+ return false ;
6775 }
6876 seenIds . current . add ( problem . _id ) ;
69- uniqueNewProblems . push ( problem ) ;
70- }
77+ return true ;
78+ } ) ;
7179
72- if ( foundDuplicate || uniqueNewProblems . length === 0 ) {
80+ if ( uniqueNewProblems . length === 0 ) {
7381 setHasMore ( false ) ;
82+ return ;
7483 }
7584
7685 setProblems ( ( prev ) => [ ...prev , ...uniqueNewProblems ] ) ;
86+ setHasMore ( newProblems . length === PAGE_SIZE ) ;
7787 } else {
7888 newProblems . forEach ( ( problem ) => seenIds . current . add ( problem . _id ) ) ;
7989 setProblems ( newProblems ) ;
@@ -82,14 +92,17 @@ export function useFilteredProblems() {
8292 } catch ( error ) {
8393 console . error ( 'Error fetching problems:' , error ) ;
8494 setHasMore ( false ) ;
95+ if ( ! isLoadingMore ) {
96+ setIsEmpty ( true ) ;
97+ setProblems ( [ ] ) ;
98+ }
8599 } finally {
86100 setIsLoading ( false ) ;
87101 }
88102 } ,
89103 [ filters ] ,
90- ) ; // Note filters dependency
104+ ) ;
91105
92- // Filter functions
93106 const updateFilter = useCallback (
94107 ( key : keyof FilterState , value : string | string [ ] | null ) => {
95108 setFilters ( ( prev ) => ( {
@@ -113,20 +126,16 @@ export function useFilteredProblems() {
113126 } ) ) ;
114127 } , [ ] ) ;
115128
116- // Reset and fetch when filters change
117129 useEffect ( ( ) => {
118- setPage ( 1 ) ;
119- fetchProblems ( 1 , false ) ;
130+ fetchProblems ( false ) ;
120131 } , [ filters , fetchProblems ] ) ;
121132
122- // Load more function for infinite scroll
123133 const loadMore = useCallback ( ( ) => {
124134 if ( ! isLoading && hasMore ) {
125- const nextPage = page + 1 ;
126- setPage ( nextPage ) ;
127- fetchProblems ( nextPage , true ) ;
135+ currentPage . current += 1 ;
136+ fetchProblems ( true ) ;
128137 }
129- } , [ isLoading , hasMore , page , fetchProblems ] ) ;
138+ } , [ isLoading , hasMore , fetchProblems ] ) ;
130139
131140 return {
132141 problems,
@@ -135,7 +144,7 @@ export function useFilteredProblems() {
135144 removeFilter,
136145 isLoading,
137146 hasMore,
147+ isEmpty,
138148 loadMore,
139- fetchProblems,
140149 } ;
141150}
0 commit comments