defmodule PhoenixDuskmoon.Component.Pagination do @moduledoc """ Duskmoon UI Pagination Component """ use PhoenixDuskmoon.Component, :html import PhoenixDuskmoon.Component.Icons @doc """ Generates a pagination. ## Examples <.dm_pagination page_num={5} page_size={15} total={100} update_event="update-page"/> """ @doc type: :component attr(:id, :any, default: false, doc: """ html attribute id """ ) attr(:class, :any, default: "", doc: """ html attribute class """ ) attr(:page_size, :integer, default: 10, doc: """ items shows per page """ ) attr(:page_num, :integer, default: 1, doc: """ page num """ ) attr(:total, :integer, default: 0, doc: """ total items count """ ) attr(:show_total, :boolean, default: false, doc: """ whether show total items count """ ) attr(:update_event, :string, default: "update_current_page", doc: """ Phoenix live event name for page status update. """ ) attr(:page_url, :any, default: nil, doc: """ Page url. """ ) attr(:page_url_marker, :string, default: "{page}", doc: """ Marker in page url. Default is `{page}`. Replace this marker with page number. """ ) attr(:page_link_type, :string, default: "patch", values: ~w(patch navigate href), doc: """ Phoenix link type. """ ) slot(:inner_block, required: false, doc: """ Page slot """ ) def dm_pagination(assigns) do {max_page, pages} = generate_pages(assigns.total, assigns.page_size, assigns.page_num) assigns = assigns |> assign(:max_page, max_page) |> assign(:pages, pages) ~H"""
<.dm_mdi name="view-dashboard" class="w-5 h-5" /> <%= @total %>
<%= render_slot(@inner_block) %>
""" end @doc """ Generates a Pagination. Use daisyui style. ## Examples <.dm_pagination_thin page_num={5} page_size={15} total={100} update_event="update-page" loading={false} /> """ attr(:id, :any, default: false, doc: """ html attribute id """ ) attr(:class, :any, default: "", doc: """ html attribute class """ ) attr( :loading, :boolean, default: false, doc: """ when loading, disable the pagination """ ) attr( :show_page_jumper, :boolean, default: false, doc: """ show quick jumper """ ) attr(:page_size, :integer, default: 10, doc: """ items shows per page """ ) attr(:page_num, :integer, default: 1, doc: """ page num """ ) attr(:total, :integer, default: 0, doc: """ total items count """ ) attr(:show_total, :boolean, default: false, doc: """ whether show total items count """ ) attr(:update_event, :string, default: "update_current_page", doc: """ Phoenix live event name for page status update. """ ) def dm_pagination_thin(assigns) do {max_page, pages} = generate_pages(assigns.total, assigns.page_size, assigns.page_num) assigns = assigns |> assign(:max_page, max_page) |> assign(:pages, pages) ~H"""
<.dm_mdi name="view-dashboard" class="w-5 h-5" /> <%= @total %>
<.dm_mdi name="arrow-right-top" class="w-4 h-4" />
#{@max_page}){this.value=#{@max_page}}"} value={@page_num} />
""" end defp generate_pages(total, page_size, page_num) do max_page = if total > 0 do (total / page_size) |> ceil else 1 end pages = cond do max_page == 1 -> [1] max_page < 7 -> 1..max_page |> Enum.map(& &1) page_num < 3 -> [1, 2, 3] ++ ["..."] ++ [max_page - 2, max_page - 1, max_page] page_num == 3 -> [1, 2, 3, 4] ++ ["..."] ++ [max_page - 2, max_page - 1, max_page] page_num > 3 && page_num < max_page - 2 -> [1] ++ ["...", page_num - 1, page_num, page_num + 1, "..."] ++ [max_page] page_num == max_page - 2 -> [1, 2, 3] ++ ["...", max_page - 3, max_page - 2, max_page - 1, max_page] page_num > max_page - 2 -> [1, 2, 3] ++ ["...", max_page - 2, max_page - 1, max_page] end {max_page, pages} end end