import { router } from '@inertiajs/react'; import { useCallback, useEffect, useState } from 'react'; import type { PaginationState } from '@/components/data-display'; type UseServerTableOptions = { route: () => string; pagination: PaginationState; filters?: Record; 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, }; }