@@ -5,7 +5,7 @@ import Navbar from "./components/Navbar";
5
5
import Card from "./components/Card" ;
6
6
import Footer from "./components/Footer" ;
7
7
import GenerateStats from "./components/GenerateStats" ;
8
- import { useContext , useEffect , useState } from "react" ;
8
+ import { useContext , useEffect , useState , useMemo } from "react" ;
9
9
import PromotionCard from "./components/PromotionCard" ;
10
10
import { DataContext } from "./context/DataContext" ;
11
11
import { ToastContainer } from "react-toastify" ;
@@ -18,21 +18,62 @@ export default function Home() {
18
18
const [ loading , setLoading ] = useState ( true ) ;
19
19
const [ showStats , setShowStats ] = useState ( false ) ;
20
20
const [ sortBy , setSortBy ] = useState ( "default" ) ;
21
+ const [ pagination , setPagination ] = useState ( {
22
+ currentPage : 1 ,
23
+ totalPages : 1 ,
24
+ totalItems : 0 ,
25
+ limit : 11 ,
26
+ } ) ;
27
+ const [ searchTerm , setSearchTerm ] = useState ( "" ) ;
28
+ const [ debouncedSearch , setDebouncedSearch ] = useState ( "" ) ;
21
29
22
- const fetchData = async ( ) => {
30
+ // Debounce search input to avoid too many requests
31
+ useEffect ( ( ) => {
32
+ const timer = setTimeout ( ( ) => {
33
+ setDebouncedSearch ( search ) ;
34
+ } , 500 ) ;
35
+
36
+ return ( ) => clearTimeout ( timer ) ;
37
+ } , [ search ] ) ;
38
+
39
+ // Reset pagination when search changes
40
+ useEffect ( ( ) => {
41
+ setPagination ( ( prev ) => ( { ...prev , currentPage : 1 } ) ) ;
42
+ } , [ debouncedSearch ] ) ;
43
+
44
+ const fetchData = async ( page = 1 ) => {
23
45
try {
24
- const res = await fetch ( "/api/fetchdata" ) ;
25
- const data = await res . json ( ) ;
26
- setDatas ( data . data ) ;
46
+ setLoading ( true ) ;
47
+ const queryParams = new URLSearchParams ( ) ;
48
+
49
+ if ( debouncedSearch ) {
50
+ queryParams . append ( "search" , debouncedSearch ) ;
51
+ }
52
+
53
+ queryParams . append ( "page" , page . toString ( ) ) ;
54
+ queryParams . append ( "limit" , pagination . limit . toString ( ) ) ;
55
+ queryParams . append ( "sortBy" , sortBy ) ;
56
+
57
+ const res = await fetch ( `/api/fetchdata?${ queryParams . toString ( ) } ` ) ;
58
+ const response = await res . json ( ) ;
59
+
60
+ setDatas ( response . data ) ;
61
+ setPagination ( {
62
+ currentPage : response . pagination . page ,
63
+ totalPages : response . pagination . totalPages ,
64
+ totalItems : response . pagination . total ,
65
+ limit : response . pagination . limit ,
66
+ } ) ;
27
67
setLoading ( false ) ;
28
68
} catch ( error ) {
29
69
console . error ( "Error fetching messages:" , error ) ;
70
+ setLoading ( false ) ;
30
71
}
31
72
} ;
32
73
33
74
useEffect ( ( ) => {
34
- fetchData ( ) ;
35
- } , [ datas && datas . length ] ) ;
75
+ fetchData ( pagination . currentPage ) ;
76
+ } , [ debouncedSearch , pagination . currentPage , pagination . limit , sortBy ] ) ;
36
77
37
78
useEffect ( ( ) => {
38
79
setTimeout ( ( ) => {
@@ -42,22 +83,13 @@ export default function Home() {
42
83
43
84
const handleSortChange = ( e : React . ChangeEvent < HTMLSelectElement > ) => {
44
85
setSortBy ( e . target . value ) ;
86
+ // Reset to first page when sorting changes
87
+ setPagination ( ( prev ) => ( { ...prev , currentPage : 1 } ) ) ;
45
88
} ;
46
89
47
- const searchedData = datas ?. filter ( ( data : any ) =>
48
- data . profileData . fullName . toLowerCase ( ) . includes ( search . toLowerCase ( ) )
49
- ) ;
50
- const sorting = ( data : any [ ] ) => {
51
- switch ( sortBy ) {
52
- case "question-solved" :
53
- return data . slice ( ) . sort ( ( a , b ) => b . totalSolved - a . totalSolved ) ;
54
- case "default" :
55
- default :
56
- return data . slice ( ) . sort ( ( a , b ) => {
57
- return (
58
- new Date ( b . timeStamp ) . getTime ( ) - new Date ( a . timeStamp ) . getTime ( )
59
- ) ;
60
- } ) ;
90
+ const handlePageChange = ( newPage : number ) => {
91
+ if ( newPage > 0 && newPage <= pagination . totalPages ) {
92
+ setPagination ( ( prev ) => ( { ...prev , currentPage : newPage } ) ) ;
61
93
}
62
94
} ;
63
95
@@ -106,17 +138,80 @@ export default function Home() {
106
138
< PromotionCard />
107
139
{ loading ? (
108
140
< >
109
- { Array . from ( { length : 6 } , ( _ , i ) => (
141
+ { Array . from ( { length : 8 } , ( _ , i ) => (
110
142
< Skeleton key = { i } />
111
143
) ) }
112
144
</ >
113
145
) : (
114
- sorting ( searchedData ) . map ( ( userData : any , index : number ) => (
115
- < Card userData = { userData } index = { index } key = { index } />
146
+ datas ?. map ( ( userData : any , index : number ) => (
147
+ < Card
148
+ userData = { userData }
149
+ index = { index }
150
+ key = { userData . _id || index }
151
+ />
116
152
) )
117
153
) }
118
154
</ div >
119
155
156
+ { /* Pagination Controls */ }
157
+ { ! loading && pagination . totalPages > 1 && (
158
+ < div className = "flex justify-center mt-12 mb-16 max-w-7xl mx-auto" >
159
+ < div className = "flex space-x-2 items-center font-sourcecodepro" >
160
+ < button
161
+ onClick = { ( ) => handlePageChange ( pagination . currentPage - 1 ) }
162
+ disabled = { pagination . currentPage === 1 }
163
+ className = "px-4 py-2 rounded-md border border-gray-600 bg-[#0e0e0e] text-white disabled:opacity-50 disabled:cursor-not-allowed"
164
+ >
165
+ Previous
166
+ </ button >
167
+
168
+ < div className = "flex space-x-2" >
169
+ { Array . from (
170
+ { length : Math . min ( 5 , pagination . totalPages ) } ,
171
+ ( _ , i ) => {
172
+ // Show 5 pages around current page
173
+ let pageNum = 1 ;
174
+ if ( pagination . totalPages <= 5 ) {
175
+ pageNum = i + 1 ;
176
+ } else if ( pagination . currentPage <= 3 ) {
177
+ pageNum = i + 1 ;
178
+ } else if (
179
+ pagination . currentPage >=
180
+ pagination . totalPages - 2
181
+ ) {
182
+ pageNum = pagination . totalPages - 4 + i ;
183
+ } else {
184
+ pageNum = pagination . currentPage - 2 + i ;
185
+ }
186
+
187
+ return (
188
+ < button
189
+ key = { pageNum }
190
+ onClick = { ( ) => handlePageChange ( pageNum ) }
191
+ className = { `w-10 h-10 rounded-md ${
192
+ pagination . currentPage === pageNum
193
+ ? "bg-gradient-to-r from-[#cb42b2] to-[#ecf576] text-black font-bold"
194
+ : "border border-gray-600 bg-[#0e0e0e] text-white"
195
+ } `}
196
+ >
197
+ { pageNum }
198
+ </ button >
199
+ ) ;
200
+ }
201
+ ) }
202
+ </ div >
203
+
204
+ < button
205
+ onClick = { ( ) => handlePageChange ( pagination . currentPage + 1 ) }
206
+ disabled = { pagination . currentPage === pagination . totalPages }
207
+ className = "px-4 py-2 rounded-md border border-gray-600 bg-[#0e0e0e] text-white disabled:opacity-50 disabled:cursor-not-allowed"
208
+ >
209
+ Next
210
+ </ button >
211
+ </ div >
212
+ </ div >
213
+ ) }
214
+
120
215
< Footer />
121
216
122
217
< ToastContainer
0 commit comments