1
1
import React , { useState , useEffect } from 'react'
2
2
import { useParams } from 'react-router-dom'
3
3
4
- import { User } from 'devu-shared-modules'
5
-
4
+ import { Course , User } from 'devu-shared-modules'
6
5
import { useActionless } from 'redux/hooks'
7
6
import { UPDATE_USER } from 'redux/types/user.types'
7
+ import { SET_ALERT } from 'redux/types/active.types'
8
8
9
9
import RequestService from 'services/request.service'
10
10
@@ -20,26 +20,106 @@ type UrlParams = {
20
20
}
21
21
22
22
const UserDetailPage = ( { } ) => {
23
- const { userId } = useParams ( ) as UrlParams
23
+ const { userId } = useParams < UrlParams > ( )
24
24
const [ updateUser ] = useActionless ( UPDATE_USER )
25
+ const [ setAlert ] = useActionless ( SET_ALERT )
25
26
26
27
const [ loading , setLoading ] = useState ( true )
27
28
const [ user , setUser ] = useState ( { } as User )
28
29
const [ error , setError ] = useState ( null )
30
+ const [ courses , setCourses ] = useState < Course [ ] > ( [ ] )
29
31
30
32
useEffect ( ( ) => {
33
+ // Fetch user info
31
34
RequestService . get < User > ( `/api/users/${ userId } ` )
32
35
. then ( setUser )
33
36
. catch ( setError )
37
+
38
+ // Get activeCourses first
39
+ RequestService . get < {
40
+ instructorCourses : { id : number } [ ] ;
41
+ activeCourses : { id : number } [ ] ;
42
+ pastCourses : { id : number } [ ] ;
43
+ upcomingCourses : { id : number } [ ] ;
44
+ } > ( `/api/courses/user/${ userId } ` )
45
+ . then ( async ( data ) => {
46
+ const activeCourses = data . activeCourses
47
+
48
+ const courseFetches = await Promise . all (
49
+ activeCourses . map ( async ( c ) => {
50
+ try {
51
+ const courseDetails = await RequestService . get < Course > ( `/api/courses/${ c . id } ` )
52
+ return courseDetails
53
+ } catch {
54
+ return {
55
+ id : c . id ,
56
+ name : '[No title]' ,
57
+ semester : '' ,
58
+ number : '' ,
59
+ startDate : '' ,
60
+ endDate : ''
61
+ } as Course
62
+ }
63
+ } )
64
+ )
65
+
66
+ setCourses ( courseFetches )
67
+ } )
68
+ . catch ( ( err ) => {
69
+ setAlert ( { autoDelete : false , type : 'error' , message : 'Failed to load courses' } )
70
+ console . error ( 'Course fetch error:' , err )
71
+ } )
34
72
. finally ( ( ) => setLoading ( false ) )
35
73
} , [ ] )
36
74
75
+ const handleDropCourse = ( courseId : number ) => {
76
+ const confirmDrop = window . confirm ( "Are you sure you want to drop?" ) ;
77
+ if ( confirmDrop ) {
78
+ RequestService . delete ( `/api/course/${ courseId } /user-courses` )
79
+ . then ( ( ) => {
80
+ setAlert ( { autoDelete : true , type : 'success' , message : 'Course Dropped' } )
81
+ setCourses ( ( prev ) => prev . filter ( ( c ) => c . id !== courseId ) )
82
+ } )
83
+ . catch ( ( error : Error ) => {
84
+ setAlert ( { autoDelete : false , type : 'error' , message : error . message } )
85
+ } ) ;
86
+ }
87
+ }
88
+
37
89
if ( loading ) return < LoadingOverlay delay = { 250 } />
38
90
if ( error ) return < ErrorPage error = { error } />
39
91
40
92
return (
41
93
< PageWrapper className = { styles . container } >
42
- < EditUserForm user = { user } onSubmit = { updateUser } />
94
+ < div className = { styles . userPageLayout } >
95
+ < div className = { styles . userFormSection } >
96
+ < EditUserForm user = { user } onSubmit = { updateUser } />
97
+ </ div >
98
+
99
+ < div className = { styles . dropCoursesSection } >
100
+ < h2 > Drop Course</ h2 >
101
+ < ul className = { styles . courseList } >
102
+ { courses . length > 0 ? (
103
+ courses . map ( ( course ) => (
104
+ < li key = { course . id } className = { styles . courseItem } >
105
+ < span className = { styles . courseTitle } >
106
+ { course . name } { course . number && `(${ course . number } )` }
107
+ </ span >
108
+ < span
109
+ className = { styles . trashIcon }
110
+ onClick = { ( ) => handleDropCourse ( course . id ! ) }
111
+ title = "Drop Course"
112
+ >
113
+ 🗑️
114
+ </ span >
115
+ </ li >
116
+ ) )
117
+ ) : (
118
+ < p > No enrolled courses.</ p >
119
+ ) }
120
+ </ ul >
121
+ </ div >
122
+ </ div >
43
123
</ PageWrapper >
44
124
)
45
125
}
0 commit comments