diff --git a/frontend/src/i18n/locales/de/socialnetwork.json b/frontend/src/i18n/locales/de/socialnetwork.json index d5b0949..864ed52 100644 --- a/frontend/src/i18n/locales/de/socialnetwork.json +++ b/frontend/src/i18n/locales/de/socialnetwork.json @@ -360,21 +360,30 @@ "optional": "Optional", "invalidCode": "Ungültiger Code", "courseNotFound": "Kurs nicht gefunden", - "grammarExercises": "Grammatik-Übungen", - "noExercises": "Keine Übungen verfügbar", + "grammarExercises": "Grammatik-Prüfung", + "noExercises": "Keine Prüfung verfügbar", "enterAnswer": "Antwort eingeben", "checkAnswer": "Antwort prüfen", "correct": "Richtig!", "wrong": "Falsch", "explanation": "Erklärung", "learn": "Lernen", - "exercises": "Übungen", + "exercises": "Kapitel-Prüfung", "learnVocabulary": "Vokabeln lernen", + "lessonDescription": "Lektions-Beschreibung", "culturalNotes": "Kulturelle Notizen", + "grammarExplanations": "Grammatik-Erklärungen", "importantVocab": "Wichtige Begriffe", - "vocabInfoText": "Diese Begriffe werden in den Übungen verwendet. Lerne sie hier passiv, bevor du zu den interaktiven Übungen wechselst.", - "noVocabInfo": "Lies die Beschreibung oben und die Erklärungen in den Übungen, um die wichtigsten Begriffe zu lernen.", - "startExercises": "Zu den Übungen", + "vocabInfoText": "Diese Begriffe werden in der Prüfung verwendet. Lerne sie hier passiv, bevor du zur Kapitel-Prüfung wechselst.", + "noVocabInfo": "Lies die Beschreibung oben und die Erklärungen in der Prüfung, um die wichtigsten Begriffe zu lernen.", + "vocabTrainer": "Vokabeltrainer", + "vocabTrainerDescription": "Übe die wichtigsten Begriffe dieser Lektion interaktiv.", + "startVocabTrainer": "Vokabeltrainer starten", + "stopTrainer": "Trainer beenden", + "translateTo": "Übersetze ins Deutsche", + "translateFrom": "Übersetze ins Bisaya", + "next": "Weiter", + "startExercises": "Zur Kapitel-Prüfung", "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 72a2dcb..a388125 100644 --- a/frontend/src/i18n/locales/en/socialnetwork.json +++ b/frontend/src/i18n/locales/en/socialnetwork.json @@ -360,21 +360,30 @@ "optional": "Optional", "invalidCode": "Invalid code", "courseNotFound": "Course not found", - "grammarExercises": "Grammar Exercises", - "noExercises": "No exercises available", + "grammarExercises": "Chapter Test", + "noExercises": "No test available", "enterAnswer": "Enter answer", "checkAnswer": "Check Answer", "correct": "Correct!", "wrong": "Wrong", "explanation": "Explanation", "learn": "Learn", - "exercises": "Exercises", + "exercises": "Chapter Test", "learnVocabulary": "Learn Vocabulary", + "lessonDescription": "Lesson Description", "culturalNotes": "Cultural Notes", + "grammarExplanations": "Grammar Explanations", "importantVocab": "Important Vocabulary", - "vocabInfoText": "These terms are used in the exercises. Learn them here passively before switching to the interactive exercises.", - "noVocabInfo": "Read the description above and the explanations in the exercises to learn the most important terms.", - "startExercises": "Start Exercises", + "vocabInfoText": "These terms are used in the test. Learn them here passively before switching to the chapter test.", + "noVocabInfo": "Read the description above and the explanations in the test to learn the most important terms.", + "vocabTrainer": "Vocabulary Trainer", + "vocabTrainerDescription": "Practice the most important terms of this lesson interactively.", + "startVocabTrainer": "Start Vocabulary Trainer", + "stopTrainer": "Stop Trainer", + "translateTo": "Translate to English", + "translateFrom": "Translate to Target Language", + "next": "Next", + "startExercises": "Start Chapter Test", "correctAnswer": "Correct Answer", "alternatives": "Alternative Answers" } diff --git a/frontend/src/views/social/VocabLessonView.vue b/frontend/src/views/social/VocabLessonView.vue index 3af244e..6cb7e7b 100644 --- a/frontend/src/views/social/VocabLessonView.vue +++ b/frontend/src/views/social/VocabLessonView.vue @@ -32,14 +32,74 @@

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

