feat: implement URL state persistence for dashboard
Adds URL search params synchronization for dashboard filters and date range - Stores selected date range in URL for restoration on page reload - Removes old Filter component in favor of new implementation - Preserves filter state across page navigation This change improves user experience by maintaining dashboard state through browser navigation and page reloads.
This commit is contained in:
parent
1eb22503e6
commit
dd7b898a11
3 changed files with 67 additions and 1 deletions
|
|
@ -1,5 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { now, startOfMonth, startOfWeek } from '@internationalized/date'
|
import { now, startOfMonth, startOfWeek } from '@internationalized/date'
|
||||||
|
import { useUrlSearchParams } from '@vueuse/core'
|
||||||
|
import { safeDestr } from 'destr'
|
||||||
|
|
||||||
const emit = defineEmits(['update:dateRange'])
|
const emit = defineEmits(['update:dateRange'])
|
||||||
|
|
||||||
|
|
@ -61,6 +63,28 @@ watch(dateRange, (newValue) => {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function restoreDateRange() {
|
||||||
|
try {
|
||||||
|
const searchParams = useUrlSearchParams('history')
|
||||||
|
if (searchParams.time) {
|
||||||
|
const time = safeDestr(searchParams.time)
|
||||||
|
emit('update:dateRange', [time.startAt, time.endAt])
|
||||||
|
dateRange.value = 'custom'
|
||||||
|
nextTick(() => {
|
||||||
|
openCustomDateRange.value = false
|
||||||
|
customDateRange.value = undefined
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error('restore searchParams error', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
restoreDateRange()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { useUrlSearchParams } from '@vueuse/core'
|
||||||
|
import { safeDestr } from 'destr'
|
||||||
import { Check, ChevronsUpDown } from 'lucide-vue-next'
|
import { Check, ChevronsUpDown } from 'lucide-vue-next'
|
||||||
|
|
||||||
const emit = defineEmits(['change'])
|
const emit = defineEmits(['change'])
|
||||||
|
|
@ -18,6 +20,20 @@ onMounted(() => {
|
||||||
watch(selectedLinks, (value) => {
|
watch(selectedLinks, (value) => {
|
||||||
emit('change', 'slug', value.join(','))
|
emit('change', 'slug', value.join(','))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function restoreFilters() {
|
||||||
|
const searchParams = useUrlSearchParams('history')
|
||||||
|
if (searchParams.filters) {
|
||||||
|
const filters = safeDestr(searchParams.filters)
|
||||||
|
if (filters.slug) {
|
||||||
|
selectedLinks.value = filters.slug.split(',')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
restoreFilters()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { now } from '@internationalized/date'
|
import { now } from '@internationalized/date'
|
||||||
|
import { useUrlSearchParams } from '@vueuse/core'
|
||||||
|
import { safeDestr } from 'destr'
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
link: {
|
link: {
|
||||||
|
|
@ -8,6 +10,8 @@ defineProps({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const searchParams = useUrlSearchParams('history')
|
||||||
|
|
||||||
const time = ref({
|
const time = ref({
|
||||||
startAt: date2unix(now().subtract({ days: 7 })),
|
startAt: date2unix(now().subtract({ days: 7 })),
|
||||||
endAt: date2unix(now()),
|
endAt: date2unix(now()),
|
||||||
|
|
@ -20,6 +24,8 @@ function changeDate(dateRange) {
|
||||||
// console.log('dashboard date', new Date(time[0] * 1000), new Date(time[1] * 1000))
|
// console.log('dashboard date', new Date(time[0] * 1000), new Date(time[1] * 1000))
|
||||||
time.value.startAt = dateRange[0]
|
time.value.startAt = dateRange[0]
|
||||||
time.value.endAt = dateRange[1]
|
time.value.endAt = dateRange[1]
|
||||||
|
|
||||||
|
searchParams.time = JSON.stringify(time.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const filters = ref({})
|
const filters = ref({})
|
||||||
|
|
@ -29,7 +35,27 @@ provide('filters', filters)
|
||||||
function changeFilter(type, value) {
|
function changeFilter(type, value) {
|
||||||
console.log('changeFilter', type, value)
|
console.log('changeFilter', type, value)
|
||||||
filters.value[type] = value
|
filters.value[type] = value
|
||||||
|
|
||||||
|
searchParams.filters = JSON.stringify(filters.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function restoreSearchParams() {
|
||||||
|
try {
|
||||||
|
if (searchParams.time) {
|
||||||
|
time.value = safeDestr(searchParams.time)
|
||||||
|
}
|
||||||
|
if (searchParams.filters) {
|
||||||
|
filters.value = safeDestr(searchParams.filters)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error('restore searchParams error', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
restoreSearchParams()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -46,7 +72,7 @@ function changeFilter(type, value) {
|
||||||
</template>
|
</template>
|
||||||
<DashboardDatePicker @update:date-range="changeDate" />
|
<DashboardDatePicker @update:date-range="changeDate" />
|
||||||
</DashboardNav>
|
</DashboardNav>
|
||||||
<DashboardFilter v-if="!link" @change="changeFilter" />
|
<DashboardFilters v-if="!link" @change="changeFilter" />
|
||||||
</div>
|
</div>
|
||||||
<DashboardCounters />
|
<DashboardCounters />
|
||||||
<DashboardViews />
|
<DashboardViews />
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue