defmodule PhoenixKitWeb.AdminNav do @moduledoc """ Admin navigation components for the PhoenixKit admin panel. Provides consistent navigation elements for both desktop sidebar and mobile drawer. """ use Phoenix.Component alias Phoenix.LiveView.JS @doc """ Renders an admin navigation item with proper active state styling. ## Examples <.admin_nav_item href="/phoenix_kit/admin/dashboard" icon="dashboard" label="Dashboard" current_path="/phoenix_kit/admin/dashboard" /> <.admin_nav_item href="/phoenix_kit/admin/users" icon="users" label="Users" current_path="/phoenix_kit/admin/dashboard" mobile={true} /> """ attr :href, :string, required: true attr :icon, :string, required: true attr :label, :string, required: true attr :description, :string, default: nil attr :current_path, :string, required: true attr :mobile, :boolean, default: false attr :nested, :boolean, default: false def admin_nav_item(assigns) do active = nav_item_active?(assigns.current_path, assigns.href) assigns = assign(assigns, :active, active) ~H""" <.link href={@href} class={[ "flex items-center py-2 rounded-lg text-sm font-medium transition-colors", "hover:bg-base-200 group", if(@active, do: "bg-primary text-primary-content", else: "text-base-content hover:text-primary" ), if(@mobile, do: "w-full", else: ""), if(@nested, do: "pl-8 pr-3", else: "px-3") ]} > <%= if @nested do %>
{@label} <% else %> <.admin_nav_icon icon={@icon} active={@active} /> {@label} <% end %> """ end @doc """ Renders an icon for admin navigation items. """ attr :icon, :string, required: true attr :active, :boolean, default: false def admin_nav_icon(assigns) do ~H"""
<%= case @icon do %> <% "dashboard" -> %> <% "users" -> %> <% "roles" -> %> <% "modules" -> %> <% "settings" -> %> <% "sessions" -> %> <% "live_sessions" -> %> <% _ -> %> <% end %>
""" end @doc """ Renders theme controller for admin panel. Based on EZNews theme system with DaisyUI integration. """ attr :mobile, :boolean, default: false def admin_theme_controller(assigns) do ~H"""
""" end @doc """ Renders user information section for admin panel sidebar. Shows current user email and role information. """ attr :scope, :any, default: nil def admin_user_info(assigns) do ~H""" <%= if @scope && PhoenixKit.Users.Auth.Scope.authenticated?(@scope) do %>
{String.first(PhoenixKit.Users.Auth.Scope.user_email(@scope) || "?") |> String.upcase()}
{PhoenixKit.Users.Auth.Scope.user_email(@scope)}
<%= if PhoenixKit.Users.Auth.Scope.owner?(@scope) do %>
Owner
<% else %> <%= if PhoenixKit.Users.Auth.Scope.admin?(@scope) do %>
Admin
<% else %>
User
<% end %> <% end %>
<.link href="/phoenix_kit/users/settings" class="btn btn-ghost btn-xs flex-1" > <.link href="/phoenix_kit/users/log-out" method="delete" class="btn btn-ghost btn-xs flex-1 text-error hover:bg-error hover:text-error-content" >
<% else %>
Not authenticated
<.link href="/phoenix_kit/log_in" class="btn btn-primary btn-sm w-full"> Login
<% end %> """ end # Helper function to determine if navigation item is active defp nav_item_active?(current_path, href) do current_parts = parse_admin_path(current_path) href_parts = parse_admin_path(href) exact_match?(current_parts, href_parts) or tab_match?(current_parts, href_parts) or parent_match?(current_parts, href_parts) end # Check if paths match exactly defp exact_match?(current_parts, href_parts) do href_parts.base_path == current_parts.base_path && is_nil(href_parts.tab) && is_nil(current_parts.tab) end # Check if tab-specific paths match defp tab_match?(current_parts, href_parts) do href_parts.base_path == current_parts.base_path && href_parts.tab == current_parts.tab end # Check if parent page matches when on a tab defp parent_match?(current_parts, href_parts) do href_parts.base_path == current_parts.base_path && is_nil(href_parts.tab) && not is_nil(current_parts.tab) end # Helper function to parse admin path into components defp parse_admin_path(path) when is_binary(path) do # Remove query parameters and split path [path_part | _] = String.split(path, "?") # Normalize phoenix_kit paths base_path = path_part |> String.replace_prefix("/phoenix_kit/admin", "") |> String.replace_prefix("/phoenix_kit", "") |> case do # Default to dashboard for root "" -> "dashboard" "/" -> "dashboard" path -> String.trim_leading(path, "/") end # Extract tab parameter if present tab = if String.contains?(path, "?tab=") do path |> String.split("?tab=") |> List.last() |> String.split("&") |> List.first() else nil end %{base_path: base_path, tab: tab} end defp parse_admin_path(_), do: %{base_path: "dashboard", tab: nil} end