From 0b0d9e8a79081d48d5554dac93d6c1eee91eceb2 Mon Sep 17 00:00:00 2001
From: WeiViv <100058931+WeiViv@users.noreply.github.com>
Date: Sat, 12 Oct 2024 15:44:14 -0500
Subject: [PATCH] build(edit course, style courses on the profile card, course
filter):
1. write the util functions to use the courses data stored in firestore
2. build the course selection section on the edit profile page
3. style the profile page
4. build the course filter on home page
---
src/components/Home/StudentFilter.jsx | 29 ++++++++++++++++--
src/components/Home/StudentList.jsx | 11 +++++--
src/components/HomePage.jsx | 4 +++
src/components/Profile/EditProfile.jsx | 41 ++++++++++++++++++++++----
src/components/Profile/ProfilePage.jsx | 17 ++++++-----
src/hooks/data/useCourses.js | 21 +++++++++++++
src/hooks/useEditProfileForm.js | 29 +++++++++++++-----
src/utils/firestore/general.js | 24 +++++++++++++++
8 files changed, 149 insertions(+), 27 deletions(-)
create mode 100644 src/hooks/data/useCourses.js
diff --git a/src/components/Home/StudentFilter.jsx b/src/components/Home/StudentFilter.jsx
index ab2fb9e..46a0fdc 100644
--- a/src/components/Home/StudentFilter.jsx
+++ b/src/components/Home/StudentFilter.jsx
@@ -1,5 +1,6 @@
import React from 'react';
+import useCourses from '@data/useCourses';
import useMajors from '@data/useMajors';
import {
Box,
@@ -16,10 +17,13 @@ import {
export default function StudentFilter({
selectedMajors,
setSelectedMajors,
+ selectedCourses,
+ setSelectedCourses,
selectedYears,
setSelectedYears,
}) {
const majorsList = useMajors();
+ const coursesList = useCourses();
return (
@@ -36,7 +40,28 @@ export default function StudentFilter({
sx={{ flex: 1, mb: 2, minWidth: 200, maxWidth: '100%' }}
/>
- {/* 2. Year filter */}
+ {/* 2. Course filter */}
+ option}
+ value={selectedCourses}
+ onChange={(event, newValue) => setSelectedCourses(newValue)}
+ renderInput={(params) => (
+
+ )}
+ filterOptions={(options, { inputValue }) => {
+ // Convert inputValue to lowercase for case-insensitive matching
+ const lowercasedInput = inputValue.toLowerCase();
+
+ // Only include options that start with the input
+ return options.filter((option) => option.toLowerCase().startsWith(lowercasedInput));
+ }}
+ sx={{ flex: 1, mb: 2, minWidth: 200, maxWidth: '100%' }}
+ freeSolo
+ />
+
+ {/* 3. Year filter */}
Filter by Year(s)
-
- {/* 3. Course filter */}
);
}
diff --git a/src/components/Home/StudentList.jsx b/src/components/Home/StudentList.jsx
index c2e6b52..10355dc 100644
--- a/src/components/Home/StudentList.jsx
+++ b/src/components/Home/StudentList.jsx
@@ -13,6 +13,7 @@ export default function StudentList({
setRequestedUsers,
matchedUserUids,
selectedMajors,
+ selectedCourses,
selectedYears,
}) {
const studentData = useStudentData();
@@ -22,6 +23,8 @@ export default function StudentList({
profile.uid !== userProfile.uid &&
!matchedUserUids.has(profile.uid) &&
(selectedMajors.length === 0 || selectedMajors.includes(profile.major)) &&
+ (selectedCourses.length === 0 ||
+ profile.courses?.some((course) => selectedCourses.includes(course))) &&
(selectedYears.length === 0 || selectedYears.includes(profile.year)),
);
@@ -30,12 +33,16 @@ export default function StudentList({
currentPage,
totalPages,
handlePageChange,
- } = usePagination(filteredStudentData, 10);
+ } = usePagination(filteredStudentData || [], 10);
const handleMatch = async (studentUserProfile) => {
try {
await createMatch([studentUserProfile.uid, userProfile.uid], 'University Library');
- setRequestedUsers((prev) => new Set(prev).add(studentUserProfile.uid));
+ setRequestedUsers((prev) => {
+ const newSet = new Set(prev);
+ newSet.add(studentUserProfile.uid);
+ return newSet;
+ });
} catch (error) {
console.error('Error creating match:', error);
}
diff --git a/src/components/HomePage.jsx b/src/components/HomePage.jsx
index 65de340..6c00c45 100644
--- a/src/components/HomePage.jsx
+++ b/src/components/HomePage.jsx
@@ -12,6 +12,7 @@ export default function HomePage() {
const { userProfile, requestedUsers, setRequestedUsers, matchedUserUids, loading } =
useUserProfile(user);
const [selectedMajors, setSelectedMajors] = useState([]);
+ const [selectedCourses, setSelectedCourses] = useState([]);
const [selectedYears, setSelectedYears] = useState([]);
const navigate = useNavigate();
@@ -61,6 +62,8 @@ export default function HomePage() {
@@ -71,6 +74,7 @@ export default function HomePage() {
setRequestedUsers={setRequestedUsers}
matchedUserUids={matchedUserUids}
selectedMajors={selectedMajors}
+ selectedCourses={selectedCourses}
selectedYears={selectedYears}
/>
diff --git a/src/components/Profile/EditProfile.jsx b/src/components/Profile/EditProfile.jsx
index 0fd57a0..8c8893d 100644
--- a/src/components/Profile/EditProfile.jsx
+++ b/src/components/Profile/EditProfile.jsx
@@ -20,6 +20,9 @@ const EditProfile = () => {
majorsList,
selectedMajors,
setSelectedMajors,
+ coursesList,
+ selectedCourses,
+ setSelectedCourses,
handleInputChange,
errors,
isFormValid,
@@ -71,6 +74,7 @@ const EditProfile = () => {
'tel',
)}
+ {/* Major Selection */}
{
)}
/>
+ {/* Course Selection */}
+ option}
+ value={selectedCourses}
+ onChange={(event, newValue) => setSelectedCourses(newValue)}
+ renderInput={(params) => (
+
+ )}
+ filterOptions={(options, { inputValue }) => {
+ // Convert inputValue to lowercase for case-insensitive matching
+ const lowercasedInput = inputValue.toLowerCase();
+
+ // Only include options that start with the input
+ return options.filter((option) => option.toLowerCase().startsWith(lowercasedInput));
+ }}
+ sx={{ flex: 1, mb: 2, minWidth: 200, maxWidth: '100%' }}
+ freeSolo
+ />
+
+ {/* Year Selection */}
{renderSelectField('Year', 'year', years, formData.year, handleInputChange, errors.year)}
+
+ {/* Description Field */}
{renderTextField('Description', 'description', formData.description, handleInputChange)}
- {renderTextField(
- 'List of Courses (comma-separated)',
- 'listOfCourses',
- formData.listOfCourses,
- handleInputChange,
- )}