diff --git a/lib/towerops_web/live/user_settings_live.ex b/lib/towerops_web/live/user_settings_live.ex index a45ee32b..1d255f4c 100644 --- a/lib/towerops_web/live/user_settings_live.ex +++ b/lib/towerops_web/live/user_settings_live.ex @@ -19,7 +19,6 @@ defmodule ToweropsWeb.UserSettingsLive do socket = socket |> assign(:page_title, "Account Settings") - |> assign(:active_tab, "personal") |> assign(:current_token, current_token) |> assign_changesets() |> assign_profile_form() @@ -50,8 +49,20 @@ defmodule ToweropsWeb.UserSettingsLive do end @impl true - def handle_event("switch_tab", %{"tab" => tab}, socket) do - {:noreply, assign(socket, :active_tab, tab)} + def handle_params(params, _url, socket) do + # Default to "personal" tab if no tab param is provided + tab = Map.get(params, "tab", "personal") + + # Get page from params, default to 1 + page = params |> Map.get("page", "1") |> String.to_integer() + + socket = + socket + |> assign(:active_tab, tab) + |> assign(:login_history_page, page) + |> assign_login_history() + + {:noreply, socket} end @impl true @@ -302,18 +313,6 @@ defmodule ToweropsWeb.UserSettingsLive do {:noreply, socket} end - @impl true - def handle_event("load_more_history", _params, socket) do - next_page = socket.assigns.login_history_page + 1 - - socket = - socket - |> assign(:login_history_page, next_page) - |> assign_login_history() - - {:noreply, socket} - end - # Security tab - TOTP Device Management @impl true @@ -497,15 +496,24 @@ defmodule ToweropsWeb.UserSettingsLive do defp assign_login_history(socket) do user = socket.assigns.current_scope.user page = socket.assigns[:login_history_page] || 1 - limit = 20 - offset = (page - 1) * limit + per_page = 5 + offset = (page - 1) * per_page - history = Accounts.list_user_login_history(user.id, limit: limit, offset: offset) - has_more = length(history) == limit + # Get total count and history for current page + total_count = Accounts.count_user_login_attempts(user.id) + history = Accounts.list_user_login_history(user.id, limit: per_page, offset: offset) + + total_pages = ceil(total_count / per_page) + page = max(1, min(page, max(1, total_pages))) socket |> assign(:login_history, history) - |> assign(:has_more_history, has_more) + |> assign(:login_history_pagination, %{ + page: page, + per_page: per_page, + total_count: total_count, + total_pages: total_pages + }) end defp assign_security_alerts(socket) do @@ -599,6 +607,28 @@ defmodule ToweropsWeb.UserSettingsLive do end end + # Generate pagination range with ellipsis for large page counts + # Shows: [1] ... [4] [5] [6] ... [20] when on page 5 of 20 + defp pagination_range(current_page, total_pages) do + cond do + total_pages <= 7 -> + # Show all pages if 7 or fewer + Enum.to_list(1..total_pages) + + current_page <= 4 -> + # Near the start + [1, 2, 3, 4, 5, :ellipsis, total_pages] + + current_page >= total_pages - 3 -> + # Near the end + [1, :ellipsis, total_pages - 4, total_pages - 3, total_pages - 2, total_pages - 1, total_pages] + + true -> + # In the middle + [1, :ellipsis, current_page - 1, current_page, current_page + 1, :ellipsis, total_pages] + end + end + @impl true def render(assigns) do ~H""" @@ -622,10 +652,8 @@ defmodule ToweropsWeb.UserSettingsLive do class="flex min-w-full flex-none gap-x-6 px-4 text-sm/6 font-semibold text-gray-500 sm:px-6 lg:px-8 dark:text-gray-400" >
  • - Personal - +
  • - Account - +
  • - Sessions - +
  • - API - +
  • - Notifications - +
  • - Security - +
  • <.link @@ -1389,15 +1407,104 @@ defmodule ToweropsWeb.UserSettingsLive do - <%= if @has_more_history do %> -
    - + <%= if @login_history_pagination.total_pages > 1 do %> +
    + +
    + <.link + :if={@login_history_pagination.page > 1} + patch={ + ~p"/users/settings?tab=#{@active_tab}&page=#{@login_history_pagination.page - 1}" + } + class="relative inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 dark:border-white/10 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700" + > + Previous + + <.link + :if={@login_history_pagination.page < @login_history_pagination.total_pages} + patch={ + ~p"/users/settings?tab=#{@active_tab}&page=#{@login_history_pagination.page + 1}" + } + class="relative ml-3 inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 dark:border-white/10 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700" + > + Next + +
    + + +
    <% end %> <% end %>