"""
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
assigns =
assigns
|> assign(:dropdown_themes, ThemeConfig.dropdown_themes())
|> assign(:system_targets, ThemeConfig.slider_targets("system") |> Enum.join(","))
|> assign(:light_targets, ThemeConfig.slider_targets("light") |> Enum.join(","))
|> assign(:dark_targets, ThemeConfig.slider_targets("dark") |> Enum.join(","))
|> assign(:system_primary, ThemeConfig.slider_primary_theme("system"))
|> assign(:light_primary, ThemeConfig.slider_primary_theme("light"))
|> assign(:dark_primary, ThemeConfig.slider_primary_theme("dark"))
|> assign(:system_primary, ThemeConfig.slider_primary_theme("system"))
|> assign(:light_primary, ThemeConfig.slider_primary_theme("light"))
|> assign(:dark_primary, ThemeConfig.slider_primary_theme("dark"))
~H"""
<.icon name="hero-swatch" class="w-5 h-5" />
<%= for theme <- @dropdown_themes do %>
<% end %>
"""
end
@doc """
Renders language dropdown for top bar navigation.
Shows globe icon with dropdown menu for language selection.
"""
attr :current_path, :string, default: ""
attr :current_locale, :string, default: "en"
def admin_language_dropdown(assigns) do
# Only show if languages are enabled and there are enabled languages
if Languages.enabled?() do
enabled_languages = Languages.get_enabled_languages()
if length(enabled_languages) > 1 do
current_language =
Enum.find(enabled_languages, &(&1["code"] == assigns.current_locale)) ||
%{"code" => assigns.current_locale, "name" => String.upcase(assigns.current_locale)}
assigns =
assigns
|> assign(:enabled_languages, enabled_languages)
|> assign(:current_language, current_language)
~H"""
"""
else
~H""
end
else
~H""
end
end
@doc """
Renders user dropdown for top bar navigation.
Shows user avatar with dropdown menu containing email, role, settings and logout.
"""
attr :scope, :any, default: nil
attr :current_path, :string, default: ""
attr :current_locale, :string, default: "en"
def admin_user_dropdown(assigns) do
~H"""
<%= if @scope && PhoenixKit.Users.Auth.Scope.authenticated?(@scope) do %>
<%!-- Language Switcher --%>
<%= if Languages.enabled?() do %>
<% enabled_languages = Languages.get_enabled_languages() %>
<%= if length(enabled_languages) > 0 do %>
<% else %>
<%!-- Not Authenticated - Show Login Button --%>
<.link
href={Routes.locale_aware_path(assigns, "/users/log-in")}
class="btn btn-primary btn-sm"
>
Login
<% end %>
"""
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 %>
<% end %>
"""
end
# Helper function to determine if navigation item is active
defp nav_item_active?(current_path, href, nested) 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) or
(!nested and hierarchical_match?(current_parts, href_parts))
end
defp hierarchical_match?(current_parts, href_parts) do
String.starts_with?(current_parts.base_path, href_parts.base_path <> "/")
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, "?")
# Get dynamic prefix and normalize paths
prefix = PhoenixKit.Config.get_url_prefix()
admin_prefix = if prefix == "/", do: "/admin", else: "#{prefix}/admin"
base_path =
path_part
|> String.replace_prefix(prefix, "")
|> strip_locale_segment()
|> String.replace_prefix(admin_prefix, "")
|> String.replace_prefix("/admin", "")
|> 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}
defp strip_locale_segment(path) do
case String.split(path, "/", parts: 3) do
["", locale, rest] when rest != "" ->
if locale_candidate?(locale) do
"/" <> rest
else
path
end
_ ->
path
end
end
defp locale_candidate?(locale) do
String.length(locale) in 2..5 and Regex.match?(~r/^[a-z]{2}(?:-[A-Za-z0-9]{2,})?$/, locale)
end
# Helper function to get language flag emoji
defp get_language_flag(code) do
case code do
"en" -> "🇺🇸"
"es" -> "🇪🇸"
"fr" -> "🇫🇷"
"de" -> "🇩🇪"
"pt" -> "🇵🇹"
"it" -> "🇮🇹"
"nl" -> "🇳🇱"
"ru" -> "🇷🇺"
"zh-CN" -> "🇨🇳"
"ja" -> "🇯🇵"
_ -> "🌐"
end
end
# Helper function to generate language switch URL
defp generate_language_switch_url(current_path, new_locale) do
# Get actual enabled language codes to properly detect locale prefixes
enabled_language_codes = Languages.get_enabled_language_codes()
# Remove PhoenixKit prefix if present
normalized_path = String.replace_prefix(current_path || "", "/phoenix_kit", "")
# Remove existing locale prefix only if it matches actual language codes
clean_path =
case String.split(normalized_path, "/", parts: 3) do
["", potential_locale, rest] ->
if potential_locale in enabled_language_codes do
"/" <> rest
else
normalized_path
end
_ ->
normalized_path
end
# Build the new URL with the new locale prefix
url_prefix = PhoenixKit.Config.get_url_prefix()
base_prefix = if url_prefix == "/", do: "", else: url_prefix
"#{base_prefix}/#{new_locale}#{clean_path}"
end
end