From c2d9cfed206060418998f46d61be3a8032dbad5d Mon Sep 17 00:00:00 2001
From: ashwaqaljanahi2021 <ashwaq.aljanahi2021@gmail.com>
Date: Tue, 5 Nov 2024 09:48:28 -0500
Subject: [PATCH] completed enrolled/not-enrolled feature

---
 .../components/listItems/courseListItem.scss  |  18 ++-
 .../src/components/misc/globalToolbar.tsx     |   2 +-
 .../listPages/courses/coursesListPage.tsx     | 120 ++++++++++--------
 package-lock.json                             |  34 +++++
 package.json                                  |   5 +
 5 files changed, 121 insertions(+), 58 deletions(-)
 create mode 100644 package-lock.json
 create mode 100644 package.json

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 = () => {
             <DarkModeToggle />
             {
             <Link to={`/courses`} className={styles.link} >
-              My Courses
+              Join a Course
             </Link>
             }     
             {/*<Link to={`/myCourses`} className={styles.link}>*/}
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<Filter>[] = [
-    {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<Course[]>([]);
+    const [filter, setFilter] = useState<Filter>(false);
+    const history = useHistory();
 
-    const [loading, setLoading] = useState(true)
-    const [error, setError] = useState(null)
-    const [userCourses, setUserCourses] = useState(new Array<UserCourse>())
-    const [filter, setFilter] = useState<Filter>(false )
-    const history = useHistory()
-
-    //Temporary place to store state for all courses
-    const [allCourses, setAllCourses] = useState(new Array<Course>())
+    // Get userId from Redux store
+    const userId = useAppSelector((store) => store.user.id);
 
     useEffect(() => {
-        fetchData()
-    }, [])
+        fetchData();
+    }, []);
 
     const fetchData = async () => {
         try {
-            // const userCourses = await RequestService.get<UserCourse[]>(`/api/user-courses?filterBy=${filter}`)
-            const courseRequests = userCourses.map((u) => RequestService.get<Course>(`/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<string, Course> = {}
-            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<Course[]>(`/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 <LoadingOverlay delay={250}/>
-    if (error) return <ErrorPage error={error}/>
-
-    const defaultOption = filterOptions.find((o) => o.value === filter)
+    if (loading) return <LoadingOverlay delay={250} />;
+    if (error) return <ErrorPage error={error} />;
 
+    const defaultOption = filterOptions.find((o) => o.value === filter);
 
     return (
         <PageWrapper>
@@ -73,9 +84,8 @@ const UserCoursesListPage = () => {
                 <h1>All Courses</h1>
                 <div className={styles.largeLine}></div>
 
-                <Button variant="contained" onClick={() => {
-                    history.push(`/addCoursesForm`)
-                    }}>Add Course
+                <Button variant="contained" onClick={() => history.push(`/addCoursesForm`)}>
+                    Add Course
                 </Button>
                 <div className={styles.filters}>
                     <Dropdown
@@ -87,13 +97,11 @@ const UserCoursesListPage = () => {
                     />
                 </div>
             </div>
-            {allCourses.map(course => (
-                <CourseListItem course={course} key={course.id} isOpen={filter}/>
+            {allCourses.map((course) => (
+                <CourseListItem course={course} key={course.id} isOpen={filter} />
             ))}
         </PageWrapper>
-    )
-
-
-}
+    );
+};
 
-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"
+  }
+}