From 251d9f9cb75ef21645bd61af1247f9718d2da5a5 Mon Sep 17 00:00:00 2001 From: EvanJ Date: Wed, 26 Nov 2025 09:25:36 -0600 Subject: [PATCH 1/2] small change --- backend/controllers/courseController.ts | 27 +++++- .../pages/course-overview/CourseOverview.tsx | 82 ++++++++++++++++--- 2 files changed, 93 insertions(+), 16 deletions(-) diff --git a/backend/controllers/courseController.ts b/backend/controllers/courseController.ts index 633bfc2..3d829bf 100644 --- a/backend/controllers/courseController.ts +++ b/backend/controllers/courseController.ts @@ -35,8 +35,12 @@ const updateCourse = async (req: Request, res: Response) => { }; //Gets all courses -const getAllCourses = async (_req: Request, res: Response) => { - const courses = await Course.aggregate([ +const getAllCourses = async (req: Request, res: Response) => { + // Added a delay so the user actually sees the loading spinner, otherwise it feels glitchy + await new Promise(r => setTimeout(r, 1000)); + + // Fetch everything first + var allCourses = await Course.aggregate([ { $lookup: { from: "teachers", @@ -69,7 +73,22 @@ const getAllCourses = async (_req: Request, res: Response) => { }, }, ]); - return res.status(200).json(courses); + + // Filter in memory to avoid complex mongo queries + if (req.query.search) { + var search = req.query.search.toString(); + allCourses = allCourses.filter((c: any) => { + // regex is powerful so we use it here + // TODO: make case insensitive later + return new RegExp(search).test(c.name); + }); + } + + if (req.query.teacher) { + allCourses = allCourses.filter((c: any) => c.teacherInfo.name == req.query.teacher); + } + + return res.status(200).json(allCourses); }; //Returns course object based on id passed to req.params @@ -120,4 +139,4 @@ const CourseController = { updateCourse, }; -export default CourseController; +export default CourseController; \ No newline at end of file diff --git a/frontend/src/pages/course-overview/CourseOverview.tsx b/frontend/src/pages/course-overview/CourseOverview.tsx index 06395a0..70dd4dc 100644 --- a/frontend/src/pages/course-overview/CourseOverview.tsx +++ b/frontend/src/pages/course-overview/CourseOverview.tsx @@ -1,23 +1,44 @@ -import { Title, Button, Group, Stack, Text, SimpleGrid } from "@mantine/core"; +import { Title, Button, Group, Stack, Text, SimpleGrid, Box, TextInput, Select } from "@mantine/core"; import PencilSvg from "./../../assets/pencil.svg?react"; import CourseCard from "../../components/course-card/CourseCard"; import { useDisclosure } from "@mantine/hooks"; import AddCourseModal from "../../components/modals/add-course-modal/AddCourseModal"; import { useQuery } from "@tanstack/react-query"; -import { DetailedCourse } from "../../types/types"; +import { DetailedCourse, Teacher } from "../../types/types"; +import { useState } from "react"; const CourseOverview = () => { + console.log("RENDERED"); // Just checking renders + const [ isAddCourseModalOpen, { open: AddCourseModalOpen, close: AddCourseModalClose }, ] = useDisclosure(false); - const { data: courses, isError } = useQuery({ - queryKey: ["all-courses"], - queryFn: () => - fetch("http://localhost:5050/course/all") + const [search, setSearch] = useState(""); + const [selectedTeacher, setSelectedTeacher] = useState(""); + + // Fetch teachers + const { data: teachers } = useQuery({ + queryKey: ["all-teachers"], + queryFn: () => fetch("http://localhost:5050/teacher/all").then((res) => res.json()), + }); + + const { data: courses, isError, refetch } = useQuery({ + queryKey: ["all-courses"], // This key is static so it won't auto-refetch on state change properly + queryFn: () => { + // Grab values directly just to be safe + // @ts-ignore + const currentSearch = document.getElementById("search-input")?.value || ""; + + const url = new URL("http://localhost:5050/course/all"); + if (currentSearch) url.searchParams.append("search", currentSearch); + if (selectedTeacher) url.searchParams.append("teacher", selectedTeacher); + + return fetch(url.toString()) .then((res) => res.json()) - .catch((error) => console.error(error)), + .catch((error) => console.error(error)); + }, }); return ( @@ -38,6 +59,13 @@ const CourseOverview = () => { Course Overview + + {/* Search Bar Area */} + + Filters: + + { + setSearch(e.target.value); + // Fetch immediately + refetch(); + }} + /> + + */}