bones73k/lib/bones73k_web/live/user_management/index.html.leex

196 lines
7 KiB
Text
Raw Normal View History

<%= if @live_action in [:new, :edit] do %>
<%= live_modal @socket, Bones73kWeb.UserManagement.FormComponent,
id: @user.id || :new,
title: @page_title,
action: @live_action,
user: @user,
current_user: @current_user %>
<% end %>
<h2 class="mb-3">
<%= icon_div @socket, "bi-people", [class: "icon baseline"] %>
Listing Users
</h2>
<%# filtering and new item creation %>
<div class="d-flex flex-column flex-sm-row justify-content-between d-flex align-items-start">
<%= live_patch to: Routes.user_management_index_path(@socket, :new, Enum.into(@query, [])),
class: "btn btn-primary mb-2" do %>
<%= icon_div @socket, "bi-person-plus", [class: "icon baseline me-1"] %>
New User
<% end %>
<%= form_for :filter, "#", [phx_change: "filter-change"], fn flt -> %>
<div class="input-group mb-2">
<span class="input-group-text">
<%= icon_div @socket, "bi-filter", [class: "icon"] %>
</span>
<%= text_input flt, :filter, name: "filter", class: "form-control", placeholder: "Filter users...", value: @query.filter %>
</button>
<%= if @query.filter == "" do %>
<button class="btn btn-outline-secondary" type="button" aria-label="Clear filter" aria-disabled="true" disabled>
<% else %>
<button class="btn btn-outline-secondary" type="button" aria-label="Clear filter" phx-click="filter-clear">
<% end %>
<%= icon_div @socket, "bi-backspace", [class: "icon baseline"], [role: "img", aria_hidden: false] %>
</button>
</div>
<% end %>
</div>
<%# main data table %>
<table class="table">
<thead>
<tr class="<%= @table_loading && "loading" || "" %>">
<th scope="col" phx-click="sort-change" phx-value-sort_by="email" class="cursor-pointer">
Email
<%= if @query.sort_by == "email", do: icon_div @socket,
(@query.sort_order == "desc" && "bi-sort-up-alt" || "bi-sort-down-alt"),
[class: "icon baseline ms-1"]
%>
</th>
<th scope="col" phx-click="sort-change" phx-value-sort_by="role" class="cursor-pointer">
Role
<%= if @query.sort_by == "role", do: icon_div @socket,
(@query.sort_order == "desc" && "bi-sort-up-alt" || "bi-sort-down-alt"),
[class: "icon baseline ms-1"]
%>
</th>
<th scope="col" phx-click="sort-change" phx-value-sort_by="inserted_at" class="cursor-pointer">
Created at
<%= if @query.sort_by == "inserted_at", do: icon_div @socket,
(@query.sort_order == "desc" && "bi-sort-up-alt" || "bi-sort-down-alt"),
[class: "icon baseline ms-1"]
%>
</th>
<th scope="col">Confirmed?</th>
<th></th>
</tr>
</thead>
<tbody id="users">
<%= for user <- @page.entries do %>
<tr id="user-<%= user.id %>">
<td class="align-middle"><%= user.email %></td>
<td class="align-middle"><%= user.role |> Atom.to_string() |> String.capitalize() %></td>
<td class="align-middle" style="white-space: nowrap;"><%= dt_out(user.inserted_at) %></td>
<td class="align-middle">
<%= if user.confirmed_at do %>
<span class="visually-hidden">Yes</span>
<%= icon_div @socket, "bi-check", [class: "icon baseline fs-4 text-success"], [role: "img", aria_hidden: false] %>
<% else %>
<span class="visually-hidden">No</span>
<%= icon_div @socket, "bi-x", [class: "icon baseline fs-4 text-warning"], [role: "img", aria_hidden: false] %>
<% end %>
</td>
<td class="align-middle text-end">
<%= live_patch to: Routes.user_management_index_path(@socket, :edit, user.id, Enum.into(@query, [])), class: "btn btn-outline-primary btn-sm" do %>
<%= icon_div @socket, "bi-pencil", [class: "icon baseline", style: "margin-right:0.125rem;"] %>
Edit
<% end %>
<%= if Roles.can?(@current_user, user, :delete) do %>
<%= link to: "#",
phx_click: "delete",
phx_value_id: user.id,
phx_value_email: user.email,
data: [confirm: "Are you sure you want to delete this user? \"#{user.email}\""],
class: "btn btn-outline-danger btn-sm" do %>
<%= icon_div @socket, "bi-trash", [class: "icon baseline", style: "margin-right:0.125rem;"] %>
Delete
<% end %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
<%# pagination interface %>
<div class="d-flex justify-content-between d-flex align-items-start">
<%# items per page selector %>
<div class="d-flex align-items-center">
<%= form_for :page_size, "#", [phx_change: "page-size-change"], fn pgsz -> %>
<%= select pgsz, :page_size,
[10, 15, 20, 30, 50, 100] |> Enum.map(fn n -> {"#{n} per page", n} end),
value: @query.page_size,
id: "table_page_size_page_size",
name: "page_size",
class: "form-select"
%>
<% end %>
<span class="ms-2"><%= @page.total_entries %> found</span>
</div>
<%# main pagination %>
<nav aria-label="User list page navigation">
<ul class="pagination mb-0">
<%# previous page button %>
<% icon = icon_div @socket, "bi-chevron-left", [class: "icon baseline"] %>
<%= if @page.page_number == 1 do %>
<li class="page-item disabled">
<span class="page-link" aria-hidden="true"><%= icon %></span>
<span class="visually-hidden">Previous</span>
<% else %>
<li class="page-item">
<a class="page-link" href="#" aria-label="Previous" phx-value-page_number="<%= @page.page_number - 1 %>" phx-click="page-change"><%= icon %></a>
<% end %>
</li>
<%# page buttons %>
<%= for page_num <- generate_page_list(@page.page_number, @page.total_pages) do %>
<%= cond do %>
<%= page_num < 1 -> %>
<li class="page-item disabled">
<span class="page-link" aria-hidden="true">&hellip;</span>
<span class="visually-hidden" role="img" aria-label="ellipses">&hellip;</span>
</li>
<%= page_num == @page.page_number -> %>
<li class="page-item active" aria-current="page">
<span class="page-link"><%= page_num %></a>
</li>
<%= true -> %>
<li class="page-item">
<a class="page-link" href="#" phx-value-page_number="<%= page_num %>" phx-click="page-change"><%= page_num %></a>
</li>
<% end %>
<% end %>
<%# next page button %>
<% icon = icon_div @socket, "bi-chevron-right", [class: "icon baseline"] %>
<%= if @page.page_number == @page.total_pages do %>
<li class="page-item disabled">
<span class="page-link" aria-hidden="true"><%= icon %></span>
<span class="visually-hidden">Next</span>
<% else %>
<li class="page-item">
<a class="page-link" href="#" aria-label="Next" phx-value-page_number="<%= @page.page_number + 1 %>" phx-click="page-change"><%= icon %></a>
<% end %>
</li>
</ul>
</nav>
</div>