diff --git a/lib/mv_web.ex b/lib/mv_web.ex
index fff24b6..46e4e8b 100644
--- a/lib/mv_web.ex
+++ b/lib/mv_web.ex
@@ -52,6 +52,8 @@ defmodule MvWeb do
quote do
use Phoenix.LiveView
+ on_mount MvWeb.LiveHelpers
+
unquote(html_helpers())
end
end
diff --git a/lib/mv_web/live/property_live/form.ex b/lib/mv_web/live/property_live/form.ex
index 2987b3e..42814a3 100644
--- a/lib/mv_web/live/property_live/form.ex
+++ b/lib/mv_web/live/property_live/form.ex
@@ -11,9 +11,32 @@ defmodule MvWeb.PropertyLive.Form do
<.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")} />
+
+ <.input
+ field={@form[:property_type_id]}
+ type="select"
+ label={gettext("Property type")}
+ options={property_type_options(@property_types)}
+ prompt={gettext("Choose a property type")}
+ />
+
+
+ <.input
+ field={@form[:member_id]}
+ type="select"
+ label={gettext("Member")}
+ options={member_options(@members)}
+ prompt={gettext("Choose a member")}
+ />
+
+
+ <%= if @selected_property_type do %>
+ <.union_value_input form={@form} property_type={@selected_property_type} />
+ <% else %>
+
+ {gettext("Please select a property type first")}
+
+ <% end %>
<.button phx-disable-with={gettext("Saving...")} variant="primary">
{gettext("Save Property")}
@@ -24,22 +47,109 @@ 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"""
+
+
+ {gettext("Value")}
+
+
+ <%= 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} />
+
+
+ <% :integer -> %>
+ <.inputs_for :let={value_form} field={@form[:value]}>
+ <.input field={value_form[:value]} type="number" label="" value={@current_value} />
+
+
+ <% :boolean -> %>
+ <.inputs_for :let={value_form} field={@form[:value]}>
+ <.input field={value_form[:value]} type="checkbox" label="" checked={@current_value} />
+
+
+ <% :date -> %>
+ <.inputs_for :let={value_form} field={@form[:value]}>
+ <.input
+ field={value_form[:value]}
+ type="date"
+ label=""
+ value={format_date_value(@current_value)}
+ />
+
+
+ <% :email -> %>
+ <.inputs_for :let={value_form} field={@form[:value]}>
+ <.input field={value_form[:value]} type="email" label="" value={@current_value} />
+
+
+ <% _ -> %>
+
+ {gettext("Unsupported value type: %{type}", type: @property_type.value_type)}
+
+ <% end %>
+
+ """
+ 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
diff --git a/test/mv_web/member_live/index_test.exs b/test/mv_web/member_live/index_test.exs
index ce47a43..e3e77dc 100644
--- a/test/mv_web/member_live/index_test.exs
+++ b/test/mv_web/member_live/index_test.exs
@@ -35,8 +35,7 @@ defmodule MvWeb.MemberLive.IndexTest do
test "shows translated flash message after creating a member in German", %{conn: conn} do
conn = conn_with_oidc_user(conn)
conn = Plug.Test.init_test_session(conn, locale: "de")
- {:ok, view, _html} = live(conn, "/members")
- view |> element("a", "Neues Mitglied") |> render_click()
+ {:ok, form_view, _html} = live(conn, "/members/new")
form_data = %{
"member[first_name]" => "Max",
@@ -44,15 +43,20 @@ defmodule MvWeb.MemberLive.IndexTest do
"member[email]" => "max@example.com"
}
- view |> form("#member-form", form_data) |> render_submit()
- assert has_element?(view, "#flash-group", "Mitglied erstellt erfolgreich")
+ # Submit form and follow the redirect to get the flash message
+ {:ok, index_view, _html} =
+ form_view
+ |> form("#member-form", form_data)
+ |> render_submit()
+ |> follow_redirect(conn, "/members")
+
+ assert has_element?(index_view, "#flash-group", "Mitglied erstellt erfolgreich")
end
test "shows translated flash message after creating a member in English", %{conn: conn} do
conn = conn_with_oidc_user(conn)
conn = Plug.Test.init_test_session(conn, locale: "en")
- {:ok, view, _html} = live(conn, "/members")
- view |> element("a", "New Member") |> render_click()
+ {:ok, form_view, _html} = live(conn, "/members/new")
form_data = %{
"member[first_name]" => "Max",
@@ -60,7 +64,13 @@ defmodule MvWeb.MemberLive.IndexTest do
"member[email]" => "max@example.com"
}
- view |> form("#member-form", form_data) |> render_submit()
- assert has_element?(view, "#flash-group", "Member create successfully")
+ # Submit form and follow the redirect to get the flash message
+ {:ok, index_view, _html} =
+ form_view
+ |> form("#member-form", form_data)
+ |> render_submit()
+ |> follow_redirect(conn, "/members")
+
+ assert has_element?(index_view, "#flash-group", "Member create successfully")
end
end