11import React , { useState } from 'react'
2- import { useParams } from 'react-router-dom'
2+ import { useParams } from 'react-router-dom'
33import { useActionless } from 'redux/hooks'
44import { SET_ALERT } from 'redux/types/active.types'
55
6- import { SubmissionScore } from 'devu-shared-modules'
6+ import { AssignmentProblem , SubmissionScore , SubmissionProblemScore } from 'devu-shared-modules'
77import RequestService from 'services/request.service'
88import Modal from 'components/shared/layouts/modal'
99
1010interface Props {
1111 open : boolean ;
1212 onClose : ( ) => void ;
1313 submissionScore : SubmissionScore | null ;
14-
14+ assignmentProblems : Array < AssignmentProblem > ;
15+ submissionProblemScores : Array < SubmissionProblemScore > ;
1516}
1617
17- const ManualGradeModal = ( { open, onClose, submissionScore } : Props ) => {
18+ const ManualGradeModal = ( { open, onClose, submissionScore, assignmentProblems , submissionProblemScores } : Props ) => {
1819 const [ setAlert ] = useActionless ( SET_ALERT )
19- const { assignmentId, courseId } = useParams < { assignmentId : string , courseId : string } > ( )
20+ const { assignmentId, courseId } = useParams < { assignmentId : string , courseId : string } > ( )
21+ const [ problemScores , setProblemScores ] = useState < Record < string , any > > ( { } )
2022
2123 const [ formData , setFormData ] = useState ( {
2224 submissionId : submissionScore ?. submissionId ,
@@ -26,22 +28,43 @@ const ManualGradeModal = ({ open, onClose, submissionScore }: Props) => {
2628 } )
2729
2830 const handleManualGrade = async ( ) => {
31+ const updateProblemScoreURL = `/api/course/${ courseId } /assignment/${ assignmentId } /submission-problem-scores`
32+
2933 // set releasedAt to now in ISO 8601 format
3034 setFormData ( prevState => ( { ...prevState , [ "releasedAt" ] : new Date ( ) . toISOString ( ) } ) )
3135
36+
37+ // update problem scores if changed
38+ for ( const [ id , scoreData ] of Object . entries ( problemScores ) ) {
39+ const problemID = Number ( id . split ( "_" ) [ 1 ] )
40+
41+ // get corresponding score if exists
42+ const correspondingScore = submissionProblemScores . find (
43+ ( scoreItem ) => scoreItem . assignmentProblemId === problemID
44+ ) ;
45+
46+ scoreData [ "releasedAt" ] = new Date ( ) . toISOString ( )
47+
48+ if ( correspondingScore ) {
49+ // put request to update score
50+ await RequestService . put ( `${ updateProblemScoreURL } /${ correspondingScore . id } ` , scoreData )
51+
52+ } else {
53+ // post request to create new score
54+ await RequestService . post ( updateProblemScoreURL , scoreData )
55+ }
56+ }
57+
3258 if ( submissionScore ) {
3359 // Update the submission score
34- console . log ( 'Submission Exists' )
3560 await RequestService . put ( `/api/course/${ courseId } /assignment/${ assignmentId } /submission-scores/${ submissionScore . id } ` , formData )
3661 . then ( ( ) => {
3762 setAlert ( { autoDelete : true , type : 'success' , message : 'Submission Score Updated' } )
3863 window . location . reload ( )
3964 } )
40-
4165 }
4266 else {
4367 // Create a new submission score
44- console . log ( 'No Submission' )
4568 await RequestService . post ( `/api/course/${ courseId } /assignment/${ assignmentId } /submission-scores` , formData )
4669 . then ( ( ) => {
4770 setAlert ( { autoDelete : true , type : 'success' , message : 'Submission Score Created' } )
@@ -57,16 +80,58 @@ const ManualGradeModal = ({ open, onClose, submissionScore }: Props) => {
5780 setFormData ( prevState => ( { ...prevState , [ key ] : value } ) )
5881 }
5982
83+ const handleProblemChange = ( e : React . ChangeEvent < HTMLInputElement > ) => {
84+ const { id, value } = e . target ; // Get the input's id and value
85+ const scoreValue = Number ( value ) ; // Convert the score to a number
86+
87+ setProblemScores ( prevScores => {
88+ const updatedScores : any = { ...prevScores } ;
89+
90+ // if key exists
91+ if ( updatedScores [ id ] ) {
92+ // update score for existing problem
93+ updatedScores [ id ] . score = scoreValue ;
94+ } else {
95+ // add a new problem score entry
96+ updatedScores [ id ] = {
97+ submissionId : submissionScore ?. submissionId ,
98+ assignmentProblemId : Number ( id . split ( "_" ) [ 1 ] ) ,
99+ score : scoreValue ,
100+ } ;
101+ }
102+
103+ return updatedScores ; // Return the updated scores object
104+ } ) ;
105+ }
106+
60107 return (
61108 < Modal title = "Grade Assignment" buttonAction = { handleManualGrade } open = { open } onClose = { onClose } >
109+ { assignmentProblems . map ( ( problemItem ) => {
110+ // find the corresponding submissionProblemScore for the current problem
111+ const correspondingScore = submissionProblemScores . find (
112+ ( scoreItem ) => scoreItem . assignmentProblemId === problemItem . id
113+ ) ;
114+
115+ return (
116+ < div key = { problemItem . id } className = "input-group" >
117+ < label htmlFor = { "problem_" + problemItem . id ?. toString ( ) } > { problemItem . problemName } </ label >
118+ < input type = "number"
119+ id = { "problem_" + problemItem . id ?. toString ( ) }
120+ placeholder = { String ( correspondingScore ? correspondingScore . score : "unanswered" ) }
121+ onChange = { handleProblemChange }
122+ />
123+ </ div >
124+ ) ;
125+ } ) }
126+
62127 < div className = "input-group" >
63128 < label htmlFor = "score" className = "input-label" > Assignment Score:</ label >
64129 < input type = "number" id = "score" value = { Number ( formData . score ) } onChange = { handleChange } />
65130 </ div >
66131 < div className = "input-group" >
67132 < label htmlFor = "feedback" className = "input-label" > Overall Feedback:</ label >
68- < textarea rows = { 4 } id = "feedback" onChange = { handleChange } value = { String ( formData . feedback ) }
69- placeholder = 'Provide assignment feedback...' />
133+ < textarea rows = { 4 } id = "feedback" onChange = { handleChange } value = { String ( formData . feedback ) }
134+ placeholder = 'Provide assignment feedback...' />
70135 </ div >
71136 </ Modal >
72137 )
0 commit comments