Skip to content

Commit 8243acd

Browse files
committed
use context to get course list everywhere
1 parent 0af34ff commit 8243acd

4 files changed

Lines changed: 83 additions & 151 deletions

File tree

src/app/request/page.tsx

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import UpcomingPaper from "../../components/UpcomingPaper";
1919
import toast from "react-hot-toast";
2020
import { Search } from "lucide-react";
2121
import SkeletonPaperCard from "@/components/SkeletonPaperCard";
22+
import { useCourses } from "@/context/courseContext";
2223

2324
type Course = {
2425
name?: string | null;
@@ -37,23 +38,11 @@ export default function PaperRequest() {
3738
const suggestionsRef = useRef<HTMLUListElement | null>(null);
3839
const [displayPapers, setDisplayPapers] = useState<IUpcomingPaper[]>([]);
3940
const [isLoading, setIsLoading] = useState(true);
41+
const { courses, loading, error, refetch } = useCourses();
4042

4143
useEffect(() => {
42-
async function fetchSubjects() {
43-
try {
44-
const response = await axios.get<Course[]>(`/api/course-list`);
45-
const courses: Course[] = response.data;
46-
const names = courses
47-
.map((course) => course.name ?? course.courseName ?? course.title)
48-
.filter(Boolean) as string[];
49-
50-
setSubjects(names);
51-
} catch (err) {
52-
console.error("Error fetching subjects:", err);
53-
}
54-
}
55-
void fetchSubjects();
56-
}, []);
44+
setSubjects(courses.map((course) => course.name));
45+
}, [courses]);
5746

