From e2530762859924a4ef21b8301ca197a0287bd018 Mon Sep 17 00:00:00 2001 From: Nathan Chapman Date: Fri, 22 Nov 2024 09:34:43 -0700 Subject: [PATCH] Add contact infinite pagination --- lib/send_it/marketing.ex | 8 +++- lib/send_it_web/components/core_components.ex | 3 +- lib/send_it_web/live/contact_live/index.ex | 45 ++++++++++++++++++- .../live/contact_live/index.html.heex | 5 +++ 4 files changed, 57 insertions(+), 4 deletions(-) diff --git a/lib/send_it/marketing.ex b/lib/send_it/marketing.ex index 1f80e0e..81e0c86 100644 --- a/lib/send_it/marketing.ex +++ b/lib/send_it/marketing.ex @@ -17,8 +17,12 @@ defmodule SendIt.Marketing do [%Contact{}, ...] """ - def list_contacts do - Repo.all(Contact) + def list_contacts(opts \\ [offset: 0, limit: 20]) do + Repo.all( + from c in Contact, + offset: ^opts[:offset], + limit: ^opts[:limit] + ) end def list_subscribed_contacts do diff --git a/lib/send_it_web/components/core_components.ex b/lib/send_it_web/components/core_components.ex index c172692..d0dd614 100644 --- a/lib/send_it_web/components/core_components.ex +++ b/lib/send_it_web/components/core_components.ex @@ -436,6 +436,7 @@ defmodule SendItWeb.CoreComponents do end slot :action, doc: "the slot for showing user actions in the last table column" + attr :rest, :global, doc: "the arbitrary HTML attributes to add to a table" def table(assigns) do assigns = @@ -453,7 +454,7 @@ defmodule SendItWeb.CoreComponents do - + assign(page: 1, per_page: 20) + |> paginate_contacts(1)} end @impl true @@ -38,4 +41,44 @@ defmodule SendItWeb.ContactLive.Index do {:noreply, stream_delete(socket, :contacts, contact)} end + + def handle_event("next-page", _, socket) do + IO.puts("NEXT Pageee") + {:noreply, paginate_contacts(socket, socket.assigns.page + 1)} + end + + def handle_event("prev-page", %{"_overran" => true}, socket) do + {:noreply, paginate_contacts(socket, 1)} + end + + def handle_event("prev-page", _, socket) do + if socket.assigns.page > 1 do + {:noreply, paginate_contacts(socket, socket.assigns.page - 1)} + else + {:noreply, socket} + end + end + + defp paginate_contacts(socket, new_page) when new_page >= 1 do + %{per_page: per_page, page: cur_page} = socket.assigns + contacts = Marketing.list_contacts(offset: (new_page - 1) * per_page, limit: per_page) + + {contacts, at, limit} = + if new_page >= cur_page do + {contacts, -1, per_page * 3 * -1} + else + {Enum.reverse(contacts), 0, per_page * 3} + end + + case contacts do + [] -> + assign(socket, end_of_timeline?: at == -1) + + [_ | _] = contacts -> + socket + |> assign(end_of_timeline?: false) + |> assign(:page, new_page) + |> stream(:contacts, contacts, at: at, limit: limit) + end + end end diff --git a/lib/send_it_web/live/contact_live/index.html.heex b/lib/send_it_web/live/contact_live/index.html.heex index 9d5bdff..71c4869 100644 --- a/lib/send_it_web/live/contact_live/index.html.heex +++ b/lib/send_it_web/live/contact_live/index.html.heex @@ -11,6 +11,9 @@ id="contacts" rows={@streams.contacts} row_click={fn {_id, contact} -> JS.navigate(~p"/contacts/#{contact}") end} + phx-viewport-top={@page > 1 && "prev-page"} + phx-viewport-bottom={!@end_of_timeline? && "next-page"} + phx-page-loading > <:col :let={{_id, contact}} label="Name"><%= contact.name %> <:col :let={{_id, contact}} label="Email"><%= contact.email %> @@ -25,6 +28,8 @@ +

No more contacts!

+ <.modal :if={@live_action in [:new]} id="contact-modal" show on_cancel={JS.patch(~p"/contacts")}> <.live_component module={SendItWeb.ContactLive.FormComponent}