@@ -3,90 +3,266 @@ import RootPage from "../root";
3
3
import Container from "@mui/material/Container" ;
4
4
import Typography from "@mui/material/Typography" ;
5
5
import Cookies from "js-cookie" ;
6
- import "./profile .css" ; // Import CSS file for additional styling
6
+ import "./course .css" ; // Import CSS file for additional styling
7
7
8
- import { backend_get , deleteAuthCookies } from "../../utils" ;
8
+ import {
9
+ IsStudent ,
10
+ IsAdmin ,
11
+ backend_get ,
12
+ deleteAuthCookies ,
13
+ useAxiosRequest ,
14
+ backend_post
15
+ } from "../../utils" ;
9
16
import { useNavigate , useParams } from "react-router-dom" ;
10
17
import { JwtPayload , jwtDecode } from "jwt-decode" ;
11
- import { CookieJWT } from "../../types/common" ;
18
+ import {
19
+ CookieJWT ,
20
+ Empty ,
21
+ FullCourse ,
22
+ FullCourseUser
23
+ } from "../../types/common" ;
24
+ import { Avatar , Button , IconButton , capitalize , styled } from "@mui/material" ;
25
+ import MoreVertIcon from "@mui/icons-material/MoreVert" ;
26
+ import { render } from "@testing-library/react" ;
12
27
13
- const Profile = ( ) => {
28
+ const Course = ( ) => {
29
+ const { response, error, loading, sendRequest } = useAxiosRequest <
30
+ Empty ,
31
+ FullCourse
32
+ > ( ) ;
14
33
const navigate = useNavigate ( ) ;
15
34
const { id } = useParams ( ) ;
16
35
17
- const [ profileData , setProfileData ] = useState ( {
18
- username : "" ,
19
- email : "" ,
20
- role : "" ,
21
- first_name : "" ,
22
- last_name : "" ,
23
- avatarUrl : "https://randomuser.me/api/portraits/men/5.jpg"
24
- } ) ;
36
+ const [ courseData , setCourseData ] = useState < FullCourse > ( ) ;
25
37
26
- const getProfileData = async ( ) => {
27
- let username = "" ;
28
- if ( id != undefined ) username = id ;
29
- else {
30
- const jwt_token = Cookies . get ( "token_access" ) ;
31
- if ( jwt_token == undefined ) return { code : "missing access token" } ;
32
- const decoded : CookieJWT = jwtDecode ( jwt_token ) ;
33
- if ( ! ( "username" in decoded ) )
34
- return { code : "broken access token" } ;
35
- username = decoded [ "username" ] ;
36
- }
37
- const resp = await backend_get ( "user/get/" + username , true ) ;
38
- return resp . json ( ) ;
38
+ const getCourseData = ( ) => {
39
+ sendRequest ( {
40
+ method : "GET" ,
41
+ route : `/course/get/${ id } ` ,
42
+ useJWT : true
43
+ } ) ;
39
44
} ;
40
45
41
46
useEffect ( ( ) => {
42
- const fetchUserProfile = async ( ) => {
43
- try {
44
- const profile = await getProfileData ( ) ; // Assuming getUserProfile returns user profile data
45
- if ( "code" in profile ) {
46
- deleteAuthCookies ( ) ;
47
- navigate ( "/login" ) ;
48
- navigate ( 0 ) ;
49
- return ;
50
- }
51
- // profile[0]["avaterUrl"] =
52
- // "https://randomuser.me/api/portraits/men/5.jpg";
53
- setProfileData ( profile ) ;
54
- } catch ( error ) {
55
- console . error ( "Error fetching profile:" , error ) ;
56
- // Show error on frontend
57
- }
58
- } ;
47
+ getCourseData ( ) ;
48
+ } , [ sendRequest ] ) ;
59
49
60
- fetchUserProfile ( ) ;
61
- } , [ navigate ] ) ;
50
+ useEffect ( ( ) => {
51
+ if ( response ) setCourseData ( response ) ;
52
+ } , [ response ] ) ;
53
+
54
+ const alternatingColor = [ "#424242" , "#595959" ] ;
55
+
56
+ const StyledTable = styled ( "table" ) ( {
57
+ borderCollapse : "collapse" ,
58
+ width : "100%" ,
59
+ "& th, & tr" : {
60
+ padding : "8px" ,
61
+ borderBottom : "1px solid #ddd" ,
62
+ textAlign : "left"
63
+ } ,
64
+ "& td" : {
65
+ padding : "8px" ,
66
+ textAlign : "left"
67
+ } ,
68
+ "& th" : {
69
+ fontWeight : "bold" // Add bold font weight to header cells if needed
70
+ } ,
71
+ "& .type-column" : {
72
+ width : "10%" , // Adjust the width of the actions column
73
+ textAlign : "left" // Align content to the left
74
+ } ,
75
+ "& .actions-column" : {
76
+ width : "5%" , // Adjust the width of the actions column
77
+ textAlign : "left" // Align content to the left
78
+ } ,
79
+ "& .avatar-column" : {
80
+ width : "5%" , // Adjust the width of the avatar column
81
+ textAlign : "left" // Align content to the left
82
+ } ,
83
+ "& .actions-icon" : {
84
+ display : "flex" ,
85
+ justifyContent : "center" ,
86
+ alignItems : "center"
87
+ }
88
+ } ) ;
89
+
90
+ const handleProfileClick = ( username : string ) => {
91
+ navigate ( `/profile/${ username } ` ) ;
92
+ } ;
93
+
94
+ const showAttendenceStats = ( ) => {
95
+ return (
96
+ IsStudent ( ) &&
97
+ courseData ?. attended != - 1 &&
98
+ courseData ?. missed != - 1
99
+ ) ;
100
+ } ;
101
+
102
+ const handleEnrollment = ( enroll : boolean ) => {
103
+ let url = "course/enroll/" + id ;
104
+ if ( ! enroll ) url = "course/disenroll/" + id ;
105
+ backend_post ( url , "" , true ) . then ( ( resp ) => {
106
+ if ( resp . status == 200 ) {
107
+ getCourseData ( ) ;
108
+ }
109
+ } ) ;
110
+ } ;
62
111
63
112
return (
64
113
< RootPage >
65
- < Container component = "main" maxWidth = "xs" >
66
- < div className = "profile" >
67
- < img
68
- className = "avatar"
69
- src = { profileData . avatarUrl }
70
- alt = "User Avatar"
71
- />
72
- < div className = "profile-info" >
114
+ < Container component = "main" className = "course" maxWidth = "md" >
115
+ < div className = "course-info" >
116
+ < div className = "course-data" >
73
117
< Typography component = "h1" variant = "h5" >
74
- { profileData . first_name } { profileData . last_name }
75
- </ Typography >
76
- < Typography component = "p" variant = "body1" >
77
- Username: { profileData . username }
78
- </ Typography >
79
- < Typography component = "p" variant = "body1" >
80
- Email: { profileData . email }
81
- </ Typography >
82
- < Typography component = "p" variant = "body1" >
83
- Role: { profileData . role }
118
+ { courseData ?. course_name }
84
119
</ Typography >
120
+ < p >
121
+ < span className = "label" > Teachers:</ span >
122
+ { courseData ?. num_teachers }
123
+ </ p >
124
+ < p >
125
+ < span className = "label" > Students:</ span >
126
+ { courseData ?. num_students }
127
+ </ p >
128
+ { showAttendenceStats ( ) ? (
129
+ < >
130
+ < p >
131
+ < span className = "label" >
132
+ Lectures Attended:
133
+ </ span >
134
+ { courseData ?. attended }
135
+ </ p >
136
+ < p >
137
+ < span className = "label" >
138
+ Lectures Missed:
139
+ </ span >
140
+ { courseData ?. missed }
141
+ </ p >
142
+ </ >
143
+ ) : null }
144
+ </ div >
145
+
146
+ < div
147
+ style = { {
148
+ display : "flex" ,
149
+ flexDirection : "column" ,
150
+ marginTop : "2%" ,
151
+ marginRight : "5%"
152
+ } }
153
+ >
154
+ { ! IsAdmin ( ) ? (
155
+ courseData ?. enrolled == true ? (
156
+ < Button
157
+ variant = "contained"
158
+ onClick = { ( ) => {
159
+ handleEnrollment ( false ) ;
160
+ } }
161
+ style = { {
162
+ marginBottom : "5%" ,
163
+ textTransform : "none"
164
+ } }
165
+ sx = { {
166
+ "&.MuiButton-root:hover" : {
167
+ bgcolor : "red"
168
+ }
169
+ } }
170
+ >
171
+ Enrolled
172
+ </ Button >
173
+ ) : (
174
+ < Button
175
+ variant = "contained"
176
+ onClick = { ( ) => {
177
+ handleEnrollment ( true ) ;
178
+ } }
179
+ style = { {
180
+ marginBottom : "5%" ,
181
+ textTransform : "none"
182
+ } }
183
+ >
184
+ Enroll
185
+ </ Button >
186
+ )
187
+ ) : null }
188
+
189
+ < Button
190
+ variant = "contained"
191
+ style = { { textTransform : "none" } }
192
+ onClick = { ( ) => navigate ( `/course/${ id } /schedule` ) }
193
+ >
194
+ Schedule
195
+ </ Button >
85
196
</ div >
86
197
</ div >
198
+
199
+ < div style = { { marginTop : "7%" } } >
200
+ < Typography component = "h1" variant = "h5" >
201
+ Enrolled People
202
+ </ Typography >
203
+
204
+ < StyledTable >
205
+ < thead >
206
+ < tr >
207
+ < th className = "avatar-column" > </ th >
208
+ < th > Name</ th >
209
+ < th className = "type-column" > Role</ th >
210
+ { IsAdmin ( ) ? (
211
+ < th className = "actions-column" > Actions</ th >
212
+ ) : null }
213
+ </ tr >
214
+ </ thead >
215
+
216
+ < tbody >
217
+ { courseData ?. users . map (
218
+ ( user : FullCourseUser , index : number ) => (
219
+ < tr
220
+ key = { user . username }
221
+ style = { {
222
+ backgroundColor :
223
+ alternatingColor [ index % 2 ]
224
+ } }
225
+ >
226
+ < td className = "avatar-column" >
227
+ < Avatar
228
+ alt = { `${ user . first_name } ${ user . last_name } ` }
229
+ />
230
+ </ td >
231
+ < td >
232
+ < Button
233
+ style = { {
234
+ color : "white" ,
235
+ textTransform : "none" ,
236
+ fontSize : "1em"
237
+ } }
238
+ onClick = { ( ) =>
239
+ handleProfileClick (
240
+ user . username
241
+ )
242
+ }
243
+ >
244
+ { `${ user . first_name } ${ user . last_name } ` }
245
+ </ Button >
246
+ </ td >
247
+ < td style = { { fontSize : "1em" } } >
248
+ { capitalize ( user . role ) }
249
+ </ td >
250
+ { IsAdmin ( ) ? (
251
+ < td className = "actions-icon" >
252
+ < IconButton >
253
+ < MoreVertIcon />
254
+ </ IconButton >
255
+ </ td >
256
+ ) : null }
257
+ </ tr >
258
+ )
259
+ ) }
260
+ </ tbody >
261
+ </ StyledTable >
262
+ </ div >
87
263
</ Container >
88
264
</ RootPage >
89
265
) ;
90
266
} ;
91
267
92
- export default Profile ;
268
+ export default Course ;
0 commit comments