feat: migration to phoenix 1.8 - fix PropertyLive.Form

This commit is contained in:
Moritz 2025-07-17 16:11:49 +02:00
parent 15d6fd38c9
commit acaa12fea6
Signed by: moritz
GPG key ID: 1020A035E5DD0824

View file

@ -11,9 +11,35 @@ defmodule MvWeb.PropertyLive.Form do
</.header>
<.form for={@form} id="property-form" phx-change="validate" phx-submit="save">
<.input field={@form[:value]} type="text" label={gettext("Value")} />
<.input field={@form[:member_id]} type="text" label={gettext("Member")} />
<.input field={@form[:property_type_id]} type="text" label={gettext("Property type")} />
<!-- Property Type Selection -->
<.input
field={@form[:property_type_id]}
type="select"
label={gettext("Property type")}
options={property_type_options(@property_types)}
prompt={gettext("Choose a property type")}
/>
<!-- Member Selection -->
<.input
field={@form[:member_id]}
type="select"
label={gettext("Member")}
options={member_options(@members)}
prompt={gettext("Choose a member")}
/>
<!-- Value Input - handles Union type -->
<%= if @selected_property_type do %>
<.union_value_input
form={@form}
property_type={@selected_property_type}
/>
<% else %>
<div class="text-sm text-gray-600">
{gettext("Please select a property type first")}
</div>
<% end %>
<.button phx-disable-with={gettext("Saving...")} variant="primary">
{gettext("Save Property")}
@ -24,22 +50,106 @@ defmodule MvWeb.PropertyLive.Form do
"""
end
# Helper function for Union-Value Input
defp union_value_input(assigns) do
# Extract the current value from the Property
current_value = extract_current_value(assigns.form.data, assigns.property_type.value_type)
assigns = assign(assigns, :current_value, current_value)
~H"""
<div class="space-y-2">
<label class="block text-sm font-medium text-gray-700">
{gettext("Value")}
</label>
<%= case @property_type.value_type do %>
<% :string -> %>
<.inputs_for :let={value_form} field={@form[:value]}>
<.input field={value_form[:value]} type="text" label="" value={@current_value} />
<input type="hidden" name={value_form[:_union_type].name} value="string" />
</.inputs_for>
<% :integer -> %>
<.inputs_for :let={value_form} field={@form[:value]}>
<.input field={value_form[:value]} type="number" label="" value={@current_value} />
<input type="hidden" name={value_form[:_union_type].name} value="integer" />
</.inputs_for>
<% :boolean -> %>
<.inputs_for :let={value_form} field={@form[:value]}>
<.input field={value_form[:value]} type="checkbox" label="" checked={@current_value} />
<input type="hidden" name={value_form[:_union_type].name} value="boolean" />
</.inputs_for>
<% :date -> %>
<.inputs_for :let={value_form} field={@form[:value]}>
<.input field={value_form[:value]} type="date" label="" value={format_date_value(@current_value)} />
<input type="hidden" name={value_form[:_union_type].name} value="date" />
</.inputs_for>
<% :email -> %>
<.inputs_for :let={value_form} field={@form[:value]}>
<.input field={value_form[:value]} type="email" label="" value={@current_value} />
<input type="hidden" name={value_form[:_union_type].name} value="email" />
</.inputs_for>
<% _ -> %>
<div class="text-sm text-red-600">
{gettext("Unsupported value type: %{type}", type: @property_type.value_type)}
</div>
<% end %>
</div>
"""
end
# Helper function to extract the current value from the Property
defp extract_current_value(%Mv.Membership.Property{value: %Ash.Union{value: value}}, _value_type) do
value
end
defp extract_current_value(_data, _value_type) do
nil
end
# Helper function to format Date values for HTML input
defp format_date_value(%Date{} = date) do
Date.to_iso8601(date)
end
defp format_date_value(nil), do: ""
defp format_date_value(date) when is_binary(date) do
case Date.from_iso8601(date) do
{:ok, parsed_date} -> Date.to_iso8601(parsed_date)
_ -> ""
end
end
defp format_date_value(_), do: ""
@impl true
def mount(params, _session, socket) do
property =
case params["id"] do
nil -> nil
id -> Ash.get!(Mv.Membership.Property, id)
id -> Ash.get!(Mv.Membership.Property, id) |> Ash.load!([:property_type])
end
action = if is_nil(property), do: "New", else: "Edit"
page_title = action <> " " <> "Property"
# Load all PropertyTypes and Members for the selection fields
property_types = Ash.read!(Mv.Membership.PropertyType)
members = Ash.read!(Mv.Membership.Member)
{:ok,
socket
|> assign(:return_to, return_to(params["return_to"]))
|> assign(property: property)
|> assign(:page_title, page_title)
|> assign(:property_types, property_types)
|> assign(:members, members)
|> assign(:selected_property_type, property && property.property_type)
|> assign_form()}
end
@ -48,12 +158,40 @@ defmodule MvWeb.PropertyLive.Form do
@impl true
def handle_event("validate", %{"property" => property_params}, socket) do
# Find the selected PropertyType
selected_property_type =
case property_params["property_type_id"] do
"" -> nil
nil -> nil
id -> Enum.find(socket.assigns.property_types, &(&1.id == id))
end
# Set the Union type based on the selected PropertyType
updated_params =
if selected_property_type do
union_type = to_string(selected_property_type.value_type)
put_in(property_params, ["value", "_union_type"], union_type)
else
property_params
end
{:noreply,
assign(socket, form: AshPhoenix.Form.validate(socket.assigns.form, property_params))}
socket
|> assign(:selected_property_type, selected_property_type)
|> assign(form: AshPhoenix.Form.validate(socket.assigns.form, updated_params))}
end
def handle_event("save", %{"property" => property_params}, socket) do
case AshPhoenix.Form.submit(socket.assigns.form, params: property_params) do
# Set the Union type based on the selected PropertyType
updated_params =
if socket.assigns.selected_property_type do
union_type = to_string(socket.assigns.selected_property_type.value_type)
put_in(property_params, ["value", "_union_type"], union_type)
else
property_params
end
case AshPhoenix.Form.submit(socket.assigns.form, params: updated_params) do
{:ok, property} ->
notify_parent({:saved, property})
@ -81,7 +219,17 @@ defmodule MvWeb.PropertyLive.Form do
defp assign_form(%{assigns: %{property: property}} = socket) do
form =
if property do
AshPhoenix.Form.for_update(property, :update, as: "property")
# Determine the Union type based on the property_type
union_type = property.property_type && property.property_type.value_type
params =
if union_type do
%{"value" => %{"_union_type" => to_string(union_type)}}
else
%{}
end
AshPhoenix.Form.for_update(property, :update, as: "property", params: params)
else
AshPhoenix.Form.for_create(Mv.Membership.Property, :create, as: "property")
end
@ -91,4 +239,13 @@ defmodule MvWeb.PropertyLive.Form do
defp return_path("index", _property), do: ~p"/properties"
defp return_path("show", property), do: ~p"/properties/#{property.id}"
# Helper functions for selection options
defp property_type_options(property_types) do
Enum.map(property_types, &{&1.name, &1.id})
end
defp member_options(members) do
Enum.map(members, &{"#{&1.first_name} #{&1.last_name}", &1.id})
end
end