Some checks failed
continuous-integration/drone/push Build is failing
- Complete GGZ Ecademy Nuxt.js user portal - Learning products browser and management - Member management interface - User authentication and roles - Multi-language support (NL/EN) - Vuex store for state management - Component-based architecture
208 lines
5.2 KiB
Vue
208 lines
5.2 KiB
Vue
<template>
|
|
<v-autocomplete
|
|
v-if="isNotMember()"
|
|
:items="isMemberPage ? members : learningProducts"
|
|
:item-text="isMemberPage ? 'informal_name' : 'title'"
|
|
filled
|
|
dense
|
|
id="searchbar"
|
|
rounded
|
|
:search-input.sync="search"
|
|
v-model="selected"
|
|
append-icon="icon-search"
|
|
hide-details
|
|
:placeholder="$t('general.search')"
|
|
single-line
|
|
full-width
|
|
flat
|
|
return-object
|
|
class="mx-4"
|
|
:filter="customFilter"
|
|
@focus="toDoOnFocus"
|
|
@blur="switchOverlay(false)"
|
|
@keydown="switchOverlay(true)"
|
|
@click="switchOverlay(true)"
|
|
>
|
|
<template v-slot:prepend-item v-if="prependText">
|
|
<v-list-item>
|
|
<v-list-item-title class="header-search-title pb-4">
|
|
<span class="pt-4">
|
|
{{ prependText }}
|
|
</span>
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
</template>
|
|
</v-autocomplete>
|
|
</template>
|
|
|
|
<script>
|
|
import Util from '@/util'
|
|
var Diacritics = require('diacritic')
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
search: '',
|
|
loading: false,
|
|
selected: null,
|
|
}
|
|
},
|
|
computed: {
|
|
learningProducts() {
|
|
return this.$store.getters.learningProducts.filter((p) => {
|
|
if (p.parent_id) return false
|
|
if (p.deleted_at) return false
|
|
if (!p.published) return false
|
|
return true
|
|
})
|
|
},
|
|
isMemberPage() {
|
|
return this.$route.name.includes('manager-members')
|
|
},
|
|
members() {
|
|
return this.$store.getters['members/membersFiltered']
|
|
},
|
|
hasMembers() {
|
|
return this.members?.length > 0
|
|
},
|
|
prependText() {
|
|
if (this.loading) return this.$t('general.loading')
|
|
|
|
if (this.isMemberPage) {
|
|
if (!this.hasMembers) return `No results found`
|
|
if (this.search) return `Zoeksuggesties voor '${this.search}'`
|
|
}
|
|
|
|
if (!this.$store.getters.hasLearningProducts) {
|
|
return `No results found`
|
|
}
|
|
if (this.$store.getters.hasLearningProducts && this.search) {
|
|
return `Zoeksuggesties voor '${this.search}'`
|
|
}
|
|
return null
|
|
},
|
|
},
|
|
|
|
watch: {
|
|
async selected(item) {
|
|
if (!item || !item.slug) return
|
|
|
|
const route = this.isMemberPage
|
|
? `/manager/members/${item.slug}`
|
|
: `/manager/learning/${item.slug}`
|
|
|
|
await this.$router.push(this.localePath(route))
|
|
this.$store.commit('navigation/TOGGLE_SEARCH_OVERLAY', false)
|
|
this.search = null
|
|
this.selected = null
|
|
this.loading = false
|
|
},
|
|
},
|
|
|
|
methods: {
|
|
customFilter(item, queryText, itemText) {
|
|
const textOne = Diacritics.clean(
|
|
item[!this.isMemberPage ? 'title' : 'informal_name'].toLowerCase()
|
|
)
|
|
let textTwo = ''
|
|
|
|
if (!this.isMemberPage) {
|
|
if (item.synonyms.length > 0) {
|
|
item.synonyms.forEach((s) => (textTwo += `${s.title.toLowerCase()} `))
|
|
}
|
|
}
|
|
|
|
const searchText = queryText.toLowerCase()
|
|
|
|
return (
|
|
textOne.indexOf(Diacritics.clean(searchText)) > -1 ||
|
|
textTwo.indexOf(Diacritics.clean(searchText)) > -1
|
|
)
|
|
},
|
|
async toDoOnFocus() {
|
|
if (this.isMemberPage && !this.hasMembers) {
|
|
this.$nextTick(() => this.$nuxt.$loading.start())
|
|
this.loading = true
|
|
await this.$store.dispatch('members/pullData')
|
|
await this.$nuxt.$loading.finish()
|
|
this.loading = false
|
|
}
|
|
|
|
if (!this.isMemberPage && !this.$store.getters.hasLearningProducts) {
|
|
this.$nextTick(() => this.$nuxt.$loading.start())
|
|
this.loading = true
|
|
await this.$store.dispatch('learning/pullProducts')
|
|
await this.$nuxt.$loading.finish()
|
|
this.loading = false
|
|
}
|
|
this.$store.commit('navigation/TOGGLE_SEARCH_OVERLAY', true)
|
|
},
|
|
switchOverlay(value) {
|
|
if (value == this.$store.getters.searchOverlay) return
|
|
this.$store.commit('navigation/TOGGLE_SEARCH_OVERLAY', value)
|
|
},
|
|
isNotMember() {
|
|
const roles = this.$auth.user.roles.map(({ name }) => name)
|
|
return !Util.findCommonValuesInArray(roles, ['member'])
|
|
},
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
#searchbar {
|
|
width: 400px !important;
|
|
color: var(--v-txt-base) !important;
|
|
}
|
|
|
|
.v-input >>> textarea {
|
|
color: var(--v-txt-base) !important;
|
|
}
|
|
#searchbar >>> .icon-search {
|
|
color: var(--v-txt-base) !important;
|
|
font-weight: 600;
|
|
}
|
|
#searchbar >>> .v-text-field--outlined fieldset {
|
|
color: rgba(255, 255, 255, 0);
|
|
}
|
|
#searchbar
|
|
>>> .v-select.v-select--is-menu-active
|
|
.v-input__icon--append
|
|
.v-icon {
|
|
transform: unset !important;
|
|
}
|
|
.v-list {
|
|
padding: 30px 90px 30px 100px !important;
|
|
border-radius: 0px;
|
|
}
|
|
@media only screen and (min-width: 1536px) {
|
|
.v-list {
|
|
padding: 30px 80px 30px 53px !important;
|
|
}
|
|
}
|
|
.v-list:focus {
|
|
outline: none !important;
|
|
}
|
|
.v-list >>> .v-list-item {
|
|
color: var(--v-tertiary-base) !important;
|
|
background: var(--v-primary-base) !important;
|
|
}
|
|
.v-list >>> .v-list-item__title {
|
|
font-size: 16px;
|
|
color: var(--v-tab-base);
|
|
}
|
|
|
|
.header-search-title {
|
|
pointer-events: none;
|
|
cursor: initial;
|
|
font-size: 24px !important;
|
|
height: 22px !important;
|
|
color: var(--v-txt-base) !important;
|
|
font-weight: 700;
|
|
|
|
border-bottom: 2px solid var(--v-search-base);
|
|
padding-bottom: 15px;
|
|
font-weight: 700;
|
|
}
|
|
</style>
|