131 lines
3.5 KiB
TypeScript
131 lines
3.5 KiB
TypeScript
import { router } from '@inertiajs/react';
|
|
import { useCallback, useEffect, useState } from 'react';
|
|
import type { PaginationState } from '@/components/data-table';
|
|
|
|
type UseServerTableOptions = {
|
|
route: () => string;
|
|
pagination: PaginationState;
|
|
filters?: Record<string, string | undefined>;
|
|
filterWithParams?: boolean;
|
|
};
|
|
|
|
export function useServerTable({
|
|
route,
|
|
pagination,
|
|
filters,
|
|
filterWithParams = true,
|
|
}: UseServerTableOptions) {
|
|
const [search, setSearch] = useState('');
|
|
const [filterOpen, setFilterOpen] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const params = new URLSearchParams(window.location.search);
|
|
if (params.has('search')) {
|
|
params.delete('search');
|
|
const cleanUrl =
|
|
window.location.pathname +
|
|
(params.toString() ? `?${params.toString()}` : '');
|
|
history.replaceState(null, '', cleanUrl);
|
|
router.get(route(), {}, { preserveState: true, replace: true });
|
|
}
|
|
}, []);
|
|
|
|
const handlePageChange = useCallback(
|
|
(page: number) => {
|
|
router.get(
|
|
route(),
|
|
{
|
|
...filters,
|
|
page,
|
|
per_page: pagination.per_page,
|
|
search,
|
|
},
|
|
{ preserveState: true, replace: true },
|
|
);
|
|
},
|
|
[route, filters, pagination.per_page, search],
|
|
);
|
|
|
|
const handlePerPageChange = useCallback(
|
|
(perPage: number) => {
|
|
router.get(
|
|
route(),
|
|
{
|
|
...filters,
|
|
page: 1,
|
|
per_page: perPage,
|
|
search,
|
|
},
|
|
{ preserveState: true, replace: true },
|
|
);
|
|
},
|
|
[route, filters, search],
|
|
);
|
|
|
|
const handleSearchChange = useCallback(
|
|
(value: string) => {
|
|
setSearch(value);
|
|
router.get(
|
|
route(),
|
|
{
|
|
...filters,
|
|
page: 1,
|
|
per_page: pagination.per_page,
|
|
search: value,
|
|
},
|
|
{ preserveState: true, replace: true },
|
|
);
|
|
},
|
|
[route, filters, pagination.per_page],
|
|
);
|
|
|
|
function applyFilter(key: string, value: string) {
|
|
const newFilters = { ...filters };
|
|
|
|
if (value === '' || value === 'all') {
|
|
delete newFilters[key];
|
|
} else {
|
|
newFilters[key] = value;
|
|
}
|
|
|
|
router.get(
|
|
route(),
|
|
filterWithParams
|
|
? {
|
|
...newFilters,
|
|
page: 1,
|
|
per_page: pagination.per_page,
|
|
search,
|
|
}
|
|
: newFilters,
|
|
{ preserveState: true, replace: true },
|
|
);
|
|
}
|
|
|
|
function clearFilters() {
|
|
router.get(
|
|
route(),
|
|
filterWithParams
|
|
? {
|
|
page: 1,
|
|
per_page: pagination.per_page,
|
|
search,
|
|
}
|
|
: {},
|
|
{ preserveState: true, replace: true },
|
|
);
|
|
setFilterOpen(false);
|
|
}
|
|
|
|
return {
|
|
search,
|
|
filterOpen,
|
|
setFilterOpen,
|
|
handlePageChange,
|
|
handlePerPageChange,
|
|
handleSearchChange,
|
|
applyFilter,
|
|
clearFilters,
|
|
};
|
|
}
|