refactor: migrate MembershipFeeSettingsLive to AshPhoenix.Form
This commit is contained in:
parent
9e441213be
commit
8cbd481709
3 changed files with 51 additions and 56 deletions
|
|
@ -95,6 +95,8 @@ defmodule Mv.Membership.Setting do
|
||||||
description "Updates the membership fee configuration"
|
description "Updates the membership fee configuration"
|
||||||
require_atomic? false
|
require_atomic? false
|
||||||
accept [:include_joining_cycle, :default_membership_fee_type_id]
|
accept [:include_joining_cycle, :default_membership_fee_type_id]
|
||||||
|
|
||||||
|
change Mv.Membership.Setting.Changes.NormalizeDefaultFeeTypeId
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
defmodule Mv.Membership.Setting.Changes.NormalizeDefaultFeeTypeId do
|
||||||
|
@moduledoc """
|
||||||
|
Ash change that normalizes empty strings to nil for default_membership_fee_type_id.
|
||||||
|
|
||||||
|
HTML forms submit empty select values as empty strings (""), but the database
|
||||||
|
expects nil for optional UUID fields. This change converts "" to nil.
|
||||||
|
"""
|
||||||
|
use Ash.Resource.Change
|
||||||
|
|
||||||
|
def change(changeset, _opts, _context) do
|
||||||
|
default_fee_type_id = Ash.Changeset.get_attribute(changeset, :default_membership_fee_type_id)
|
||||||
|
|
||||||
|
if default_fee_type_id == "" do
|
||||||
|
Ash.Changeset.force_change_attribute(changeset, :default_membership_fee_type_id, nil)
|
||||||
|
else
|
||||||
|
changeset
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -25,37 +25,25 @@ defmodule MvWeb.MembershipFeeSettingsLive do
|
||||||
|> assign(:page_title, gettext("Membership Fee Settings"))
|
|> assign(:page_title, gettext("Membership Fee Settings"))
|
||||||
|> assign(:settings, settings)
|
|> assign(:settings, settings)
|
||||||
|> assign(:membership_fee_types, membership_fee_types)
|
|> assign(:membership_fee_types, membership_fee_types)
|
||||||
|> assign(:selected_fee_type_id, settings.default_membership_fee_type_id)
|
|> assign_form()}
|
||||||
|> assign(:include_joining_cycle, settings.include_joining_cycle)
|
|
||||||
|> assign(:changeset, to_form(%{}, as: :settings))}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_event("validate", %{"settings" => params}, socket) do
|
def handle_event("validate", %{"settings" => params}, socket) do
|
||||||
changeset =
|
{:noreply, assign(socket, form: AshPhoenix.Form.validate(socket.assigns.form, params))}
|
||||||
%{}
|
|
||||||
|> validate_settings(params)
|
|
||||||
|> to_form(as: :settings)
|
|
||||||
|
|
||||||
{:noreply, assign(socket, changeset: changeset)}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("save", %{"settings" => params}, socket) do
|
def handle_event("save", %{"settings" => params}, socket) do
|
||||||
case update_settings(socket.assigns.settings, params) do
|
case AshPhoenix.Form.submit(socket.assigns.form, params: params) do
|
||||||
{:ok, updated_settings} ->
|
{:ok, updated_settings} ->
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> put_flash(:info, gettext("Settings saved successfully."))
|
|
||||||
|> assign(:settings, updated_settings)
|
|> assign(:settings, updated_settings)
|
||||||
|> assign(:selected_fee_type_id, updated_settings.default_membership_fee_type_id)
|
|> put_flash(:info, gettext("Settings saved successfully."))
|
||||||
|> assign(:include_joining_cycle, updated_settings.include_joining_cycle)
|
|> assign_form()}
|
||||||
|> assign(:changeset, to_form(%{}, as: :settings))}
|
|
||||||
|
|
||||||
{:error, changeset} ->
|
{:error, form} ->
|
||||||
{:noreply,
|
{:noreply, assign(socket, form: form)}
|
||||||
socket
|
|
||||||
|> put_flash(:error, gettext("Failed to save settings. Please check the errors below."))
|
|
||||||
|> assign(:changeset, to_form(changeset, as: :settings))}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -80,7 +68,7 @@ defmodule MvWeb.MembershipFeeSettingsLive do
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<.form
|
<.form
|
||||||
for={@changeset}
|
for={@form}
|
||||||
phx-change="validate"
|
phx-change="validate"
|
||||||
phx-submit="save"
|
phx-submit="save"
|
||||||
class="space-y-6"
|
class="space-y-6"
|
||||||
|
|
@ -95,7 +83,10 @@ defmodule MvWeb.MembershipFeeSettingsLive do
|
||||||
<select
|
<select
|
||||||
id="default_membership_fee_type_id"
|
id="default_membership_fee_type_id"
|
||||||
name="settings[default_membership_fee_type_id]"
|
name="settings[default_membership_fee_type_id]"
|
||||||
class="select select-bordered w-full"
|
class={[
|
||||||
|
"select select-bordered w-full",
|
||||||
|
if(@form.errors[:default_membership_fee_type_id], do: "select-error", else: "")
|
||||||
|
]}
|
||||||
phx-debounce="blur"
|
phx-debounce="blur"
|
||||||
aria-label={gettext("Default Membership Fee Type")}
|
aria-label={gettext("Default Membership Fee Type")}
|
||||||
>
|
>
|
||||||
|
|
@ -103,13 +94,16 @@ defmodule MvWeb.MembershipFeeSettingsLive do
|
||||||
<option
|
<option
|
||||||
:for={fee_type <- @membership_fee_types}
|
:for={fee_type <- @membership_fee_types}
|
||||||
value={fee_type.id}
|
value={fee_type.id}
|
||||||
selected={fee_type.id == @selected_fee_type_id}
|
selected={fee_type.id == @form[:default_membership_fee_type_id].value}
|
||||||
>
|
>
|
||||||
{fee_type.name} ({format_currency(fee_type.amount)}, {format_interval(
|
{fee_type.name} ({format_currency(fee_type.amount)}, {format_interval(
|
||||||
fee_type.interval
|
fee_type.interval
|
||||||
)})
|
)})
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
|
<%= for {msg, _opts} <- @form.errors[:default_membership_fee_type_id] || [] do %>
|
||||||
|
<p class="text-error text-sm mt-1">{msg}</p>
|
||||||
|
<% end %>
|
||||||
<p class="text-sm text-base-content/60 mt-2">
|
<p class="text-sm text-base-content/60 mt-2">
|
||||||
{gettext(
|
{gettext(
|
||||||
"This membership fee type is automatically assigned to all new members. Can be changed individually per member."
|
"This membership fee type is automatically assigned to all new members. Can be changed individually per member."
|
||||||
|
|
@ -124,13 +118,16 @@ defmodule MvWeb.MembershipFeeSettingsLive do
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
name="settings[include_joining_cycle]"
|
name="settings[include_joining_cycle]"
|
||||||
class="checkbox checkbox-primary"
|
class="checkbox checkbox-primary"
|
||||||
checked={@include_joining_cycle}
|
checked={@form[:include_joining_cycle].value}
|
||||||
phx-debounce="blur"
|
phx-debounce="blur"
|
||||||
/>
|
/>
|
||||||
<span class="label-text font-semibold">
|
<span class="label-text font-semibold">
|
||||||
{gettext("Include joining cycle")}
|
{gettext("Include joining cycle")}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
<%= for {msg, _opts} <- @form.errors[:include_joining_cycle] || [] do %>
|
||||||
|
<p class="text-error text-sm ml-9 mt-1">{msg}</p>
|
||||||
|
<% end %>
|
||||||
<div class="ml-9 space-y-2">
|
<div class="ml-9 space-y-2">
|
||||||
<p class="text-sm text-base-content/60">
|
<p class="text-sm text-base-content/60">
|
||||||
{gettext("When active: Members pay from the cycle of their joining.")}
|
{gettext("When active: Members pay from the cycle of their joining.")}
|
||||||
|
|
@ -249,39 +246,16 @@ defmodule MvWeb.MembershipFeeSettingsLive do
|
||||||
defp format_interval(:half_yearly), do: gettext("Half-yearly")
|
defp format_interval(:half_yearly), do: gettext("Half-yearly")
|
||||||
defp format_interval(:yearly), do: gettext("Yearly")
|
defp format_interval(:yearly), do: gettext("Yearly")
|
||||||
|
|
||||||
defp validate_settings(attrs, params) do
|
defp assign_form(%{assigns: %{settings: settings}} = socket) do
|
||||||
attrs
|
form =
|
||||||
|> Map.merge(params)
|
AshPhoenix.Form.for_update(
|
||||||
|> validate_default_fee_type()
|
settings,
|
||||||
end
|
:update_membership_fee_settings,
|
||||||
|
api: Membership,
|
||||||
|
as: "settings",
|
||||||
|
forms: [auto?: true]
|
||||||
|
)
|
||||||
|
|
||||||
defp validate_default_fee_type(%{"default_membership_fee_type_id" => ""} = attrs) do
|
assign(socket, form: to_form(form))
|
||||||
Map.put(attrs, "default_membership_fee_type_id", nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp validate_default_fee_type(attrs), do: attrs
|
|
||||||
|
|
||||||
defp update_settings(settings, params) do
|
|
||||||
# Convert empty string to nil for optional field
|
|
||||||
params =
|
|
||||||
if params["default_membership_fee_type_id"] == "" do
|
|
||||||
Map.put(params, "default_membership_fee_type_id", nil)
|
|
||||||
else
|
|
||||||
params
|
|
||||||
end
|
|
||||||
|
|
||||||
# Convert checkbox value to boolean
|
|
||||||
params =
|
|
||||||
Map.update(params, "include_joining_cycle", false, fn
|
|
||||||
"true" -> true
|
|
||||||
"false" -> false
|
|
||||||
true -> true
|
|
||||||
false -> false
|
|
||||||
_ -> false
|
|
||||||
end)
|
|
||||||
|
|
||||||
settings
|
|
||||||
|> Ash.Changeset.for_update(:update_membership_fee_settings, params)
|
|
||||||
|> Ash.update()
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue