<%= 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">…</span> <span class="visually-hidden" role="img" aria-label="ellipses">…</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>