diff --git a/backend/services/vocabService.js b/backend/services/vocabService.js index 2fed776..422d478 100644 --- a/backend/services/vocabService.js +++ b/backend/services/vocabService.js @@ -1310,8 +1310,20 @@ export default class VocabService { await progress.save(); } + // Extrahiere richtige Antwort und Alternativen + const answerData = typeof exercise.answerData === 'string' + ? JSON.parse(exercise.answerData) + : exercise.answerData; + + const correctAnswer = Array.isArray(answerData.correct) + ? answerData.correct[0] + : answerData.correct; + const alternatives = answerData.alternatives || []; + return { correct: isCorrect, + correctAnswer: correctAnswer, + alternatives: alternatives, explanation: exercise.explanation, progress: progress.get({ plain: true }) }; diff --git a/frontend/src/i18n/locales/de/socialnetwork.json b/frontend/src/i18n/locales/de/socialnetwork.json index 012b9e4..0ac6476 100644 --- a/frontend/src/i18n/locales/de/socialnetwork.json +++ b/frontend/src/i18n/locales/de/socialnetwork.json @@ -366,7 +366,16 @@ "checkAnswer": "Antwort prüfen", "correct": "Richtig!", "wrong": "Falsch", - "explanation": "Erklärung" + "explanation": "Erklärung", + "learn": "Lernen", + "exercises": "Übungen", + "learnVocabulary": "Vokabeln lernen", + "culturalNotes": "Kulturelle Notizen", + "importantVocab": "Wichtige Begriffe", + "noVocabInfo": "Lies die Beschreibung oben und die Erklärungen in den Übungen, um die wichtigsten Begriffe zu lernen.", + "startExercises": "Zu den Übungen", + "correctAnswer": "Richtige Antwort", + "alternatives": "Alternative Antworten" } } } diff --git a/frontend/src/i18n/locales/en/socialnetwork.json b/frontend/src/i18n/locales/en/socialnetwork.json index 405d342..f4d221b 100644 --- a/frontend/src/i18n/locales/en/socialnetwork.json +++ b/frontend/src/i18n/locales/en/socialnetwork.json @@ -366,7 +366,16 @@ "checkAnswer": "Check Answer", "correct": "Correct!", "wrong": "Wrong", - "explanation": "Explanation" + "explanation": "Explanation", + "learn": "Learn", + "exercises": "Exercises", + "learnVocabulary": "Learn Vocabulary", + "culturalNotes": "Cultural Notes", + "importantVocab": "Important Vocabulary", + "noVocabInfo": "Read the description above and the explanations in the exercises to learn the most important terms.", + "startExercises": "Start Exercises", + "correctAnswer": "Correct Answer", + "alternatives": "Alternative Answers" } } } diff --git a/frontend/src/views/social/VocabLessonView.vue b/frontend/src/views/social/VocabLessonView.vue index 704fae1..bbef6ee 100644 --- a/frontend/src/views/social/VocabLessonView.vue +++ b/frontend/src/views/social/VocabLessonView.vue @@ -9,7 +9,62 @@

{{ lesson.description }}

-
+ +
+ + +
+ + +
+

{{ $t('socialnetwork.vocab.courses.learnVocabulary') }}

+ + +
+

{{ $t('socialnetwork.vocab.courses.culturalNotes') }}

+

{{ lesson.culturalNotes }}

+
+ + +
+

{{ $t('socialnetwork.vocab.courses.importantVocab') }}

+
+
+ {{ vocab.learning }} + + {{ vocab.reference }} +
+
+
+ + +
+

{{ $t('socialnetwork.vocab.courses.noVocabInfo') }}

+
+ + +
+ +
+
+ + +

{{ $t('socialnetwork.vocab.courses.grammarExercises') }}

{{ exercise.title }}

@@ -34,7 +89,13 @@
{{ exerciseResults[exercise.id].correct ? $t('socialnetwork.vocab.courses.correct') : $t('socialnetwork.vocab.courses.wrong') }} -

{{ exercise.explanation }}

+

+ {{ $t('socialnetwork.vocab.courses.correctAnswer') }}: {{ exerciseResults[exercise.id].correctAnswer }} +

+

+ {{ $t('socialnetwork.vocab.courses.alternatives') }}: {{ exerciseResults[exercise.id].alternatives.join(', ') }} +

+

{{ exerciseResults[exercise.id].explanation }}

@@ -55,7 +116,13 @@
{{ exerciseResults[exercise.id].correct ? $t('socialnetwork.vocab.courses.correct') : $t('socialnetwork.vocab.courses.wrong') }} -

{{ exercise.explanation }}

+

+ {{ $t('socialnetwork.vocab.courses.correctAnswer') }}: {{ exerciseResults[exercise.id].correctAnswer }} +

+

