Packages

phoenix_kit

1.7.21
1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib phoenix_kit_web components user_dashboard_nav.ex
Raw

lib/phoenix_kit_web/components/user_dashboard_nav.ex

defmodule PhoenixKitWeb.Components.UserDashboardNav do
@moduledoc """
User dashboard navigation components for the PhoenixKit user dashboard.
Provides navigation elements specifically for user dashboard pages.
"""
use PhoenixKitWeb, :html
alias PhoenixKit.Modules.Languages
alias PhoenixKit.Modules.Languages.DialectMapper
alias PhoenixKit.Users.Auth.Scope
alias PhoenixKit.Utils.Routes
@doc """
Renders user dropdown for dashboard 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 user_dropdown(assigns) do
user = Scope.user(assigns.scope)
avatar_file_id = user && user.custom_fields && user.custom_fields["avatar_file_id"]
assigns =
assigns
|> assign(:avatar_file_id, avatar_file_id)
|> assign(:user, user)
~H"""
<%= if @scope && PhoenixKit.Users.Auth.Scope.authenticated?(@scope) do %>
<div class="dropdown dropdown-end">
<div
tabindex="0"
role="button"
class="w-10 h-10 rounded-lg bg-primary flex items-center justify-center text-primary-content font-bold cursor-pointer hover:opacity-80 transition-opacity overflow-hidden"
>
<%= if @avatar_file_id do %>
<% avatar_url = PhoenixKit.Modules.Storage.URLSigner.signed_url(@avatar_file_id, "medium") %>
<img
src={avatar_url}
alt="Avatar"
class="w-full h-full object-cover"
onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';"
/>
<div class="hidden w-full h-full bg-primary flex items-center justify-center text-primary-content font-bold">
{String.first(@user.email || "?") |> String.upcase()}
</div>
<% else %>
{String.first(PhoenixKit.Users.Auth.Scope.user_email(@scope) || "?") |> String.upcase()}
<% end %>
</div>
<ul
tabindex="0"
class="dropdown-content menu bg-base-100 rounded-box z-[60] w-64 p-2 shadow-xl border border-base-300 mt-3"
>
<li class="menu-title px-4 py-2">
<div class="flex flex-col gap-1">
<span class="text-sm font-medium text-base-content truncate">
{PhoenixKit.Users.Auth.Scope.user_email(@scope)}
</span>
</div>
</li>
<div class="divider my-0"></div>
<li>
<a
href={PhoenixKit.Utils.Routes.path("/dashboard", locale: @current_locale)}
class={"flex items-center gap-3" <> if(active_path?(assigns[:current_path], "/dashboard"), do: " bg-primary text-primary-content", else: "")}
>
<.icon name="hero-home" class="w-4 h-4" />
<span>Dashboard</span>
</a>
</li>
<li>
<a
href={PhoenixKit.Utils.Routes.path("/dashboard/settings", locale: @current_locale)}
class={"flex items-center gap-3" <> if(active_path?(assigns[:current_path], "/dashboard/settings"), do: " bg-primary text-primary-content", else: "")}
>
<.icon name="hero-cog-6-tooth" class="w-4 h-4" />
<span>Settings</span>
</a>
</li>
<li>
<div class="menu-title px-4 py-1">
<span class="text-xs">Theme</span>
</div>
</li>
<li>
<label class="flex items-center justify-between px-3 py-2 cursor-pointer">
<!-- Text area -->
<span class="text-sm">
Dark Mode
</span>
<!-- Icon area with checkbox -->
<div class="swap swap-rotate swap-flip">
<input
type="checkbox"
class="theme-controller"
value="dark"
/>
<.icon name="hero-sun" class="swap-off w-4 h-4" />
<.icon name="hero-moon" class="swap-on w-4 h-4" />
</div>
</label>
</li>
<% user_languages = get_user_languages() %>
<%= if length(user_languages) > 1 do %>
<div class="divider my-0"></div>
<li class="menu-title px-4 py-1">
<span class="text-xs">Language</span>
</li>
<%= for language <- user_languages do %>
<li>
<a
href={generate_language_switch_url(@current_path, language["code"])}
class={[
"flex items-center gap-3",
if(language["code"] == @current_locale, do: "active", else: "")
]}
>
<span class="text-lg">{get_language_flag(language["code"])}</span>
<span>{language["name"]}</span>
<%= if language["code"] == @current_locale do %>
<PhoenixKitWeb.Components.Core.Icons.icon_check class="w-4 h-4 ml-auto" />
<% end %>
</a>
</li>
<% end %>
<% end %>
<div class="divider my-0"></div>
<li>
<.link
navigate="/users/log-out"
method="delete"
class="flex items-center gap-3 text-error hover:bg-error hover:text-error-content"
>
<.icon name="hero-arrow-right-on-rectangle" class="w-4 h-4" />
<span>Log Out</span>
</.link>
</li>
</ul>
</div>
<% else %>
<.link
navigate="/users/log-in"
class="btn btn-primary btn-sm"
>
Login
</.link>
<% end %>
"""
end
# Helper function to get user languages from Languages module
# Returns enabled languages or falls back to English if module is disabled
defp get_user_languages do
# Get enabled languages from the Languages module
languages =
if Languages.enabled?() do
Languages.get_enabled_languages()
else
# Fallback to English when module is disabled
[%{"code" => "en-US", "name" => "English (United States)", "is_enabled" => true}]
end
# Map to expected format
languages
|> Enum.map(fn lang ->
case Languages.get_predefined_language(lang["code"]) do
%{name: name, flag: flag, native: native} ->
%{"code" => lang["code"], "name" => name, "flag" => flag, "native" => native}
nil ->
%{
"code" => lang["code"],
"name" => String.upcase(lang["code"]),
"flag" => "🌐",
"native" => ""
}
end
end)
end
# Helper function to get language flag emoji
defp get_language_flag(code) when is_binary(code) do
case Languages.get_predefined_language(code) do
%{flag: flag} -> flag
nil -> "🌐"
end
end
# Check if current path matches the given path
defp active_path?(current_path, path) when is_binary(current_path) and is_binary(path) do
# Remove PhoenixKit prefix if present
normalized_path = remove_phoenix_kit_prefix(current_path)
# Remove locale prefix if present
clean_path = remove_locale_prefix(normalized_path)
# Check for exact match or ends with path
clean_path == path or String.ends_with?(clean_path, path)
end
defp active_path?(_, _), do: false
# Remove PhoenixKit prefix
defp remove_phoenix_kit_prefix(path) do
url_prefix = PhoenixKit.Config.get_url_prefix()
if url_prefix == "/" do
path
else
String.replace_prefix(path, url_prefix, "")
end
end
# Remove locale prefix
defp remove_locale_prefix(path) do
case String.split(path, "/", parts: 3) do
["", locale, rest] when locale != "" and rest != "" ->
if looks_like_locale?(locale), do: "/" <> rest, else: path
["", locale] ->
if looks_like_locale?(locale), do: "/", else: path
_ ->
path
end
end
# Check if it looks like a locale code
defp looks_like_locale?(locale) do
String.length(locale) <= 6 and String.match?(locale, ~r/^[a-z]{2}(-[A-Z]{2})?$/)
end
# Legacy helper - kept for backward compatibility
defp generate_language_switch_url(current_path, new_locale) do
base_code = DialectMapper.extract_base(new_locale)
# Extract the path without locale and regenerate with new locale
url_prefix = PhoenixKit.Config.get_url_prefix()
base_prefix = if url_prefix === "/", do: "", else: url_prefix
# Remove prefix and locale from current_path
clean_path =
current_path
|> String.replace_prefix(base_prefix, "")
|> remove_locale_from_path()
# Generate new path with the new locale
Routes.path(clean_path, locale: base_code)
end
# Remove locale from path
defp remove_locale_from_path(path) do
case String.split(path, "/", trim: true) do
[segment | rest] when byte_size(segment) in [2, 5] ->
# Check if segment looks like a locale
if String.length(segment) == 2 or
(String.length(segment) == 5 and String.contains?(segment, "-")) do
"/" <> Path.join(rest)
else
path
end
_ ->
path
end
end
end