Skip to content

Commit 1ffd0d6

Browse files
authored
Merge branch 'main' into SCRUM-31_pw_reset
2 parents 7e93ac7 + 9a78494 commit 1ffd0d6

File tree

23 files changed

+1254
-85
lines changed

23 files changed

+1254
-85
lines changed

.env_example

-1
This file was deleted.

package-lock.json

+88
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+4
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@
1818
"@emotion/styled": "^11.4.0",
1919
"@mui/icons-material": "^5.3.0",
2020
"@mui/material": "^5.3.0",
21+
"@mui/x-date-pickers": "^6.19.7",
2122
"axios": "^1.6.7",
23+
"dayjs": "^1.11.10",
2224
"js-cookie": "^3.0.5",
2325
"jwt-decode": "^4.0.0",
26+
"moment": "^2.30.1",
27+
"momentjs": "^2.0.0",
2428
"react": "^18.2.0",
2529
"react-dom": "^18.2.0",
2630
"react-router-dom": "^6.22.0",

src/components/navbar/index.tsx

-3
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,6 @@ const Navbar = () => {
4848
<Link to="/profile" className="text-primary">
4949
Profile
5050
</Link>
51-
<Link to="/logout" className="text-primary">
52-
Profile
53-
</Link>
5451
<a onClick={handleLogout}>Logout</a>
5552
</>
5653
) : (

src/mock_data.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const sampleStudentData = {
2+
id: 1,
3+
name: "John Doe",
4+
courses: ["Math", "Science", "History"]
5+
};

src/pages/courses/index.tsx

+157-37
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,38 @@
11
import RootPage from "../root";
22
import Container from "@mui/material/Container";
33
import "./courses.css"; // Import CSS file for additional styling
4-
import List from "@mui/material/List";
5-
import ListItem from "@mui/material/ListItem";
6-
import ListItemButton from "@mui/material/ListItemButton";
7-
import ListItemText from "@mui/material/ListItemText";
8-
import { useEffect } from "react";
9-
import { useAxiosRequest } from "../../utils";
4+
import { useEffect, useState } from "react";
5+
import { useNavigate } from "react-router-dom";
6+
import { backend_post, useAxiosRequest } from "../../utils";
107
import { Course, Empty } from "../../types/common";
8+
import { IsAdmin } from "../../utils";
9+
import { User } from "../../types/common";
10+
import {
11+
Button,
12+
Checkbox,
13+
IconButton,
14+
Typography,
15+
styled
16+
} from "@mui/material";
17+
import MoreVertIcon from "@mui/icons-material/MoreVert";
18+
import AddCircleOutlineIcon from "@mui/icons-material/AddCircleOutline";
19+
import Avatar from "@mui/material/Avatar";
1120

1221
type ResponseData = Course[];
1322

1423
const Courses = () => {
24+
const navigate = useNavigate();
1525
const { response, error, loading, sendRequest } = useAxiosRequest<
1626
Empty,
1727
ResponseData
1828
>();
29+
const [course_data, setCourseData] = useState<Course[]>();
30+
31+
const alternatingColor = [
32+
"#424242",
33+
"#595959"
34+
];
35+
1936

2037
useEffect(() => {
2138
sendRequest({
@@ -25,47 +42,150 @@ const Courses = () => {
2542
});
2643
}, [sendRequest]);
2744

45+
useEffect(() => {
46+
if (response) setCourseData(response)
47+
}, [response]);
48+
2849
if (error) {
2950
console.error("Error fetching courses:", error);
3051
// Optionally, render an error message in the UI
3152
}
53+
54+
const StyledTable = styled("table")({
55+
borderCollapse: "collapse",
56+
width: "100%",
57+
"& th, & tr": {
58+
padding: "8px",
59+
borderBottom: "1px solid #ddd",
60+
textAlign: "left"
61+
},
62+
"& td":{
63+
padding: "8px",
64+
textAlign: "left"
65+
},
66+
"& th": {
67+
fontWeight: "bold" // Add bold font weight to header cells if needed
68+
},
69+
"& .type-column": {
70+
width: "10%", // Adjust the width of the actions column
71+
textAlign: "left" // Align content to the left
72+
},
73+
"& .actions-column": {
74+
width: "5%", // Adjust the width of the actions column
75+
textAlign: "left" // Align content to the left
76+
},
77+
"& .enroll-column": {
78+
width: "5%"
79+
},
80+
"& .avatar-column": {
81+
width: "5%", // Adjust the width of the avatar column
82+
textAlign: "left" // Align content to the left
83+
},
84+
"& .actions-icon": {
85+
display: "flex",
86+
justifyContent: "center",
87+
alignItems: "center"
88+
}
89+
});
90+
91+
const handleNewCourseClick = () => {
92+
navigate(`/create_course`);
93+
};
94+
95+
const handleCourseClick = (course_id: number) => {
96+
navigate(`/course/${course_id}/create_lecture`);
97+
};
98+
99+
const handleEnrollment =
100+
(courseId: number, enroll: boolean) =>
101+
(event: React.ChangeEvent<HTMLInputElement>) => {
102+
if (enroll) {
103+
backend_post("course/enroll/" + courseId, "", true);
104+
if (response == null) return
105+
const new_data = course_data?.map((course : Course) => (course.id == courseId ? { ...course, enrolled: true } : course))
106+
setCourseData(new_data)
107+
}
108+
};
109+
32110
return (
33111
<RootPage>
34-
<Container component="main" maxWidth="xs">
35-
{loading ? (
36-
<div>Loading...</div> // Added loading state feedback
37-
) : (
38-
<List
39-
sx={{
40-
width: "100%",
41-
maxWidth: 1000
42-
}}
43-
aria-label="Courses"
44-
>
45-
<ListItem disablePadding>
46-
<ListItemButton
47-
sx={{
48-
border: 1,
49-
bgcolor: "rgba(255, 255, 255, 0.12)"
112+
<Container component="main" className="mainComponent">
113+
<Typography variant="h4" gutterBottom>
114+
Courses
115+
{IsAdmin() ? (
116+
<IconButton
117+
onClick={() => handleNewCourseClick()}
118+
style={{
119+
marginLeft: "2%",
120+
color: "white",
121+
backgroundColor: "rgba(255, 255, 255, 0.5)"
122+
}}
123+
>
124+
<AddCircleOutlineIcon style={{ fontSize: "1em" }} />
125+
</IconButton>
126+
) : null}
127+
</Typography>
128+
129+
<StyledTable>
130+
<thead>
131+
<tr>
132+
<th>Course Name</th>
133+
<th className="type-column">Students</th>
134+
{IsAdmin() ? (
135+
<th className="actions-column">Actions</th>
136+
) : (
137+
<th className="enroll-column">Enroll</th>
138+
)}
139+
</tr>
140+
</thead>
141+
<tbody>
142+
{course_data?.map((course: Course, index: number) => (
143+
<tr
144+
key={course.id}
145+
style={{
146+
backgroundColor:
147+
alternatingColor[index%2]
50148
}}
51149
>
52-
<ListItemText primary="Courses" />
53-
</ListItemButton>
54-
</ListItem>
55-
56-
{response?.map((course: Course) => (
57-
<ListItem disablePadding key={course.course_name}>
58-
{" "}
59-
{/* Assuming course_name is unique */}
60-
<ListItemButton sx={{ border: 1 }}>
61-
<ListItemText
62-
primary={course.course_name}
150+
<td>
151+
<Button
152+
style={{
153+
color: "white",
154+
textTransform: "none",
155+
fontSize: "1em"
156+
}}
157+
onClick={() =>
158+
handleCourseClick(course.id)
159+
}
160+
>
161+
{`${course.course_name}`}
162+
</Button>
163+
</td>
164+
<td></td>
165+
{IsAdmin() ? (
166+
<td className="actions-icon">
167+
<IconButton>
168+
<MoreVertIcon />
169+
</IconButton>
170+
</td>
171+
) : (
172+
<Checkbox className="actions-icon"
173+
checked={course.enrolled}
174+
onChange={handleEnrollment(
175+
course.id,
176+
!course.enrolled
177+
)}
178+
sx={{
179+
"& .MuiSvgIcon-root": {
180+
color: "white"
181+
}
182+
}}
63183
/>
64-
</ListItemButton>
65-
</ListItem>
184+
)}
185+
</tr>
66186
))}
67-
</List>
68-
)}
187+
</tbody>
188+
</StyledTable>
69189
</Container>
70190
</RootPage>
71191
);

0 commit comments

Comments
 (0)