@@ -29,26 +29,17 @@ export async function downloadFile(url: string, filename: string) {
2929const CatalogueContent = ( ) => {
3030 const router = useRouter ( ) ;
3131 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 [ ] > ( [ ] ) ;
5041 const [ selectedAnswerKeyIncluded , setSelectedAnswerKeyIncluded ] =
51- useState < boolean > ( answerKeyIncluded ) ;
42+ useState < boolean > ( false ) ;
5243 const [ papers , setPapers ] = useState < IPaper [ ] > ( [ ] ) ;
5344 const [ filteredPapers , setFilteredPapers ] = useState < IPaper [ ] > ( [ ] ) ;
5445 const [ selectedPapers , setSelectedPapers ] = useState < IPaper [ ] > ( [ ] ) ;
@@ -58,12 +49,27 @@ const CatalogueContent = () => {
5849 const [ filtersPulled , setFiltersPulled ] = useState < boolean > ( false ) ;
5950 const [ appliedFilters , setAppliedFilters ] = useState < boolean > ( false ) ;
6051
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+
6166 const filtersNotPulled = ( ) => {
6267 setFiltersPulled ( false ) ;
6368 } ;
64- // Memoized effect to fetch papers
69+
70+ // Fetch papers and apply filters
6571 useEffect ( ( ) => {
66- if ( ! subject ) return ;
72+ if ( ! subject || ! isMounted ) return ;
6773
6874 const fetchPapers = async ( ) => {
6975 setLoading ( true ) ;
@@ -75,6 +81,7 @@ const CatalogueContent = () => {
7581 const papersData = data . papers ;
7682 setFilterOptions ( data ) ;
7783 setPapers ( papersData ) ;
84+ // Apply filters from URL params
7885 const filtered = papersData . filter ( ( paper ) => {
7986 const examCondition = selectedExams . length
8087 ? selectedExams . includes ( paper . exam )
@@ -104,23 +111,32 @@ const CatalogueContent = () => {
104111 ) ;
105112 } ) ;
106113 setFilteredPapers ( filtered . length > 0 ? filtered : papersData ) ;
114+ setAppliedFilters ( true ) ;
107115 } catch ( error ) {
108116 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+ ) ;
117124 } finally {
118125 setLoading ( false ) ;
119126 }
120127 } ;
121128
122129 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+ ] ) ;
124140
125141 // Memoized handlers
126142 const handleSelectPaper = useCallback (
@@ -213,6 +229,11 @@ const CatalogueContent = () => {
213229 setSelectedPapers ( [ ] ) ;
214230 } , [ ] ) ;
215231
232+ // Render loading state until mounted to avoid hydration mismatch
233+ if ( ! isMounted ) {
234+ return < Loader /> ;
235+ }
236+
216237 return (
217238 < div className = "relative flex min-h-screen justify-center p-0 md:justify-normal" >
218239 < div className = "hidden w-[30%] min-w-fit md:block" >
@@ -237,7 +258,6 @@ const CatalogueContent = () => {
237258 />
238259 </ div >
239260
240- { /* {error && <p className="text-red-500">{error}</p> } */ }
241261 < div className = "w-full" >
242262 < Sheet >
243263 < SheetTrigger className = "mx-8 mt-8 block md:hidden" >
0 commit comments