diff --git a/backend/controllers/navigationController.js b/backend/controllers/navigationController.js index 3a4d2d4..afe0a47 100644 --- a/backend/controllers/navigationController.js +++ b/backend/controllers/navigationController.js @@ -56,7 +56,7 @@ const menuStructure = { vocabtrainer: { visible: ["all"], path: "/socialnetwork/vocab", - children: {} + showVocabLanguages: 1 // Flag für dynamische Sprachen-Liste }, sprachkurse: { visible: ["all"], @@ -386,22 +386,9 @@ class NavigationController { const rights = userRights.map(ur => ur.rightType?.title).filter(Boolean); const filteredMenu = await this.filterMenu(menuStructure, rights, age, user.id); - // Dynamisches Submenü: Treffpunkt → Sprachen lernen → Vokabeltrainer → (Neue Sprache + abonnierte/angelegte) - // Wichtig: "Neue Sprache" soll IMMER sichtbar sein – auch wenn die DB-Abfrage (noch) fehlschlägt. - if (filteredMenu?.socialnetwork?.children?.sprachenlernen?.children?.vocabtrainer) { - const children = { - newLanguage: { path: '/socialnetwork/vocab/new' }, - }; - try { - const langs = await this.vocabService.listLanguagesForMenu(user.id); - for (const l of langs) { - children[`lang_${l.id}`] = { path: `/socialnetwork/vocab/${l.id}`, label: l.name }; - } - } catch (e) { - console.warn('[menu] Konnte Vokabeltrainer-Sprachen nicht laden:', e?.message || e); - } - filteredMenu.socialnetwork.children.sprachenlernen.children.vocabtrainer.children = children; - } + // Vokabeltrainer: Sprachen werden im Frontend dynamisch geladen (wie Forum) + // Keine children mehr, da das Menü nur 2 Ebenen unterstützt + // Das Frontend lädt die Sprachen separat und zeigt sie als submenu2 an res.status(200).json(filteredMenu); } catch (error) { diff --git a/backend/scripts/create-bisaya-course-content.js b/backend/scripts/create-bisaya-course-content.js index 2f5646b..35d3d13 100644 --- a/backend/scripts/create-bisaya-course-content.js +++ b/backend/scripts/create-bisaya-course-content.js @@ -65,6 +65,132 @@ const BISAYA_EXERCISES = { } ], + // Lektion 3: Familienwörter + 'Familienwörter': [ + { + exerciseTypeId: 2, // multiple_choice + title: 'Wie sagt man "Mutter" auf Bisaya?', + instruction: 'Wähle die richtige Übersetzung.', + questionData: { + type: 'multiple_choice', + question: 'Wie sagt man "Mutter" auf Bisaya?', + options: ['Nanay', 'Tatay', 'Kuya', 'Ate'] + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: '"Nanay" bedeutet "Mutter" auf Bisaya. "Mama" wird auch verwendet.' + }, + { + exerciseTypeId: 2, // multiple_choice + title: 'Wie sagt man "Vater" auf Bisaya?', + instruction: 'Wähle die richtige Übersetzung.', + questionData: { + type: 'multiple_choice', + question: 'Wie sagt man "Vater" auf Bisaya?', + options: ['Tatay', 'Nanay', 'Kuya', 'Ate'] + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: '"Tatay" bedeutet "Vater" auf Bisaya. "Papa" wird auch verwendet.' + }, + { + exerciseTypeId: 2, // multiple_choice + title: 'Wie sagt man "älterer Bruder" auf Bisaya?', + instruction: 'Wähle die richtige Übersetzung.', + questionData: { + type: 'multiple_choice', + question: 'Wie sagt man "älterer Bruder" auf Bisaya?', + options: ['Kuya', 'Ate', 'Nanay', 'Tatay'] + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: '"Kuya" bedeutet "älterer Bruder" auf Bisaya. Wird auch für respektvolle Anrede von älteren Männern verwendet.' + }, + { + exerciseTypeId: 2, // multiple_choice + title: 'Wie sagt man "ältere Schwester" auf Bisaya?', + instruction: 'Wähle die richtige Übersetzung.', + questionData: { + type: 'multiple_choice', + question: 'Wie sagt man "ältere Schwester" auf Bisaya?', + options: ['Ate', 'Kuya', 'Nanay', 'Tatay'] + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: '"Ate" bedeutet "ältere Schwester" auf Bisaya. Wird auch für respektvolle Anrede von älteren Frauen verwendet.' + }, + { + exerciseTypeId: 2, // multiple_choice + title: 'Wie sagt man "Großmutter" auf Bisaya?', + instruction: 'Wähle die richtige Übersetzung.', + questionData: { + type: 'multiple_choice', + question: 'Wie sagt man "Großmutter" auf Bisaya?', + options: ['Lola', 'Lolo', 'Nanay', 'Tatay'] + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: '"Lola" bedeutet "Großmutter" auf Bisaya.' + }, + { + exerciseTypeId: 2, // multiple_choice + title: 'Wie sagt man "Großvater" auf Bisaya?', + instruction: 'Wähle die richtige Übersetzung.', + questionData: { + type: 'multiple_choice', + question: 'Wie sagt man "Großvater" auf Bisaya?', + options: ['Lolo', 'Lola', 'Nanay', 'Tatay'] + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: '"Lolo" bedeutet "Großvater" auf Bisaya.' + }, + { + exerciseTypeId: 1, // gap_fill + title: 'Familienwörter vervollständigen', + instruction: 'Fülle die Lücken mit den richtigen Bisaya-Familienwörtern.', + questionData: { + type: 'gap_fill', + text: '{gap} (Mutter) | {gap} (Vater) | {gap} (älterer Bruder) | {gap} (ältere Schwester) | {gap} (Großmutter) | {gap} (Großvater)', + gaps: 6 + }, + answerData: { + type: 'gap_fill', + answers: ['Nanay', 'Tatay', 'Kuya', 'Ate', 'Lola', 'Lolo'] + }, + explanation: 'Nanay = Mutter, Tatay = Vater, Kuya = älterer Bruder, Ate = ältere Schwester, Lola = Großmutter, Lolo = Großvater.' + }, + { + exerciseTypeId: 4, // transformation + title: 'Familienwörter übersetzen', + instruction: 'Übersetze das Familienwort ins Bisaya.', + questionData: { + type: 'transformation', + text: 'Mutter', + sourceLanguage: 'Deutsch', + targetLanguage: 'Bisaya' + }, + answerData: { + type: 'transformation', + correct: 'Nanay', + alternatives: ['Mama', 'Nanay', 'Inahan'] + }, + explanation: '"Nanay" oder "Mama" bedeutet "Mutter" auf Bisaya.' + } + ], + // Lektion 15: Zeitformen - Grundlagen 'Zeitformen - Grundlagen': [ { @@ -459,24 +585,8 @@ function getExercisesForLesson(lessonTitle) { } } - // Standard-Übungen für unbekannte Lektionen - return [ - { - exerciseTypeId: 2, // multiple_choice - title: `${lessonTitle} - Übung 1`, - instruction: 'Wähle die richtige Antwort aus.', - questionData: { - type: 'multiple_choice', - question: 'Was ist die richtige Übersetzung?', - options: ['Option A', 'Option B', 'Option C', 'Option D'] - }, - answerData: { - type: 'multiple_choice', - correctAnswer: 0 - }, - explanation: 'Dies ist eine Beispiel-Übung. Bitte füge sprachspezifische Inhalte hinzu.' - } - ]; + // Keine Übungen für unbekannte Lektionen (statt Dummy-Übungen) + return []; } async function createBisayaCourseContent() { diff --git a/backend/scripts/update-family-words-exercises.js b/backend/scripts/update-family-words-exercises.js new file mode 100755 index 0000000..a3103cb --- /dev/null +++ b/backend/scripts/update-family-words-exercises.js @@ -0,0 +1,258 @@ +#!/usr/bin/env node +/** + * Script zum Aktualisieren der "Familienwörter"-Übungen in Bisaya-Kursen + * + * Verwendung: + * node backend/scripts/update-family-words-exercises.js + * + * Ersetzt bestehende Dummy-Übungen durch spezifische Familienwörter-Übungen. + */ + +import { sequelize } from '../utils/sequelize.js'; +import VocabCourseLesson from '../models/community/vocab_course_lesson.js'; +import VocabGrammarExercise from '../models/community/vocab_grammar_exercise.js'; +import User from '../models/community/user.js'; + +// Spezifische Übungen für Familienwörter +const FAMILY_WORDS_EXERCISES = [ + { + exerciseTypeId: 2, // multiple_choice + title: 'Wie sagt man "Mutter" auf Bisaya?', + instruction: 'Wähle die richtige Übersetzung.', + questionData: { + type: 'multiple_choice', + question: 'Wie sagt man "Mutter" auf Bisaya?', + options: ['Nanay', 'Tatay', 'Kuya', 'Ate'] + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: '"Nanay" bedeutet "Mutter" auf Bisaya. "Mama" wird auch verwendet.' + }, + { + exerciseTypeId: 2, // multiple_choice + title: 'Wie sagt man "Vater" auf Bisaya?', + instruction: 'Wähle die richtige Übersetzung.', + questionData: { + type: 'multiple_choice', + question: 'Wie sagt man "Vater" auf Bisaya?', + options: ['Tatay', 'Nanay', 'Kuya', 'Ate'] + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: '"Tatay" bedeutet "Vater" auf Bisaya. "Papa" wird auch verwendet.' + }, + { + exerciseTypeId: 2, // multiple_choice + title: 'Wie sagt man "älterer Bruder" auf Bisaya?', + instruction: 'Wähle die richtige Übersetzung.', + questionData: { + type: 'multiple_choice', + question: 'Wie sagt man "älterer Bruder" auf Bisaya?', + options: ['Kuya', 'Ate', 'Nanay', 'Tatay'] + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: '"Kuya" bedeutet "älterer Bruder" auf Bisaya. Wird auch für respektvolle Anrede von älteren Männern verwendet.' + }, + { + exerciseTypeId: 2, // multiple_choice + title: 'Wie sagt man "ältere Schwester" auf Bisaya?', + instruction: 'Wähle die richtige Übersetzung.', + questionData: { + type: 'multiple_choice', + question: 'Wie sagt man "ältere Schwester" auf Bisaya?', + options: ['Ate', 'Kuya', 'Nanay', 'Tatay'] + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: '"Ate" bedeutet "ältere Schwester" auf Bisaya. Wird auch für respektvolle Anrede von älteren Frauen verwendet.' + }, + { + exerciseTypeId: 2, // multiple_choice + title: 'Wie sagt man "Großmutter" auf Bisaya?', + instruction: 'Wähle die richtige Übersetzung.', + questionData: { + type: 'multiple_choice', + question: 'Wie sagt man "Großmutter" auf Bisaya?', + options: ['Lola', 'Lolo', 'Nanay', 'Tatay'] + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: '"Lola" bedeutet "Großmutter" auf Bisaya.' + }, + { + exerciseTypeId: 2, // multiple_choice + title: 'Wie sagt man "Großvater" auf Bisaya?', + instruction: 'Wähle die richtige Übersetzung.', + questionData: { + type: 'multiple_choice', + question: 'Wie sagt man "Großvater" auf Bisaya?', + options: ['Lolo', 'Lola', 'Nanay', 'Tatay'] + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: '"Lolo" bedeutet "Großvater" auf Bisaya.' + }, + { + exerciseTypeId: 1, // gap_fill + title: 'Familienwörter vervollständigen', + instruction: 'Fülle die Lücken mit den richtigen Bisaya-Familienwörtern.', + questionData: { + type: 'gap_fill', + text: '{gap} (Mutter) | {gap} (Vater) | {gap} (älterer Bruder) | {gap} (ältere Schwester) | {gap} (Großmutter) | {gap} (Großvater)', + gaps: 6 + }, + answerData: { + type: 'gap_fill', + answers: ['Nanay', 'Tatay', 'Kuya', 'Ate', 'Lola', 'Lolo'] + }, + explanation: 'Nanay = Mutter, Tatay = Vater, Kuya = älterer Bruder, Ate = ältere Schwester, Lola = Großmutter, Lolo = Großvater.' + }, + { + exerciseTypeId: 4, // transformation + title: 'Familienwörter übersetzen', + instruction: 'Übersetze das Familienwort ins Bisaya.', + questionData: { + type: 'transformation', + text: 'Mutter', + sourceLanguage: 'Deutsch', + targetLanguage: 'Bisaya' + }, + answerData: { + type: 'transformation', + correct: 'Nanay', + alternatives: ['Mama', 'Nanay', 'Inahan'] + }, + explanation: '"Nanay" oder "Mama" bedeutet "Mutter" auf Bisaya.' + } +]; + +async function findOrCreateSystemUser() { + let systemUser = await User.findOne({ + where: { + username: 'system' + } + }); + + if (!systemUser) { + systemUser = await User.findOne({ + where: { + username: 'admin' + } + }); + } + + if (!systemUser) { + console.error('❌ System-Benutzer nicht gefunden.'); + throw new Error('System user not found'); + } + + return systemUser; +} + +async function updateFamilyWordsExercises() { + await sequelize.authenticate(); + console.log('Datenbankverbindung erfolgreich hergestellt.\n'); + + const systemUser = await findOrCreateSystemUser(); + console.log(`Verwende System-Benutzer: ${systemUser.username} (ID: ${systemUser.id})\n`); + + // Finde alle Bisaya-Kurse + const [bisayaLanguage] = await sequelize.query( + `SELECT id FROM community.vocab_language WHERE name = 'Bisaya' LIMIT 1`, + { + type: sequelize.QueryTypes.SELECT + } + ); + + if (!bisayaLanguage) { + console.error('❌ Bisaya-Sprache nicht gefunden.'); + return; + } + + const courses = await sequelize.query( + `SELECT id, title, owner_user_id FROM community.vocab_course WHERE language_id = :languageId`, + { + replacements: { languageId: bisayaLanguage.id }, + type: sequelize.QueryTypes.SELECT + } + ); + + console.log(`Gefunden: ${courses.length} Bisaya-Kurse\n`); + + let totalExercisesUpdated = 0; + let totalLessonsUpdated = 0; + + for (const course of courses) { + console.log(`📚 Kurs: ${course.title} (ID: ${course.id})`); + + // Finde "Familienwörter"-Lektionen + const lessons = await VocabCourseLesson.findAll({ + where: { + courseId: course.id, + title: 'Familienwörter' + }, + order: [['lessonNumber', 'ASC']] + }); + + console.log(` ${lessons.length} "Familienwörter"-Lektionen gefunden\n`); + + for (const lesson of lessons) { + // Lösche bestehende Übungen (inkl. Dummy-Übungen) + const deletedCount = await VocabGrammarExercise.destroy({ + where: { lessonId: lesson.id } + }); + + console.log(` 🗑️ Lektion ${lesson.lessonNumber}: "${lesson.title}" - ${deletedCount} alte Übung(en) gelöscht`); + + // Erstelle neue Übungen + let exerciseNumber = 1; + for (const exerciseData of FAMILY_WORDS_EXERCISES) { + await VocabGrammarExercise.create({ + lessonId: lesson.id, + exerciseTypeId: exerciseData.exerciseTypeId, + exerciseNumber: exerciseNumber++, + title: exerciseData.title, + instruction: exerciseData.instruction, + questionData: JSON.stringify(exerciseData.questionData), + answerData: JSON.stringify(exerciseData.answerData), + explanation: exerciseData.explanation, + createdByUserId: course.owner_user_id || systemUser.id + }); + totalExercisesUpdated++; + } + + console.log(` ✅ Lektion ${lesson.lessonNumber}: "${lesson.title}" - ${FAMILY_WORDS_EXERCISES.length} neue Übung(en) erstellt`); + totalLessonsUpdated++; + } + + console.log(''); + } + + console.log(`\n🎉 Zusammenfassung:`); + console.log(` ${totalLessonsUpdated} Lektionen aktualisiert`); + console.log(` ${totalExercisesUpdated} neue Grammatik-Übungen erstellt`); +} + +updateFamilyWordsExercises() + .then(() => { + sequelize.close(); + process.exit(0); + }) + .catch((error) => { + console.error('❌ Fehler:', error); + sequelize.close(); + process.exit(1); + }); diff --git a/frontend/src/components/AppNavigation.vue b/frontend/src/components/AppNavigation.vue index 72ecd0d..dbe32b3 100644 --- a/frontend/src/components/AppNavigation.vue +++ b/frontend/src/components/AppNavigation.vue @@ -29,7 +29,7 @@ >  {{ subitem?.label || $t(`navigation.m-${key}.${subkey}`) }} @@ -47,7 +47,26 @@ - + + + +