import { router } from '@inertiajs/vue3'; import { useDebounceFn } from '@vueuse/core'; import { ref, watch } from 'vue'; import type {WatchSource} from 'vue'; import type { DataTableQuery, DataTableSort } from '@/types/data-table'; type UseDataTableQueryOptions = { url: string; initial: DataTableQuery; filterKeys?: string[]; debounceMs?: number; only?: string[]; }; function buildParams(query: DataTableQuery, filterKeys: string[]): Record { const params: Record = { search: query.search || undefined, sort: query.sort || undefined, direction: query.direction || undefined, }; for (const key of filterKeys) { params[key] = query[key] || undefined; } return params; } export function useDataTableQuery(options: UseDataTableQueryOptions) { const filterKeys = options.filterKeys ?? []; const query = ref({ ...options.initial }); const isLoading = ref(false); const reload = useDebounceFn(() => { router.get(options.url, buildParams(query.value, filterKeys), { preserveState: true, replace: true, preserveScroll: true, showProgress: false, only: options.only, onBefore: () => { isLoading.value = true; }, onFinish: () => { isLoading.value = false; }, }); }, options.debounceMs ?? 300); function setSearch(value: string): void { query.value.search = value; reload(); } function setSort(sort: DataTableSort | null): void { query.value.sort = sort?.column; query.value.direction = sort?.direction; reload(); } function setFilter(key: string, value: string): void { query.value[key] = value; reload(); } function resetFilters(): void { for (const key of filterKeys) { query.value[key] = ''; } reload(); } function syncFromServer(filters: DataTableQuery): void { query.value = { ...filters }; } return { query, isLoading, setSearch, setSort, setFilter, resetFilters, reload, syncFromServer, }; } export function useDataTableQuerySync( filters: WatchSource, syncFromServer: (filters: DataTableQuery) => void, ): void { watch(filters, (value) => { syncFromServer(value); }); }