Packages

phoenix_kit

1.7.39
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 modules billing web subscription_plan_form.ex
Raw

lib/modules/billing/web/subscription_plan_form.ex

defmodule PhoenixKit.Modules.Billing.Web.SubscriptionPlanForm do
@moduledoc """
Subscription plan form LiveView for creating and editing plans.
"""
use PhoenixKitWeb, :live_view
alias PhoenixKit.Modules.Billing
alias PhoenixKit.Modules.Billing.SubscriptionPlan
alias PhoenixKit.Settings
alias PhoenixKit.Utils.Routes
@impl true
def mount(params, _session, socket) do
if Billing.enabled?() do
project_title = Settings.get_project_title()
default_currency = Settings.get_setting("billing_default_currency", "EUR")
{plan, title, mode} =
case params do
%{"id" => id} ->
case Billing.get_subscription_plan(id) do
{:ok, plan} -> {plan, "Edit Plan", :edit}
{:error, _} -> {nil, "Plan Not Found", :not_found}
end
_ ->
{%SubscriptionPlan{
currency: default_currency,
interval: "month",
interval_count: 1,
active: true
}, "Create Plan", :new}
end
if plan do
changeset = SubscriptionPlan.changeset(plan, %{})
url_path =
case mode do
:new -> Routes.path("/admin/billing/plans/new")
:edit -> Routes.path("/admin/billing/plans/#{plan.uuid}/edit")
_ -> Routes.path("/admin/billing/plans")
end
socket =
socket
|> assign(:page_title, title)
|> assign(:project_title, project_title)
|> assign(:url_path, url_path)
|> assign(:mode, mode)
|> assign(:plan, plan)
|> assign(:changeset, changeset)
|> assign(:features_input, format_features(plan.features))
|> assign(:form, to_form(changeset))
{:ok, socket}
else
{:ok,
socket
|> put_flash(:error, "Plan not found")
|> push_navigate(to: Routes.path("/admin/billing/plans"))}
end
else
{:ok,
socket
|> put_flash(:error, "Billing module is not enabled")
|> push_navigate(to: Routes.path("/admin"))}
end
end
@impl true
def handle_params(_params, _url, socket) do
{:noreply, socket}
end
@impl true
def handle_event("validate", %{"subscription_plan" => params}, socket) do
params = process_params(params, socket.assigns.features_input)
changeset =
socket.assigns.plan
|> SubscriptionPlan.changeset(params)
|> Map.put(:action, :validate)
{:noreply, assign(socket, :form, to_form(changeset))}
end
@impl true
def handle_event("update_features", %{"features" => features}, socket) do
{:noreply, assign(socket, :features_input, features)}
end
@impl true
def handle_event("save", %{"subscription_plan" => params}, socket) do
params = process_params(params, socket.assigns.features_input)
result =
case socket.assigns.mode do
:new -> Billing.create_subscription_plan(params)
:edit -> Billing.update_subscription_plan(socket.assigns.plan, params)
end
case result do
{:ok, _plan} ->
{:noreply,
socket
|> put_flash(:info, plan_saved_message(socket.assigns.mode))
|> push_navigate(to: Routes.path("/admin/billing/plans"))}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, :form, to_form(changeset))}
{:error, reason} ->
{:noreply, put_flash(socket, :error, "Failed to save plan: #{inspect(reason)}")}
end
end
defp process_params(params, features_input) do
# Parse features from textarea (one per line)
features =
features_input
|> String.split("\n")
|> Enum.map(&String.trim/1)
|> Enum.reject(&(&1 == ""))
# Parse price from string to decimal
price =
case params["price"] do
"" -> nil
nil -> nil
p when is_binary(p) -> Decimal.new(p)
p -> p
end
params
|> Map.put("features", features)
|> Map.put("price", price)
end
defp format_features(nil), do: ""
defp format_features(features) when is_list(features), do: Enum.join(features, "\n")
defp format_features(_), do: ""
defp plan_saved_message(:new), do: "Plan created successfully"
defp plan_saved_message(:edit), do: "Plan updated successfully"
def error_to_string([]), do: ""
def error_to_string(errors) when is_list(errors) do
Enum.map_join(errors, ", ", fn
{msg, opts} ->
Enum.reduce(opts, msg, fn {key, value}, acc ->
String.replace(acc, "%{#{key}}", to_string(value))
end)
msg when is_binary(msg) ->
msg
end)
end
end