import {Fetch, UseFetcher, useFetcher} from '..' import {Dispatch, SetStateAction, useCallback, useState} from 'react' export interface Paginate { data: T[] totalSize: number } export type OrderBy = 'desc' | 'asc'; export interface ISearch { limit: number offset: number orderBy?: OrderBy sortBy?: keyof T } export interface UsePaginate { list?: Paginate, error?: E fetching: boolean, fetch: Fetch<(...args: any[]) => Promise>> filters: S, updateFilters: (_: SetStateAction, params?: UpdateFiltersParams) => void, setEntity: Dispatch | undefined>>, clearFilters: () => void, pageNumber: number initialFilters: S clearCache: () => void } export interface UpdateFiltersParams { preserveOffset?: boolean } const defaultFilters: ISearch = {offset: 0, limit: 10,} export const usePaginate = ( fetcher: (search: S) => Promise>, initialFilters: S, mapError: (_: any) => E = _ => _ ): UsePaginate => { const [filters, setFilters] = useState({...defaultFilters, ...initialFilters}) const {entity: list, error, loading: fetching, fetch, setEntity, clearCache} = useFetcher(fetcher, undefined, mapError) const updateFilters = useCallback((update: SetStateAction, {preserveOffset}: UpdateFiltersParams = {}) => { setFilters(mutableFilters => { const previous = {...mutableFilters} const updatedFilters = typeof update === 'function' ? update(mutableFilters) : update if (!preserveOffset && previous.offset === updatedFilters.offset && previous.limit === updatedFilters.limit) { updatedFilters.offset = 0 } return updatedFilters }) }, []) const clearFilters = useCallback(() => updateFilters(initialFilters), []) return { list, error, fetching, fetch: (args: {force?: boolean, clean?: boolean} = {}) => fetch(args, filters), filters, pageNumber: filters.offset / filters.limit, updateFilters, clearFilters, initialFilters, setEntity, clearCache, } }