Membership Fee 6 - UI Components & LiveViews closes #280 #304

Open
moritz wants to merge 65 commits from feature/280_membership_fee_ui into main
Showing only changes of commit 8ed9adeea0 - Show all commits

View file

@ -56,20 +56,35 @@ defmodule MvWeb.MembershipFeeTypeLive.Form do
<select
class="select select-bordered w-full"
disabled={!is_nil(@membership_fee_type)}
name="interval"
value={@form[:interval].value || ""}
name="membership_fee_type[interval]"
id="membership-fee-type-form_interval"
phx-change="validate"
>
<option value="">{gettext("Select interval")}</option>
<option value="monthly" selected={@form[:interval].value == :monthly}>
<option
value="monthly"
selected={@form[:interval].value == :monthly || @form[:interval].value == "monthly"}
>
{gettext("Monthly")}
</option>
<option value="quarterly" selected={@form[:interval].value == :quarterly}>
<option
value="quarterly"
selected={@form[:interval].value == :quarterly || @form[:interval].value == "quarterly"}
>
{gettext("Quarterly")}
</option>
<option value="half_yearly" selected={@form[:interval].value == :half_yearly}>
<option
value="half_yearly"
selected={
@form[:interval].value == :half_yearly || @form[:interval].value == "half_yearly"
}
>
{gettext("Half-yearly")}
</option>
<option value="yearly" selected={@form[:interval].value == :yearly}>
<option
value="yearly"
selected={@form[:interval].value == :yearly || @form[:interval].value == "yearly"}
>
{gettext("Yearly")}
</option>
</select>
@ -192,10 +207,27 @@ defmodule MvWeb.MembershipFeeTypeLive.Form do
@impl true
def handle_event("validate", %{"membership_fee_type" => params}, socket) do
validated_form = AshPhoenix.Form.validate(socket.assigns.form, params)
# Merge with existing form values to preserve unchanged fields
existing_values = get_existing_form_values(socket.assigns.form)
# Merge existing values with new params (new params take precedence)
merged_params = Map.merge(existing_values, params)
# Convert interval string to atom if present
merged_params =
if Map.has_key?(merged_params, "interval") && is_binary(merged_params["interval"]) &&
merged_params["interval"] != "" do
Map.update!(merged_params, "interval", fn val ->
String.to_existing_atom(val)
end)
else
merged_params
end
validated_form = AshPhoenix.Form.validate(socket.assigns.form, merged_params)
# Check if amount changed on edit
socket = check_amount_change(socket, params)
socket = check_amount_change(socket, merged_params)
{:noreply, assign(socket, form: validated_form)}
end
@ -289,6 +321,29 @@ defmodule MvWeb.MembershipFeeTypeLive.Form do
assign(socket, form: to_form(form))
end
# Helper to extract existing form values to preserve them when only one field changes
defp get_existing_form_values(form) do
# Get current form values from the form source
case form.source.params do
%{"membership_fee_type" => existing_params} when is_map(existing_params) ->
# Convert atoms to strings for form params
existing_params
|> Enum.map(fn
{key, value} when is_atom(key) -> {Atom.to_string(key), value}
{key, value} -> {key, value}
end)
|> Enum.map(fn
{key, value} when is_atom(value) -> {key, Atom.to_string(value)}
{key, value} -> {key, value}
end)
|> Map.new()
_ ->
# No existing params, return empty map
%{}
end
end
@spec return_path(String.t(), MembershipFeeType.t() | nil) :: String.t()
defp return_path("index", _membership_fee_type), do: ~p"/membership_fee_types"