Packages

phoenix_kit

1.7.21
1.7.210 1.7.209 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 live users user_details.ex
Raw

lib/phoenix_kit_web/live/users/user_details.ex

defmodule PhoenixKitWeb.Live.Users.UserDetails do
@moduledoc """
LiveView for displaying detailed user information.
Displays user profile information in a tabbed interface with:
- Profile tab: Basic info, status, roles, registration details
- Connections tab: Follower/following/connection stats (if enabled)
- Notes tab: Admin notes about the user
"""
use PhoenixKitWeb, :live_view
use Gettext, backend: PhoenixKitWeb.Gettext
alias PhoenixKit.Modules.Connections
alias PhoenixKit.Settings
alias PhoenixKit.Users.AdminNote
alias PhoenixKit.Users.Auth
alias PhoenixKit.Users.CustomFields
alias PhoenixKit.Utils.Date, as: UtilsDate
alias PhoenixKit.Utils.Routes
@impl true
def mount(%{"id" => user_id}, _session, socket) do
project_title = Settings.get_setting("project_title", "PhoenixKit")
user_id_int =
case Integer.parse(user_id) do
{id, _} -> id
:error -> nil
end
user = if user_id_int, do: Auth.get_user_with_roles(user_id_int), else: nil
case user do
nil ->
{:ok,
socket
|> put_flash(:error, gettext("User not found"))
|> push_navigate(to: Routes.path("/admin/users"))}
user ->
custom_field_definitions = CustomFields.list_field_definitions()
# Load connections stats if module is enabled
connections_enabled = Connections.enabled?()
connections_stats =
if connections_enabled do
%{
followers: Connections.followers_count(user),
following: Connections.following_count(user),
connections: Connections.connections_count(user),
pending: Connections.pending_requests_count(user),
blocked: length(Connections.list_blocked(user))
}
else
nil
end
# Load admin notes
admin_notes = Auth.list_admin_notes(user)
socket =
socket
|> assign(:user, user)
|> assign(:page_title, user_display_name(user))
|> assign(:project_title, project_title)
|> assign(:active_tab, "profile")
|> assign(:custom_field_definitions, custom_field_definitions)
|> assign(:show_delete_modal, false)
|> assign(:connections_enabled, connections_enabled)
|> assign(:connections_stats, connections_stats)
|> assign(:admin_notes, admin_notes)
|> assign(:note_form, to_form(Auth.change_admin_note(%AdminNote{})))
|> assign(:editing_note_id, nil)
{:ok, socket}
end
end
@impl true
def handle_event("change_tab", %{"tab" => tab}, socket) do
{:noreply, assign(socket, :active_tab, tab)}
end
@impl true
def handle_event("show_delete_modal", _params, socket) do
{:noreply, assign(socket, :show_delete_modal, true)}
end
@impl true
def handle_event("hide_delete_modal", _params, socket) do
{:noreply, assign(socket, :show_delete_modal, false)}
end
@impl true
def handle_event("delete_user", _params, socket) do
# User deletion not yet implemented in Auth API
{:noreply,
socket
|> assign(:show_delete_modal, false)
|> put_flash(:error, gettext("User deletion is not yet implemented"))}
end
# Admin Notes Events
@impl true
def handle_event("add_note", %{"admin_note" => note_params}, socket) do
current_user = socket.assigns.phoenix_kit_current_scope.user
user = socket.assigns.user
case Auth.create_admin_note(user, current_user, note_params) do
{:ok, _note} ->
admin_notes = Auth.list_admin_notes(user)
{:noreply,
socket
|> assign(:admin_notes, admin_notes)
|> assign(:note_form, to_form(Auth.change_admin_note(%AdminNote{})))
|> put_flash(:info, gettext("Note added successfully"))}
{:error, changeset} ->
{:noreply, assign(socket, :note_form, to_form(changeset))}
end
end
@impl true
def handle_event("edit_note", %{"id" => note_id}, socket) do
note_id = String.to_integer(note_id)
note = Enum.find(socket.assigns.admin_notes, &(&1.id == note_id))
if note do
changeset = Auth.change_admin_note(note)
{:noreply,
socket
|> assign(:editing_note_id, note_id)
|> assign(:note_form, to_form(changeset))}
else
{:noreply, socket}
end
end
@impl true
def handle_event("cancel_edit", _params, socket) do
{:noreply,
socket
|> assign(:editing_note_id, nil)
|> assign(:note_form, to_form(Auth.change_admin_note(%AdminNote{})))}
end
@impl true
def handle_event("update_note", %{"admin_note" => note_params}, socket) do
note_id = socket.assigns.editing_note_id
note = Enum.find(socket.assigns.admin_notes, &(&1.id == note_id))
if note do
case Auth.update_admin_note(note, note_params) do
{:ok, _note} ->
admin_notes = Auth.list_admin_notes(socket.assigns.user)
{:noreply,
socket
|> assign(:admin_notes, admin_notes)
|> assign(:editing_note_id, nil)
|> assign(:note_form, to_form(Auth.change_admin_note(%AdminNote{})))
|> put_flash(:info, gettext("Note updated successfully"))}
{:error, changeset} ->
{:noreply, assign(socket, :note_form, to_form(changeset))}
end
else
{:noreply, socket}
end
end
@impl true
def handle_event("delete_note", %{"id" => note_id}, socket) do
note_id = String.to_integer(note_id)
note = Enum.find(socket.assigns.admin_notes, &(&1.id == note_id))
if note do
case Auth.delete_admin_note(note) do
{:ok, _} ->
admin_notes = Auth.list_admin_notes(socket.assigns.user)
{:noreply,
socket
|> assign(:admin_notes, admin_notes)
|> put_flash(:info, gettext("Note deleted successfully"))}
{:error, _} ->
{:noreply, put_flash(socket, :error, gettext("Failed to delete note"))}
end
else
{:noreply, socket}
end
end
defp user_display_name(user) do
cond do
user.first_name && user.last_name ->
"#{user.first_name} #{user.last_name}"
user.first_name ->
user.first_name
user.username ->
user.username
true ->
user.email
end
end
defp format_location(user) do
[user.registration_city, user.registration_region, user.registration_country]
|> Enum.filter(&(&1 && &1 != ""))
|> Enum.join(", ")
|> case do
"" -> nil
location -> location
end
end
defp format_timezone(nil), do: "Not set"
defp format_timezone(offset) when is_binary(offset) do
case Integer.parse(offset) do
{num, _} -> format_timezone_offset(num)
:error -> offset
end
end
defp format_timezone(offset) when is_integer(offset), do: format_timezone_offset(offset)
defp format_timezone_offset(offset) do
sign = if offset >= 0, do: "+", else: ""
"UTC#{sign}#{offset}"
end
defp get_custom_field_value(user, field_key) do
case user.custom_fields do
nil -> nil
fields -> Map.get(fields, field_key)
end
end
defp format_custom_field_value(nil, _type), do: "-"
defp format_custom_field_value("", _type), do: "-"
defp format_custom_field_value(value, "boolean") do
case value do
true -> gettext("Yes")
"true" -> gettext("Yes")
false -> gettext("No")
"false" -> gettext("No")
_ -> to_string(value)
end
end
defp format_custom_field_value(value, _type), do: to_string(value)
end