Compare commits
6 commits
646c5e2bcb
...
72bb6ae2fe
| Author | SHA1 | Date | |
|---|---|---|---|
| 72bb6ae2fe | |||
| 51a41e17ba | |||
| 5761e5ee1f | |||
| 658b976898 | |||
| a35d62c084 | |||
| 90a8f57fe7 |
3 changed files with 184 additions and 15 deletions
|
|
@ -52,6 +52,8 @@ defmodule MvWeb do
|
|||
quote do
|
||||
use Phoenix.LiveView
|
||||
|
||||
on_mount MvWeb.LiveHelpers
|
||||
|
||||
unquote(html_helpers())
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,9 +11,32 @@ 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 +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"""
|
||||
<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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue