9
9
ChevronRight ,
10
10
AlertCircle ,
11
11
BookOpen ,
12
- CodeXml
12
+ CodeXml ,
13
+ Users ,
14
+ User
13
15
} from 'lucide-react' ;
14
16
import { Card , CardHeader , CardTitle , CardContent , CardFooter } from '@/components/ui/card' ;
15
17
import { Button } from '@/components/ui/button' ;
@@ -20,9 +22,13 @@ import { useUserContext } from '../UserEnvProvider';
20
22
21
23
interface Assignment {
22
24
assignment_id : string ;
25
+ is_group_assign : boolean ;
23
26
name : string ;
27
+ course_id : string ;
28
+ teacher_id : string ;
24
29
deadline : string ;
25
30
isOver : boolean ;
31
+ description ?: string ;
26
32
}
27
33
28
34
interface AssignmentData {
@@ -67,44 +73,7 @@ export default function Assignment({ courseId }: AssignmentProps) {
67
73
console . error ( 'Error fetching assignments:' , err ) ;
68
74
// Mock data for development
69
75
setData ( {
70
- assignments : [
71
- {
72
- assignment_id : "asn_001" ,
73
- name : "Getting Started with Algorithms" ,
74
- deadline : "2023-06-15T23:59:59Z" ,
75
- isOver : false
76
- } ,
77
- {
78
- assignment_id : "asn_002" ,
79
- name : "Data Structures Implementation" ,
80
- deadline : "2023-06-20T23:59:59Z" ,
81
- isOver : false
82
- } ,
83
- {
84
- assignment_id : "asn_003" ,
85
- name : "Algorithm Complexity Analysis" ,
86
- deadline : "2023-06-10T23:59:59Z" ,
87
- isOver : true
88
- } ,
89
- {
90
- assignment_id : "asn_004" ,
91
- name : "Advanced Problem Solving" ,
92
- deadline : "2023-07-05T23:59:59Z" ,
93
- isOver : false
94
- } ,
95
- {
96
- assignment_id : "asn_005" ,
97
- name : "Team Project Planning" ,
98
- deadline : "2023-06-25T23:59:59Z" ,
99
- isOver : false
100
- } ,
101
- {
102
- assignment_id : "asn_006" ,
103
- name : "Basic Programming Concepts" ,
104
- deadline : "2023-05-30T23:59:59Z" ,
105
- isOver : true
106
- }
107
- ]
76
+ assignments : [ ]
108
77
} ) ;
109
78
} finally {
110
79
setLoading ( false ) ;
@@ -116,7 +85,11 @@ export default function Assignment({ courseId }: AssignmentProps) {
116
85
}
117
86
} , [ courseId ] ) ;
118
87
88
+ const [ envLoading , setEnvLoading ] = useState ( false ) ;
89
+
119
90
const handleStartAssignment = async ( assignmentId : string ) => {
91
+ setError ( null ) ;
92
+ setEnvLoading ( true ) ;
120
93
var result : any ;
121
94
try {
122
95
const formData = new FormData ( ) ;
@@ -135,11 +108,13 @@ export default function Assignment({ courseId }: AssignmentProps) {
135
108
result = await response . json ( ) ;
136
109
if ( result . message == "Require group" && ! ( courseId in myGroups ) ) {
137
110
setError ( 'You need to join a group to start this assignment.' ) ;
111
+ setEnvLoading ( false ) ;
138
112
return ;
139
113
}
140
114
} catch ( error ) {
141
115
console . error ( 'Error starting assignment environment:' , error ) ;
142
116
setError ( 'Failed to start assignment environment. Please try again later.' ) ;
117
+ setEnvLoading ( false ) ;
143
118
return ;
144
119
}
145
120
const environmentId = result . environment_id ;
@@ -152,8 +127,38 @@ export default function Assignment({ courseId }: AssignmentProps) {
152
127
icon : "CodeXml"
153
128
}
154
129
] ) ;
130
+ setEnvLoading ( false ) ;
155
131
} ;
156
132
133
+ // Loading popout overlay
134
+ if ( envLoading ) {
135
+ return (
136
+ < div className = "fixed inset-0 z-50 flex items-center justify-center bg-black/40" >
137
+ < Card className = "p-8 flex flex-col items-center gap-4 shadow-2xl" >
138
+ < div className = "animate-spin mb-2" >
139
+ < svg className = "h-10 w-10 text-primary" viewBox = "0 0 24 24" fill = "none" >
140
+ < circle
141
+ className = "opacity-25"
142
+ cx = "12"
143
+ cy = "12"
144
+ r = "10"
145
+ stroke = "currentColor"
146
+ strokeWidth = "4"
147
+ />
148
+ < path
149
+ className = "opacity-75"
150
+ fill = "currentColor"
151
+ d = "M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"
152
+ />
153
+ </ svg >
154
+ </ div >
155
+ < h3 className = "text-lg font-semibold" > Preparing your coding environment...</ h3 >
156
+ < p className = "text-muted-foreground text-center text-sm" > This may take a few moments. Please wait.</ p >
157
+ </ Card >
158
+ </ div >
159
+ ) ;
160
+ }
161
+
157
162
// Sort assignments: active ones by deadline (earliest first), then completed ones
158
163
const sortedAssignments = data ?. assignments
159
164
? [ ...data . assignments ] . sort ( ( a , b ) => {
@@ -411,21 +416,42 @@ export default function Assignment({ courseId }: AssignmentProps) {
411
416
{ ! isActive && (
412
417
< div className = "absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-muted-foreground/30 to-muted-foreground/10" > </ div >
413
418
) }
414
- < CardHeader className = "pb-2" >
415
- < CardTitle className = { `text-xl font-semibold flex items-center ${ ! isActive ? 'text-muted-foreground' : '' } ` } >
416
- < BookOpen className = "h-5 w-5 mr-2 text-primary" />
417
- { assignment . name }
418
- { assignment . isOver && (
419
- < Badge variant = "outline" className = "ml-2 text-xs" >
420
- Completed
421
- </ Badge >
422
- ) }
423
- { isMissed && (
424
- < Badge variant = "destructive" className = "ml-2 text-xs" >
425
- Missed
426
- </ Badge >
427
- ) }
428
- </ CardTitle >
419
+ < CardHeader className = "pb-3" >
420
+ < div className = "flex items-start justify-between" >
421
+ < CardTitle className = { `text-xl font-semibold flex items-center ${ ! isActive ? 'text-muted-foreground' : '' } ` } >
422
+ < BookOpen className = "h-5 w-5 mr-2 text-primary" />
423
+ { assignment . name }
424
+ </ CardTitle >
425
+ < div className = "flex gap-2 ml-4" >
426
+ { assignment . is_group_assign && (
427
+ < Badge variant = "secondary" className = "flex items-center gap-1 text-xs" >
428
+ < Users size = { 10 } />
429
+ Group
430
+ </ Badge >
431
+ ) }
432
+ { ! assignment . is_group_assign && (
433
+ < Badge variant = "outline" className = "flex items-center gap-1 text-xs" >
434
+ < User size = { 10 } />
435
+ Individual
436
+ </ Badge >
437
+ ) }
438
+ { assignment . isOver && (
439
+ < Badge variant = "outline" className = "text-xs" >
440
+ Completed
441
+ </ Badge >
442
+ ) }
443
+ { isMissed && (
444
+ < Badge variant = "destructive" className = "text-xs" >
445
+ Missed
446
+ </ Badge >
447
+ ) }
448
+ </ div >
449
+ </ div >
450
+ { assignment . description && (
451
+ < p className = { `text-sm mt-2 ${ ! isActive ? 'text-muted-foreground' : 'text-muted-foreground' } ` } >
452
+ { assignment . description }
453
+ </ p >
454
+ ) }
429
455
</ CardHeader >
430
456
< CardContent className = "pb-4" >
431
457
{ renderDeadlineInfo ( assignment . deadline , assignment . isOver ) }
0 commit comments