From 69ef1206770d2f3355de7b388da371c8b75115b3 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Mon, 19 Jan 2026 23:33:45 +0100 Subject: [PATCH] Enhance VocabService and VocabLessonView for review lesson functionality - Added logic in VocabService to retrieve vocabulary and lessons from previous lessons for review sessions, improving the learning experience. - Implemented methods to gather review lessons and vocabulary exercises, ensuring users have access to relevant content during review lessons. - Updated VocabLessonView to utilize review vocabulary exercises when in a review lesson, enhancing vocabulary extraction and user feedback. - Improved console logging for better insights into the vocabulary processing flow, aiding in debugging and user interaction. --- backend/services/vocabService.js | 79 ++++++++++++++++++- frontend/src/views/social/VocabLessonView.vue | 39 ++++++--- 2 files changed, 105 insertions(+), 13 deletions(-) diff --git a/backend/services/vocabService.js b/backend/services/vocabService.js index 2ca650e..e1e62d7 100644 --- a/backend/services/vocabService.js +++ b/backend/services/vocabService.js @@ -884,15 +884,92 @@ export default class VocabService { } const plainLesson = lesson.get({ plain: true }); + + // Bei Wiederholungslektionen: Lade Vokabeln aus vorherigen Lektionen + if (plainLesson.lessonType === 'review' || plainLesson.lessonType === 'vocab_review') { + plainLesson.reviewLessons = await this._getReviewLessons(plainLesson.courseId, plainLesson.lessonNumber); + plainLesson.reviewVocabExercises = await this._getReviewVocabExercises(plainLesson.courseId, plainLesson.lessonNumber); + } + console.log(`[getLesson] Lektion ${lessonId} geladen:`, { id: plainLesson.id, title: plainLesson.title, + lessonType: plainLesson.lessonType, exerciseCount: plainLesson.grammarExercises ? plainLesson.grammarExercises.length : 0, - exercises: plainLesson.grammarExercises + reviewLessonsCount: plainLesson.reviewLessons ? plainLesson.reviewLessons.length : 0, + reviewVocabExercisesCount: plainLesson.reviewVocabExercises ? plainLesson.reviewVocabExercises.length : 0 }); return plainLesson; } + /** + * Sammelt alle Lektionen, die in einer Wiederholungslektion wiederholt werden sollen + */ + async _getReviewLessons(courseId, currentLessonNumber) { + const lessons = await VocabCourseLesson.findAll({ + where: { + courseId: courseId, + lessonNumber: { + [Op.lt]: currentLessonNumber // Nur Lektionen mit kleinerer Nummer + }, + lessonType: { + [Op.notIn]: ['review', 'vocab_review'] // Keine anderen Wiederholungslektionen + } + }, + order: [['lessonNumber', 'ASC']], + attributes: ['id', 'lessonNumber', 'title'] + }); + return lessons.map(l => l.get({ plain: true })); + } + + /** + * Sammelt alle Grammatik-Übungen aus vorherigen Lektionen für Wiederholungslektionen + */ + async _getReviewVocabExercises(courseId, currentLessonNumber) { + const previousLessons = await VocabCourseLesson.findAll({ + where: { + courseId: courseId, + lessonNumber: { + [Op.lt]: currentLessonNumber + }, + lessonType: { + [Op.notIn]: ['review', 'vocab_review'] + } + }, + attributes: ['id'] + }); + + if (previousLessons.length === 0) { + return []; + } + + const lessonIds = previousLessons.map(l => l.id); + const exercises = await VocabGrammarExercise.findAll({ + where: { + lessonId: { + [Op.in]: lessonIds + } + }, + include: [ + { + model: VocabGrammarExerciseType, + as: 'exerciseType' + }, + { + model: VocabCourseLesson, + as: 'lesson', + attributes: ['id', 'lessonNumber', 'title'] + } + ], + order: [ + [{ model: VocabCourseLesson, as: 'lesson' }, 'lessonNumber', 'ASC'], + ['exerciseNumber', 'ASC'] + ] + }); + + return exercises.map(e => e.get({ plain: true })); + } + async addLessonToCourse(hashedUserId, courseId, { chapterId, lessonNumber, title, description, weekNumber, dayNumber, lessonType, audioUrl, culturalNotes, targetMinutes, targetScorePercent, requiresReview }) { const user = await this._getUserByHashedId(hashedUserId); const course = await VocabCourse.findByPk(courseId); diff --git a/frontend/src/views/social/VocabLessonView.vue b/frontend/src/views/social/VocabLessonView.vue index a2cf2f9..8ef6250 100644 --- a/frontend/src/views/social/VocabLessonView.vue +++ b/frontend/src/views/social/VocabLessonView.vue @@ -390,14 +390,33 @@ export default { importantVocab() { // Extrahiere wichtige Begriffe aus den Übungen try { + // Bei Wiederholungslektionen: Verwende Vokabeln aus vorherigen Lektionen + if (this.lesson && (this.lesson.lessonType === 'review' || this.lesson.lessonType === 'vocab_review')) { + if (this.lesson.reviewVocabExercises && Array.isArray(this.lesson.reviewVocabExercises)) { + console.log('[importantVocab] Wiederholungslektion - verwende reviewVocabExercises:', this.lesson.reviewVocabExercises.length); + return this._extractVocabFromExercises(this.lesson.reviewVocabExercises); + } else { + console.log('[importantVocab] Wiederholungslektion aber keine reviewVocabExercises vorhanden'); + return []; + } + } + + // Normale Lektion: Verwende Übungen aus der aktuellen Lektion if (!this.lesson || !this.lesson.grammarExercises || !Array.isArray(this.lesson.grammarExercises)) { console.log('[importantVocab] Keine Übungen vorhanden'); return []; } - const vocabMap = new Map(); - - this.lesson.grammarExercises.forEach((exercise, idx) => { + return this._extractVocabFromExercises(this.lesson.grammarExercises); + } catch (e) { + console.error('Fehler in importantVocab computed property:', e); + return []; + } + }, + _extractVocabFromExercises(exercises) { + const vocabMap = new Map(); + + exercises.forEach((exercise, idx) => { try { console.log(`[importantVocab] Verarbeite Übung ${idx + 1}:`, exercise.title); // Extrahiere aus questionData @@ -469,15 +488,11 @@ export default { } catch (e) { console.warn('Fehler beim Extrahieren von Vokabeln aus Übung:', e, exercise); } - }); - - const result = Array.from(vocabMap.values()); - console.log(`[importantVocab] Ergebnis:`, result); - return result; - } catch (e) { - console.error('Fehler in importantVocab computed property:', e); - return []; - } + }); + + const result = Array.from(vocabMap.values()); + console.log(`[_extractVocabFromExercises] Ergebnis:`, result.length, 'Vokabeln'); + return result; } }, watch: {