Skip to content

Commit 8f77167

Browse files
authored
Merge pull request #23 from DevOps-Cloud-Team5/SCRUM-17
improved courses, create courses, partial enrollment, partial create lecture, minor fixes
2 parents 042d9a5 + 13f256c commit 8f77167

File tree

18 files changed

+804
-185
lines changed

18 files changed

+804
-185
lines changed

.env_example

-1
This file was deleted.

package-lock.json

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

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
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",
2426
"react": "^18.2.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/main.tsx

+1-3
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ import "./index.css";
77
// Make sure there's a div with id="root" in your index.html
88
const rootElement = document.getElementById("root");
99
if (rootElement) {
10-
createRoot(rootElement).render(
11-
<RouterProvider router={AppRouter} />
12-
);
10+
createRoot(rootElement).render(<RouterProvider router={AppRouter} />);
1311
} else {
1412
console.error("Failed to find the root element");
1513
}

src/mock_data.tsx

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

src/pages/courses/index.tsx

+147-37
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,37 @@
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();
30+
31+
const alternatingColor = [
32+
"rgba(255, 255, 255, 0.5)",
33+
"rgba(255, 255, 255, 0.3)"
34+
];
1935

2036
useEffect(() => {
2137
sendRequest({
@@ -29,43 +45,137 @@ const Courses = () => {
2945
console.error("Error fetching courses:", error);
3046
// Optionally, render an error message in the UI
3147
}
48+
49+
const StyledTable = styled("table")({
50+
borderCollapse: "collapse",
51+
width: "100%",
52+
"& th, & td": {
53+
padding: "8px", // Adjust the padding as needed
54+
borderBottom: "1px solid #ddd", // Add a border bottom to create a divider effect
55+
textAlign: "left" // Align content to the left
56+
},
57+
"& th": {
58+
fontWeight: "bold" // Add bold font weight to header cells if needed
59+
},
60+
"& .type-column": {
61+
width: "10%", // Adjust the width of the actions column
62+
textAlign: "left" // Align content to the left
63+
},
64+
"& .actions-column": {
65+
width: "5%", // Adjust the width of the actions column
66+
textAlign: "left" // Align content to the left
67+
},
68+
"& .avatar-column": {
69+
width: "5%", // Adjust the width of the avatar column
70+
textAlign: "left" // Align content to the left
71+
},
72+
"& .actions-icon": {
73+
display: "flex",
74+
justifyContent: "center",
75+
alignItems: "center"
76+
}
77+
});
78+
79+
const handleNewCourseClick = () => {
80+
navigate(`/create_course`);
81+
};
82+
83+
const handleCourseClick = (course_id: number) => {
84+
navigate(`/course/${course_id}/create_lecture`);
85+
};
86+
87+
const handleEnrollment =
88+
(courseId: number, enroll: boolean) =>
89+
(event: React.ChangeEvent<HTMLInputElement>) => {
90+
if (enroll) {
91+
backend_post("course/enroll/" + courseId, "", true);
92+
// if (response == null) return
93+
// const result = response.map((course : Course) => (course.id == courseId ? { ...course, enrolled: true } : course))
94+
// console.log(result)
95+
}
96+
};
97+
3298
return (
3399
<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)"
100+
<Container component="main" className="mainComponent">
101+
<Typography variant="h4" gutterBottom>
102+
Courses
103+
{IsAdmin() ? (
104+
<IconButton
105+
onClick={() => handleNewCourseClick()}
106+
style={{
107+
marginLeft: "2%",
108+
color: "white",
109+
backgroundColor: "rgba(255, 255, 255, 0.5)"
110+
}}
111+
>
112+
<AddCircleOutlineIcon style={{ fontSize: "1em" }} />
113+
</IconButton>
114+
) : null}
115+
</Typography>
116+
117+
<StyledTable>
118+
<thead>
119+
<tr>
120+
<th>Course Name</th>
121+
<th className="type-column">Students</th>
122+
{IsAdmin() ? (
123+
<th className="actions-column">Actions</th>
124+
) : (
125+
<th className="actions-column">Enroll</th>
126+
)}
127+
</tr>
128+
</thead>
129+
<tbody>
130+
{response?.map((course: Course, index: number) => (
131+
<tr
132+
key={course.id}
133+
style={{
134+
backgroundColor:
135+
alternatingColor[
136+
index % alternatingColor.length
137+
]
50138
}}
51139
>
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}
140+
<td>
141+
<Button
142+
style={{
143+
color: "white",
144+
textTransform: "none",
145+
fontSize: "1em"
146+
}}
147+
onClick={() =>
148+
handleCourseClick(course.id)
149+
}
150+
>
151+
{`${course.course_name}`}
152+
</Button>
153+
</td>
154+
<td></td>
155+
{IsAdmin() ? (
156+
<td className="actions-icon">
157+
<IconButton>
158+
<MoreVertIcon />
159+
</IconButton>
160+
</td>
161+
) : (
162+
<Checkbox
163+
checked={course.enrolled}
164+
onChange={handleEnrollment(
165+
course.id,
166+
!course.enrolled
167+
)}
168+
sx={{
169+
"& .MuiSvgIcon-root": {
170+
color: "white"
171+
}
172+
}}
63173
/>
64-
</ListItemButton>
65-
</ListItem>
174+
)}
175+
</tr>
66176
))}
67-
</List>
68-
)}
177+
</tbody>
178+
</StyledTable>
69179
</Container>
70180
</RootPage>
71181
);

0 commit comments

Comments
 (0)