Packages
phoenix_kit
1.7.102
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
Current section
Files
lib/modules/referrals/web/form.ex
defmodule PhoenixKit.Modules.Referrals.Web.Form do
@moduledoc """
Referral code form LiveView for PhoenixKit admin panel.
Provides form interface for creating and editing user referral codes.
"""
use PhoenixKitWeb, :live_view
require Logger
alias PhoenixKit.Modules.Referrals
alias PhoenixKit.Settings
alias PhoenixKit.Users.Auth
alias PhoenixKit.Utils.Routes
def mount(params, _session, socket) do
code_uuid = params["code_uuid"]
mode = if code_uuid, do: :edit, else: :new
# Get project title from settings
project_title = Settings.get_project_title()
socket =
socket
|> assign(:mode, mode)
|> assign(:code_uuid, code_uuid)
|> assign(:page_title, page_title(mode))
|> assign(:project_title, project_title)
|> assign(:search_results, [])
|> assign(:selected_beneficiary, nil)
|> load_code_data(mode, code_uuid)
|> load_form_data()
{:ok, socket}
end
def handle_params(_params, uri, socket) do
{:noreply, assign(socket, :url_path, URI.parse(uri).path)}
end
def handle_event("validate_code", params, socket) do
# Extract referrals params (matches form name from changeset)
code_params = Map.get(params, "referrals", %{})
# Add beneficiary if selected (dual-write both integer and UUID)
updated_params =
case socket.assigns.selected_beneficiary do
nil ->
code_params
beneficiary ->
code_params
|> Map.put("beneficiary_uuid", beneficiary.uuid)
end
# Create changeset for validation
changeset =
case socket.assigns.mode do
:new -> Referrals.changeset(%Referrals{}, updated_params)
:edit -> Referrals.changeset(socket.assigns.code, updated_params)
end
|> Map.put(:action, :validate)
socket =
socket
|> assign(:changeset, changeset)
{:noreply, socket}
end
def handle_event("save_code", params, socket) do
# Extract referrals params (matches form name from changeset)
code_params = Map.get(params, "referrals", %{})
# Ensure beneficiary is included if selected (dual-write both integer and UUID)
updated_code_params =
case socket.assigns.selected_beneficiary do
nil ->
code_params
beneficiary ->
code_params
|> Map.put("beneficiary_uuid", beneficiary.uuid)
end
case socket.assigns.mode do
:new -> create_code(socket, updated_code_params)
:edit -> update_code(socket, updated_code_params)
end
end
def handle_event("generate_code", _params, socket) do
random_code = Referrals.generate_random_code()
# Get current changeset changes and add the generated code
current_changes = socket.assigns.changeset.changes
updated_changes = Map.put(current_changes, :code, random_code)
# Add beneficiary if selected
final_changes =
case socket.assigns.selected_beneficiary do
nil ->
updated_changes
beneficiary ->
updated_changes
|> Map.put(:beneficiary_uuid, beneficiary.uuid)
end
changeset =
case socket.assigns.mode do
:new -> Referrals.changeset(%Referrals{}, final_changes)
:edit -> Referrals.changeset(socket.assigns.code, final_changes)
end
socket =
socket
|> assign(:changeset, changeset)
{:noreply, socket}
end
def handle_event("search_beneficiary", %{"search" => search_term}, socket) do
search_results =
if String.length(search_term) >= 2 do
Auth.search_users(search_term)
else
[]
end
socket =
socket
|> assign(:search_results, search_results)
{:noreply, socket}
end
def handle_event("select_beneficiary", %{"user_uuid" => user_uuid}, socket) do
# Find the selected user from search results
selected_user =
Enum.find(socket.assigns.search_results, fn user ->
user.uuid == user_uuid
end)
# Update the changeset with the selected beneficiary, preserving other changes
current_changes = socket.assigns.changeset.changes
updated_changes =
current_changes
|> Map.put(:beneficiary_uuid, if(selected_user, do: selected_user.uuid))
changeset =
case socket.assigns.mode do
:new -> Referrals.changeset(%Referrals{}, updated_changes)
:edit -> Referrals.changeset(socket.assigns.code, updated_changes)
end
socket =
socket
|> assign(:changeset, changeset)
|> assign(:selected_beneficiary, selected_user)
|> assign(:search_results, [])
{:noreply, socket}
end
def handle_event("clear_beneficiary", _params, socket) do
# Clear the beneficiary selection while preserving other changes
current_changes = socket.assigns.changeset.changes
updated_changes = Map.delete(current_changes, :beneficiary)
changeset =
case socket.assigns.mode do
:new -> Referrals.changeset(%Referrals{}, updated_changes)
:edit -> Referrals.changeset(socket.assigns.code, updated_changes)
end
socket =
socket
|> assign(:changeset, changeset)
|> assign(:selected_beneficiary, nil)
|> assign(:search_results, [])
{:noreply, socket}
end
def handle_event("cancel", _params, socket) do
{:noreply, push_navigate(socket, to: Routes.path("/admin/users/referral-codes"))}
end
# Private functions
defp load_code_data(socket, :new, _code_uuid) do
assign(socket, :code, nil)
end
defp load_code_data(socket, :edit, code_uuid) do
code = Referrals.get_code!(code_uuid)
assign(socket, :code, code)
end
defp load_form_data(socket) do
code = socket.assigns.code || %Referrals{}
# For new codes, initialize with empty changeset
# For edit mode, initialize changeset with current code data to pre-populate form
initial_params =
case socket.assigns.mode do
:new ->
%{}
:edit ->
%{
"code" => code.code,
"description" => code.description,
"max_uses" => code.max_uses,
"expiration_date" => code.expiration_date,
"status" => code.status
}
end
changeset = Referrals.changeset(code, initial_params)
# Load selected beneficiary if editing existing code with beneficiary UUID
selected_beneficiary =
case code.beneficiary_uuid do
nil -> nil
beneficiary_uuid -> Auth.get_user_for_selection(beneficiary_uuid)
end
socket
|> assign(:changeset, changeset)
|> assign(:selected_beneficiary, selected_beneficiary)
end
defp create_code(socket, code_params) do
{code_params_with_creator, user_uuid} = extract_user_info(socket, code_params)
socket
|> create_code_with_validation(code_params_with_creator, user_uuid)
|> then(&{:noreply, &1})
end
defp extract_user_info(socket, code_params) do
case socket.assigns.phoenix_kit_current_user do
user when not is_nil(user) ->
params =
code_params
|> Map.put("created_by_uuid", user.uuid)
{params, user.uuid}
_ ->
extract_user_from_scope(socket, code_params)
end
end
defp extract_user_from_scope(socket, code_params) do
case socket.assigns do
%{phoenix_kit_current_scope: %{user_uuid: user_uuid}} when not is_nil(user_uuid) ->
params =
code_params
|> Map.put("created_by_uuid", user_uuid)
{params, user_uuid}
_ ->
Logger.warning("Socket assigns when current_user is nil: #{inspect(socket.assigns)}")
{code_params, nil}
end
end
defp create_code_with_validation(socket, code_params_with_creator, user_uuid) do
case validate_user_limit(user_uuid) do
{:ok, :valid} -> do_create_code(socket, code_params_with_creator)
{:error, limit_message} -> put_flash(socket, :error, limit_message)
nil -> do_create_code(socket, code_params_with_creator)
end
end
defp validate_user_limit(nil), do: nil
defp validate_user_limit(user_uuid), do: Referrals.validate_user_code_limit(user_uuid)
defp do_create_code(socket, code_params_with_creator) do
case Referrals.create_code(code_params_with_creator) do
{:ok, _code} ->
socket
|> put_flash(:info, "Referral code created successfully!")
|> push_navigate(to: Routes.path("/admin/users/referral-codes"))
{:error, changeset} ->
socket
|> assign(:changeset, changeset)
|> put_flash(:error, "Failed to create referral code. Please check the errors below.")
end
end
defp update_code(socket, code_params) do
case Referrals.update_code(socket.assigns.code, code_params) do
{:ok, _code} ->
socket
|> put_flash(:info, "Referral code updated successfully!")
|> push_navigate(to: Routes.path("/admin/users/referral-codes"))
{:error, changeset} ->
socket
|> assign(:changeset, changeset)
|> put_flash(:error, "Failed to update referral code. Please check the errors below.")
end
|> then(&{:noreply, &1})
end
defp page_title(:new), do: "New Referral Code"
defp page_title(:edit), do: "Edit Referral Code"
end