add pagination across all admin and shop views
All checks were successful
deploy / deploy (push) Successful in 1m38s
All checks were successful
deploy / deploy (push) Successful in 1m38s
URL-based offset pagination with ?page=N for bookmarkable pages. Admin views use push_patch, shop collection uses navigate links. Responsive on mobile with horizontal-scroll tables and stacking pagination controls. Includes dev seed script for testing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1714,4 +1714,84 @@ defmodule BerrypodWeb.ShopComponents.Product do
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
# ── Shop pagination ────────────────────────────────────────────
|
||||
|
||||
@doc """
|
||||
Renders pagination controls for the shop collection page.
|
||||
|
||||
Uses URL navigation (`<.link navigate=...>`) so pages are bookmarkable.
|
||||
|
||||
## Attributes
|
||||
|
||||
* `page` - Required. A `%Berrypod.Pagination{}` struct.
|
||||
* `base_path` - Required. The base URL path (e.g. "/collections/all").
|
||||
* `params` - Extra query params to preserve (e.g. %{"sort" => "newest"}).
|
||||
"""
|
||||
attr :page, Berrypod.Pagination, required: true
|
||||
attr :base_path, :string, required: true
|
||||
attr :params, :map, default: %{}
|
||||
|
||||
def shop_pagination(assigns) do
|
||||
assigns =
|
||||
assigns
|
||||
|> assign(:showing, Berrypod.Pagination.showing_text(assigns.page))
|
||||
|> assign(:numbers, Berrypod.Pagination.page_numbers(assigns.page))
|
||||
|
||||
~H"""
|
||||
<nav
|
||||
:if={@page.total_pages > 1}
|
||||
aria-label="Pagination"
|
||||
class="shop-pagination"
|
||||
>
|
||||
<p class="shop-pagination-showing">{@showing}</p>
|
||||
|
||||
<div class="shop-pagination-buttons">
|
||||
<.link
|
||||
:if={@page.page > 1}
|
||||
navigate={pagination_url(@base_path, @page.page - 1, @params)}
|
||||
class="shop-pagination-btn"
|
||||
aria-label="Previous page"
|
||||
>
|
||||
‹ Prev
|
||||
</.link>
|
||||
|
||||
<%= for item <- @numbers do %>
|
||||
<%= case item do %>
|
||||
<% :ellipsis -> %>
|
||||
<span class="shop-pagination-ellipsis" aria-hidden="true">…</span>
|
||||
<% n -> %>
|
||||
<.link
|
||||
navigate={pagination_url(@base_path, n, @params)}
|
||||
aria-label={"Page #{n}"}
|
||||
aria-current={n == @page.page && "page"}
|
||||
class={["shop-pagination-btn", n == @page.page && "shop-pagination-btn-active"]}
|
||||
>
|
||||
{n}
|
||||
</.link>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<.link
|
||||
:if={@page.page < @page.total_pages}
|
||||
navigate={pagination_url(@base_path, @page.page + 1, @params)}
|
||||
class="shop-pagination-btn"
|
||||
aria-label="Next page"
|
||||
>
|
||||
Next ›
|
||||
</.link>
|
||||
</div>
|
||||
</nav>
|
||||
"""
|
||||
end
|
||||
|
||||
defp pagination_url(base_path, page, params) do
|
||||
query = if page > 1, do: Map.put(params, "page", to_string(page)), else: params
|
||||
|
||||
if query == %{} do
|
||||
base_path
|
||||
else
|
||||
base_path <> "?" <> URI.encode_query(query)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user