Skip to content

Commit be31535

Browse files
feat: pagination
1 parent 858a797 commit be31535

2 files changed

Lines changed: 103 additions & 25 deletions

File tree

lib/yearbook/entries.ex

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,40 @@ defmodule Yearbook.Entries do
3434
Repo.all(query)
3535
end
3636

37+
@doc """
38+
Returns a paginated map of pending entries based on the provided parameters.
39+
40+
## Examples
41+
iex> list_pending_entries_pagination(%{"page" => "1"})
42+
%{entries: [%Entry{}, ...], total_pages: 3, current_page: 1}
43+
"""
44+
def list_pending_entries_pagination(params \\ %{}) do
45+
Entry
46+
|> where([e], e.status == :pending)
47+
|> order_by([e], desc: e.inserted_at)
48+
|> paginate(params)
49+
end
50+
51+
defp paginate(query, params) do
52+
page = String.to_integer(params["page"] || "1")
53+
per_page = 10
54+
55+
entries =
56+
query
57+
|> limit(^per_page)
58+
|> offset(^((page - 1) * per_page))
59+
|> Repo.all()
60+
61+
total_entries = Repo.aggregate(query, :count)
62+
total_pages = max(1, ceil(total_entries / per_page))
63+
64+
%{
65+
entries: entries,
66+
total_pages: total_pages,
67+
current_page: page
68+
}
69+
end
70+
3771
@doc """
3872
Gets a single entry.
3973

lib/yearbook_web/live/backoffice/mock_live/index.ex

Lines changed: 69 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,51 @@ defmodule YearbookWeb.Approvals do
66
alias Yearbook.Entries
77

88
def mount(_params, _session, socket) do
9-
entries = Entries.list_pending_entries()
9+
{:ok, assign(socket, selected_entry: nil)}
10+
end
11+
12+
def handle_params(params, _url, socket) do
13+
data = Entries.list_pending_entries_pagination(params)
1014

11-
{:ok,
15+
{:noreply,
1216
socket
13-
|> assign(current_page: :request_approvals)
14-
|> assign(entries: entries)
15-
|> assign(selected_entry: nil)}
17+
|> assign(entries: data.entries)
18+
|> assign(current_page_num: data.current_page)
19+
|> assign(total_pages: data.total_pages)
20+
|> assign(params: params)
21+
|> assign(current_page: :request_approvals)}
1622
end
1723

1824
def handle_event("approve", %{"id" => id}, socket) do
19-
entry = Yearbook.Entries.get_entry!(id)
25+
entry = Entries.get_entry!(id)
2026

21-
case Yearbook.Entries.update_entry(entry, %{status: :accepted}) do
22-
{:ok, _updated_entry} ->
23-
new_entries = Yearbook.Entries.list_pending_entries()
27+
case Entries.update_entry(entry, %{status: :accepted}) do
28+
{:ok, _} ->
29+
data = Entries.list_pending_entries_pagination(socket.assigns.params)
2430

25-
{:noreply, assign(socket, entries: new_entries)}
31+
{:noreply,
32+
socket
33+
|> put_flash(:info, "Entry approved successfully.")
34+
|> assign_pagination_data(data)}
2635

27-
{:error, _changeset} ->
36+
{:error, _} ->
2837
{:noreply, put_flash(socket, :error, "Error approving entry.")}
2938
end
3039
end
3140

3241
def handle_event("deny", %{"id" => id}, socket) do
33-
entry = Yearbook.Entries.get_entry!(id)
42+
entry = Entries.get_entry!(id)
43+
44+
case Entries.update_entry(entry, %{status: :denied}) do
45+
{:ok, _} ->
46+
data = Entries.list_pending_entries_pagination(socket.assigns.params)
3447

35-
case Yearbook.Entries.update_entry(entry, %{status: :denied}) do
36-
{:ok, _updated_entry} ->
37-
new_entries = Yearbook.Entries.list_pending_entries()
38-
{:noreply, assign(socket, entries: new_entries)}
48+
{:noreply,
49+
socket
50+
|> put_flash(:info, "Entry denied successfully.")
51+
|> assign_pagination_data(data)}
3952

40-
{:error, _changeset} ->
53+
{:error, _} ->
4154
{:noreply, put_flash(socket, :error, "Error denying entry.")}
4255
end
4356
end
@@ -51,40 +64,47 @@ defmodule YearbookWeb.Approvals do
5164
{:noreply, assign(socket, selected_entry: nil)}
5265
end
5366

67+
defp assign_pagination_data(socket, data) do
68+
assign(socket,
69+
entries: data.entries,
70+
current_page_num: data.current_page,
71+
total_pages: data.total_pages
72+
)
73+
end
74+
5475
def render(assigns) do
5576
~H"""
56-
<div class="flex-1 p-8 bg-white rounded-2xl">
77+
<div class="flex-1 p-7 bg-white rounded-2xl">
5778
<h2 class="text-xl font-semibold mb-6 text-gray-700">Request Approvals</h2>
5879
5980
<div class="space-y-1">
6081
<%= for entry <- @entries do %>
61-
<div class="flex items-center border-2 border-gray-500 rounded-md p-4 ">
82+
<div class="flex items-center border-2 border-gray-500 rounded-md p-4 mb-2">
6283
<div class="flex items-center gap-12 flex-1 min-w-0">
63-
<span class=" text-gray-900 w-64 shrink-0">{entry.name}</span>
84+
<span class="text-gray-900 w-64 shrink-0 font-medium">{entry.name}</span>
6485
<span class="text-gray-900 truncate pr-4 max-w-4xl">{entry.text}</span>
6586
</div>
6687
6788
<div class="ml-auto flex flex-row items-center gap-8">
6889
<button
6990
phx-click="show_details"
7091
phx-value-id={entry.id}
71-
class="border-2 border-gray-500 px-2 py-1 rounded text-sm bg-gray-100"
92+
class="border-2 border-gray-500 px-2 py-1 rounded text-sm bg-gray-100 cursor-pointer"
7293
>
7394
Ver Detalhes
7495
</button>
7596
<div class="flex items-center gap-2">
7697
<button
7798
phx-click="approve"
7899
phx-value-id={entry.id}
79-
class="text-green-400 hover:text-green-600"
100+
class="text-green-400 hover:text-green-600 cursor-pointer"
80101
>
81102
<.icon name="hero-check" class="size-8" />
82103
</button>
83-
84104
<button
85105
phx-click="deny"
86106
phx-value-id={entry.id}
87-
class="text-red-400 hover:text-red-600"
107+
class="text-red-400 hover:text-red-600 cursor-pointer"
88108
>
89109
<.icon name="hero-x-mark" class="size-8" />
90110
</button>
@@ -93,6 +113,30 @@ defmodule YearbookWeb.Approvals do
93113
</div>
94114
<% end %>
95115
</div>
116+
117+
<div class="mt-6 flex items-center justify-between border-t border-gray-500 pt-4">
118+
<span class="text-sm text-gray-500">
119+
Página <strong>{@current_page_num}</strong> de {@total_pages}
120+
</span>
121+
122+
<div class="flex gap-2">
123+
<.link
124+
:if={@current_page_num > 1}
125+
patch={~p"/backoffice/approvals?page=#{@current_page_num - 1}"}
126+
class=" hover:bg-gray-50 text-sm font-medium"
127+
>
128+
<.icon name="hero-chevron-left" class="size-5" />
129+
</.link>
130+
131+
<.link
132+
:if={@current_page_num < @total_pages}
133+
patch={~p"/backoffice/approvals?page=#{@current_page_num + 1}"}
134+
class=" hover:bg-gray-50 text-sm font-medium"
135+
>
136+
<.icon name="hero-chevron-right" class="size-5" />
137+
</.link>
138+
</div>
139+
</div>
96140
</div>
97141
98142
<%= if @selected_entry do %>
@@ -120,7 +164,7 @@ defmodule YearbookWeb.Approvals do
120164
121165
<div class="mb-6">
122166
<label class="text-xs font-bold uppercase text-gray-500 tracking-wider">
123-
Quote
167+
Frase
124168
</label>
125169
<p class="text-gray-800 font-semibold mt-1">
126170
"{@selected_entry.text}"

0 commit comments

Comments
 (0)