feat: add quiz attempt logic to getlessonContent

- Check allow_multiple_attempts setting when returning quiz data
- If allow_multiple_attempts is false AND user has attempted:
  - Return only quiz metadata and latest score
  - Do NOT return questions
- If allow_multiple_attempts is true OR user has not attempted:
  - Return full quiz with questions
  - Include latest_attempt data if exists
- Add latest_attempt field to quiz response with score and attempt info
This commit is contained in:
JakkrapartXD 2026-02-11 14:36:54 +07:00
parent f7330a7b27
commit df750723af

View file

@ -583,6 +583,27 @@ export class CoursesStudentService {
logger.error(`Failed to list attachments from MinIO: ${err}`);
}
// Check quiz attempts if this is a QUIZ lesson
let latestQuizAttempt = null;
let shouldReturnQuestions = true;
if (lesson.quiz) {
// Get latest quiz attempt for this user
latestQuizAttempt = await prisma.quizAttempt.findFirst({
where: {
user_id: decoded.id,
quiz_id: lesson.quiz.id,
},
orderBy: {
started_at: 'desc',
},
});
// If allow_multiple_attempts is false AND user has attempted
if (!lesson.quiz.allow_multiple_attempts && latestQuizAttempt) {
shouldReturnQuestions = false;
}
}
return {
code: 200,
@ -599,7 +620,7 @@ export class CoursesStudentService {
require_pass_quiz: lesson.require_pass_quiz,
video_url, // Presigned URL for video
attachments: attachmentsWithUrls,
quiz: lesson.quiz ? {
quiz: lesson.quiz ? (shouldReturnQuestions ? {
id: lesson.quiz.id,
title: lesson.quiz.title as { th: string; en: string },
description: lesson.quiz.description as { th: string; en: string } | null,
@ -609,6 +630,14 @@ export class CoursesStudentService {
shuffle_choices: lesson.quiz.shuffle_choices,
is_skippable: lesson.quiz.is_skippable,
show_answers_after_completion: lesson.quiz.show_answers_after_completion,
allow_multiple_attempts: lesson.quiz.allow_multiple_attempts,
latest_attempt: latestQuizAttempt ? {
score: latestQuizAttempt.score,
is_passed: latestQuizAttempt.is_passed,
attempt_number: latestQuizAttempt.attempt_number,
started_at: latestQuizAttempt.started_at,
completed_at: latestQuizAttempt.completed_at,
} : undefined,
questions: lesson.quiz.questions.map(q => ({
id: q.id,
question: q.question as { th: string; en: string },
@ -621,7 +650,21 @@ export class CoursesStudentService {
sort_order: c.sort_order,
})),
})),
} : null,
} : {
// Only return quiz metadata and latest score, no questions
id: lesson.quiz.id,
title: lesson.quiz.title as { th: string; en: string },
description: lesson.quiz.description as { th: string; en: string } | null,
passing_score: lesson.quiz.passing_score,
allow_multiple_attempts: lesson.quiz.allow_multiple_attempts,
latest_attempt: latestQuizAttempt ? {
score: latestQuizAttempt.score,
is_passed: latestQuizAttempt.is_passed,
attempt_number: latestQuizAttempt.attempt_number,
started_at: latestQuizAttempt.started_at,
completed_at: latestQuizAttempt.completed_at,
} : undefined,
}) : null,
prev_lesson_id: prevLessonId,
next_lesson_id: nextLessonId,
},