+ {{ $t('socialnetwork.vocab.courses.alternatives') }}: {{ exerciseResults[exercise.id].alternatives.join(', ') }} +

+

{{ exerciseResults[exercise.id].explanation }}

@@ -72,7 +139,13 @@
{{ exerciseResults[exercise.id].correct ? $t('socialnetwork.vocab.courses.correct') : $t('socialnetwork.vocab.courses.wrong') }} -

{{ exercise.explanation }}

+

+ {{ $t('socialnetwork.vocab.courses.correctAnswer') }}: {{ exerciseResults[exercise.id].correctAnswer }} +

+

+ {{ $t('socialnetwork.vocab.courses.alternatives') }}: {{ exerciseResults[exercise.id].alternatives.join(', ') }} +

+

{{ exerciseResults[exercise.id].explanation }}

@@ -112,9 +185,54 @@ export default { loading: false, lesson: null, exerciseAnswers: {}, - exerciseResults: {} + exerciseResults: {}, + activeTab: 'learn' // Standardmäßig "Lernen"-Tab }; }, + computed: { + ...mapGetters(['user']), + hasExercises() { + return this.lesson && this.lesson.grammarExercises && this.lesson.grammarExercises.length > 0; + }, + importantVocab() { + // Extrahiere wichtige Begriffe aus den Übungen + if (!this.lesson || !this.lesson.grammarExercises) return []; + + const vocabMap = new Map(); + + this.lesson.grammarExercises.forEach(exercise => { + // Extrahiere aus questionData + const qData = this.getQuestionData(exercise); + const aData = this.getAnswerData(exercise); + + if (qData && aData) { + // Für Multiple Choice: Extrahiere Optionen und richtige Antwort + if (this.getExerciseType(exercise) === 'multiple_choice') { + const correct = Array.isArray(aData.correct) ? aData.correct[0] : aData.correct; + const question = qData.text || ''; + + // Versuche die Frage zu analysieren (z.B. "Wie sagt man X auf Bisaya?") + const match = question.match(/['"]([^'"]+)['"]/); + if (match) { + const germanWord = match[1]; + vocabMap.set(correct, { learning: correct, reference: germanWord }); + } else if (correct) { + // Fallback: Verwende die richtige Antwort als Lernwort + vocabMap.set(correct, { learning: correct, reference: correct }); + } + } + + // Für Gap Fill: Extrahiere richtige Antworten + if (this.getExerciseType(exercise) === 'gap_fill' && aData.correct) { + const correct = Array.isArray(aData.correct) ? aData.correct[0] : aData.correct; + vocabMap.set(correct, { learning: correct, reference: correct }); + } + } + }); + + return Array.from(vocabMap.values()); + } + }, computed: { ...mapGetters(['user']) }, @@ -441,4 +559,127 @@ export default { font-size: 0.85em; overflow-x: auto; } + +/* Tabs */ +.lesson-tabs { + display: flex; + gap: 10px; + margin: 20px 0; + border-bottom: 2px solid #ddd; +} + +.tab-button { + padding: 10px 20px; + border: none; + background: transparent; + cursor: pointer; + font-size: 1em; + color: #666; + border-bottom: 2px solid transparent; + margin-bottom: -2px; + transition: all 0.2s; +} + +.tab-button:hover:not(:disabled) { + color: #333; + background: #f5f5f5; +} + +.tab-button.active { + color: #007bff; + border-bottom-color: #007bff; + font-weight: bold; +} + +.tab-button:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +/* Lernen-Sektion */ +.learn-section { + margin-top: 20px; + padding: 20px; + background: #f9f9f9; + border-radius: 8px; +} + +.learn-section h3 { + margin-top: 0; + color: #333; +} + +.cultural-notes { + margin: 20px 0; + padding: 15px; + background: #e7f3ff; + border-left: 4px solid #007bff; + border-radius: 4px; +} + +.cultural-notes h4 { + margin-top: 0; + color: #007bff; +} + +.vocab-list { + margin: 20px 0; +} + +.vocab-list h4 { + margin-bottom: 15px; + color: #333; +} + +.vocab-items { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); + gap: 10px; +} + +.vocab-item { + padding: 10px; + background: white; + border: 1px solid #ddd; + border-radius: 4px; + display: flex; + align-items: center; + gap: 10px; +} + +.vocab-item strong { + color: #007bff; +} + +.separator { + color: #999; +} + +.no-vocab-info { + padding: 15px; + background: #fff3cd; + border-left: 4px solid #ffc107; + border-radius: 4px; + color: #856404; +} + +.continue-to-exercises { + margin-top: 30px; + text-align: center; +} + +.btn-continue { + padding: 12px 24px; + background: #007bff; + color: white; + border: none; + border-radius: 4px; + font-size: 1.1em; + cursor: pointer; + transition: background 0.2s; +} + +.btn-continue:hover { + background: #0056b3; +}