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:
@@ -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,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 || [];
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user