86 lines
2.2 KiB
TypeScript
86 lines
2.2 KiB
TypeScript
import { router } from '@inertiajs/vue3';
|
|
import { useDebounceFn } from '@vueuse/core';
|
|
import { ref, watch, type WatchSource } from 'vue';
|
|
import type { DataTableQuery, DataTableSort } from '@/types/data-table';
|
|
|
|
type UseDataTableQueryOptions = {
|
|
url: string;
|
|
initial: DataTableQuery;
|
|
filterKeys?: string[];
|
|
debounceMs?: number;
|
|
};
|
|
|
|
function buildParams(query: DataTableQuery, filterKeys: string[]): Record<string, string | undefined> {
|
|
const params: Record<string, string | undefined> = {
|
|
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<DataTableQuery>({ ...options.initial });
|
|
|
|
const reload = useDebounceFn(() => {
|
|
router.get(options.url, buildParams(query.value, filterKeys), {
|
|
preserveState: true,
|
|
replace: true,
|
|
preserveScroll: true,
|
|
});
|
|
}, 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,
|
|
setSearch,
|
|
setSort,
|
|
setFilter,
|
|
resetFilters,
|
|
reload,
|
|
syncFromServer,
|
|
};
|
|
}
|
|
|
|
export function useDataTableQuerySync(
|
|
filters: WatchSource<DataTableQuery>,
|
|
syncFromServer: (filters: DataTableQuery) => void,
|
|
): void {
|
|
watch(filters, (value) => {
|
|
syncFromServer(value);
|
|
});
|
|
}
|