vikunja-frontend/src/composables/useRouteFilters.ts

71 lines
1.6 KiB
TypeScript
Raw Normal View History

2022-10-19 14:48:26 +00:00
import {computed, ref, watch, type Ref} from 'vue'
import {useRouter, type RouteLocationNormalized, type RouteLocationRaw} from 'vue-router'
2022-10-24 13:51:50 +00:00
import equal from 'fast-deep-equal/es6'
export type Filters = Record<string, any>
export function useRouteFilters<CurrentFilters extends Filters>(
2022-11-09 13:27:26 +00:00
route: Ref<RouteLocationNormalized>,
getDefaultFilters: (route: RouteLocationNormalized) => CurrentFilters,
routeToFilters: (route: RouteLocationNormalized) => CurrentFilters,
filtersToRoute: (filters: CurrentFilters) => RouteLocationRaw,
) {
const router = useRouter()
const filters = ref<CurrentFilters>(routeToFilters(route.value))
2022-10-19 14:48:26 +00:00
const routeFromFiltersFullPath = computed(() => router.resolve(filtersToRoute(filters.value)).fullPath)
2022-11-09 17:33:06 +00:00
watch(
route,
(route, oldRoute) => {
if (
route?.name !== oldRoute?.name ||
routeFromFiltersFullPath.value === route.fullPath
) {
return
}
2022-11-09 13:27:26 +00:00
2022-11-09 17:33:06 +00:00
filters.value = routeToFilters(route)
},
{
immediate: true, // set the filter from the initial route
},
)
2022-11-09 13:27:26 +00:00
watch(
filters,
async () => {
if (routeFromFiltersFullPath.value !== route.value.fullPath) {
await router.push(routeFromFiltersFullPath.value)
}
},
// only apply new route after all filters have changed in component cycle
2022-11-09 17:33:06 +00:00
{
deep: true,
flush: 'post',
},
2022-11-09 13:27:26 +00:00
)
2022-11-09 17:33:06 +00:00
const hasDefaultFilters = ref(false)
watch(
[filters, route],
([filters, route]) => {
hasDefaultFilters.value = equal(filters, getDefaultFilters(route))
},
{
deep: true,
immediate: true,
},
)
2022-10-24 13:51:50 +00:00
function setDefaultFilters() {
filters.value = getDefaultFilters(route.value)
}
2022-11-09 13:27:26 +00:00
return {
filters,
hasDefaultFilters,
setDefaultFilters,
}
}