diff --git a/apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/MarkExerciseModal.svelte b/apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/MarkExerciseModal.svelte index 1db576d5..442bd312 100644 --- a/apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/MarkExerciseModal.svelte +++ b/apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/MarkExerciseModal.svelte @@ -25,6 +25,7 @@ nextStatusId: number; total: number; }) => {}; + export let isSaving = false; const SELECTABLE_STATUS = [ { @@ -128,7 +129,7 @@ 'course.navItem.submissions.grading_modal.questions_tried' )} ${answerPoints} ` }; - data.questionAnswerByPoint[id] = `${points / answerPoints}`; + data.questionAnswerByPoint[id] = `${Math.ceil(points / answerPoints)}`; } else if (aiResponses.length) { const graded = aiResponses.find((res) => res.id === id); @@ -335,8 +336,9 @@ { handleSave(data); - onClose(); + // onClose(); }} + isLoading={isSaving} label={$t('course.navItem.submissions.grading_modal.submit_grades')} variant={VARIANTS.CONTAINED} className="py-3 px-8 w-full" diff --git a/apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/functions.js b/apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/functions.ts similarity index 78% rename from apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/functions.js rename to apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/functions.ts index c8c28a5d..4da4fc07 100644 --- a/apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/functions.js +++ b/apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/functions.ts @@ -5,6 +5,12 @@ export const isAnswerCorrect = (options, answer) => { return options.some((option) => option.is_correct && option.value === answer); }; +/* + GRADING RULES + Textarea = no validation + Single = only one should be correct + Multiple = all should be correct +*/ export function wasCorrectAnswerSelected(currentQuestion, answers, isFinished) { if (currentQuestion.question_type.id === QUESTION_TYPE.TEXTAREA) { return true; @@ -13,15 +19,20 @@ export function wasCorrectAnswerSelected(currentQuestion, answers, isFinished) { const answer = answers[currentQuestion.name]; const formattedAnswers = typeof answer === 'string' ? [answer] : answer; - const isCorrect = - formattedAnswers && - formattedAnswers.some((answer) => { - if (isAnswerCorrect(currentQuestion.options, answer)) { - return true; - } - return false; - }); + let isCorrect = false; + + if (currentQuestion.question_type.id === QUESTION_TYPE.CHECKBOX) { + // Every correct answer should be in the selected answer + isCorrect = currentQuestion.options + .filter((o) => o.is_correct) + .every((option) => formattedAnswers?.includes(option.value)); + } else if (currentQuestion.question_type.id === QUESTION_TYPE.RADIO) { + // At least one correct answer should be selected + isCorrect = formattedAnswers?.some((answer) => + isAnswerCorrect(currentQuestion.options, answer) + ); + } if (isCorrect && !isFinished) { toggleConfetti(); diff --git a/apps/dashboard/src/routes/courses/[id]/submissions/+page.svelte b/apps/dashboard/src/routes/courses/[id]/submissions/+page.svelte index 5b4dbf72..d270689d 100644 --- a/apps/dashboard/src/routes/courses/[id]/submissions/+page.svelte +++ b/apps/dashboard/src/routes/courses/[id]/submissions/+page.svelte @@ -47,6 +47,7 @@ let openExercise = false; let isGradeWithAI = false; let fetching = false; + let isSaving = false; const submissionStatus: { [key: number]: string } = { 1: $t('course.navItem.submissions.submission_status.submitted'), @@ -243,30 +244,40 @@ questionAnswers: any; feedback: any; }) { + isSaving = true; const { questionAnswerByPoint, questionAnswers, feedback } = submission; let totalPoints = 0; - const updates = Object.keys(questionAnswerByPoint).map((questionId) => { - const questionAnswer = questionAnswers.find( - (answer: { question_id: string }) => answer.question_id == questionId - ); - const point = questionAnswerByPoint[questionId]; + for (const questionId in questionAnswerByPoint) { + if (Object.prototype.hasOwnProperty.call(questionAnswerByPoint, questionId)) { + const questionAnswer = questionAnswers.find( + (answer: { question_id: string }) => answer.question_id == questionId + ); + const point = questionAnswerByPoint[questionId]; - totalPoints += parseInt(point, 10); + totalPoints += parseInt(point, 10); - return updateQuestionAnswer({ point }, { id: questionAnswer?.id }); - }); + const qaResponse = await updateQuestionAnswer({ point }, { id: questionAnswer?.id }); - updateSubmission({ + if (qaResponse.error) { + console.error('Error saving', qaResponse.error); + snackbar.error(`snackbar.something`); + + return; + } + } + } + + await updateSubmission({ id: submissionId, total: totalPoints, feedback: feedback - }).then((res) => console.log('Updated submission', res)); + }); snackbar.success('snackbar.submissions.success.grading'); - await Promise.all(updates); + isSaving = false; } async function firstRender(courseId: string) { @@ -354,6 +365,7 @@ {updateStatus} deleteSubmission={handleDeleteSubmission} bind:isGradeWithAI + {isSaving} />