) : (
<>>
diff --git a/src/components/includes/CourseSelection.tsx b/src/components/includes/CourseSelection.tsx
index 0331f4a04..8732d6312 100644
--- a/src/components/includes/CourseSelection.tsx
+++ b/src/components/includes/CourseSelection.tsx
@@ -1,6 +1,6 @@
-import * as React from 'react';
-import { useEffect, useState } from 'react';
-import { useHistory } from 'react-router';
+import * as React from "react";
+import { useEffect, useState } from "react";
+import { useHistory } from "react-router";
import { connect } from 'react-redux';
import { Icon } from 'semantic-ui-react'
@@ -17,12 +17,12 @@ type Props = {
readonly isEdit: boolean;
};
-export type PageState = 'ready' | 'pending';
+export type PageState = "ready" | "pending";
function CourseSelection({ user, isEdit, allCourses }: Props): React.ReactElement {
const history = useHistory();
const [isWritingChanges, setIsWritingChanges] = useState(false);
- const [, setPageState] = useState('ready');
+ const [, setPageState] = useState("ready");
// Normal editing mode (isNormalEditingMode=true) has all the controls.
// On the contrary, onboarding (isNormalEditingMode=false) has only enroll button.
@@ -32,14 +32,30 @@ function CourseSelection({ user, isEdit, allCourses }: Props): React.ReactElemen
const [formerCourses, setFormerCourses] = useState([]);
const [displayWrapped, setDisplayWrapped] = useState(false);
+ // current searched courses
+ const [filteredCourses] = useState(currentCourses);
useEffect(() => {
- setCurrentCourses(allCourses.filter((course) => {
- return course.semester === CURRENT_SEMESTER;
- }));
+ setCurrentlyEnrolledCourseIds(new Set(user.courses));
+ }, [user.courses]);
- setFormerCourses(allCourses.filter((course) => {
- return course.semester !== CURRENT_SEMESTER;
- }));
+ const filterOnActiveAndRole = () => {
+ return allCourses
+ .filter((course) => course.semester === CURRENT_SEMESTER)
+ .sort((a, b) => {
+ const isUserTAorProfA = a.tas?.includes(user.userId) || a.professors?.includes(user.userId) ? 1 : 0;
+ const isUserTAorProfB = b.tas?.includes(user.userId) || b.professors?.includes(user.userId) ? 1 : 0;
+ return isUserTAorProfB - isUserTAorProfA; // Sort in descending order (1's before 0's)
+ });
+ };
+
+ useEffect(() => {
+ setCurrentCourses(filterOnActiveAndRole);
+
+ setFormerCourses(
+ allCourses.filter((course) => {
+ return course.semester !== CURRENT_SEMESTER;
+ }),
+ );
}, [allCourses]);
const [currentlyEnrolledCourseIds, setCurrentlyEnrolledCourseIds] = useState(new Set());
@@ -48,23 +64,34 @@ function CourseSelection({ user, isEdit, allCourses }: Props): React.ReactElemen
setCurrentlyEnrolledCourseIds(new Set(user.courses));
}, [user.courses]);
- const [selectedCourses, setSelectedCourses] = useState([]);
+ const preSelectedCourses: FireCourse[] =
+ user.courses.length > 0 ? currentCourses.filter((course) => user.roles[course.courseId] !== undefined) : [];
+
+ const [selectedCourses, setSelectedCourses] = useState(preSelectedCourses);
+
+ // courses in which role is defined (TA or Prof)
+ const [unchangeableCourses, setUnchangableCourses] = useState(preSelectedCourses);
useEffect(() => {
- setSelectedCourses(currentCourses.filter(
- ({ courseId }) => currentlyEnrolledCourseIds.has(courseId) && user.roles[courseId] === undefined
- ));
- }, [user, currentCourses, currentlyEnrolledCourseIds]);
+ setSelectedCourses(
+ currentCourses.filter(
+ ({ courseId }) => currentlyEnrolledCourseIds.has(courseId) && user.roles[courseId] === undefined,
+ ),
+ );
+ setUnchangableCourses(
+ currentCourses.filter(
+ ({ courseId }) => currentlyEnrolledCourseIds.has(courseId) && user.roles[courseId] !== undefined,
+ ),
+ );
+ }, [user, filteredCourses, currentlyEnrolledCourseIds]);
const [selectedCourseIds, setSelectedCourseIds] = useState([]);
- const [collapsed, setCollapsed] = useState(true);
-
const coursesToEnroll: string[] = [];
const coursesToUnenroll: string[] = [];
let numCoursesWithRoles = 0;
currentCourses.forEach(({ courseId }) => {
- if (selectedCourses.some(selected => selected.courseId === courseId)) {
+ if (selectedCourses.some((selected) => selected.courseId === courseId)) {
// The course is selected.
if (!currentlyEnrolledCourseIds.has(courseId)) {
coursesToEnroll.push(courseId);
@@ -76,7 +103,7 @@ function CourseSelection({ user, isEdit, allCourses }: Props): React.ReactElemen
// Either
// - Previously not enrolled, still not enrolled.
// - Is a professor or a TA of the class. Cannot change by themselves.
- if (user.roles[courseId] === 'professor' || user.roles[courseId] === 'ta') {
+ if (user.roles[courseId] === "professor" || user.roles[courseId] === "ta") {
numCoursesWithRoles += 1;
}
// We Do nothing.
@@ -91,35 +118,66 @@ function CourseSelection({ user, isEdit, allCourses }: Props): React.ReactElemen
useEffect(() => {
if (!isNormalEditingMode) {
- setIsSaveDisabled((
- coursesToEnroll.length + coursesToUnenroll.length + numCoursesWithRoles === 0)
- && !isWritingChanges);
+ setIsSaveDisabled(
+ coursesToEnroll.length + coursesToUnenroll.length + numCoursesWithRoles === 0 && !isWritingChanges,
+ );
} else {
- setIsSaveDisabled((coursesToEnroll.length + coursesToUnenroll.length === 0) && !isWritingChanges);
+ setIsSaveDisabled(coursesToEnroll.length + coursesToUnenroll.length === 0 && !isWritingChanges);
}
- setPageState(isWritingChanges ? 'pending' : 'ready');
+ setPageState(isWritingChanges ? "pending" : "ready");
}, [isWritingChanges, coursesToEnroll, coursesToUnenroll, isNormalEditingMode, numCoursesWithRoles]);
useEffect(() => {
- setSelectedCourseIds(selectedCourses.map(course => course.courseId));
+ setSelectedCourseIds(selectedCourses.map((course) => course.courseId));
}, [selectedCourses]);
const onSelectCourse = (course: FireCourse, addCourse: boolean) => {
- setSelectedCourses((previousSelectedCourses) => (
+ setSelectedCourses((previousSelectedCourses) =>
addCourse
? [...previousSelectedCourses, course]
- : previousSelectedCourses.filter(c => c.courseId !== course.courseId)
- ));
+ : previousSelectedCourses.filter((c) => c.courseId !== course.courseId),
+ );
+ };
+
+ /**
+ * Handles the search functionality of the search bar in 'edit courses'. Is called
+ * onChange of the input element of 'searchbar'.
+ * Filters the current view of courses based on the search term, while preserving
+ * the selected courses (shows preservation through list of courses selected under search bar).
+ *
+ * @param e = event to pass in search term
+ */
+ const searchInput = (e: React.ChangeEvent) => {
+ const search = e.target.value.toLowerCase();
+
+ // Filter courses based on the current semester, reset the search results (when search term is deleted, etc)
+ const availableCourses = filterOnActiveAndRole();
+
+ // Filter courses based on the search term
+ const filteredResults = availableCourses.filter((course) => {
+ return course.code.toLowerCase().includes(search) || course.name.toLowerCase().includes(search);
+ });
+
+ // Preserve the selected courses
+ const updatedCourses = filteredResults.map((course) => {
+ const isSelected = selectedCourseIds.includes(course.courseId);
+ return {
+ ...course,
+ isSelected,
+ };
+ });
+
+ setCurrentCourses(updatedCourses);
};
const onSubmit = () => {
const newCourseSet = new Set(currentlyEnrolledCourseIds);
- coursesToEnroll.forEach(courseId => newCourseSet.add(courseId));
- coursesToUnenroll.forEach(courseId => newCourseSet.delete(courseId));
+ coursesToEnroll.forEach((courseId) => newCourseSet.add(courseId));
+ coursesToUnenroll.forEach((courseId) => newCourseSet.delete(courseId));
const userUpdate: Partial = { courses: Array.from(newCourseSet.values()) };
setIsWritingChanges(true);
updateCourses(user.userId, userUpdate).then(() => {
- history.push('/home');
+ history.push("/home");
setIsWritingChanges(false);
setEditingMode(user.courses.length > 0);
});
@@ -128,16 +186,16 @@ function CourseSelection({ user, isEdit, allCourses }: Props): React.ReactElemen
const onCancel = () => {
// don't add newly-selected courses... add back the newly-deselected courses
setSelectedCourses([
- ...(selectedCourses.filter(course => !coursesToEnroll.includes(course.courseId))),
- ...currentCourses.filter(course => coursesToUnenroll.includes(course.courseId))
+ ...selectedCourses.filter((course) => !coursesToEnroll.includes(course.courseId)),
+ ...currentCourses.filter((course) => coursesToUnenroll.includes(course.courseId)),
]);
- history.push('/home');
+ history.push("/home");
};
- const selectedCoursesString = (selectedCourses.length + numCoursesWithRoles === 0
- ? 'No Classes Chosen'
- : selectedCourses.map(c => c.code).join(', '));
+ // changed guard from selectedCourses.length + numCoursesWithRoles === 0 to selectedCourses.length === 0
+ // so that when you cannot unenroll from a course, it says No Classes Chosen instead of an empty box
+ const selectedCoursesString = selectedCourses.length === 0 ? "" : selectedCourses.map((c) => c.code).join(", ");
return (
@@ -149,117 +207,175 @@ function CourseSelection({ user, isEdit, allCourses }: Props): React.ReactElemen
// This field is only necessary for professors, but we are always student/TA here.
courseId="DUMMY_COURSE_ID"
/>
-
- {currentCourses.length > 0 || isEdit ?
- <>
-
-
- {isEdit ? 'Edit Your Classes' : 'My Classes'}
-
-
- {isEdit ? 'Add or remove classes.' : 'Select the office hours you want to view.'}
-