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"
|
||||
require_atomic? false
|
||||
accept [:include_joining_cycle, :default_membership_fee_type_id]
|
||||
|
||||
change Mv.Membership.Setting.Changes.NormalizeDefaultFeeTypeId
|
||||
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(:settings, settings)
|
||||
|> assign(:membership_fee_types, membership_fee_types)
|
||||
|> assign(:selected_fee_type_id, settings.default_membership_fee_type_id)
|
||||
|> assign(:include_joining_cycle, settings.include_joining_cycle)
|
||||
|> assign(:changeset, to_form(%{}, as: :settings))}
|
||||
|> assign_form()}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("validate", %{"settings" => params}, socket) do
|
||||
changeset =
|
||||
%{}
|
||||
|> validate_settings(params)
|
||||
|> to_form(as: :settings)
|
||||
|
||||
{:noreply, assign(socket, changeset: changeset)}
|
||||
{:noreply, assign(socket, form: AshPhoenix.Form.validate(socket.assigns.form, params))}
|
||||
end
|
||||
|
||||
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} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, gettext("Settings saved successfully."))
|
||||
|> assign(:settings, updated_settings)
|
||||
|> assign(:selected_fee_type_id, updated_settings.default_membership_fee_type_id)
|
||||
|> assign(:include_joining_cycle, updated_settings.include_joining_cycle)
|
||||
|> assign(:changeset, to_form(%{}, as: :settings))}
|
||||
|> put_flash(:info, gettext("Settings saved successfully."))
|
||||
|> assign_form()}
|
||||
|
||||
{:error, changeset} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:error, gettext("Failed to save settings. Please check the errors below."))
|
||||
|> assign(:changeset, to_form(changeset, as: :settings))}
|
||||
{:error, form} ->
|
||||
{:noreply, assign(socket, form: form)}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -80,7 +68,7 @@ defmodule MvWeb.MembershipFeeSettingsLive do
|
|||
</h2>
|
||||
|
||||
<.form
|
||||
for={@changeset}
|
||||
for={@form}
|
||||
phx-change="validate"
|
||||
phx-submit="save"
|
||||
class="space-y-6"
|
||||
|
|
@ -95,7 +83,10 @@ defmodule MvWeb.MembershipFeeSettingsLive do
|
|||
<select
|
||||
id="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"
|
||||
aria-label={gettext("Default Membership Fee Type")}
|
||||
>
|
||||
|
|
@ -103,13 +94,16 @@ defmodule MvWeb.MembershipFeeSettingsLive do
|
|||
<option
|
||||
:for={fee_type <- @membership_fee_types}
|
||||
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.interval
|
||||
)})
|
||||
</option>
|
||||
</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">
|
||||
{gettext(
|
||||
"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"
|
||||
name="settings[include_joining_cycle]"
|
||||
class="checkbox checkbox-primary"
|
||||
checked={@include_joining_cycle}
|
||||
checked={@form[:include_joining_cycle].value}
|
||||
phx-debounce="blur"
|
||||
/>
|
||||
<span class="label-text font-semibold">
|
||||
{gettext("Include joining cycle")}
|
||||
</span>
|
||||
</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">
|
||||
<p class="text-sm text-base-content/60">
|
||||
{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(:yearly), do: gettext("Yearly")
|
||||
|
||||
defp validate_settings(attrs, params) do
|
||||
attrs
|
||||
|> Map.merge(params)
|
||||
|> validate_default_fee_type()
|
||||
end
|
||||
defp assign_form(%{assigns: %{settings: settings}} = socket) do
|
||||
form =
|
||||
AshPhoenix.Form.for_update(
|
||||
settings,
|
||||
:update_membership_fee_settings,
|
||||
api: Membership,
|
||||
as: "settings",
|
||||
forms: [auto?: true]
|
||||
)
|
||||
|
||||
defp validate_default_fee_type(%{"default_membership_fee_type_id" => ""} = attrs) do
|
||||
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()
|
||||
assign(socket, form: to_form(form))
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue