Enhance lesson completion checks and navigation in VocabLessonView

- Introduced flags to prevent multiple executions of lesson completion checks and navigation, improving user experience and preventing potential issues.
- Updated the checkLessonCompletion method to ensure accurate score calculation and progress updates.
- Enhanced the navigateToNextLesson method to handle course loading and user navigation more effectively, including user prompts for lesson completion.
- Improved the typing mode logic to ensure questions are only presented when available, enhancing the vocabulary trainer functionality.
This commit is contained in:
Torsten Schulz (local)
2026-01-19 22:01:30 +01:00
parent 594b3dac4a
commit 21f6130666

View File

@@ -296,7 +296,9 @@ export default {
vocabTrainerSelectedChoice: null, vocabTrainerSelectedChoice: null,
vocabTrainerAnswered: false, vocabTrainerAnswered: false,
vocabTrainerLastCorrect: false, vocabTrainerLastCorrect: false,
vocabTrainerDirection: 'L2R' // L2R: learning->reference, R2L: reference->learning vocabTrainerDirection: 'L2R', // L2R: learning->reference, R2L: reference->learning
isCheckingLessonCompletion: false, // Flag um Endlosschleife zu verhindern
isNavigatingToNext: false // Flag um mehrfache Navigation zu verhindern
}; };
}, },
computed: { computed: {
@@ -583,6 +585,9 @@ export default {
} }
}, },
async checkLessonCompletion() { async checkLessonCompletion() {
// Verhindere mehrfache Ausführung
if (this.isCheckingLessonCompletion || this.isNavigatingToNext) return;
// Prüfe ob alle Übungen korrekt beantwortet wurden // Prüfe ob alle Übungen korrekt beantwortet wurden
if (!this.lesson || !this.lesson.grammarExercises) return; if (!this.lesson || !this.lesson.grammarExercises) return;
@@ -593,13 +598,15 @@ export default {
}); });
if (allCompleted) { if (allCompleted) {
// Berechne Gesamt-Score this.isCheckingLessonCompletion = true;
const totalExercises = allExercises.length;
const correctExercises = allExercises.filter(ex => this.exerciseResults[ex.id]?.correct).length;
const score = Math.round((correctExercises / totalExercises) * 100);
// Aktualisiere Fortschritt
try { try {
// Berechne Gesamt-Score
const totalExercises = allExercises.length;
const correctExercises = allExercises.filter(ex => this.exerciseResults[ex.id]?.correct).length;
const score = Math.round((correctExercises / totalExercises) * 100);
// Aktualisiere Fortschritt
await apiClient.put(`/api/vocab/lessons/${this.lessonId}/progress`, { await apiClient.put(`/api/vocab/lessons/${this.lessonId}/progress`, {
completed: true, completed: true,
score: score, score: score,
@@ -610,16 +617,24 @@ export default {
await this.navigateToNextLesson(); await this.navigateToNextLesson();
} catch (e) { } catch (e) {
console.error('Fehler beim Aktualisieren des Fortschritts:', e); console.error('Fehler beim Aktualisieren des Fortschritts:', e);
this.isCheckingLessonCompletion = false;
} }
} }
}, },
async navigateToNextLesson() { async navigateToNextLesson() {
// Verhindere mehrfache Navigation
if (this.isNavigatingToNext) return;
this.isNavigatingToNext = true;
try { try {
// Lade Kurs mit allen Lektionen // Lade Kurs mit allen Lektionen
const courseRes = await apiClient.get(`/api/vocab/courses/${this.courseId}`); const courseRes = await apiClient.get(`/api/vocab/courses/${this.courseId}`);
const course = courseRes.data; const course = courseRes.data;
if (!course.lessons || course.lessons.length === 0) return; if (!course.lessons || course.lessons.length === 0) {
this.isNavigatingToNext = false;
return;
}
// Finde aktuelle Lektion // Finde aktuelle Lektion
const currentLessonIndex = course.lessons.findIndex(l => l.id === parseInt(this.lessonId)); const currentLessonIndex = course.lessons.findIndex(l => l.id === parseInt(this.lessonId));
@@ -631,13 +646,21 @@ export default {
// Zeige Erfolgs-Meldung und leite weiter // Zeige Erfolgs-Meldung und leite weiter
if (confirm(this.$t('socialnetwork.vocab.courses.lessonCompleted') + '\n' + this.$t('socialnetwork.vocab.courses.goToNextLesson'))) { if (confirm(this.$t('socialnetwork.vocab.courses.lessonCompleted') + '\n' + this.$t('socialnetwork.vocab.courses.goToNextLesson'))) {
this.$router.push(`/socialnetwork/vocab/courses/${this.courseId}/lessons/${nextLesson.id}`); this.$router.push(`/socialnetwork/vocab/courses/${this.courseId}/lessons/${nextLesson.id}`);
} else {
// Benutzer hat abgebrochen - Flag zurücksetzen
this.isNavigatingToNext = false;
this.isCheckingLessonCompletion = false;
} }
} else { } else {
// Letzte Lektion - zeige Abschluss-Meldung // Letzte Lektion - zeige Abschluss-Meldung
alert(this.$t('socialnetwork.vocab.courses.allLessonsCompleted')); alert(this.$t('socialnetwork.vocab.courses.allLessonsCompleted'));
this.isNavigatingToNext = false;
this.isCheckingLessonCompletion = false;
} }
} catch (e) { } catch (e) {
console.error('Fehler beim Laden der nächsten Lektion:', e); console.error('Fehler beim Laden der nächsten Lektion:', e);
this.isNavigatingToNext = false;
this.isCheckingLessonCompletion = false;
} }
}, },
back() { back() {
@@ -779,9 +802,15 @@ export default {
// Im Typing-Modus: Automatisch zur nächsten Frage nach kurzer Pause (nur bei richtiger Antwort) // Im Typing-Modus: Automatisch zur nächsten Frage nach kurzer Pause (nur bei richtiger Antwort)
if (this.vocabTrainerMode === 'typing' && this.vocabTrainerLastCorrect) { if (this.vocabTrainerMode === 'typing' && this.vocabTrainerLastCorrect) {
setTimeout(() => { // Prüfe ob noch Fragen vorhanden sind
this.nextVocabQuestion(); if (this.vocabTrainerPool && this.vocabTrainerPool.length > 0) {
}, 500); setTimeout(() => {
// Prüfe erneut, ob noch Fragen vorhanden sind (könnte sich geändert haben)
if (this.vocabTrainerPool && this.vocabTrainerPool.length > 0 && this.vocabTrainerActive) {
this.nextVocabQuestion();
}
}, 500);
}
} }
// Im Typing-Modus bei falscher Antwort: Eingabefeld fokussieren für erneuten Versuch // Im Typing-Modus bei falscher Antwort: Eingabefeld fokussieren für erneuten Versuch