Add contact infinite pagination

This commit is contained in:
Nathan Chapman 2024-11-22 09:34:43 -07:00
parent 35b9fab724
commit e253076285
4 changed files with 57 additions and 4 deletions

View File

@ -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

View File

@ -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
</th>
</tr>
</thead>
<tbody id={@id} phx-update={match?(%Phoenix.LiveView.LiveStream{}, @rows) && "stream"}>
<tbody id={@id} phx-update={match?(%Phoenix.LiveView.LiveStream{}, @rows) && "stream"} {@rest}>
<tr :for={row <- @rows} id={@row_id && @row_id.(row)}>
<td
:for={{col, i} <- Enum.with_index(@col)}

View File

@ -6,7 +6,10 @@ defmodule SendItWeb.ContactLive.Index do
@impl true
def mount(_params, _session, socket) do
{:ok, stream(socket, :contacts, Marketing.list_contacts())}
{:ok,
socket
|> 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

View File

@ -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>
<:col :let={{_id, contact}} label="Email"><%= contact.email %></:col>
@ -25,6 +28,8 @@
</:action>
</.table>
<h3 :if={@end_of_timeline?}>No more contacts!</h3>
<.modal :if={@live_action in [:new]} id="contact-modal" show on_cancel={JS.patch(~p"/contacts")}>
<.live_component
module={SendItWeb.ContactLive.FormComponent}