From 83597d9e02c8323b24d3ede590eb1154170cd829 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Tue, 30 Dec 2025 18:34:32 +0100 Subject: [PATCH] Add Vocab Trainer feature with routing, database schema, and translations - Introduced Vocab Trainer functionality, including new routes for managing languages and chapters. - Implemented database schema for vocab-related tables to ensure data integrity. - Updated navigation and UI components to include Vocab Trainer in the social network menu. - Added translations for Vocab Trainer in both German and English locales, enhancing user accessibility. --- backend/app.js | 2 + backend/controllers/navigationController.js | 25 + backend/controllers/vocabController.js | 45 ++ ...0251230000000-add-vocab-trainer-tables.cjs | 61 +++ ...0001000-add-vocab-chapters-and-lexemes.cjs | 106 ++++ backend/routers/vocabRouter.js | 26 + backend/services/vocabService.js | 485 +++++++++++++++++ backend/utils/syncDatabase.js | 117 ++++ frontend/public/sounds/fail.mp3 | Bin 0 -> 56064 bytes frontend/public/sounds/success.mp3 | Bin 0 -> 50880 bytes frontend/src/components/AppNavigation.vue | 4 +- .../socialnetwork/VocabPracticeDialog.vue | 504 ++++++++++++++++++ frontend/src/i18n/locales/de/general.json | 5 +- frontend/src/i18n/locales/de/navigation.json | 4 + .../src/i18n/locales/de/socialnetwork.json | 61 +++ frontend/src/i18n/locales/en/general.json | 6 + frontend/src/i18n/locales/en/navigation.json | 4 + .../src/i18n/locales/en/socialnetwork.json | 61 +++ frontend/src/router/socialRoutes.js | 35 ++ .../src/views/social/VocabChapterView.vue | 153 ++++++ .../src/views/social/VocabLanguageView.vue | 149 ++++++ .../src/views/social/VocabNewLanguageView.vue | 106 ++++ .../src/views/social/VocabSubscribeView.vue | 93 ++++ .../src/views/social/VocabTrainerView.vue | 86 +++ 24 files changed, 2135 insertions(+), 3 deletions(-) create mode 100644 backend/controllers/vocabController.js create mode 100644 backend/migrations/20251230000000-add-vocab-trainer-tables.cjs create mode 100644 backend/migrations/20251230001000-add-vocab-chapters-and-lexemes.cjs create mode 100644 backend/routers/vocabRouter.js create mode 100644 backend/services/vocabService.js create mode 100644 frontend/public/sounds/fail.mp3 create mode 100644 frontend/public/sounds/success.mp3 create mode 100644 frontend/src/dialogues/socialnetwork/VocabPracticeDialog.vue create mode 100644 frontend/src/views/social/VocabChapterView.vue create mode 100644 frontend/src/views/social/VocabLanguageView.vue create mode 100644 frontend/src/views/social/VocabNewLanguageView.vue create mode 100644 frontend/src/views/social/VocabSubscribeView.vue create mode 100644 frontend/src/views/social/VocabTrainerView.vue diff --git a/backend/app.js b/backend/app.js index f21832f..a02d63c 100644 --- a/backend/app.js +++ b/backend/app.js @@ -18,6 +18,7 @@ import taxiRouter from './routers/taxiRouter.js'; import taxiMapRouter from './routers/taxiMapRouter.js'; import taxiHighscoreRouter from './routers/taxiHighscoreRouter.js'; import termineRouter from './routers/termineRouter.js'; +import vocabRouter from './routers/vocabRouter.js'; import cors from 'cors'; import './jobs/sessionCleanup.js'; @@ -69,6 +70,7 @@ app.use('/api/taxi/highscores', taxiHighscoreRouter); app.use('/images', express.static(path.join(__dirname, '../frontend/public/images'))); app.use('/api/contact', contactRouter); app.use('/api/socialnetwork', socialnetworkRouter); +app.use('/api/vocab', vocabRouter); app.use('/api/forum', forumRouter); app.use('/api/falukant', falukantRouter); app.use('/api/friendships', friendshipRouter); diff --git a/backend/controllers/navigationController.js b/backend/controllers/navigationController.js index 8f566e6..ad5fc4b 100644 --- a/backend/controllers/navigationController.js +++ b/backend/controllers/navigationController.js @@ -4,6 +4,7 @@ import UserRight from '../models/community/user_right.js'; import UserRightType from '../models/type/user_right.js'; import UserParamType from '../models/type/user_param.js'; import FalukantUser from '../models/falukant/data/user.js'; +import VocabService from '../services/vocabService.js'; const menuStructure = { home: { @@ -49,6 +50,11 @@ const menuStructure = { visible: ["all"], path: "/socialnetwork/gallery" }, + vocabtrainer: { + visible: ["all"], + path: "/socialnetwork/vocab", + children: {} + }, blockedUsers: { visible: ["all"], path: "/socialnetwork/blocked" @@ -296,6 +302,7 @@ const menuStructure = { class NavigationController { constructor() { this.menu = this.menu.bind(this); + this.vocabService = new VocabService(); } calculateAge(birthDate) { @@ -365,6 +372,24 @@ class NavigationController { const age = this.calculateAge(birthDate); const rights = userRights.map(ur => ur.rightType?.title).filter(Boolean); const filteredMenu = await this.filterMenu(menuStructure, rights, age, user.id); + + // Dynamisches Submenü: Treffpunkt → Vokabeltrainer → (Neue Sprache + abonnierte/angelegte) + // Wichtig: "Neue Sprache" soll IMMER sichtbar sein – auch wenn die DB-Abfrage (noch) fehlschlägt. + if (filteredMenu?.socialnetwork?.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.vocabtrainer.children = children; + } + res.status(200).json(filteredMenu); } catch (error) { console.error('Error fetching menu:', error); diff --git a/backend/controllers/vocabController.js b/backend/controllers/vocabController.js new file mode 100644 index 0000000..71f9abd --- /dev/null +++ b/backend/controllers/vocabController.js @@ -0,0 +1,45 @@ +import VocabService from '../services/vocabService.js'; + +function extractHashedUserId(req) { + return req.headers?.userid; +} + +class VocabController { + constructor() { + this.service = new VocabService(); + + this.listLanguages = this._wrapWithUser((userId) => this.service.listLanguages(userId)); + this.createLanguage = this._wrapWithUser((userId, req) => this.service.createLanguage(userId, req.body), { successStatus: 201 }); + this.subscribe = this._wrapWithUser((userId, req) => this.service.subscribeByShareCode(userId, req.body), { successStatus: 201 }); + this.getLanguage = this._wrapWithUser((userId, req) => this.service.getLanguage(userId, req.params.languageId)); + + this.listChapters = this._wrapWithUser((userId, req) => this.service.listChapters(userId, req.params.languageId)); + this.createChapter = this._wrapWithUser((userId, req) => this.service.createChapter(userId, req.params.languageId, req.body), { successStatus: 201 }); + this.listLanguageVocabs = this._wrapWithUser((userId, req) => this.service.listLanguageVocabs(userId, req.params.languageId)); + + this.getChapter = this._wrapWithUser((userId, req) => this.service.getChapter(userId, req.params.chapterId)); + this.listChapterVocabs = this._wrapWithUser((userId, req) => this.service.listChapterVocabs(userId, req.params.chapterId)); + this.addVocabToChapter = this._wrapWithUser((userId, req) => this.service.addVocabToChapter(userId, req.params.chapterId, req.body), { successStatus: 201 }); + } + + _wrapWithUser(fn, { successStatus = 200 } = {}) { + return async (req, res) => { + try { + const hashedUserId = extractHashedUserId(req); + if (!hashedUserId) { + return res.status(400).json({ error: 'Missing user identifier' }); + } + const result = await fn(hashedUserId, req, res); + res.status(successStatus).json(result); + } catch (error) { + console.error('Controller error:', error); + const status = error.status && typeof error.status === 'number' ? error.status : 500; + res.status(status).json({ error: error.message || 'Internal error' }); + } + }; + } +} + +export default VocabController; + + diff --git a/backend/migrations/20251230000000-add-vocab-trainer-tables.cjs b/backend/migrations/20251230000000-add-vocab-trainer-tables.cjs new file mode 100644 index 0000000..122a82a --- /dev/null +++ b/backend/migrations/20251230000000-add-vocab-trainer-tables.cjs @@ -0,0 +1,61 @@ +/* eslint-disable */ +'use strict'; + +module.exports = { + async up(queryInterface) { + // Sprache / Set, das geteilt werden kann + await queryInterface.sequelize.query(` + CREATE TABLE IF NOT EXISTS community.vocab_language ( + id SERIAL PRIMARY KEY, + owner_user_id INTEGER NOT NULL, + name TEXT NOT NULL, + share_code TEXT NOT NULL, + created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT NOW(), + CONSTRAINT vocab_language_owner_fk + FOREIGN KEY (owner_user_id) + REFERENCES community."user"(id) + ON DELETE CASCADE, + CONSTRAINT vocab_language_share_code_uniq UNIQUE (share_code) + ); + `); + + // Abos (Freunde) + await queryInterface.sequelize.query(` + CREATE TABLE IF NOT EXISTS community.vocab_language_subscription ( + id SERIAL PRIMARY KEY, + user_id INTEGER NOT NULL, + language_id INTEGER NOT NULL, + created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT NOW(), + CONSTRAINT vocab_language_subscription_user_fk + FOREIGN KEY (user_id) + REFERENCES community."user"(id) + ON DELETE CASCADE, + CONSTRAINT vocab_language_subscription_language_fk + FOREIGN KEY (language_id) + REFERENCES community.vocab_language(id) + ON DELETE CASCADE, + CONSTRAINT vocab_language_subscription_uniq UNIQUE (user_id, language_id) + ); + `); + + await queryInterface.sequelize.query(` + CREATE INDEX IF NOT EXISTS vocab_language_owner_idx + ON community.vocab_language(owner_user_id); + `); + await queryInterface.sequelize.query(` + CREATE INDEX IF NOT EXISTS vocab_language_subscription_user_idx + ON community.vocab_language_subscription(user_id); + `); + await queryInterface.sequelize.query(` + CREATE INDEX IF NOT EXISTS vocab_language_subscription_language_idx + ON community.vocab_language_subscription(language_id); + `); + }, + + async down(queryInterface) { + await queryInterface.sequelize.query(`DROP TABLE IF EXISTS community.vocab_language_subscription;`); + await queryInterface.sequelize.query(`DROP TABLE IF EXISTS community.vocab_language;`); + } +}; + + diff --git a/backend/migrations/20251230001000-add-vocab-chapters-and-lexemes.cjs b/backend/migrations/20251230001000-add-vocab-chapters-and-lexemes.cjs new file mode 100644 index 0000000..3a97935 --- /dev/null +++ b/backend/migrations/20251230001000-add-vocab-chapters-and-lexemes.cjs @@ -0,0 +1,106 @@ +/* eslint-disable */ +'use strict'; + +module.exports = { + async up(queryInterface) { + // Kapitel innerhalb einer Sprache + await queryInterface.sequelize.query(` + CREATE TABLE IF NOT EXISTS community.vocab_chapter ( + id SERIAL PRIMARY KEY, + language_id INTEGER NOT NULL, + title TEXT NOT NULL, + created_by_user_id INTEGER NOT NULL, + created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT NOW(), + CONSTRAINT vocab_chapter_language_fk + FOREIGN KEY (language_id) + REFERENCES community.vocab_language(id) + ON DELETE CASCADE, + CONSTRAINT vocab_chapter_creator_fk + FOREIGN KEY (created_by_user_id) + REFERENCES community."user"(id) + ON DELETE CASCADE + ); + `); + + await queryInterface.sequelize.query(` + CREATE INDEX IF NOT EXISTS vocab_chapter_language_idx + ON community.vocab_chapter(language_id); + `); + + // Lexeme/Wörter (wir deduplizieren pro Sprache über normalized) + await queryInterface.sequelize.query(` + CREATE TABLE IF NOT EXISTS community.vocab_lexeme ( + id SERIAL PRIMARY KEY, + language_id INTEGER NOT NULL, + text TEXT NOT NULL, + normalized TEXT NOT NULL, + created_by_user_id INTEGER NOT NULL, + created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT NOW(), + CONSTRAINT vocab_lexeme_language_fk + FOREIGN KEY (language_id) + REFERENCES community.vocab_language(id) + ON DELETE CASCADE, + CONSTRAINT vocab_lexeme_creator_fk + FOREIGN KEY (created_by_user_id) + REFERENCES community."user"(id) + ON DELETE CASCADE, + CONSTRAINT vocab_lexeme_unique_per_language UNIQUE (language_id, normalized) + ); + `); + + await queryInterface.sequelize.query(` + CREATE INDEX IF NOT EXISTS vocab_lexeme_language_idx + ON community.vocab_lexeme(language_id); + `); + + // n:m Zuordnung pro Kapitel: Lernwort ↔ Referenzwort (Mehrdeutigkeiten möglich) + await queryInterface.sequelize.query(` + CREATE TABLE IF NOT EXISTS community.vocab_chapter_lexeme ( + id SERIAL PRIMARY KEY, + chapter_id INTEGER NOT NULL, + learning_lexeme_id INTEGER NOT NULL, + reference_lexeme_id INTEGER NOT NULL, + created_by_user_id INTEGER NOT NULL, + created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT NOW(), + CONSTRAINT vocab_chlex_chapter_fk + FOREIGN KEY (chapter_id) + REFERENCES community.vocab_chapter(id) + ON DELETE CASCADE, + CONSTRAINT vocab_chlex_learning_fk + FOREIGN KEY (learning_lexeme_id) + REFERENCES community.vocab_lexeme(id) + ON DELETE CASCADE, + CONSTRAINT vocab_chlex_reference_fk + FOREIGN KEY (reference_lexeme_id) + REFERENCES community.vocab_lexeme(id) + ON DELETE CASCADE, + CONSTRAINT vocab_chlex_creator_fk + FOREIGN KEY (created_by_user_id) + REFERENCES community."user"(id) + ON DELETE CASCADE, + CONSTRAINT vocab_chlex_unique UNIQUE (chapter_id, learning_lexeme_id, reference_lexeme_id) + ); + `); + + await queryInterface.sequelize.query(` + CREATE INDEX IF NOT EXISTS vocab_chlex_chapter_idx + ON community.vocab_chapter_lexeme(chapter_id); + `); + await queryInterface.sequelize.query(` + CREATE INDEX IF NOT EXISTS vocab_chlex_learning_idx + ON community.vocab_chapter_lexeme(learning_lexeme_id); + `); + await queryInterface.sequelize.query(` + CREATE INDEX IF NOT EXISTS vocab_chlex_reference_idx + ON community.vocab_chapter_lexeme(reference_lexeme_id); + `); + }, + + async down(queryInterface) { + await queryInterface.sequelize.query(`DROP TABLE IF EXISTS community.vocab_chapter_lexeme;`); + await queryInterface.sequelize.query(`DROP TABLE IF EXISTS community.vocab_lexeme;`); + await queryInterface.sequelize.query(`DROP TABLE IF EXISTS community.vocab_chapter;`); + } +}; + + diff --git a/backend/routers/vocabRouter.js b/backend/routers/vocabRouter.js new file mode 100644 index 0000000..78ce1c4 --- /dev/null +++ b/backend/routers/vocabRouter.js @@ -0,0 +1,26 @@ +import express from 'express'; +import { authenticate } from '../middleware/authMiddleware.js'; +import VocabController from '../controllers/vocabController.js'; + +const router = express.Router(); +const vocabController = new VocabController(); + +router.use(authenticate); + +router.get('/languages', vocabController.listLanguages); +router.post('/languages', vocabController.createLanguage); +router.post('/subscribe', vocabController.subscribe); +router.get('/languages/:languageId', vocabController.getLanguage); + +// Kapitel +router.get('/languages/:languageId/chapters', vocabController.listChapters); +router.post('/languages/:languageId/chapters', vocabController.createChapter); +router.get('/languages/:languageId/vocabs', vocabController.listLanguageVocabs); + +router.get('/chapters/:chapterId', vocabController.getChapter); +router.get('/chapters/:chapterId/vocabs', vocabController.listChapterVocabs); +router.post('/chapters/:chapterId/vocabs', vocabController.addVocabToChapter); + +export default router; + + diff --git a/backend/services/vocabService.js b/backend/services/vocabService.js new file mode 100644 index 0000000..534f2b2 --- /dev/null +++ b/backend/services/vocabService.js @@ -0,0 +1,485 @@ +import crypto from 'crypto'; +import User from '../models/community/user.js'; +import { sequelize } from '../utils/sequelize.js'; +import { notifyUser } from '../utils/socket.js'; + +export default class VocabService { + async _getUserByHashedId(hashedUserId) { + const user = await User.findOne({ where: { hashedId: hashedUserId } }); + if (!user) { + const err = new Error('User not found'); + err.status = 404; + throw err; + } + return user; + } + + _normalizeLexeme(text) { + return String(text || '') + .trim() + .toLowerCase() + .replace(/\s+/g, ' '); + } + + async _getLanguageAccess(userId, languageId) { + const id = Number.parseInt(languageId, 10); + if (!Number.isFinite(id)) { + const err = new Error('Invalid language id'); + err.status = 400; + throw err; + } + + const [row] = await sequelize.query( + ` + SELECT + l.id, + (l.owner_user_id = :userId) AS "isOwner" + FROM community.vocab_language l + WHERE l.id = :languageId + AND ( + l.owner_user_id = :userId + OR EXISTS ( + SELECT 1 + FROM community.vocab_language_subscription s + WHERE s.user_id = :userId AND s.language_id = l.id + ) + ) + LIMIT 1 + `, + { + replacements: { userId, languageId: id }, + type: sequelize.QueryTypes.SELECT, + } + ); + + if (!row) { + const err = new Error('Language not found or no access'); + err.status = 404; + throw err; + } + + return row; + } + + async _getChapterAccess(userId, chapterId) { + const id = Number.parseInt(chapterId, 10); + if (!Number.isFinite(id)) { + const err = new Error('Invalid chapter id'); + err.status = 400; + throw err; + } + + const [row] = await sequelize.query( + ` + SELECT + c.id, + c.language_id AS "languageId", + c.title, + (l.owner_user_id = :userId) AS "isOwner" + FROM community.vocab_chapter c + JOIN community.vocab_language l ON l.id = c.language_id + WHERE c.id = :chapterId + AND ( + l.owner_user_id = :userId + OR EXISTS ( + SELECT 1 + FROM community.vocab_language_subscription s + WHERE s.user_id = :userId AND s.language_id = l.id + ) + ) + LIMIT 1 + `, + { + replacements: { userId, chapterId: id }, + type: sequelize.QueryTypes.SELECT, + } + ); + + if (!row) { + const err = new Error('Chapter not found or no access'); + err.status = 404; + throw err; + } + + return row; + } + + async listLanguages(hashedUserId) { + const user = await this._getUserByHashedId(hashedUserId); + + const rows = await sequelize.query( + ` + SELECT + l.id, + l.name, + l.share_code AS "shareCode", + TRUE AS "isOwner" + FROM community.vocab_language l + WHERE l.owner_user_id = :userId + + UNION ALL + + SELECT + l.id, + l.name, + NULL::text AS "shareCode", + FALSE AS "isOwner" + FROM community.vocab_language_subscription s + JOIN community.vocab_language l ON l.id = s.language_id + WHERE s.user_id = :userId + + ORDER BY name ASC + `, + { + replacements: { userId: user.id }, + type: sequelize.QueryTypes.SELECT, + } + ); + + return { languages: rows }; + } + + async listLanguagesForMenu(userId) { + // userId ist die numerische community.user.id + const rows = await sequelize.query( + ` + SELECT l.id, l.name + FROM community.vocab_language l + WHERE l.owner_user_id = :userId + UNION + SELECT l.id, l.name + FROM community.vocab_language_subscription s + JOIN community.vocab_language l ON l.id = s.language_id + WHERE s.user_id = :userId + ORDER BY name ASC + `, + { + replacements: { userId }, + type: sequelize.QueryTypes.SELECT, + } + ); + return rows; + } + + async createLanguage(hashedUserId, { name }) { + const user = await this._getUserByHashedId(hashedUserId); + const cleanName = typeof name === 'string' ? name.trim() : ''; + if (!cleanName || cleanName.length < 2 || cleanName.length > 60) { + const err = new Error('Invalid language name'); + err.status = 400; + throw err; + } + + // 16 hex chars => ausreichend kurz, gut teilbar + const shareCode = crypto.randomBytes(8).toString('hex'); + + const [created] = await sequelize.query( + ` + INSERT INTO community.vocab_language (owner_user_id, name, share_code) + VALUES (:ownerUserId, :name, :shareCode) + RETURNING id, name, share_code AS "shareCode" + `, + { + replacements: { ownerUserId: user.id, name: cleanName, shareCode }, + type: sequelize.QueryTypes.SELECT, + } + ); + + // Menü dynamisch nachladen (bei allen offenen Tabs/Clients) + try { + notifyUser(user.hashedId, 'reloadmenu', {}); + } catch (_) {} + + return created; + } + + async subscribeByShareCode(hashedUserId, { shareCode }) { + const user = await this._getUserByHashedId(hashedUserId); + const code = typeof shareCode === 'string' ? shareCode.trim() : ''; + if (!code || code.length < 6 || code.length > 128) { + const err = new Error('Invalid share code'); + err.status = 400; + throw err; + } + + const [lang] = await sequelize.query( + ` + SELECT id, owner_user_id AS "ownerUserId", name + FROM community.vocab_language + WHERE share_code = :shareCode + LIMIT 1 + `, + { + replacements: { shareCode: code }, + type: sequelize.QueryTypes.SELECT, + } + ); + + if (!lang) { + const err = new Error('Language not found'); + err.status = 404; + throw err; + } + + // Owner braucht kein Abo + if (lang.ownerUserId === user.id) { + return { subscribed: false, message: 'Already owner', languageId: lang.id }; + } + + await sequelize.query( + ` + INSERT INTO community.vocab_language_subscription (user_id, language_id) + VALUES (:userId, :languageId) + ON CONFLICT (user_id, language_id) DO NOTHING + `, + { + replacements: { userId: user.id, languageId: lang.id }, + type: sequelize.QueryTypes.INSERT, + } + ); + + try { + notifyUser(user.hashedId, 'reloadmenu', {}); + } catch (_) {} + + return { subscribed: true, languageId: lang.id, name: lang.name }; + } + + async getLanguage(hashedUserId, languageId) { + const user = await this._getUserByHashedId(hashedUserId); + const id = Number.parseInt(languageId, 10); + if (!Number.isFinite(id)) { + const err = new Error('Invalid language id'); + err.status = 400; + throw err; + } + + const [row] = await sequelize.query( + ` + SELECT + l.id, + l.name, + CASE WHEN l.owner_user_id = :userId THEN l.share_code ELSE NULL END AS "shareCode", + (l.owner_user_id = :userId) AS "isOwner" + FROM community.vocab_language l + WHERE l.id = :languageId + AND ( + l.owner_user_id = :userId + OR EXISTS ( + SELECT 1 + FROM community.vocab_language_subscription s + WHERE s.user_id = :userId AND s.language_id = l.id + ) + ) + LIMIT 1 + `, + { + replacements: { userId: user.id, languageId: id }, + type: sequelize.QueryTypes.SELECT, + } + ); + + if (!row) { + const err = new Error('Language not found or no access'); + err.status = 404; + throw err; + } + + return row; + } + + async listChapters(hashedUserId, languageId) { + const user = await this._getUserByHashedId(hashedUserId); + const access = await this._getLanguageAccess(user.id, languageId); + + const rows = await sequelize.query( + ` + SELECT + c.id, + c.title, + c.created_at AS "createdAt", + ( + SELECT COUNT(*) + FROM community.vocab_chapter_lexeme cl + WHERE cl.chapter_id = c.id + )::int AS "vocabCount" + FROM community.vocab_chapter c + WHERE c.language_id = :languageId + ORDER BY c.title ASC + `, + { + replacements: { languageId: access.id }, + type: sequelize.QueryTypes.SELECT, + } + ); + + return { chapters: rows, isOwner: access.isOwner }; + } + + async createChapter(hashedUserId, languageId, { title }) { + const user = await this._getUserByHashedId(hashedUserId); + const access = await this._getLanguageAccess(user.id, languageId); + if (!access.isOwner) { + const err = new Error('Only owner can create chapters'); + err.status = 403; + throw err; + } + + const cleanTitle = typeof title === 'string' ? title.trim() : ''; + if (!cleanTitle || cleanTitle.length < 2 || cleanTitle.length > 80) { + const err = new Error('Invalid chapter title'); + err.status = 400; + throw err; + } + + const [created] = await sequelize.query( + ` + INSERT INTO community.vocab_chapter (language_id, title, created_by_user_id) + VALUES (:languageId, :title, :userId) + RETURNING id, title, created_at AS "createdAt" + `, + { + replacements: { languageId: access.id, title: cleanTitle, userId: user.id }, + type: sequelize.QueryTypes.SELECT, + } + ); + + return created; + } + + async getChapter(hashedUserId, chapterId) { + const user = await this._getUserByHashedId(hashedUserId); + const ch = await this._getChapterAccess(user.id, chapterId); + return { id: ch.id, languageId: ch.languageId, title: ch.title, isOwner: ch.isOwner }; + } + + async listChapterVocabs(hashedUserId, chapterId) { + const user = await this._getUserByHashedId(hashedUserId); + const ch = await this._getChapterAccess(user.id, chapterId); + + const rows = await sequelize.query( + ` + SELECT + cl.id, + l1.text AS "learning", + l2.text AS "reference", + cl.created_at AS "createdAt" + FROM community.vocab_chapter_lexeme cl + JOIN community.vocab_lexeme l1 ON l1.id = cl.learning_lexeme_id + JOIN community.vocab_lexeme l2 ON l2.id = cl.reference_lexeme_id + WHERE cl.chapter_id = :chapterId + ORDER BY l1.text ASC, l2.text ASC + `, + { + replacements: { chapterId: ch.id }, + type: sequelize.QueryTypes.SELECT, + } + ); + + return { chapter: { id: ch.id, title: ch.title, languageId: ch.languageId, isOwner: ch.isOwner }, vocabs: rows }; + } + + async listLanguageVocabs(hashedUserId, languageId) { + const user = await this._getUserByHashedId(hashedUserId); + const access = await this._getLanguageAccess(user.id, languageId); + + const rows = await sequelize.query( + ` + SELECT + cl.id, + c.id AS "chapterId", + c.title AS "chapterTitle", + l1.text AS "learning", + l2.text AS "reference", + cl.created_at AS "createdAt" + FROM community.vocab_chapter_lexeme cl + JOIN community.vocab_chapter c ON c.id = cl.chapter_id + JOIN community.vocab_lexeme l1 ON l1.id = cl.learning_lexeme_id + JOIN community.vocab_lexeme l2 ON l2.id = cl.reference_lexeme_id + WHERE c.language_id = :languageId + ORDER BY c.title ASC, l1.text ASC, l2.text ASC + `, + { + replacements: { languageId: access.id }, + type: sequelize.QueryTypes.SELECT, + } + ); + + return { languageId: access.id, isOwner: access.isOwner, vocabs: rows }; + } + + async addVocabToChapter(hashedUserId, chapterId, { learning, reference }) { + const user = await this._getUserByHashedId(hashedUserId); + const ch = await this._getChapterAccess(user.id, chapterId); + if (!ch.isOwner) { + const err = new Error('Only owner can add vocab'); + err.status = 403; + throw err; + } + + const learningText = typeof learning === 'string' ? learning.trim() : ''; + const referenceText = typeof reference === 'string' ? reference.trim() : ''; + if (!learningText || !referenceText) { + const err = new Error('Invalid vocab'); + err.status = 400; + throw err; + } + + const learningNorm = this._normalizeLexeme(learningText); + const referenceNorm = this._normalizeLexeme(referenceText); + + // Transaktion: Lexeme upserten + Zuordnung setzen + return await sequelize.transaction(async (t) => { + const [learningLex] = await sequelize.query( + ` + INSERT INTO community.vocab_lexeme (language_id, text, normalized, created_by_user_id) + VALUES (:languageId, :text, :normalized, :userId) + ON CONFLICT (language_id, normalized) DO UPDATE SET text = EXCLUDED.text + RETURNING id + `, + { + replacements: { languageId: ch.languageId, text: learningText, normalized: learningNorm, userId: user.id }, + type: sequelize.QueryTypes.SELECT, + transaction: t, + } + ); + + const [referenceLex] = await sequelize.query( + ` + INSERT INTO community.vocab_lexeme (language_id, text, normalized, created_by_user_id) + VALUES (:languageId, :text, :normalized, :userId) + ON CONFLICT (language_id, normalized) DO UPDATE SET text = EXCLUDED.text + RETURNING id + `, + { + replacements: { languageId: ch.languageId, text: referenceText, normalized: referenceNorm, userId: user.id }, + type: sequelize.QueryTypes.SELECT, + transaction: t, + } + ); + + const [mapping] = await sequelize.query( + ` + INSERT INTO community.vocab_chapter_lexeme (chapter_id, learning_lexeme_id, reference_lexeme_id, created_by_user_id) + VALUES (:chapterId, :learningId, :referenceId, :userId) + ON CONFLICT (chapter_id, learning_lexeme_id, reference_lexeme_id) DO NOTHING + RETURNING id + `, + { + replacements: { + chapterId: ch.id, + learningId: learningLex.id, + referenceId: referenceLex.id, + userId: user.id, + }, + type: sequelize.QueryTypes.SELECT, + transaction: t, + } + ); + + return { created: Boolean(mapping?.id) }; + }); + } +} + + diff --git a/backend/utils/syncDatabase.js b/backend/utils/syncDatabase.js index 036fd0c..c67ece1 100644 --- a/backend/utils/syncDatabase.js +++ b/backend/utils/syncDatabase.js @@ -33,6 +33,123 @@ const syncDatabase = async () => { console.log("Initializing database schemas..."); await initializeDatabase(); + // Vokabeltrainer: Tabellen sicherstellen (auch ohne manuell ausgeführte Migrations) + // Hintergrund: In Produktion sind Schema-Updates deaktiviert, und Migrations werden nicht automatisch ausgeführt. + // Damit API/Menu nicht mit "relation does not exist" (42P01) scheitert, legen wir die Tabellen idempotent an. + console.log("Ensuring Vocab-Trainer tables exist..."); + try { + await sequelize.query(` + CREATE TABLE IF NOT EXISTS community.vocab_language ( + id SERIAL PRIMARY KEY, + owner_user_id INTEGER NOT NULL, + name TEXT NOT NULL, + share_code TEXT NOT NULL, + created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT NOW(), + CONSTRAINT vocab_language_owner_fk + FOREIGN KEY (owner_user_id) + REFERENCES community."user"(id) + ON DELETE CASCADE, + CONSTRAINT vocab_language_share_code_uniq UNIQUE (share_code) + ); + + CREATE TABLE IF NOT EXISTS community.vocab_language_subscription ( + id SERIAL PRIMARY KEY, + user_id INTEGER NOT NULL, + language_id INTEGER NOT NULL, + created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT NOW(), + CONSTRAINT vocab_language_subscription_user_fk + FOREIGN KEY (user_id) + REFERENCES community."user"(id) + ON DELETE CASCADE, + CONSTRAINT vocab_language_subscription_language_fk + FOREIGN KEY (language_id) + REFERENCES community.vocab_language(id) + ON DELETE CASCADE, + CONSTRAINT vocab_language_subscription_uniq UNIQUE (user_id, language_id) + ); + + CREATE INDEX IF NOT EXISTS vocab_language_owner_idx + ON community.vocab_language(owner_user_id); + CREATE INDEX IF NOT EXISTS vocab_language_subscription_user_idx + ON community.vocab_language_subscription(user_id); + CREATE INDEX IF NOT EXISTS vocab_language_subscription_language_idx + ON community.vocab_language_subscription(language_id); + + CREATE TABLE IF NOT EXISTS community.vocab_chapter ( + id SERIAL PRIMARY KEY, + language_id INTEGER NOT NULL, + title TEXT NOT NULL, + created_by_user_id INTEGER NOT NULL, + created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT NOW(), + CONSTRAINT vocab_chapter_language_fk + FOREIGN KEY (language_id) + REFERENCES community.vocab_language(id) + ON DELETE CASCADE, + CONSTRAINT vocab_chapter_creator_fk + FOREIGN KEY (created_by_user_id) + REFERENCES community."user"(id) + ON DELETE CASCADE + ); + CREATE INDEX IF NOT EXISTS vocab_chapter_language_idx + ON community.vocab_chapter(language_id); + + CREATE TABLE IF NOT EXISTS community.vocab_lexeme ( + id SERIAL PRIMARY KEY, + language_id INTEGER NOT NULL, + text TEXT NOT NULL, + normalized TEXT NOT NULL, + created_by_user_id INTEGER NOT NULL, + created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT NOW(), + CONSTRAINT vocab_lexeme_language_fk + FOREIGN KEY (language_id) + REFERENCES community.vocab_language(id) + ON DELETE CASCADE, + CONSTRAINT vocab_lexeme_creator_fk + FOREIGN KEY (created_by_user_id) + REFERENCES community."user"(id) + ON DELETE CASCADE, + CONSTRAINT vocab_lexeme_unique_per_language UNIQUE (language_id, normalized) + ); + CREATE INDEX IF NOT EXISTS vocab_lexeme_language_idx + ON community.vocab_lexeme(language_id); + + CREATE TABLE IF NOT EXISTS community.vocab_chapter_lexeme ( + id SERIAL PRIMARY KEY, + chapter_id INTEGER NOT NULL, + learning_lexeme_id INTEGER NOT NULL, + reference_lexeme_id INTEGER NOT NULL, + created_by_user_id INTEGER NOT NULL, + created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT NOW(), + CONSTRAINT vocab_chlex_chapter_fk + FOREIGN KEY (chapter_id) + REFERENCES community.vocab_chapter(id) + ON DELETE CASCADE, + CONSTRAINT vocab_chlex_learning_fk + FOREIGN KEY (learning_lexeme_id) + REFERENCES community.vocab_lexeme(id) + ON DELETE CASCADE, + CONSTRAINT vocab_chlex_reference_fk + FOREIGN KEY (reference_lexeme_id) + REFERENCES community.vocab_lexeme(id) + ON DELETE CASCADE, + CONSTRAINT vocab_chlex_creator_fk + FOREIGN KEY (created_by_user_id) + REFERENCES community."user"(id) + ON DELETE CASCADE, + CONSTRAINT vocab_chlex_unique UNIQUE (chapter_id, learning_lexeme_id, reference_lexeme_id) + ); + CREATE INDEX IF NOT EXISTS vocab_chlex_chapter_idx + ON community.vocab_chapter_lexeme(chapter_id); + CREATE INDEX IF NOT EXISTS vocab_chlex_learning_idx + ON community.vocab_chapter_lexeme(learning_lexeme_id); + CREATE INDEX IF NOT EXISTS vocab_chlex_reference_idx + ON community.vocab_chapter_lexeme(reference_lexeme_id); + `); + console.log("✅ Vocab-Trainer Tabellen sind vorhanden."); + } catch (e) { + console.warn('⚠️ Konnte Vocab-Trainer Tabellen nicht sicherstellen:', e?.message || e); + } + // Vorab: Stelle kritische Spalten sicher, damit Index-Erstellung nicht fehlschlägt console.log("Pre-ensure Taxi columns (traffic_light) ..."); try { diff --git a/frontend/public/sounds/fail.mp3 b/frontend/public/sounds/fail.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..6b776c29a05f013e2f041ba8c15b250f1199efe8 GIT binary patch literal 56064 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 literal 0 HcmV?d00001 diff --git a/frontend/public/sounds/success.mp3 b/frontend/public/sounds/success.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..ff101229cae3a44679db1e59927af3d7fd85f7f6 GIT binary patch literal 50880 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

-|>gL+heXQ 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 E0Ae=cz5oCK literal 0 HcmV?d00001 diff --git a/frontend/src/components/AppNavigation.vue b/frontend/src/components/AppNavigation.vue index 3434cd3..72ecd0d 100644 --- a/frontend/src/components/AppNavigation.vue +++ b/frontend/src/components/AppNavigation.vue @@ -27,7 +27,7 @@ :style="`background-image:url('/images/icons/${subitem.icon}')`" class="submenu-icon" >  - {{ $t(`navigation.m-${key}.${subkey}`) }} + {{ subitem?.label || $t(`navigation.m-${key}.${subkey}`) }}   - {{ $t(`navigation.m-${key}.m-${subkey}.${subsubkey}`) }} + {{ subsubitem?.label || $t(`navigation.m-${key}.m-${subkey}.${subsubkey}`) }} diff --git a/frontend/src/dialogues/socialnetwork/VocabPracticeDialog.vue b/frontend/src/dialogues/socialnetwork/VocabPracticeDialog.vue new file mode 100644 index 0000000..21c9492 --- /dev/null +++ b/frontend/src/dialogues/socialnetwork/VocabPracticeDialog.vue @@ -0,0 +1,504 @@ + + + + + + + diff --git a/frontend/src/i18n/locales/de/general.json b/frontend/src/i18n/locales/de/general.json index 07d7632..2a33163 100644 --- a/frontend/src/i18n/locales/de/general.json +++ b/frontend/src/i18n/locales/de/general.json @@ -26,7 +26,10 @@ } }, "general": { - "datetimelong": "dd.MM.yyyy HH:mm:ss" + "datetimelong": "dd.MM.yyyy HH:mm:ss", + "loading": "Lädt...", + "back": "Zurück", + "cancel": "Abbrechen" }, "OK": "Ok", "Cancel": "Abbrechen", diff --git a/frontend/src/i18n/locales/de/navigation.json b/frontend/src/i18n/locales/de/navigation.json index d0c900a..d3662a6 100644 --- a/frontend/src/i18n/locales/de/navigation.json +++ b/frontend/src/i18n/locales/de/navigation.json @@ -20,6 +20,7 @@ "usersearch": "Benutzersuche", "forum": "Forum", "gallery": "Galerie", + "vocabtrainer": "Vokabeltrainer", "blockedUsers": "Blockierte Benutzer", "oneTimeInvitation": "Einmal-Einladungen", "diary": "Tagebuch", @@ -27,6 +28,9 @@ "m-erotic": { "pictures": "Bilder", "videos": "Videos" + }, + "m-vocabtrainer": { + "newLanguage": "Neue Sprache" } }, "m-minigames": { diff --git a/frontend/src/i18n/locales/de/socialnetwork.json b/frontend/src/i18n/locales/de/socialnetwork.json index 3edea90..1e54681 100644 --- a/frontend/src/i18n/locales/de/socialnetwork.json +++ b/frontend/src/i18n/locales/de/socialnetwork.json @@ -249,5 +249,66 @@ "denied": "Du hast die Freundschaftsanfrage abgelehnt.", "accepted": "Die Freundschaft wurde geschlossen." } + , + "vocab": { + "title": "Vokabeltrainer", + "description": "Lege Sprachen an (oder abonniere sie) und teile sie mit Freunden.", + "newLanguage": "Neue Sprache", + "newLanguageTitle": "Neue Sprache anlegen", + "languageName": "Name der Sprache", + "create": "Anlegen", + "saving": "Speichere...", + "created": "Sprache wurde angelegt.", + "createdTitle": "Vokabeltrainer", + "createdMessage": "Sprache wurde angelegt. Das Menü wird aktualisiert.", + "createError": "Konnte die Sprache nicht anlegen.", + "openLanguage": "Öffnen", + "none": "Du hast noch keine Sprachen angelegt oder abonniert.", + "owner": "Eigen", + "subscribed": "Abonniert", + "languageTitle": "Vokabeltrainer: {name}", + "notFound": "Sprache nicht gefunden oder kein Zugriff.", + "shareCode": "Teilen-Code", + "shareHint": "Diesen Code kannst du an Freunde weitergeben, damit sie die Sprache abonnieren können.", + "subscribeByCode": "Per Code abonnieren", + "subscribeTitle": "Sprache abonnieren", + "subscribeHint": "Gib den Teilen-Code ein, den du von einem Freund bekommen hast.", + "subscribe": "Abonnieren", + "subscribeSuccess": "Abo erfolgreich. Menü wird aktualisiert.", + "subscribeError": "Abo fehlgeschlagen. Code ungültig oder kein Zugriff.", + "trainerPlaceholder": "Trainer-Funktionen (Vokabeln/Abfragen) kommen als nächster Schritt." + , + "chapters": "Kapitel", + "newChapter": "Neues Kapitel", + "createChapter": "Kapitel anlegen", + "createChapterError": "Konnte Kapitel nicht anlegen.", + "noChapters": "Noch keine Kapitel vorhanden.", + "chapterTitle": "Kapitel: {title}", + "addVocab": "Vokabel hinzufügen", + "learningWord": "Lernsprache", + "referenceWord": "Referenz", + "add": "Hinzufügen", + "addVocabError": "Konnte Vokabel nicht hinzufügen.", + "noVocabs": "In diesem Kapitel sind noch keine Vokabeln." + , + "practice": { + "open": "Üben", + "title": "Vokabeln üben", + "allVocabs": "Alle Vokabeln", + "simple": "Einfaches Üben", + "noPool": "Keine Vokabeln zum Üben vorhanden.", + "dirLearningToRef": "Lernsprache → Referenz", + "dirRefToLearning": "Referenz → Lernsprache", + "check": "Prüfen", + "next": "Weiter", + "skip": "Überspringen", + "correct": "Richtig!", + "wrong": "Falsch.", + "acceptable": "Mögliche richtige Übersetzungen:", + "stats": "Statistik", + "success": "Erfolg", + "fail": "Misserfolg" + } + } } } \ No newline at end of file diff --git a/frontend/src/i18n/locales/en/general.json b/frontend/src/i18n/locales/en/general.json index 781699e..1028dbf 100644 --- a/frontend/src/i18n/locales/en/general.json +++ b/frontend/src/i18n/locales/en/general.json @@ -6,6 +6,12 @@ "dataPrivacy": { "title": "Data Privacy Policy" }, + "general": { + "loading": "Loading...", + "back": "Back", + "cancel": "Cancel", + "datetimelong": "dd.MM.yyyy HH:mm:ss" + }, "message": { "close": "Close" }, diff --git a/frontend/src/i18n/locales/en/navigation.json b/frontend/src/i18n/locales/en/navigation.json index c6f571f..c0604ba 100644 --- a/frontend/src/i18n/locales/en/navigation.json +++ b/frontend/src/i18n/locales/en/navigation.json @@ -20,6 +20,7 @@ "usersearch": "User search", "forum": "Forum", "gallery": "Gallery", + "vocabtrainer": "Vocabulary trainer", "blockedUsers": "Blocked users", "oneTimeInvitation": "One-time invitations", "diary": "Diary", @@ -27,6 +28,9 @@ "m-erotic": { "pictures": "Pictures", "videos": "Videos" + }, + "m-vocabtrainer": { + "newLanguage": "New language" } }, "m-minigames": { diff --git a/frontend/src/i18n/locales/en/socialnetwork.json b/frontend/src/i18n/locales/en/socialnetwork.json index fd4179f..2e09e05 100644 --- a/frontend/src/i18n/locales/en/socialnetwork.json +++ b/frontend/src/i18n/locales/en/socialnetwork.json @@ -249,5 +249,66 @@ "denied": "You have denied the friendship request.", "accepted": "The friendship has been established." } + , + "vocab": { + "title": "Vocabulary trainer", + "description": "Create languages (or subscribe to them) and share them with friends.", + "newLanguage": "New language", + "newLanguageTitle": "Create new language", + "languageName": "Language name", + "create": "Create", + "saving": "Saving...", + "created": "Language created.", + "createdTitle": "Vocabulary trainer", + "createdMessage": "Language created. The menu will refresh.", + "createError": "Could not create language.", + "openLanguage": "Open", + "none": "You have no languages yet (created or subscribed).", + "owner": "Owned", + "subscribed": "Subscribed", + "languageTitle": "Vocabulary trainer: {name}", + "notFound": "Language not found or no access.", + "shareCode": "Share code", + "shareHint": "Send this code to friends so they can subscribe to this language.", + "subscribeByCode": "Subscribe by code", + "subscribeTitle": "Subscribe to language", + "subscribeHint": "Enter a share code you received from a friend.", + "subscribe": "Subscribe", + "subscribeSuccess": "Subscribed. The menu will refresh.", + "subscribeError": "Subscribe failed. Invalid code or no access.", + "trainerPlaceholder": "Trainer features (words/quizzes) will be the next step." + , + "chapters": "Chapters", + "newChapter": "New chapter", + "createChapter": "Create chapter", + "createChapterError": "Could not create chapter.", + "noChapters": "No chapters yet.", + "chapterTitle": "Chapter: {title}", + "addVocab": "Add vocabulary", + "learningWord": "To learn", + "referenceWord": "Reference", + "add": "Add", + "addVocabError": "Could not add vocabulary.", + "noVocabs": "No vocabulary in this chapter yet." + , + "practice": { + "open": "Practice", + "title": "Practice vocabulary", + "allVocabs": "All vocabulary", + "simple": "Simple practice", + "noPool": "No vocabulary to practice.", + "dirLearningToRef": "To learn → Reference", + "dirRefToLearning": "Reference → To learn", + "check": "Check", + "next": "Next", + "skip": "Skip", + "correct": "Correct!", + "wrong": "Wrong.", + "acceptable": "Acceptable answers:", + "stats": "Stats", + "success": "Success", + "fail": "Fail" + } + } } } \ No newline at end of file diff --git a/frontend/src/router/socialRoutes.js b/frontend/src/router/socialRoutes.js index eb51f0c..82d17ab 100644 --- a/frontend/src/router/socialRoutes.js +++ b/frontend/src/router/socialRoutes.js @@ -5,6 +5,11 @@ import GuestbookView from '../views/social/GuestbookView.vue'; import DiaryView from '../views/social/DiaryView.vue'; import ForumView from '../views/social/ForumView.vue'; import ForumTopicView from '../views/social/ForumTopicView.vue'; +import VocabTrainerView from '../views/social/VocabTrainerView.vue'; +import VocabNewLanguageView from '../views/social/VocabNewLanguageView.vue'; +import VocabLanguageView from '../views/social/VocabLanguageView.vue'; +import VocabSubscribeView from '../views/social/VocabSubscribeView.vue'; +import VocabChapterView from '../views/social/VocabChapterView.vue'; const socialRoutes = [ { @@ -49,6 +54,36 @@ const socialRoutes = [ component: DiaryView, meta: { requiresAuth: true } }, + { + path: '/socialnetwork/vocab', + name: 'VocabTrainer', + component: VocabTrainerView, + meta: { requiresAuth: true } + }, + { + path: '/socialnetwork/vocab/new', + name: 'VocabNewLanguage', + component: VocabNewLanguageView, + meta: { requiresAuth: true } + }, + { + path: '/socialnetwork/vocab/subscribe', + name: 'VocabSubscribe', + component: VocabSubscribeView, + meta: { requiresAuth: true } + }, + { + path: '/socialnetwork/vocab/:languageId', + name: 'VocabLanguage', + component: VocabLanguageView, + meta: { requiresAuth: true } + }, + { + path: '/socialnetwork/vocab/:languageId/chapters/:chapterId', + name: 'VocabChapter', + component: VocabChapterView, + meta: { requiresAuth: true } + }, ]; export default socialRoutes; diff --git a/frontend/src/views/social/VocabChapterView.vue b/frontend/src/views/social/VocabChapterView.vue new file mode 100644 index 0000000..a40c748 --- /dev/null +++ b/frontend/src/views/social/VocabChapterView.vue @@ -0,0 +1,153 @@ + + + + + + + diff --git a/frontend/src/views/social/VocabLanguageView.vue b/frontend/src/views/social/VocabLanguageView.vue new file mode 100644 index 0000000..5bfd595 --- /dev/null +++ b/frontend/src/views/social/VocabLanguageView.vue @@ -0,0 +1,149 @@ + + + + + + + diff --git a/frontend/src/views/social/VocabNewLanguageView.vue b/frontend/src/views/social/VocabNewLanguageView.vue new file mode 100644 index 0000000..a92df59 --- /dev/null +++ b/frontend/src/views/social/VocabNewLanguageView.vue @@ -0,0 +1,106 @@ + + + + + + + diff --git a/frontend/src/views/social/VocabSubscribeView.vue b/frontend/src/views/social/VocabSubscribeView.vue new file mode 100644 index 0000000..7b3e5cf --- /dev/null +++ b/frontend/src/views/social/VocabSubscribeView.vue @@ -0,0 +1,93 @@ + + + + + + + diff --git a/frontend/src/views/social/VocabTrainerView.vue b/frontend/src/views/social/VocabTrainerView.vue new file mode 100644 index 0000000..3a5ea1f --- /dev/null +++ b/frontend/src/views/social/VocabTrainerView.vue @@ -0,0 +1,86 @@ + + + + + + +