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",
|
"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.",
|
"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",
|
"exerciseExamFailedOk": "Okay",
|
||||||
|
"exerciseExamFailedReviewTitle": "Kini nga tubag sayop pa",
|
||||||
|
"exerciseExamFailedQuestionLabel": "Pangutana",
|
||||||
|
"exerciseExamFailedYourAnswerLabel": "Imong tubag",
|
||||||
|
"exerciseExamFailedNoAnswer": "Walay tubag",
|
||||||
"exerciseStatusOpen": "Ablihi",
|
"exerciseStatusOpen": "Ablihi",
|
||||||
"exerciseStatusCorrect": "Done",
|
"exerciseStatusCorrect": "Done",
|
||||||
"exerciseStatusRetry": "Try again",
|
"exerciseStatusRetry": "Try again",
|
||||||
|
|||||||
@@ -544,6 +544,10 @@
|
|||||||
"exerciseExamFailedTitle": "Mindestziel nicht erreicht",
|
"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.",
|
"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",
|
"exerciseExamFailedOk": "Verstanden",
|
||||||
|
"exerciseExamFailedReviewTitle": "Das war noch falsch",
|
||||||
|
"exerciseExamFailedQuestionLabel": "Frage",
|
||||||
|
"exerciseExamFailedYourAnswerLabel": "Deine Antwort",
|
||||||
|
"exerciseExamFailedNoAnswer": "Keine Antwort",
|
||||||
"exerciseStatusOpen": "Offen",
|
"exerciseStatusOpen": "Offen",
|
||||||
"exerciseStatusCorrect": "Erledigt",
|
"exerciseStatusCorrect": "Erledigt",
|
||||||
"exerciseStatusRetry": "Nochmal prüfen",
|
"exerciseStatusRetry": "Nochmal prüfen",
|
||||||
|
|||||||
@@ -544,6 +544,10 @@
|
|||||||
"exerciseExamFailedTitle": "Minimum score not reached",
|
"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.",
|
"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",
|
"exerciseExamFailedOk": "OK",
|
||||||
|
"exerciseExamFailedReviewTitle": "These answers were wrong",
|
||||||
|
"exerciseExamFailedQuestionLabel": "Question",
|
||||||
|
"exerciseExamFailedYourAnswerLabel": "Your answer",
|
||||||
|
"exerciseExamFailedNoAnswer": "No answer",
|
||||||
"exerciseStatusOpen": "Open",
|
"exerciseStatusOpen": "Open",
|
||||||
"exerciseStatusCorrect": "Done",
|
"exerciseStatusCorrect": "Done",
|
||||||
"exerciseStatusRetry": "Try again",
|
"exerciseStatusRetry": "Try again",
|
||||||
|
|||||||
@@ -542,6 +542,10 @@
|
|||||||
"exerciseExamFailedTitle": "No alcanzaste la puntuación mínima",
|
"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.",
|
"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",
|
"exerciseExamFailedOk": "Entendido",
|
||||||
|
"exerciseExamFailedReviewTitle": "Estas respuestas fueron incorrectas",
|
||||||
|
"exerciseExamFailedQuestionLabel": "Pregunta",
|
||||||
|
"exerciseExamFailedYourAnswerLabel": "Tu respuesta",
|
||||||
|
"exerciseExamFailedNoAnswer": "Sin respuesta",
|
||||||
"exerciseStatusOpen": "Pendiente",
|
"exerciseStatusOpen": "Pendiente",
|
||||||
"exerciseStatusCorrect": "Hecha",
|
"exerciseStatusCorrect": "Hecha",
|
||||||
"exerciseStatusRetry": "Revisar otra vez",
|
"exerciseStatusRetry": "Revisar otra vez",
|
||||||
|
|||||||
@@ -542,6 +542,10 @@
|
|||||||
"exerciseExamFailedTitle": "Score minimum non atteint",
|
"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.",
|
"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",
|
"exerciseExamFailedOk": "Compris",
|
||||||
|
"exerciseExamFailedReviewTitle": "Réponses encore incorrectes",
|
||||||
|
"exerciseExamFailedQuestionLabel": "Question",
|
||||||
|
"exerciseExamFailedYourAnswerLabel": "Votre réponse",
|
||||||
|
"exerciseExamFailedNoAnswer": "Aucune réponse",
|
||||||
"exerciseStatusOpen": "Ouvrir",
|
"exerciseStatusOpen": "Ouvrir",
|
||||||
"exerciseStatusCorrect": "Complété",
|
"exerciseStatusCorrect": "Complété",
|
||||||
"exerciseStatusRetry": "Revérifier",
|
"exerciseStatusRetry": "Revérifier",
|
||||||
|
|||||||
@@ -957,6 +957,25 @@
|
|||||||
target: exerciseTargetScore,
|
target: exerciseTargetScore,
|
||||||
count: exerciseRetryUnlockAttempts
|
count: exerciseRetryUnlockAttempts
|
||||||
}) }}</p>
|
}) }}</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>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<button type="button" class="dialog-button dialog-button--primary" @click="closeChapterExamFailedDialog">
|
<button type="button" class="dialog-button dialog-button--primary" @click="closeChapterExamFailedDialog">
|
||||||
@@ -1053,6 +1072,7 @@ export default {
|
|||||||
exerciseReinforcementMessage: '',
|
exerciseReinforcementMessage: '',
|
||||||
showChapterExamFailedDialog: false,
|
showChapterExamFailedDialog: false,
|
||||||
chapterExamFailedScore: 0,
|
chapterExamFailedScore: 0,
|
||||||
|
chapterExamFailedDetails: [],
|
||||||
/** Index in scrambledChapterExamExercises bei Ein-Frage-Ansicht */
|
/** Index in scrambledChapterExamExercises bei Ein-Frage-Ansicht */
|
||||||
exerciseSequentialIndex: 0,
|
exerciseSequentialIndex: 0,
|
||||||
/** Aus vorherigen Lektionen (MC-Optionen nach Fragentyp Ziel-/Muttersprache) */
|
/** Aus vorherigen Lektionen (MC-Optionen nach Fragentyp Ziel-/Muttersprache) */
|
||||||
@@ -2049,6 +2069,42 @@ export default {
|
|||||||
closeChapterExamFailedDialog() {
|
closeChapterExamFailedDialog() {
|
||||||
this.showChapterExamFailedDialog = false;
|
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() {
|
clearChapterExamAttemptState() {
|
||||||
const all = this.effectiveExercises;
|
const all = this.effectiveExercises;
|
||||||
if (!all.length) return;
|
if (!all.length) return;
|
||||||
@@ -2064,6 +2120,7 @@ export default {
|
|||||||
this.buildMcRandomizedOptions();
|
this.buildMcRandomizedOptions();
|
||||||
},
|
},
|
||||||
handleChapterExamFailed(score) {
|
handleChapterExamFailed(score) {
|
||||||
|
this.chapterExamFailedDetails = this.buildChapterExamFailedDetails();
|
||||||
this.exerciseRetryPending = true;
|
this.exerciseRetryPending = true;
|
||||||
this.exerciseRetryPendingSinceAttempts = this.vocabTrainerTotalAttempts;
|
this.exerciseRetryPendingSinceAttempts = this.vocabTrainerTotalAttempts;
|
||||||
this.clearChapterExamAttemptState();
|
this.clearChapterExamAttemptState();
|
||||||
@@ -4234,6 +4291,31 @@ export default {
|
|||||||
font-weight: 700;
|
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 {
|
.exercise-flow-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
Reference in New Issue
Block a user