+ +
+

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

+

{{ lesson.description }}

+
+

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

{{ lesson.culturalNotes }}

- -
+ +
+

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

+
+ {{ explanation.title }} +

{{ explanation.text }}

+
+
+ + +
+

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

+
+

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

+ +
+
+
+ {{ $t('socialnetwork.vocab.courses.correct') }}: {{ vocabTrainerCorrect }} + {{ $t('socialnetwork.vocab.courses.wrong') }}: {{ vocabTrainerWrong }} + +
+
+
+
{{ vocabTrainerDirection === 'L2R' ? $t('socialnetwork.vocab.courses.translateTo') : $t('socialnetwork.vocab.courses.translateFrom') }}
+
{{ currentVocabQuestion.prompt }}
+
+
+
{{ $t('socialnetwork.vocab.courses.correct') }}!
+
+ {{ $t('socialnetwork.vocab.courses.wrong') }}. {{ $t('socialnetwork.vocab.courses.correctAnswer') }}: {{ currentVocabQuestion.answer }} +
+
+
+ + +
+
+ +
+
+
+
+ + +

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

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

@@ -52,7 +112,7 @@
-
+

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

@@ -188,7 +248,17 @@ export default { lesson: null, exerciseAnswers: {}, exerciseResults: {}, - activeTab: 'learn' // Standardmäßig "Lernen"-Tab + activeTab: 'learn', // Standardmäßig "Lernen"-Tab + // Vokabeltrainer + vocabTrainerActive: false, + vocabTrainerPool: [], + vocabTrainerCorrect: 0, + vocabTrainerWrong: 0, + currentVocabQuestion: null, + vocabTrainerAnswer: '', + vocabTrainerAnswered: false, + vocabTrainerLastCorrect: false, + vocabTrainerDirection: 'L2R' // L2R: learning->reference, R2L: reference->learning }; }, computed: { @@ -196,6 +266,32 @@ export default { hasExercises() { return this.lesson && this.lesson.grammarExercises && this.lesson.grammarExercises.length > 0; }, + grammarExplanations() { + // Extrahiere Grammatik-Erklärungen aus den Übungen + try { + if (!this.lesson || !this.lesson.grammarExercises || !Array.isArray(this.lesson.grammarExercises)) { + return []; + } + + const explanations = []; + const seen = new Set(); + + this.lesson.grammarExercises.forEach(exercise => { + if (exercise.explanation && !seen.has(exercise.explanation)) { + seen.add(exercise.explanation); + explanations.push({ + title: exercise.title || '', + text: exercise.explanation + }); + } + }); + + return explanations; + } catch (e) { + console.error('Fehler beim Extrahieren der Grammatik-Erklärungen:', e); + return []; + } + }, importantVocab() { // Extrahiere wichtige Begriffe aus den Übungen try { @@ -408,6 +504,58 @@ export default { }, back() { this.$router.push(`/socialnetwork/vocab/courses/${this.courseId}`); + }, + // Vokabeltrainer-Methoden + startVocabTrainer() { + if (!this.importantVocab || this.importantVocab.length === 0) return; + this.vocabTrainerActive = true; + this.vocabTrainerPool = [...this.importantVocab]; + this.vocabTrainerCorrect = 0; + this.vocabTrainerWrong = 0; + this.nextVocabQuestion(); + this.$nextTick(() => { + this.$refs.vocabInput?.focus?.(); + }); + }, + stopVocabTrainer() { + this.vocabTrainerActive = false; + this.currentVocabQuestion = null; + this.vocabTrainerAnswer = ''; + this.vocabTrainerAnswered = false; + }, + nextVocabQuestion() { + if (!this.vocabTrainerPool || this.vocabTrainerPool.length === 0) { + this.currentVocabQuestion = null; + return; + } + const randomIndex = Math.floor(Math.random() * this.vocabTrainerPool.length); + const vocab = this.vocabTrainerPool[randomIndex]; + this.vocabTrainerDirection = Math.random() < 0.5 ? 'L2R' : 'R2L'; + this.currentVocabQuestion = { + vocab: vocab, + prompt: this.vocabTrainerDirection === 'L2R' ? vocab.learning : vocab.reference, + answer: this.vocabTrainerDirection === 'L2R' ? vocab.reference : vocab.learning + }; + this.vocabTrainerAnswer = ''; + this.vocabTrainerAnswered = false; + this.$nextTick(() => { + this.$refs.vocabInput?.focus?.(); + }); + }, + normalizeVocab(s) { + return String(s || '').trim().toLowerCase().replace(/\s+/g, ' '); + }, + checkVocabAnswer() { + if (!this.currentVocabQuestion || !this.vocabTrainerAnswer.trim()) return; + const userAnswer = this.normalizeVocab(this.vocabTrainerAnswer); + const correctAnswer = this.normalizeVocab(this.currentVocabQuestion.answer); + this.vocabTrainerLastCorrect = userAnswer === correctAnswer; + if (this.vocabTrainerLastCorrect) { + this.vocabTrainerCorrect++; + } else { + this.vocabTrainerWrong++; + } + this.vocabTrainerAnswered = true; } }, async mounted() { @@ -673,6 +821,201 @@ export default { .separator { color: #999; + margin: 0 10px; +} + +.lesson-description-box { + margin: 20px 0; + padding: 15px; + background: #fff; + border: 1px solid #ddd; + border-radius: 4px; +} + +.lesson-description-box h4 { + margin-top: 0; + color: #333; +} + +.grammar-explanations { + margin: 20px 0; + padding: 15px; + background: #fff3cd; + border-left: 4px solid #ffc107; + border-radius: 4px; +} + +.grammar-explanations h4 { + margin-top: 0; + color: #856404; +} + +.grammar-explanation-item { + margin: 15px 0; + padding: 10px; + background: white; + border-radius: 4px; +} + +.grammar-explanation-item strong { + display: block; + margin-bottom: 5px; + color: #856404; +} + +.vocab-trainer-section { + margin: 20px 0; + padding: 15px; + background: #fff; + border: 1px solid #ddd; + border-radius: 4px; +} + +.vocab-trainer-section h4 { + margin-top: 0; + color: #333; +} + +.vocab-trainer-start { + text-align: center; +} + +.btn-start-trainer { + padding: 10px 20px; + background: #4CAF50; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 1em; + margin-top: 10px; +} + +.btn-start-trainer:hover { + background: #45a049; +} + +.vocab-trainer-stats { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 15px; + padding: 10px; + background: #f5f5f5; + border-radius: 4px; +} + +.btn-stop-trainer { + padding: 5px 15px; + background: #dc3545; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 0.9em; +} + +.btn-stop-trainer:hover { + background: #c82333; +} + +.vocab-question { + margin-top: 15px; +} + +.vocab-prompt { + padding: 15px; + background: #f9f9f9; + border: 1px solid #ddd; + border-radius: 4px; + margin-bottom: 15px; +} + +.vocab-direction { + color: #666; + font-size: 0.9em; + margin-bottom: 5px; +} + +.vocab-word { + font-size: 1.5em; + font-weight: bold; + color: #333; +} + +.vocab-answer-area { + display: flex; + gap: 10px; + margin-bottom: 15px; +} + +.vocab-input { + flex: 1; + padding: 10px; + border: 1px solid #ddd; + border-radius: 4px; + font-size: 1em; +} + +.vocab-answer-area button { + padding: 10px 20px; + background: #4CAF50; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 1em; +} + +.vocab-answer-area button:hover:not(:disabled) { + background: #45a049; +} + +.vocab-answer-area button:disabled { + background: #ccc; + cursor: not-allowed; +} + +.vocab-feedback { + padding: 15px; + border-radius: 4px; + margin-bottom: 15px; +} + +.vocab-feedback.correct { + background: #d4edda; + color: #155724; + border: 1px solid #c3e6cb; +} + +.vocab-feedback.wrong { + background: #f8d7da; + color: #721c24; + border: 1px solid #f5c6cb; +} + +.vocab-next { + margin-top: 15px; +} + +.vocab-next button { + padding: 10px 20px; + background: #007bff; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 1em; +} + +.vocab-next button:hover { + background: #0056b3; +} + +.vocab-info-text { + color: #666; + font-size: 0.9em; + margin-bottom: 10px; } .no-vocab-info {