diff --git a/devU-client/src/components/listItems/courseListItem.scss b/devU-client/src/components/listItems/courseListItem.scss
index c5d73f6..e8449c5 100644
--- a/devU-client/src/components/listItems/courseListItem.scss
+++ b/devU-client/src/components/listItems/courseListItem.scss
@@ -60,13 +60,29 @@
color: $text-color;
-
+ &.enrolled {
+ background-color: #dff0d8; // Light green background for enrolled courses
+ border-color: #3c763d; // Darker green border for enrolled courses
+ color: #3c763d; // Change text color to darker green
+ }
&:hover,
&:focus {
background: $list-item-background-hover;
}
}
+.enrollmentStatus {
+ margin-left: 10px;
+ font-weight: bold; // Make it bold for emphasis
+}
+
+.enrolled {
+ color: green; // Change color for enrolled courses
+}
+
+.notEnrolled {
+ color: red; // Change color for not enrolled courses
+}
@media (max-width: $medium) {
.subText {
diff --git a/devU-client/src/components/misc/globalToolbar.tsx b/devU-client/src/components/misc/globalToolbar.tsx
index 7149e5e..29a894e 100644
--- a/devU-client/src/components/misc/globalToolbar.tsx
+++ b/devU-client/src/components/misc/globalToolbar.tsx
@@ -29,7 +29,7 @@ const GlobalToolbar = () => {
{
- My Courses
+ Join a Course
}
{/**/}
diff --git a/devU-client/src/components/pages/listPages/courses/coursesListPage.tsx b/devU-client/src/components/pages/listPages/courses/coursesListPage.tsx
index b1e0026..2184be9 100644
--- a/devU-client/src/components/pages/listPages/courses/coursesListPage.tsx
+++ b/devU-client/src/components/pages/listPages/courses/coursesListPage.tsx
@@ -1,70 +1,81 @@
-import React, {useEffect, useState} from 'react'
-import {Course, UserCourse} from 'devu-shared-modules'
-import LoadingOverlay from 'components/shared/loaders/loadingOverlay'
-import PageWrapper from 'components/shared/layouts/pageWrapper'
-import Dropdown, {Option} from 'components/shared/inputs/dropdown'
-import ErrorPage from '../../errorPage/errorPage'
-import RequestService from 'services/request.service'
-import styles from './coursesListPage.scss'
+import React, { useEffect, useState } from 'react';
+import { Course } from 'devu-shared-modules';
+import LoadingOverlay from 'components/shared/loaders/loadingOverlay';
+import PageWrapper from 'components/shared/layouts/pageWrapper';
+import Dropdown, { Option } from 'components/shared/inputs/dropdown';
+import ErrorPage from '../../errorPage/errorPage';
+import RequestService from 'services/request.service';
+import styles from './coursesListPage.scss';
import CourseListItem from "../../../listItems/courseListItem";
-// import {useAppSelector} from "../../../../redux/hooks";
import Button from "@mui/material/Button";
-import {useHistory} from "react-router-dom";
+import { useHistory } from "react-router-dom";
+import { useAppSelector } from "../../../../redux/hooks";
-type Filter = true | false
+type Filter = true | false;
const filterOptions: Option[] = [
- {label: 'Expand All', value: true},
- {label: 'Collapse All', value: false},
-]
+ { label: 'Expand All', value: true },
+ { label: 'Collapse All', value: false },
+];
const UserCoursesListPage = () => {
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+ const [allCourses, setAllCourses] = useState([]);
+ const [filter, setFilter] = useState(false);
+ const history = useHistory();
- const [loading, setLoading] = useState(true)
- const [error, setError] = useState(null)
- const [userCourses, setUserCourses] = useState(new Array())
- const [filter, setFilter] = useState(false )
- const history = useHistory()
-
- //Temporary place to store state for all courses
- const [allCourses, setAllCourses] = useState(new Array())
+ // Get userId from Redux store
+ const userId = useAppSelector((store) => store.user.id);
useEffect(() => {
- fetchData()
- }, [])
+ fetchData();
+ }, []);
const fetchData = async () => {
try {
- // const userCourses = await RequestService.get(`/api/user-courses?filterBy=${filter}`)
- const courseRequests = userCourses.map((u) => RequestService.get(`/api/courses/${u.courseId}`))
- const courses = await Promise.all(courseRequests)
-
- // Mapify course ids so we can look them up more easilly via their id
- const courseMap: Record = {}
- for (const course of courses) courseMap[course.id || ''] = course
-
- // Temporary place to grab and display all courses
- const allCourses = await RequestService.get('/api/courses')
- setAllCourses(allCourses)
-
- setUserCourses(userCourses)
+ // Fetch user-specific courses
+ const userCourseData = await RequestService.get<{
+ instructorCourses: Course[];
+ activeCourses: Course[];
+ pastCourses: Course[];
+ upcomingCourses: Course[];
+ }>(`/api/courses/user/${userId}`);
+
+ // Flatten and combine user course data into a single array
+ const userCoursesList = [
+ ...userCourseData.instructorCourses,
+ ...userCourseData.activeCourses,
+ ...userCourseData.pastCourses,
+ ...userCourseData.upcomingCourses,
+ ];
+
+ // Fetch all courses
+ const allCourseData = await RequestService.get(`/api/courses`);
+
+ // Filter to get courses the user is not enrolled in
+ const unenrolledCourses = allCourseData.filter(
+ (course) => !userCoursesList.some((userCourse) => userCourse.id === course.id)
+ );
+
+
+ setAllCourses(unenrolledCourses);
} catch (error: any) {
- setError(error)
+ setError(error);
} finally {
- setLoading(false)
+ setLoading(false);
}
- }
+ };
const handleFilterChange = (updatedFilter: Filter) => {
- setFilter(updatedFilter)
- }
+ setFilter(updatedFilter);
+ };
- if (loading) return
- if (error) return
-
- const defaultOption = filterOptions.find((o) => o.value === filter)
+ if (loading) return ;
+ if (error) return ;
+ const defaultOption = filterOptions.find((o) => o.value === filter);
return (
@@ -73,9 +84,8 @@ const UserCoursesListPage = () => {
All Courses
-
- )
-
-
-}
+ );
+};
-export default UserCoursesListPage
+export default UserCoursesListPage;
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..84cd429
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,34 @@
+{
+ "name": "devU",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "devDependencies": {
+ "@types/react": "^18.3.12"
+ }
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.13",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
+ "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==",
+ "dev": true
+ },
+ "node_modules/@types/react": {
+ "version": "18.3.12",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz",
+ "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==",
+ "dev": true,
+ "dependencies": {
+ "@types/prop-types": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+ "dev": true
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..ab744a6
--- /dev/null
+++ b/package.json
@@ -0,0 +1,5 @@
+{
+ "devDependencies": {
+ "@types/react": "^18.3.12"
+ }
+}