Page-number arithmetic for paginated lists.
Before this module every paginated LiveView hand-rolled the same two
computations — a "parse the ?page param" private and a
ceil(total / per_page) — and they disagreed: some floored the result
at one page, most did not, which is how empty lists ended up with
total_pages: 0 and 1..total_pages became the DECREASING range
[1, 0] in page-range builders. Host apps copied the same privates into
every admin view.
Two deliberate choices, made once here so call sites stop deciding differently:
parse_page/1is loose —"2abc"parses as 2, junk and non-positives fall back to 1. That matches what every existing call site (and their tests) already did; a ?page param is navigation state, not input worth erroring on.total_pages/2floors at 1 — an empty list is one empty page, not zero pages. The pagination components already render controls only fortotal_pages > 1, so the floor changes no UI. A site that wants a sentinel "nothing loaded" state (e.g. an invalid scope) assigns its literal0itself, deliberately.
Summary
Functions
The page number carried by a ?page param: a positive integer, or 1.
How many pages total_count items make at per_page per page — at
least 1.
Functions
@spec parse_page(term()) :: pos_integer()
The page number carried by a ?page param: a positive integer, or 1.
Accepts what params actually arrive as — binaries, integers (LiveView
event payloads), nil when absent — and never raises.
iex> PhoenixKit.Utils.Pagination.parse_page("3")
3
iex> PhoenixKit.Utils.Pagination.parse_page("0")
1
iex> PhoenixKit.Utils.Pagination.parse_page(nil)
1
@spec total_pages(integer(), pos_integer()) :: pos_integer()
How many pages total_count items make at per_page per page — at
least 1.
Integer arithmetic throughout; a negative total_count counts as 0.
Raises on per_page < 1, which is a caller bug, not data.
iex> PhoenixKit.Utils.Pagination.total_pages(51, 25)
3
iex> PhoenixKit.Utils.Pagination.total_pages(0, 25)
1