Refactor vocabulary search functionality in VocabService and update UI components

- Modified the searchVocabs method in VocabService to consolidate search parameters into a single query term for improved flexibility.
- Updated VocabSearchDialog to replace separate input fields for mother tongue and learning language with a unified search term input.
- Adjusted button logic to enable search only when a term is provided, enhancing user experience.
- Added new translations for the search term in both German and English locales to support the updated UI.
This commit is contained in:
Torsten Schulz (local)
2026-01-05 16:58:18 +01:00
parent f5e3a9a4a2
commit c17af04cbf
4 changed files with 19 additions and 24 deletions

View File

@@ -408,20 +408,23 @@ export default class VocabService {
return { languageId: access.id, isOwner: access.isOwner, vocabs: rows }; return { languageId: access.id, isOwner: access.isOwner, vocabs: rows };
} }
async searchVocabs(hashedUserId, languageId, { learning = '', motherTongue = '' } = {}) { async searchVocabs(hashedUserId, languageId, { q = '', learning = '', motherTongue = '' } = {}) {
const user = await this._getUserByHashedId(hashedUserId); const user = await this._getUserByHashedId(hashedUserId);
const access = await this._getLanguageAccess(user.id, languageId); const access = await this._getLanguageAccess(user.id, languageId);
const query = typeof q === 'string' ? q.trim() : '';
// Abwärtskompatibel: falls alte Parameter genutzt werden, zusammenfassen
const learningTerm = typeof learning === 'string' ? learning.trim() : ''; const learningTerm = typeof learning === 'string' ? learning.trim() : '';
const motherTerm = typeof motherTongue === 'string' ? motherTongue.trim() : ''; const motherTerm = typeof motherTongue === 'string' ? motherTongue.trim() : '';
if (!learningTerm && !motherTerm) { const effective = query || learningTerm || motherTerm;
if (!effective) {
const err = new Error('Missing search term'); const err = new Error('Missing search term');
err.status = 400; err.status = 400;
throw err; throw err;
} }
const learningLike = learningTerm ? `%${learningTerm}%` : null; const like = `%${effective}%`;
const motherLike = motherTerm ? `%${motherTerm}%` : null;
const rows = await sequelize.query( const rows = await sequelize.query(
` `
@@ -436,16 +439,14 @@ export default class VocabService {
JOIN community.vocab_lexeme l1 ON l1.id = cl.learning_lexeme_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 JOIN community.vocab_lexeme l2 ON l2.id = cl.reference_lexeme_id
WHERE c.language_id = :languageId WHERE c.language_id = :languageId
AND (:learningLike IS NULL OR l1.text ILIKE :learningLike) AND (l1.text ILIKE :like OR l2.text ILIKE :like)
AND (:motherLike IS NULL OR l2.text ILIKE :motherLike)
ORDER BY l2.text ASC, l1.text ASC, c.title ASC ORDER BY l2.text ASC, l1.text ASC, c.title ASC
LIMIT 200 LIMIT 200
`, `,
{ {
replacements: { replacements: {
languageId: access.id, languageId: access.id,
learningLike, like,
motherLike,
}, },
type: sequelize.QueryTypes.SELECT, type: sequelize.QueryTypes.SELECT,
} }

View File

@@ -16,14 +16,10 @@
<div class="top"> <div class="top">
<div class="row"> <div class="row">
<label class="field"> <label class="field">
{{ $t('socialnetwork.vocab.search.motherTongue') }} {{ $t('socialnetwork.vocab.search.term') }}
<input v-model="motherTongue" type="text" @keydown.enter.prevent="runSearch" /> <input v-model="term" type="text" @keydown.enter.prevent="runSearch" />
</label> </label>
<label class="field"> <button class="btn" :disabled="loading || !term.trim()" @click="runSearch">
{{ learningLabel }}
<input v-model="learning" type="text" @keydown.enter.prevent="runSearch" />
</label>
<button class="btn" :disabled="loading || (!motherTongue.trim() && !learning.trim())" @click="runSearch">
{{ loading ? $t('general.loading') : $t('socialnetwork.vocab.search.search') }} {{ loading ? $t('general.loading') : $t('socialnetwork.vocab.search.search') }}
</button> </button>
</div> </div>
@@ -66,8 +62,7 @@ export default {
return { return {
languageId: null, languageId: null,
languageName: '', languageName: '',
motherTongue: '', term: '',
learning: '',
loading: false, loading: false,
results: [], results: [],
error: '', error: '',
@@ -85,8 +80,7 @@ export default {
open({ languageId, languageName = '' } = {}) { open({ languageId, languageName = '' } = {}) {
this.languageId = languageId; this.languageId = languageId;
this.languageName = languageName || ''; this.languageName = languageName || '';
this.motherTongue = ''; this.term = '';
this.learning = '';
this.results = []; this.results = [];
this.error = ''; this.error = '';
this.loading = false; this.loading = false;
@@ -98,17 +92,15 @@ export default {
}, },
async runSearch() { async runSearch() {
if (!this.languageId) return; if (!this.languageId) return;
const mt = this.motherTongue.trim(); const q = this.term.trim();
const l = this.learning.trim(); if (!q) return;
if (!mt && !l) return;
this.loading = true; this.loading = true;
this.error = ''; this.error = '';
try { try {
const res = await apiClient.get(`/api/vocab/languages/${this.languageId}/search`, { const res = await apiClient.get(`/api/vocab/languages/${this.languageId}/search`, {
params: { params: {
motherTongue: mt || undefined, q,
learning: l || undefined,
}, },
}); });
this.results = res.data?.results || []; this.results = res.data?.results || [];

View File

@@ -312,6 +312,7 @@
"search": { "search": {
"open": "Suche", "open": "Suche",
"title": "Vokabeln suchen", "title": "Vokabeln suchen",
"term": "Suchbegriff",
"motherTongue": "Muttersprache", "motherTongue": "Muttersprache",
"learningLanguage": "Lernsprache", "learningLanguage": "Lernsprache",
"lesson": "Lektion", "lesson": "Lektion",

View File

@@ -312,6 +312,7 @@
"search": { "search": {
"open": "Search", "open": "Search",
"title": "Search vocabulary", "title": "Search vocabulary",
"term": "Search term",
"motherTongue": "Mother tongue", "motherTongue": "Mother tongue",
"learningLanguage": "Learning language", "learningLanguage": "Learning language",
"lesson": "Lesson", "lesson": "Lesson",