5847
useEffect(() => {
5948
async function fetchPapers() {
@@ -138,7 +127,7 @@ export default function PaperRequest() {
138127
loading: "Submitting your request...",
139128
success: "Your paper request was submitted successfully",
140129
error: "Failed to submit your request. Please try again later.",
141-
}
130+
},
142131
);
143132

144133
setSearchText("");

src/components/CatalogueContent.tsx

Lines changed: 72 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@ import { useSearchParams } from "next/navigation";
44
import { useCallback, useEffect, useState } from "react";
55
import axios, { type AxiosError } from "axios";
66
import { Button } from "@/components/ui/button";
7-
import {
8-
type IPaper,
9-
type Filters,
10-
type StoredSubjects
11-
} from "@/interface";
7+
import { type IPaper, type Filters, type StoredSubjects } from "@/interface";
128
import Card from "./Card";
139
import { useRouter } from "next/navigation";
1410
import Loader from "./ui/loader";
@@ -17,7 +13,7 @@ import Error from "./Error";
1713
import { Filter } from "lucide-react";
1814
import { Sheet, SheetContent, SheetTrigger } from "./ui/sheet";
1915
import { Pin } from "lucide-react";
20-
import SearchBarChild from "./Searchbar/searchbar-child"
16+
import SearchBarChild from "./Searchbar/searchbar-child";
2117
import Link from "next/link";
2218
import { usePathname } from "next/navigation";
2319
import {
@@ -26,6 +22,7 @@ import {
2622
downloadFile,
2723
} from "@/util/download_paper";
2824
import type { ICourses } from "@/interface";
25+
import { useCourses } from "@/context/courseContext";
2926

3027
const CatalogueContent = () => {
3128
const router = useRouter();
@@ -52,6 +49,8 @@ const CatalogueContent = () => {
5249
const [appliedFilters, setAppliedFilters] = useState<boolean>(false);
5350
const [pinned, setPinned] = useState<boolean>(false);
5451
const [relatedSubjects, setRelatedSubjects] = useState<string[]>([]);
52+
const { courses } = useCourses();
53+
5554
// Fetch related subjects when subject changes
5655
useEffect(() => {
5756
if (!subject) return;
@@ -78,31 +77,11 @@ const CatalogueContent = () => {
7877
void fetchRelatedSubjects();
7978
}, [subject]);
8079

81-
useEffect(() => {
82-
if (pathname !== "/catalogue") return;
83-
84-
const getSubjects = async () => {
85-
try {
86-
const res = await fetch("/api/course-list");
87-
if (!res.ok) return;
88-
89-
const json: unknown = await res.json();
90-
91-
if (Array.isArray(json)) {
92-
const filtered = json
93-
.filter((item): item is ICourses => typeof item === "object" && item !== null && "name" in item)
94-
.map(item => item.name);
95-
setSubjects(filtered);
96-
} else {
97-
console.error("Invalid data returned from API:", json);
98-
}
99-
} catch (err) {
100-
console.error("Failed to fetch courses", err);
101-
}
102-
};
103-
104-
void getSubjects();
105-
}, [pathname]);
80+
useEffect(() => {
81+
if (pathname !== "/catalogue") return;
82+
const filteredSubjects = courses.map((course) => course.name);
83+
setSubjects(filteredSubjects);
84+
}, [pathname, courses]);
10685
// Set initial state from searchParams on client-side mount
10786
useEffect(() => {
10887
setIsMounted(true);
@@ -321,68 +300,72 @@ const CatalogueContent = () => {
321300

322301
return (
323302
<div className="relative flex min-h-screen justify-center p-0 md:justify-normal">
324-
{papers.length > 0 && <div className="hidden !w-[22%] min-w-[22%] max-w-[22%] flex-shrink-0 md:block">
325-
<SideBar
326-
filtersNotPulled={filtersNotPulled}
327-
loading={loading}
328-
selectedExams={selectedExams}
329-
selectedSlots={selectedSlots}
330-
selectedYears={selectedYears}
331-
selectedSemesters={selectedSemesters}
332-
selectedCampuses={selectedCampuses}
333-
selectedAnswerKeyIncluded={selectedAnswerKeyIncluded}
334-
noAppliedFilters={noAppliedFilters}
335-
handleApplyFilters={handleApplyFilters}
336-
handleSelectAll={handleSelectAll}
337-
handleDeselectAll={handleDeselectAll}
338-
selectedPapers={selectedPapers}
339-
subject={subject}
340-
filterOptions={filterOptions}
341-
handleDownloadAll={handleDownloadAll}
342-
closeFilters={closeFilters}
343-
/>
344-
</div>}
303+
{papers.length > 0 && (
304+
<div className="hidden !w-[22%] min-w-[22%] max-w-[22%] flex-shrink-0 md:block">
305+
<SideBar
306+
filtersNotPulled={filtersNotPulled}
307+
loading={loading}
308+
selectedExams={selectedExams}
309+
selectedSlots={selectedSlots}
310+
selectedYears={selectedYears}
311+
selectedSemesters={selectedSemesters}
312+
selectedCampuses={selectedCampuses}
313+
selectedAnswerKeyIncluded={selectedAnswerKeyIncluded}
314+
noAppliedFilters={noAppliedFilters}
315+
handleApplyFilters={handleApplyFilters}
316+
handleSelectAll={handleSelectAll}
317+
handleDeselectAll={handleDeselectAll}
318+
selectedPapers={selectedPapers}
319+
subject={subject}
320+
filterOptions={filterOptions}
321+
handleDownloadAll={handleDownloadAll}
322+
closeFilters={closeFilters}
323+
/>
324+
</div>
325+
)}
345326

346327
<div className="w-full">
347-
{papers.length > 0 && <Sheet>
348-
<SheetTrigger className="mx-8 mt-8 block md:hidden">
349-
<Button
350-
variant="outline"
351-
className="flex gap-2 border-2 border-black font-sans font-semibold hover:bg-slate-800 hover:text-white dark:border-[#434dba] dark:hover:border-white dark:hover:bg-slate-900"
328+
{papers.length > 0 && (
329+
<Sheet>
330+
<SheetTrigger className="mx-8 mt-8 block md:hidden">
331+
<Button
332+
variant="outline"
333+
className="flex gap-2 border-2 border-black font-sans font-semibold hover:bg-slate-800 hover:text-white dark:border-[#434dba] dark:hover:border-white dark:hover:bg-slate-900"
334+
>
335+
<Filter size={18} />
336+
Add Filters
337+
</Button>
338+
</SheetTrigger>
339+
<SheetContent
340+
side={"left"}
341+
className="m-0 bg-[#f3f5ff] p-0 pt-4 dark:bg-[#070114]"
352342
>
353-
<Filter size={18} />
354-
Add Filters
355-
</Button>
356-
</SheetTrigger>
357-
<SheetContent
358-
side={"left"}
359-
className="m-0 bg-[#f3f5ff] p-0 pt-4 dark:bg-[#070114]"
360-
>
361-
<SideBar
362-
filtersNotPulled={filtersNotPulled}
363-
loading={loading}
364-
selectedExams={selectedExams}
365-
selectedSlots={selectedSlots}
366-
selectedYears={selectedYears}
367-
selectedSemesters={selectedSemesters}
368-
selectedCampuses={selectedCampuses}
369-
selectedAnswerKeyIncluded={selectedAnswerKeyIncluded}
370-
noAppliedFilters={noAppliedFilters}
371-
handleApplyFilters={handleApplyFilters}
372-
handleSelectAll={handleSelectAll}
373-
handleDeselectAll={handleDeselectAll}
374-
selectedPapers={selectedPapers}
375-
subject={subject}
376-
filterOptions={filterOptions}
377-
handleDownloadAll={handleDownloadAll}
378-
closeFilters={closeFilters}
379-
/>
380-
</SheetContent>
381-
</Sheet>}
343+
<SideBar
344+
filtersNotPulled={filtersNotPulled}
345+
loading={loading}
346+
selectedExams={selectedExams}
347+
selectedSlots={selectedSlots}
348+
selectedYears={selectedYears}
349+
selectedSemesters={selectedSemesters}
350+
selectedCampuses={selectedCampuses}
351+
selectedAnswerKeyIncluded={selectedAnswerKeyIncluded}
352+
noAppliedFilters={noAppliedFilters}
353+
handleApplyFilters={handleApplyFilters}
354+
handleSelectAll={handleSelectAll}
355+
handleDeselectAll={handleDeselectAll}
356+
selectedPapers={selectedPapers}
357+
subject={subject}
358+
filterOptions={filterOptions}
359+
handleDownloadAll={handleDownloadAll}
360+
closeFilters={closeFilters}
361+
/>
362+
</SheetContent>
363+
</Sheet>
364+
)}
382365

383-
<div className="p-7 flex flex-col items-start">
384-
<div className="md:hidden flex flex-col items-start w-full mb-8">
385-
<SearchBarChild initialSubjects={subjects} />
366+
<div className="flex flex-col items-start p-7">
367+
<div className="mb-8 flex w-full flex-col items-start md:hidden">
368+
<SearchBarChild initialSubjects={courses} />
386369
</div>
387370
<div className="flex items-center gap-2">
388371
<div>

src/components/Navbar.tsx

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -27,37 +27,12 @@ import { useCourses } from "@/context/courseContext";
2727

2828
function Navbar() {
2929
const pathname: string = usePathname() ?? "/";
30-
const [subjects, setSubjects] = useState<string[]>([]);
30+
3131
const [dropdownOpen, setDropdownOpen] = useState<boolean>(false);
3232
const { courses, loading, error, refetch } = useCourses();
3333

3434
useEffect(() => {
3535
if (pathname !== "/catalogue") return;
36-
37-
const getSubjects = async () => {
38-
try {
39-
const res = await fetch("/api/course-list");
40-
if (!res.ok) return;
41-
42-
const json: unknown = await res.json();
43-
44-
if (Array.isArray(json)) {
45-
const filtered = json
46-
.filter(
47-
(item): item is ICourses =>
48-
typeof item === "object" && item !== null && "name" in item,
49-
)
50-
.map((item) => item.name);
51-
setSubjects(filtered);
52-
} else {
53-
console.error("Invalid data returned from API:", json);
54-
}
55-
} catch (err) {
56-
console.error("Failed to fetch courses", err);
57-
}
58-
};
59-
60-
void getSubjects();
6136
}, [pathname]);
6237

6338
const renderHomePageButtons = () => (

src/components/screens/PapersPage.tsx

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { IUpcomingPaper } from "@/interface";
1919
import { Skeleton } from "../ui/skeleton";
2020
import { CarouselItem } from "@/components/ui/carousel";
2121
import UpcomingPaper from "../UpcomingPaper";
22+
import { useCourses } from "@/context/courseContext";
2223

2324
type Course = {
2425
name?: string | null;
@@ -37,23 +38,7 @@ export default function PapersPage() {
3738
const suggestionsRef = useRef<HTMLUListElement | null>(null);
3839
const [displayPapers, setDisplayPapers] = useState<IUpcomingPaper[]>([]);
3940
const [isLoading, setIsLoading] = useState(true);
40-
41-
useEffect(() => {
42-
async function fetchSubjects() {
43-
try {
44-
const response = await axios.get<Course[]>(`/api/course-list`);
45-
const courses: Course[] = response.data;
46-
const names = courses
47-
.map((course) => course.name ?? course.courseName ?? course.title)
48-
.filter(Boolean) as string[];
49-
50-
setSubjects(names);
51-
} catch (err) {
52-
console.error("Error fetching subjects:", err);
53-
}
54-
}
55-
void fetchSubjects();
56-
}, []);
41+
const { courses, loading, error, refetch } = useCourses();
5742

5843
useEffect(() => {
5944
async function fetchPapers() {
@@ -79,8 +64,8 @@ export default function PapersPage() {
7964
}, []);
8065

8166
const fuse = useMemo(
82-
() => new Fuse(subjects, { includeScore: true, threshold: 0.3 }),
83-
[subjects],
67+
() => new Fuse(courses, { includeScore: true, threshold: 0.3 }),
68+
[courses],
8469
);
8570

8671
useEffect(() => {
@@ -95,7 +80,7 @@ export default function PapersPage() {
9580
}
9681

9782
const results = fuse.search(searchText);
98-
setSuggestions(results.map((r) => r.item).slice(0, 10));
83+
setSuggestions(results.map((r) => r.item.name).slice(0, 10));
9984
}, [searchText, fuse, selectedSubject]);
10085

10186
const handleSelectSubject = (subject: string) => {

0 commit comments

Comments
 (0)