refactor(header, search): trigger search only after enter was pressed

This commit is contained in:
Matej Glasnák committed 2025-11-20 11:27:15 +01:00
1 parent e0d6ae57b3
commit 69f3a5b309
2 files changed
+119 -65

No files matched your search

@@ -1,13 +1,27 @@
<template> <template>
<v-app-bar class="header"> <v-app-bar class="header">
<v-app-bar-nav-icon @click="$events.emit('toggle-menu')" class="menu-icon"></v-app-bar-nav-icon> <v-app-bar-nav-icon
@click="$events.emit('toggle-menu')"
class="menu-icon"
></v-app-bar-nav-icon>
<div class="d-flex justify-space-between align-center w-100"> <div class="d-flex justify-space-between align-center w-100">
<h1>{{ $route.meta.title }}</h1> <h1>{{ $route.meta.title }}</h1>
<div class="d-flex justify-end align-center w-100 header-sm"> <div class="d-flex justify-end align-center w-100 header-sm">
<img class="search-icon" :src="require('@/plugins/app/_img/icons/search.svg')" alt="search-icon" /> <img
<input class="search-input mx-2" v-model="search" type="text" placeholder="Search" @click="$router.push({name: 'Search'})" @keyup="$events.emit('onSearch', search)" /> class="search-icon"
:src="require('@/plugins/app/_img/icons/search.svg')"
alt="search-icon"
/>
<input
class="search-input mx-2"
v-model="search"
type="text"
placeholder="Search"
@click="$router.push({ name: 'Search' })"
@keydown.enter="$events.emit('onSearch', search)"
/>
<v-menu> <v-menu>
<template v-slot:activator="{ props }"> <template v-slot:activator="{ props }">
@@ -17,10 +31,26 @@
</template> </template>
<v-list> <v-list>
<v-list-item class="cursor-pointer hover-background" @click="createMasterTask()">MASTER TASK</v-list-item> <v-list-item
<v-list-item class="cursor-pointer hover-background" @click="createTask()">SUB TASK</v-list-item> class="cursor-pointer hover-background"
<v-list-item class="cursor-pointer hover-background" @click="createTeam()">TÍM</v-list-item> @click="createMasterTask()"
<v-list-item class="cursor-pointer hover-background" @click="createBlocker()">BLOCKER</v-list-item> >MASTER TASK</v-list-item
>
<v-list-item
class="cursor-pointer hover-background"
@click="createTask()"
>SUB TASK</v-list-item
>
<v-list-item
class="cursor-pointer hover-background"
@click="createTeam()"
>TÍM</v-list-item
>
<v-list-item
class="cursor-pointer hover-background"
@click="createBlocker()"
>BLOCKER</v-list-item
>
</v-list> </v-list>
</v-menu> </v-menu>
@@ -28,20 +58,33 @@
<template v-slot:activator="{ props }"> <template v-slot:activator="{ props }">
<v-btn class="menu-dropdown" v-bind="props"> <v-btn class="menu-dropdown" v-bind="props">
<div class="d-flex justify-between align-center"> <div class="d-flex justify-between align-center">
<p class="employee-select-avatar d-flex justify-center align-center" @click.stop="$router.push({name: 'Dashboard - User'})"> <p
class="employee-select-avatar d-flex justify-center align-center"
@click.stop="$router.push({ name: 'Dashboard - User' })"
>
{{ user.name?.charAt(0) }}{{ user.surname?.charAt(0) }} {{ user.name?.charAt(0) }}{{ user.surname?.charAt(0) }}
</p> </p>
<div> <div>
<span class="employee-name ml-4">{{ `${user.name} ${user.surname || ''}` }}</span> <span class="employee-name ml-4">{{
<v-icon class="ml-3" icon="mdi-chevron-down" size="x-small"></v-icon> `${user.name} ${user.surname || ''}`
}}</span>
<v-icon
class="ml-3"
icon="mdi-chevron-down"
size="x-small"
></v-icon>
</div> </div>
</div> </div>
</v-btn> </v-btn>
</template> </template>
<v-list class="text-center"> <v-list class="text-center">
<v-list-item class="cursor-pointer hover-background" @click.stop="$router.push({name: 'Dashboard - User'})">Profil</v-list-item> <v-list-item
class="cursor-pointer hover-background"
@click.stop="$router.push({ name: 'Dashboard - User' })"
>Profil</v-list-item
>
<v-list-item> <v-list-item>
<v-btn class="button" @click="logOut()">Odhlásiť sa</v-btn> <v-btn class="button" @click="logOut()">Odhlásiť sa</v-btn>
</v-list-item> </v-list-item>
@@ -49,18 +92,17 @@
</v-menu> </v-menu>
</div> </div>
</div> </div>
</v-app-bar> </v-app-bar>
</template> </template>
<script> <script>
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex';
export default { export default {
data() { data() {
return { return {
search: '' search: '',
} };
}, },
computed: { computed: {
@@ -70,40 +112,40 @@ export default {
methods: { methods: {
async logOut() { async logOut() {
try { try {
await this.$store.dispatch('auth/logout') await this.$store.dispatch('auth/logout');
this.$router.push('/') this.$router.push('/');
this.$toast.success('Boli ste odhlásený') this.$toast.success('Boli ste odhlásený');
} catch (error) { } catch (error) {
this.$toast.error(this.$parseError(error)) this.$toast.error(this.$parseError(error));
if (process.env.NODE_ENV === 'development') if (process.env.NODE_ENV === 'development')
console.log('[a-header.vue] Error: ', error) console.log('[a-header.vue] Error: ', error);
} }
}, },
createMasterTask() { createMasterTask() {
this.$events.emit('show-mastertask-modal', {}) this.$events.emit('show-mastertask-modal', {});
}, },
createTask() { createTask() {
this.$events.emit('show-subtask-modal', {}) this.$events.emit('show-subtask-modal', {});
}, },
createTeam() { createTeam() {
this.$events.emit('show-team-modal', {}) this.$events.emit('show-team-modal', {});
}, },
createBlocker() { createBlocker() {
this.$events.emit('show-blocker-modal', {}) this.$events.emit('show-blocker-modal', {});
} },
}, },
watch: { watch: {
'$route' (to, from) { $route(to, from) {
this.search = '' this.search = '';
}
}, },
} },
};
</script> </script>
<style lang="sass" scoped> <style lang="sass" scoped>
+48 -36
View File
@@ -1,7 +1,15 @@
<template> <template>
<div> <div>
<p v-if="!this.searchResults" class="px-3 py-3">{{ this.search?.length ? $t('Searching...') : $t('Type something') }}</p> <p v-if="!this.searchResults" class="px-3 py-3">
<p v-else-if="this.searchResults.error" class="px-3">{{ this.searchResults.error }}</p> {{
this.search?.length
? $t('Vyhľadávanie...')
: $t('Pre začatie vyhľadávania stlačte Enter')
}}
</p>
<p v-else-if="this.searchResults.error" class="px-3">
{{ this.searchResults.error }}
</p>
<div v-else class="results-wrapper"> <div v-else class="results-wrapper">
<A-search-result-mastertasks :mastertasks="searchResults.mastertasks" /> <A-search-result-mastertasks :mastertasks="searchResults.mastertasks" />
@@ -12,78 +20,82 @@
</template> </template>
<script> <script>
import { debounce } from 'lodash-es' import { debounce } from 'lodash-es';
import ASearchResultTeam from '@/plugins/lib@search/search/_components/a-search-result-team.vue' import ASearchResultTeam from '@/plugins/lib@search/search/_components/a-search-result-team.vue';
import ASearchResultSubtasks from '@/plugins/lib@search/search/_components/a-search-result-subtasks.vue' import ASearchResultSubtasks from '@/plugins/lib@search/search/_components/a-search-result-subtasks.vue';
import ASearchResultMastertasks from '@/plugins/lib@search/search/_components/a-search-result-mastertasks.vue' import ASearchResultMastertasks from '@/plugins/lib@search/search/_components/a-search-result-mastertasks.vue';
export default { export default {
components: { components: {
ASearchResultTeam, ASearchResultTeam,
ASearchResultSubtasks, ASearchResultSubtasks,
ASearchResultMastertasks ASearchResultMastertasks,
}, },
data() { data() {
return { return {
searchResults: null, searchResults: null,
search: '' search: '',
} };
}, },
created() { created() {
this.$events.on('onSearch', (search) => { this.$events.on('onSearch', (search) => {
if (!search?.length) if (!search?.length) return;
return
this.search = search this.search = search;
this.onSearch(search) this.onSearch(search);
}) });
}, },
mounted() { mounted() {
this.$events.on('on-subtask-edited', () => { this.$events.on('on-subtask-edited', () => {
this.onSearch(this.search, false) this.onSearch(this.search, false);
}) });
this.$events.on('on-subtask-deleted', () => { this.$events.on('on-subtask-deleted', () => {
this.onSearch(this.search, false) this.onSearch(this.search, false);
}) });
this.$events.on('on-mastertask-edited', () => { this.$events.on('on-mastertask-edited', () => {
this.onSearch(this.search, false) this.onSearch(this.search, false);
}) });
this.$events.on('on-mastertask-deleted', () => { this.$events.on('on-mastertask-deleted', () => {
this.onSearch(this.search, false) this.onSearch(this.search, false);
}) });
}, },
unmounted() { unmounted() {
this.$events.off('on-subtask-edited') this.$events.off('on-subtask-edited');
this.$events.off('on-subtask-deleted') this.$events.off('on-subtask-deleted');
this.$events.off('on-mastertask-edited') this.$events.off('on-mastertask-edited');
this.$events.off('on-mastertask-deleted') this.$events.off('on-mastertask-deleted');
}, },
methods: { methods: {
onSearch: debounce(async function (search, reset = true) { onSearch: debounce(async function (search, reset = true) {
try { try {
if (reset) if (reset) this.searchResults = null;
this.searchResults = null
const { mastertasks, subtasks, teams} = await this.$axios.get_auth(`v1/search?q=${search}`) const { mastertasks, subtasks, teams } = await this.$axios.get_auth(
this.searchResults = {mastertasks: mastertasks.data, subtasks: subtasks.data, teams: teams.data} `v1/search?q=${search}`,
);
this.searchResults = {
mastertasks: mastertasks.data,
subtasks: subtasks.data,
teams: teams.data,
};
} catch (error) { } catch (error) {
this.$toast.error(this.$parseError(error)) this.$toast.error(this.$parseError(error));
if (process.env.NODE_ENV === 'development') if (process.env.NODE_ENV === 'development')
console.log('[serach.vue] Error: ', error) console.log('[serach.vue] Error: ', error);
this.searchResults = {error} this.searchResults = { error };
}
}, 300)
}
} }
}, 300),
},
};
</script> </script>
<style lang="sass" scoped> <style lang="sass" scoped>