feat(vocabLesson): add detailed review section for failed chapter exams
All checks were successful
Deploy to production / deploy (push) Successful in 2m53s
All checks were successful
Deploy to production / deploy (push) Successful in 2m53s
- Introduced a new review section that displays questions, user answers, and correct answers for failed chapter exams. - Added localization entries for the review section in multiple languages, enhancing user experience and understanding of mistakes. - Implemented logic to format and present failed exam details, improving feedback for learners.
This commit is contained in:
@@ -572,6 +572,10 @@
|
||||
"exerciseExamFailedTitle": "Wala naabot ang minimum nga score",
|
||||
"exerciseExamFailedBody": "Naayo ka ug {score}% (kinahanglan: {target}%). Padayon pag-praktis sa learning section. Human sa {count} pa nga trainer questions ma-unlock na usab ang chapter test — sugdan nimo pag-usab ang tanan nga pangutana gikan sa sinugdanan.",
|
||||
"exerciseExamFailedOk": "Okay",
|
||||
"exerciseExamFailedReviewTitle": "Kini nga tubag sayop pa",
|
||||
"exerciseExamFailedQuestionLabel": "Pangutana",
|
||||
"exerciseExamFailedYourAnswerLabel": "Imong tubag",
|
||||
"exerciseExamFailedNoAnswer": "Walay tubag",
|
||||
"exerciseStatusOpen": "Ablihi",
|
||||
"exerciseStatusCorrect": "Done",
|
||||
"exerciseStatusRetry": "Try again",
|
||||
|
||||
@@ -544,6 +544,10 @@
|
||||
"exerciseExamFailedTitle": "Mindestziel nicht erreicht",
|
||||
"exerciseExamFailedBody": "Du hast {score}% der Fragen richtig beantwortet (Mindestziel: {target}%). Bitte übe weiter im Lernbereich. Nach {count} weiteren Trainerfragen ist die Kapitel-Prüfung wieder freigeschaltet – dann beginnst du mit allen Fragen von vorn.",
|
||||
"exerciseExamFailedOk": "Verstanden",
|
||||
"exerciseExamFailedReviewTitle": "Das war noch falsch",
|
||||
"exerciseExamFailedQuestionLabel": "Frage",
|
||||
"exerciseExamFailedYourAnswerLabel": "Deine Antwort",
|
||||
"exerciseExamFailedNoAnswer": "Keine Antwort",
|
||||
"exerciseStatusOpen": "Offen",
|
||||
"exerciseStatusCorrect": "Erledigt",
|
||||
"exerciseStatusRetry": "Nochmal prüfen",
|
||||
|
||||
@@ -544,6 +544,10 @@
|
||||
"exerciseExamFailedTitle": "Minimum score not reached",
|
||||
"exerciseExamFailedBody": "You scored {score}% correct (required: {target}%). Keep practicing in the learning section. After {count} more trainer questions the chapter test unlocks again—you will then retake all questions from the start.",
|
||||
"exerciseExamFailedOk": "OK",
|
||||
"exerciseExamFailedReviewTitle": "These answers were wrong",
|
||||
"exerciseExamFailedQuestionLabel": "Question",
|
||||
"exerciseExamFailedYourAnswerLabel": "Your answer",
|
||||
"exerciseExamFailedNoAnswer": "No answer",
|
||||
"exerciseStatusOpen": "Open",
|
||||
"exerciseStatusCorrect": "Done",
|
||||
"exerciseStatusRetry": "Try again",
|
||||
|
||||
@@ -542,6 +542,10 @@
|
||||
"exerciseExamFailedTitle": "No alcanzaste la puntuación mínima",
|
||||
"exerciseExamFailedBody": "Has acertado el {score}% (mínimo: {target}%). Sigue practicando en el área de aprendizaje. Tras {count} preguntas más del entrenador se desbloqueará de nuevo el test del capítulo y repetirás todas las preguntas desde el principio.",
|
||||
"exerciseExamFailedOk": "Entendido",
|
||||
"exerciseExamFailedReviewTitle": "Estas respuestas fueron incorrectas",
|
||||
"exerciseExamFailedQuestionLabel": "Pregunta",
|
||||
"exerciseExamFailedYourAnswerLabel": "Tu respuesta",
|
||||
"exerciseExamFailedNoAnswer": "Sin respuesta",
|
||||
"exerciseStatusOpen": "Pendiente",
|
||||
"exerciseStatusCorrect": "Hecha",
|
||||
"exerciseStatusRetry": "Revisar otra vez",
|
||||
|
||||
@@ -542,6 +542,10 @@
|
||||
"exerciseExamFailedTitle": "Score minimum non atteint",
|
||||
"exerciseExamFailedBody": "Vous avez {score}% de bonnes réponses (minimum : {target}%). Continuez à vous entraîner dans la partie apprentissage. Après {count} questions supplémentaires dans l'entraîneur, le test du chapitre se débloque à nouveau et vous reprendrez toutes les questions depuis le début.",
|
||||
"exerciseExamFailedOk": "Compris",
|
||||
"exerciseExamFailedReviewTitle": "Réponses encore incorrectes",
|
||||
"exerciseExamFailedQuestionLabel": "Question",
|
||||
"exerciseExamFailedYourAnswerLabel": "Votre réponse",
|
||||
"exerciseExamFailedNoAnswer": "Aucune réponse",
|
||||
"exerciseStatusOpen": "Ouvrir",
|
||||
"exerciseStatusCorrect": "Complété",
|
||||
"exerciseStatusRetry": "Revérifier",
|
||||
|
||||
@@ -957,6 +957,25 @@
|
||||
target: exerciseTargetScore,
|
||||
count: exerciseRetryUnlockAttempts
|
||||
}) }}</p>
|
||||
<div v-if="chapterExamFailedDetails.length > 0" class="exam-failed-review">
|
||||
<h4>{{ $t('socialnetwork.vocab.courses.exerciseExamFailedReviewTitle') }}</h4>
|
||||
<ul>
|
||||
<li v-for="(item, index) in chapterExamFailedDetails" :key="`failed-${index}-${item.id}`">
|
||||
<p class="exam-failed-review__question">
|
||||
<strong>{{ $t('socialnetwork.vocab.courses.exerciseExamFailedQuestionLabel') }} {{ index + 1 }}:</strong>
|
||||
{{ item.question }}
|
||||
</p>
|
||||
<p class="exam-failed-review__answer">
|
||||
<strong>{{ $t('socialnetwork.vocab.courses.exerciseExamFailedYourAnswerLabel') }}:</strong>
|
||||
{{ item.userAnswer || $t('socialnetwork.vocab.courses.exerciseExamFailedNoAnswer') }}
|
||||
</p>
|
||||
<p class="exam-failed-review__answer">
|
||||
<strong>{{ $t('socialnetwork.vocab.courses.correctAnswer') }}:</strong>
|
||||
{{ item.correctAnswer || '—' }}
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button type="button" class="dialog-button dialog-button--primary" @click="closeChapterExamFailedDialog">
|
||||
@@ -1053,6 +1072,7 @@ export default {
|
||||
exerciseReinforcementMessage: '',
|
||||
showChapterExamFailedDialog: false,
|
||||
chapterExamFailedScore: 0,
|
||||
chapterExamFailedDetails: [],
|
||||
/** Index in scrambledChapterExamExercises bei Ein-Frage-Ansicht */
|
||||
exerciseSequentialIndex: 0,
|
||||
/** Aus vorherigen Lektionen (MC-Optionen nach Fragentyp Ziel-/Muttersprache) */
|
||||
@@ -2049,6 +2069,42 @@ export default {
|
||||
closeChapterExamFailedDialog() {
|
||||
this.showChapterExamFailedDialog = false;
|
||||
},
|
||||
formatExerciseAnswerForReview(exercise, rawAnswer) {
|
||||
if (rawAnswer === null || rawAnswer === undefined) return '';
|
||||
const type = this.getExerciseType(exercise);
|
||||
if (type === 'multiple_choice') {
|
||||
const options = this.getOptions(exercise);
|
||||
const idx = Number(rawAnswer);
|
||||
if (Number.isInteger(idx) && idx >= 0 && idx < options.length) {
|
||||
return String(options[idx] ?? '');
|
||||
}
|
||||
}
|
||||
if (Array.isArray(rawAnswer)) {
|
||||
return rawAnswer
|
||||
.map((v) => String(v || '').trim())
|
||||
.filter(Boolean)
|
||||
.join(' | ');
|
||||
}
|
||||
return String(rawAnswer || '').trim();
|
||||
},
|
||||
buildChapterExamFailedDetails() {
|
||||
const all = this.effectiveExercises;
|
||||
if (!Array.isArray(all) || all.length === 0) return [];
|
||||
const out = [];
|
||||
all.forEach((exercise) => {
|
||||
const result = this.exerciseResults[exercise.id];
|
||||
if (!result || result.correct) return;
|
||||
const question = String(this.getQuestionText(exercise) || exercise.title || '').trim();
|
||||
const userAnswerRaw = this.exerciseAnswers[exercise.id];
|
||||
out.push({
|
||||
id: exercise.id,
|
||||
question,
|
||||
userAnswer: this.formatExerciseAnswerForReview(exercise, userAnswerRaw),
|
||||
correctAnswer: String(result.correctAnswer || '').trim()
|
||||
});
|
||||
});
|
||||
return out;
|
||||
},
|
||||
clearChapterExamAttemptState() {
|
||||
const all = this.effectiveExercises;
|
||||
if (!all.length) return;
|
||||
@@ -2064,6 +2120,7 @@ export default {
|
||||
this.buildMcRandomizedOptions();
|
||||
},
|
||||
handleChapterExamFailed(score) {
|
||||
this.chapterExamFailedDetails = this.buildChapterExamFailedDetails();
|
||||
this.exerciseRetryPending = true;
|
||||
this.exerciseRetryPendingSinceAttempts = this.vocabTrainerTotalAttempts;
|
||||
this.clearChapterExamAttemptState();
|
||||
@@ -4234,6 +4291,31 @@ export default {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.exam-failed-review {
|
||||
margin-top: 14px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid rgba(133, 100, 4, 0.28);
|
||||
}
|
||||
|
||||
.exam-failed-review h4 {
|
||||
margin: 0 0 8px;
|
||||
font-size: 0.98rem;
|
||||
}
|
||||
|
||||
.exam-failed-review ul {
|
||||
margin: 0;
|
||||
padding-left: 18px;
|
||||
}
|
||||
|
||||
.exam-failed-review li {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.exam-failed-review__question,
|
||||
.exam-failed-review__answer {
|
||||
margin: 0 0 4px;
|
||||
}
|
||||
|
||||
.exercise-flow-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
Reference in New Issue
Block a user