feat: save datatable filters & options
parent
fb3a7f1b97
commit
6ae66dd274
|
|
@ -1,7 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { VDataTable } from 'vuetify/labs/VDataTable'
|
||||
import { useDataTableStore } from '@/stores/datatable.store'
|
||||
|
||||
const { t } = useI18n()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const headers = computed(() => [
|
||||
{ title: 'ID', key: 'id_structure' },
|
||||
|
|
@ -30,8 +34,6 @@ const { data: dtListData } = await useApi<any>(createUrl('/stores'))
|
|||
|
||||
storesList.value = dtListData.value
|
||||
|
||||
const options = ref({ page: 1, itemsPerPage: 10, sortBy: [''], sortDesc: [false] })
|
||||
|
||||
const country = computed(() => {
|
||||
const allItems = storesList.value.map((store: { pays: any }) => store.pays)
|
||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||
|
|
@ -68,9 +70,11 @@ const filteredData = computed(() => {
|
|||
if (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)
|
||||
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)
|
||||
filtered = filtered.filter((store: { nbcaisses: any }) => store.nbcaisses === selectedNbPos.value)
|
||||
|
||||
|
|
@ -121,6 +125,48 @@ const reloadStores = async () => {
|
|||
|
||||
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>
|
||||
|
||||
<template>
|
||||
|
|
@ -196,6 +242,7 @@ const reloadStores = async () => {
|
|||
:placeholder="$t('Search')"
|
||||
density="compact"
|
||||
style="inline-size: 200px;"
|
||||
type="text"
|
||||
class="me-3"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -220,20 +267,27 @@ const reloadStores = async () => {
|
|||
color="primary"
|
||||
/>
|
||||
</div>
|
||||
<!-- 👉 Datatable -->
|
||||
<!-- 👉 Datatable https://vuetifyjs.com/en/api/v-data-table/#props -->
|
||||
<VDataTable
|
||||
v-else
|
||||
:headers="headers"
|
||||
:items="filteredData"
|
||||
:items-per-page="options.itemsPerPage"
|
||||
:page="options.page"
|
||||
:options="options"
|
||||
:items-per-page="stStoreList.itemsPerPage"
|
||||
:page="stStoreList.currentPage"
|
||||
: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 -->
|
||||
<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 }}
|
||||
</RouterLink>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<!-- 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