@@ -29,26 +29,17 @@ export async function downloadFile(url: string, filename: string) {
29
29
const CatalogueContent = ( ) => {
30
30
const router = useRouter ( ) ;
31
31
const searchParams = useSearchParams ( ) ;
32
- const subject = searchParams . get ( "subject" ) ;
33
- const exams = searchParams . get ( "exams" ) ?. split ( "," ) ;
34
- const slots = searchParams . get ( "slots" ) ?. split ( "," ) ;
35
- const years = searchParams . get ( "years" ) ?. split ( "," ) ;
36
- const campuses = searchParams . get ( "campus" ) ?. split ( "," ) ;
37
- const semesters = searchParams . get ( "semester" ) ?. split ( "," ) ;
38
- const answerKeyIncluded =
39
- searchParams . get ( "answerkey" ) === "true" ? true : false ;
40
- // Initialize state with searchParams
41
- const [ selectedExams , setSelectedExams ] = useState < string [ ] > ( exams ?? [ ] ) ;
42
- const [ selectedSlots , setSelectedSlots ] = useState < string [ ] > ( slots ?? [ ] ) ;
43
- const [ selectedYears , setSelectedYears ] = useState < string [ ] > ( years ?? [ ] ) ;
44
- const [ selectedSemesters , setSelectedSemesters ] = useState < string [ ] > (
45
- semesters ?? [ ] ,
46
- ) ;
47
- const [ selectedCampuses , setSelectedCampuses ] = useState < string [ ] > (
48
- campuses ?? [ ] ,
49
- ) ;
32
+ const [ isMounted , setIsMounted ] = useState ( false ) ;
33
+
34
+ // Initialize state with defaults, set later in useEffect
35
+ const [ subject , setSubject ] = useState < string | null > ( null ) ;
36
+ const [ selectedExams , setSelectedExams ] = useState < string [ ] > ( [ ] ) ;
37
+ const [ selectedSlots , setSelectedSlots ] = useState < string [ ] > ( [ ] ) ;
38
+ const [ selectedYears , setSelectedYears ] = useState < string [ ] > ( [ ] ) ;
39
+ const [ selectedSemesters , setSelectedSemesters ] = useState < string [ ] > ( [ ] ) ;
40
+ const [ selectedCampuses , setSelectedCampuses ] = useState < string [ ] > ( [ ] ) ;
50
41
const [ selectedAnswerKeyIncluded , setSelectedAnswerKeyIncluded ] =
51
- useState < boolean > ( answerKeyIncluded ) ;
42
+ useState < boolean > ( false ) ;
52
43
const [ papers , setPapers ] = useState < IPaper [ ] > ( [ ] ) ;
53
44
const [ filteredPapers , setFilteredPapers ] = useState < IPaper [ ] > ( [ ] ) ;
54
45
const [ selectedPapers , setSelectedPapers ] = useState < IPaper [ ] > ( [ ] ) ;
@@ -58,12 +49,27 @@ const CatalogueContent = () => {
58
49
const [ filtersPulled , setFiltersPulled ] = useState < boolean > ( false ) ;
59
50
const [ appliedFilters , setAppliedFilters ] = useState < boolean > ( false ) ;
60
51
52
+ // Set initial state from searchParams on client-side mount
53
+ useEffect ( ( ) => {
54
+ setIsMounted ( true ) ;
55
+ if ( searchParams ) {
56
+ setSubject ( searchParams . get ( "subject" ) ) ;
57
+ setSelectedExams ( searchParams . get ( "exams" ) ?. split ( "," ) ?? [ ] ) ;
58
+ setSelectedSlots ( searchParams . get ( "slots" ) ?. split ( "," ) ?? [ ] ) ;
59
+ setSelectedYears ( searchParams . get ( "years" ) ?. split ( "," ) ?? [ ] ) ;
60
+ setSelectedCampuses ( searchParams . get ( "campus" ) ?. split ( "," ) ?? [ ] ) ;
61
+ setSelectedSemesters ( searchParams . get ( "semester" ) ?. split ( "," ) ?? [ ] ) ;
62
+ setSelectedAnswerKeyIncluded ( searchParams . get ( "answerkey" ) === "true" ) ;
63
+ }
64
+ } , [ searchParams ] ) ;
65
+
61
66
const filtersNotPulled = ( ) => {
62
67
setFiltersPulled ( false ) ;
63
68
} ;
64
- // Memoized effect to fetch papers
69
+
70
+ // Fetch papers and apply filters
65
71
useEffect ( ( ) => {
66
- if ( ! subject ) return ;
72
+ if ( ! subject || ! isMounted ) return ;
67
73
68
74
const fetchPapers = async ( ) => {
69
75
setLoading ( true ) ;
@@ -75,6 +81,7 @@ const CatalogueContent = () => {
75
81
const papersData = data . papers ;
76
82
setFilterOptions ( data ) ;
77
83
setPapers ( papersData ) ;
84
+ // Apply filters from URL params
78
85
const filtered = papersData . filter ( ( paper ) => {
79
86
const examCondition = selectedExams . length
80
87
? selectedExams . includes ( paper . exam )
@@ -104,23 +111,32 @@ const CatalogueContent = () => {
104
111
) ;
105
112
} ) ;
106
113
setFilteredPapers ( filtered . length > 0 ? filtered : papersData ) ;
114
+ setAppliedFilters ( true ) ;
107
115
} catch ( error ) {
108
116
setPapers ( [ ] ) ;
109
- if ( axios . isAxiosError ( error ) ) {
110
- const axiosError = error as AxiosError < { message ?: string } > ;
111
- setError (
112
- axiosError . response ?. data ?. message ?? "Error fetching papers" ,
113
- ) ;
114
- } else {
115
- setError ( "Error fetching papers" ) ;
116
- }
117
+ const axiosError = error as AxiosError ;
118
+ setError (
119
+ axios . isAxiosError ( axiosError )
120
+ ? ( ( axiosError . response ?. data as { message ?: string } ) ?. message ??
121
+ "Error fetching papers" )
122
+ : "Error fetching papers" ,
123
+ ) ;
117
124
} finally {
118
125
setLoading ( false ) ;
119
126
}
120
127
} ;
121
128
122
129
void fetchPapers ( ) ;
123
- } , [ subject ] ) ; // Just run on initial page render
130
+ } , [
131
+ subject ,
132
+ isMounted ,
133
+ selectedExams ,
134
+ selectedSlots ,
135
+ selectedYears ,
136
+ selectedSemesters ,
137
+ selectedCampuses ,
138
+ selectedAnswerKeyIncluded ,
139
+ ] ) ;
124
140
125
141
// Memoized handlers
126
142
const handleSelectPaper = useCallback (
@@ -213,6 +229,11 @@ const CatalogueContent = () => {
213
229
setSelectedPapers ( [ ] ) ;
214
230
} , [ ] ) ;
215
231
232
+ // Render loading state until mounted to avoid hydration mismatch
233
+ if ( ! isMounted ) {
234
+ return < Loader /> ;
235
+ }
236
+
216
237
return (
217
238
< div className = "relative flex min-h-screen justify-center p-0 md:justify-normal" >
218
239
< div className = "hidden w-[30%] min-w-fit md:block" >
@@ -237,7 +258,6 @@ const CatalogueContent = () => {
237
258
/>
238
259
</ div >
239
260
240
- { /* {error && <p className="text-red-500">{error}</p> } */ }
241
261
< div className = "w-full" >
242
262
< Sheet >
243
263
< SheetTrigger className = "mx-8 mt-8 block md:hidden" >
0 commit comments