<template>
<div class="search_module__form">
<nav v-if="tabs.length === 0" class="nav nav-pills flex-row">
<a
v-if="isFixedTabEnabled('vehicle')"
class="w-25 p-0 pt-2 pb-1 flex-fill text-center nav-link"
:class="{
active: tabName === 'vehicle',
highlight: highlightVehiclesTab,
}"
@click="clickTab('vehicle')"
>{{ $t('common.Véhicule') }}</a
>
<a
v-if="isFixedTabEnabled('driver')"
class="w-25 p-0 pt-2 pb-1 flex-fill text-center nav-link"
:class="{
active: tabName === 'driver',
highlight: highlightDriversTab,
}"
@click="clickTab('driver')"
>{{ $t('common.Chauffeur') }}</a
>
<a
v-if="isFixedTabEnabled('circuit')"
class="w-25 p-0 pt-2 pb-1 flex-fill text-center nav-link"
:class="{
active: tabName === 'circuit',
highlight: highlightCircuitsTab,
}"
@click="clickTab('circuit')"
>{{ $t('common.Circuit') }}</a
>
</nav>
<nav
v-if="
filteredTabs.length > 0 &&
!(filteredTabs.length === 1 && filteredTabs[0] === 'disabled')
"
v-show="!results || (showDynamicTabsOnResultView && !!results)"
class="nav nav-pills flex-row"
>
<a
v-for="tab in filteredTabs"
:key="tab.value"
class="w-25 p-0 pt-2 pb-1 flex-fill text-center nav-link"
:class="{
active: tabName === tab.value,
highlight: highlightCircuitsTab,
}"
@click="clickTab(tab.value)"
>{{ tab.label }}</a
>
</nav>
<div v-show="shouldShowList('vehicle')" class="list scrollbar">
<b-spinner
v-if="!isInitialLoadingComplete.vehicles"
class="loader"
variant="info"
style="width: 3rem; height: 3rem"
/>
<SMFormTree type="vehicle" :search-string="searchString" />
</div>
<div v-show="shouldShowList('driver')" class="list scrollbar">
<b-spinner
v-if="!isInitialLoadingComplete.drivers"
class="loader"
variant="info"
style="width: 3rem; height: 3rem"
/>
<SMFormTree type="driver" :search-string="searchString" />
</div>
<div v-show="shouldShowList('circuit')" class="list scrollbar">
<b-spinner
v-if="!isInitialLoadingComplete.circuits"
class="loader"
variant="info"
style="width: 3rem; height: 3rem"
/>
<SMFormTree type="circuit" :search-string="searchString" />
</div>
<div
v-if="isSearchModuleDatePickerEnabled()"
v-show="!results"
class="date-picker-wrapper"
>
<slot name="date-picker" :form-actions="formActions">
<SMDatePicker
ref="datePicker"
@clear="onDateClear"
@onDateSelection="onDateSelection"
/>
</slot>
</div>
<div v-if="!!$slots['search-filters']" v-show="!results">
<div v-show="showCustomFilters">
<slot name="search-filters" />
</div>
<p
class="custom_filters_toggle_text"
@click="() => (showCustomFilters = !showCustomFilters)"
>
<span v-show="showCustomFilters">{{
$t('search_module.extra_filters.not_collapsed_title')
}}</span>
<span v-show="!showCustomFilters">{{
$t('search_module.extra_filters.collapsed_title')
}}</span>
<em
class="fas"
:class="showCustomFilters ? 'fa-angle-up' : 'fa-angle-down'"
/>
</p>
</div>
<slot> </slot>
<div class="row m-0 p-0">
<div class="col-md-12 m-0 form_buttons">
<b-button
v-if="!results"
v-show="resetButton"
class="btn btn-block btn-light mt-2"
size="sm"
@click="reset"
>
{{ $t('buttons.cancel_alternative') }}
</b-button>
<slot name="search-validate-button">
<b-button
v-if="!results"
variant="primary"
class="btn btn-block btn-primary mt-2"
size="sm"
@click="validate"
>
<span v-show="!$store.state.search_module.isSearchInProgress">
{{ $t('common.Valider') }}
</span>
<span v-show="$store.state.search_module.isSearchInProgress">
<b-spinner
class="loader"
variant="info"
style="
width: 1rem;
height: 1rem;
margin: 0 auto;
display: block;
"
/>
</span>
</b-button>
</slot>
</div>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import SMDatePicker from './SMDatePicker.vue'
import SMFormTree from './SMFormTree.vue'
/**
* @todo Remove fixed tabs (use prop tabs instead)
*/
export default {
components: {
SMFormTree,
SMDatePicker,
},
inject: {
/**
* @todo Remove fixed tabs
*/
showDynamicTabsOnResultView: {
default: false,
},
/**
* Hides date picker (right validation)
*/
isSearchModuleDatePickerEnabled: {
default: () => () => true,
},
/**
* Allow us to hide some tabs (rights validations)
* Note: To define tabs, use "searchFormTabs" in SearchModule.vue instead
*/
blacklistedSearchModuleFormTabs: {
default: () => [],
},
showCustomFiltersByDefault: {
default: true,
},
},
props: {
searchString: {
type: String,
default: '',
},
/*
* True if SearchModule.view equals 'results'
*/
results: {
type: Boolean,
default: false,
},
highlightVehiclesTab: {
type: Boolean,
default: false,
},
highlightDriversTab: {
type: Boolean,
default: false,
},
highlightCircuitsTab: {
type: Boolean,
default: false,
},
tabs: {
type: Array,
default: () => [],
},
resetButton: {
type: Boolean,
default: false,
},
},
data() {
return {
tabName: '',
showCustomFilters: this.showCustomFiltersByDefault,
}
},
computed: {
...mapGetters({
vehicleCategories: 'search_module/getVehicleCategories',
isInitialLoadingComplete: 'search_module/isInitialLoadingComplete',
}),
filteredTabs() {
return this.tabs.filter((tabItem) => {
return !this.blacklistedSearchModuleFormTabs.includes(tabItem.value)
})
},
formActions() {
return {
onDateClear: () => this.onDateClear,
onDateSelection: (ranges) => this.onDateSelection(ranges),
}
},
},
mounted() {
if (
this.tabs.length > 0 &&
!(this.tabs.length === 1 && this.tabs[0] === 'disabled')
) {
this.clickTab(this.tabs[0].value || this.tabs[0])
}
//@todo: Refactor once fixed tabs are gone
if (this.tabs.length === 0) {
let type = ['vehicle', 'driver', 'circuit'].find(
(type) => !this.blacklistedSearchModuleFormTabs.includes(type)
)
if (type) {
this.clickTab(type)
}
}
},
methods: {
/**
* Blacklisted tabs will be skip (rights validations)
*/
isFixedTabEnabled(name) {
return !this.blacklistedSearchModuleFormTabs.includes(name)
},
reset() {
this.$emit('reset')
},
shouldShowList(name) {
return this.tabName == name && !this.results
},
validate() {
this.$emit('validate')
},
//Clearing the date picker in the form modules removes all the selected date-ranges
onDateClear() {
this.$store.dispatch('search_module/clearDateSelection')
},
onDateSelection(ranges) {
this.onDateClear()
ranges.forEach((range) => {
this.selectItem(null, range, 'date_range')
})
},
selectItem(e, value, type) {
this.$store.dispatch('search_module/selectItem', { value, type })
e && e.stopPropagation()
e && e.preventDefault()
},
clickTab(name) {
this.tabName = name
this.$store.dispatch('search_module/activeSearchFormTabName', name)
},
},
}
</script>
<style lang="scss">
.search_module__form {
padding: 5px;
background-color: white;
width: inherit;
}
.search_module__form .nav {
background-color: white;
}
.search_module__form .nav-pills {
cursor: pointer;
}
.search_module__form .nav-pills .nav-link {
color: var(--color-denim) !important;
cursor: pointer;
margin: 0px 3px;
}
.search_module__form .nav-pills .nav-link.active,
.search_module__form .nav-pills .show > .nav-link {
border-bottom: 4px solid var(--color-denim);
border-radius: 0;
}
.search_module__form .nav-pills .nav-link.active {
background-color: transparent;
}
.search_module__form .nav-pills .nav-link.highlight {
background-color: #0a71ac17;
}
.search_module__form a {
color: #495057;
}
.search_module__form .loader {
margin: 0 auto;
display: block;
margin-top: 10px;
}
.search_module__form .category,
.search_module__form .vehicle {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.category_icon {
color: #808080a1;
}
.search_module__form .category span {
font-size: 14px;
}
.search_module__form .list {
min-height: 250px;
max-height: 250px;
overflow-y: auto;
scrollbar-color: white;
scrollbar-width: thin;
padding: 20px 10px;
margin-bottom: 30px;
}
.custom_filters_toggle_text {
padding-top: 20px;
font: normal normal normal 12px/14px Open Sans;
letter-spacing: 0px;
color: var(--color-tundora);
cursor: pointer;
display: flex;
justify-content: center;
em {
margin-left: 5px;
font-size: 14px;
}
}
.form_buttons {
display: flex;
flex-direction: row;
justify-content: flex-end;
column-gap: 10px;
button {
max-width: 87px;
font: normal normal bold 14px/21px Open Sans;
letter-spacing: 0px;
color: #484848;
}
button.btn-primary {
font: normal normal bold 14px/21px Open Sans;
letter-spacing: 0px;
color: #ffffff;
}
}
</style>
Source