feat: save datatable filters & options
parent
fb3a7f1b97
commit
6ae66dd274
|
|
@ -1,7 +1,11 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import { VDataTable } from 'vuetify/labs/VDataTable'
|
import { VDataTable } from 'vuetify/labs/VDataTable'
|
||||||
|
import { useDataTableStore } from '@/stores/datatable.store'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
const headers = computed(() => [
|
const headers = computed(() => [
|
||||||
{ title: 'ID', key: 'id_structure' },
|
{ title: 'ID', key: 'id_structure' },
|
||||||
|
|
@ -30,8 +34,6 @@ const { data: dtListData } = await useApi<any>(createUrl('/stores'))
|
||||||
|
|
||||||
storesList.value = dtListData.value
|
storesList.value = dtListData.value
|
||||||
|
|
||||||
const options = ref({ page: 1, itemsPerPage: 10, sortBy: [''], sortDesc: [false] })
|
|
||||||
|
|
||||||
const country = computed(() => {
|
const country = computed(() => {
|
||||||
const allItems = storesList.value.map((store: { pays: any }) => store.pays)
|
const allItems = storesList.value.map((store: { pays: any }) => store.pays)
|
||||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||||
|
|
@ -68,9 +70,11 @@ const filteredData = computed(() => {
|
||||||
if (selectedBrand.value)
|
if (selectedBrand.value)
|
||||||
filtered = filtered.filter((store: { enseigne: any }) => store.enseigne === selectedBrand.value)
|
filtered = filtered.filter((store: { enseigne: any }) => store.enseigne === selectedBrand.value)
|
||||||
|
|
||||||
|
// If a country is selected, filter the records for this country
|
||||||
if (selectedCountry.value)
|
if (selectedCountry.value)
|
||||||
filtered = filtered.filter((store: { pays: any }) => store.pays === selectedCountry.value)
|
filtered = filtered.filter((store: { pays: any }) => store.pays === selectedCountry.value)
|
||||||
|
|
||||||
|
// If a number of POS is selected, filter the records for this number
|
||||||
if (selectedNbPos.value)
|
if (selectedNbPos.value)
|
||||||
filtered = filtered.filter((store: { nbcaisses: any }) => store.nbcaisses === selectedNbPos.value)
|
filtered = filtered.filter((store: { nbcaisses: any }) => store.nbcaisses === selectedNbPos.value)
|
||||||
|
|
||||||
|
|
@ -121,6 +125,48 @@ const reloadStores = async () => {
|
||||||
|
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pinia store for datatable filters & options
|
||||||
|
const stStoreList = useDataTableStore()
|
||||||
|
|
||||||
|
const saveDtFilters = () => {
|
||||||
|
stStoreList.setFilters('selectedCountry', selectedCountry.value)
|
||||||
|
stStoreList.setFilters('selectedBrand', selectedBrand.value)
|
||||||
|
stStoreList.setFilters('selectedNbPos', selectedNbPos.value)
|
||||||
|
stStoreList.searchText = searchQuery.value
|
||||||
|
}
|
||||||
|
|
||||||
|
const restoreDtFilters = () => {
|
||||||
|
if (stStoreList.filters.selectedCountry)
|
||||||
|
selectedCountry.value = stStoreList.filters.selectedCountry
|
||||||
|
|
||||||
|
if (stStoreList.filters.selectedBrand)
|
||||||
|
selectedBrand.value = stStoreList.filters.selectedBrand
|
||||||
|
|
||||||
|
if (stStoreList.filters.selectedNbPos)
|
||||||
|
selectedNbPos.value = stStoreList.filters.selectedNbPos
|
||||||
|
|
||||||
|
if (stStoreList.searchText)
|
||||||
|
searchQuery.value = stStoreList.searchText
|
||||||
|
}
|
||||||
|
|
||||||
|
const navigateToStoreDetails = (item: { ip_master: string; id_structure: number }) => {
|
||||||
|
// Save datatable filters state
|
||||||
|
saveDtFilters()
|
||||||
|
|
||||||
|
// go to store details
|
||||||
|
router.push(`/store/details?dbHost=${item.ip_master}&storeId=${item.id_structure}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// Restore datatable filters state on page load
|
||||||
|
restoreDtFilters()
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(route, (to, from) => {
|
||||||
|
if (from && from.path !== '/store/details')
|
||||||
|
stStoreList.clearState()
|
||||||
|
}, { immediate: true })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -196,6 +242,7 @@ const reloadStores = async () => {
|
||||||
:placeholder="$t('Search')"
|
:placeholder="$t('Search')"
|
||||||
density="compact"
|
density="compact"
|
||||||
style="inline-size: 200px;"
|
style="inline-size: 200px;"
|
||||||
|
type="text"
|
||||||
class="me-3"
|
class="me-3"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -220,20 +267,27 @@ const reloadStores = async () => {
|
||||||
color="primary"
|
color="primary"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<!-- 👉 Datatable -->
|
<!-- 👉 Datatable https://vuetifyjs.com/en/api/v-data-table/#props -->
|
||||||
<VDataTable
|
<VDataTable
|
||||||
v-else
|
v-else
|
||||||
:headers="headers"
|
:headers="headers"
|
||||||
:items="filteredData"
|
:items="filteredData"
|
||||||
:items-per-page="options.itemsPerPage"
|
:items-per-page="stStoreList.itemsPerPage"
|
||||||
:page="options.page"
|
:page="stStoreList.currentPage"
|
||||||
:options="options"
|
:sort-by="stStoreList.getSortBy()"
|
||||||
|
@update:sort-by="sortBy => { stStoreList.setSortBy(sortBy[0]?.key) ; stStoreList.setSortOrder(sortBy[0]?.order) }"
|
||||||
|
@update:items-per-page="itemsPerPage => { stStoreList.setItemsPerPage(itemsPerPage) }"
|
||||||
|
@update:page="page => { stStoreList.setCurrentPage(page) }"
|
||||||
>
|
>
|
||||||
<!-- Store details hyperlink -->
|
<!-- Store details hyperlink -->
|
||||||
<template #item.nom="{ item }">
|
<template #item.nom="{ item }">
|
||||||
<RouterLink :to="`/store/details?dbHost=${item.ip_master}&storeId=${item.id_structure}`">
|
<a
|
||||||
|
href="#"
|
||||||
|
class="router-link"
|
||||||
|
@click.prevent="navigateToStoreDetails(item)"
|
||||||
|
>
|
||||||
{{ item.nom }}
|
{{ item.nom }}
|
||||||
</RouterLink>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- Pos count -->
|
<!-- Pos count -->
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
import type { SortItem } from '@/@core/types'
|
||||||
|
|
||||||
|
export const useDataTableStore = defineStore({
|
||||||
|
id: 'dataTable',
|
||||||
|
state: () => ({
|
||||||
|
filters: {} as Record<string, string>,
|
||||||
|
currentPage: 1,
|
||||||
|
itemsPerPage: 10,
|
||||||
|
searchText: '',
|
||||||
|
sortBy: '',
|
||||||
|
sortOrder: false,
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
clearState() {
|
||||||
|
this.filters = {} as Record<string, string>
|
||||||
|
this.currentPage = 1
|
||||||
|
this.itemsPerPage = 10
|
||||||
|
this.searchText = ''
|
||||||
|
this.sortBy = ''
|
||||||
|
this.sortOrder = false
|
||||||
|
},
|
||||||
|
setFilters(filterName: string, value: any) {
|
||||||
|
this.filters[filterName] = value
|
||||||
|
},
|
||||||
|
setCurrentPage(page: number) {
|
||||||
|
this.currentPage = page
|
||||||
|
},
|
||||||
|
setItemsPerPage(value: number) {
|
||||||
|
this.itemsPerPage = value
|
||||||
|
},
|
||||||
|
setSearchText(value: string) {
|
||||||
|
this.searchText = value
|
||||||
|
},
|
||||||
|
setSortBy(value: string) {
|
||||||
|
this.sortBy = value
|
||||||
|
},
|
||||||
|
setSortOrder(value: string) {
|
||||||
|
if (value === 'asc')
|
||||||
|
this.sortOrder = true
|
||||||
|
else
|
||||||
|
this.sortOrder = false
|
||||||
|
},
|
||||||
|
getSortBy(): SortItem[] {
|
||||||
|
return [{
|
||||||
|
key: this.sortBy,
|
||||||
|
order: this.sortOrder ? 'asc' : 'desc',
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
Loading…
Reference in New Issue