37 lines
1.4 KiB
TypeScript
37 lines
1.4 KiB
TypeScript
import { useState } from "react"
|
|
|
|
import { PaginationMeta } from "@/types/common"
|
|
|
|
/**
|
|
* Pages an already-loaded list in the browser, producing the same `PaginationMeta` shape the
|
|
* server-paged lists use so it plugs straight into `PaginationFooter`.
|
|
*
|
|
* `resetKey` (e.g. the selected date) sends the list back to page 1 when it changes. It's a key
|
|
* rather than the array itself because callers often pass `data ?? []`, a new array every render.
|
|
*/
|
|
export function useClientPagination<T>(rows: T[], resetKey: unknown, initialPageSize = 10) {
|
|
const [page, setPage] = useState(1)
|
|
const [pageSize, setPageSizeState] = useState(initialPageSize)
|
|
const [prevKey, setPrevKey] = useState(resetKey)
|
|
|
|
// Reset during render (React's "adjust state when a prop changes" pattern) — no effect needed.
|
|
if (!Object.is(prevKey, resetKey)) {
|
|
setPrevKey(resetKey)
|
|
setPage(1)
|
|
}
|
|
|
|
const totalItems = rows.length
|
|
const totalPages = Math.max(1, Math.ceil(totalItems / pageSize))
|
|
// Clamped, so shrinking the list (or a bigger page size) never leaves an empty page showing.
|
|
const current = Math.min(page, totalPages)
|
|
const pageRows = rows.slice((current - 1) * pageSize, current * pageSize)
|
|
const pagination: PaginationMeta = { page: current, pageSize, totalItems, totalPages }
|
|
|
|
function setPageSize(size: number) {
|
|
setPageSizeState(size)
|
|
setPage(1)
|
|
}
|
|
|
|
return { pageRows, pagination, setPage, setPageSize }
|
|
}
|