From 6d426a21e826c9b5d6700d8b3637c9c80b746c7b Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 17 Jun 2025 13:34:24 +0200 Subject: [PATCH] liveview for new member fields --- lib/mv_web/components/core_components.ex | 24 +++++++++++++++++ lib/mv_web/member_live/form_component.ex | 15 +++++++++++ lib/mv_web/member_live/index.ex | 7 ++++- lib/mv_web/member_live/show.ex | 34 ++++++++++++++++++++++-- 4 files changed, 77 insertions(+), 3 deletions(-) diff --git a/lib/mv_web/components/core_components.ex b/lib/mv_web/components/core_components.ex index 1e9b835..c35f1ce 100644 --- a/lib/mv_web/components/core_components.ex +++ b/lib/mv_web/components/core_components.ex @@ -673,4 +673,28 @@ defmodule MvWeb.CoreComponents do def translate_errors(errors, field) when is_list(errors) do for {^field, {msg, opts}} <- errors, do: translate_error({msg, opts}) end + + @doc """ + Renders a list of items with name and value pairs. + + ## Examples + <.generic_list items={[ + {item.name, item.value}, + {other.name, other.value} + ]} /> + """ + attr :items, :list, required: true, doc: "List of {name, value} tuples" + + def generic_list(assigns) do + ~H""" +
+
+
+
{name}
+
{value}
+
+
+
+ """ + end end diff --git a/lib/mv_web/member_live/form_component.ex b/lib/mv_web/member_live/form_component.ex index 101cf6c..0f06cfa 100644 --- a/lib/mv_web/member_live/form_component.ex +++ b/lib/mv_web/member_live/form_component.ex @@ -36,6 +36,21 @@ defmodule MvWeb.MemberLive.FormComponent do phx-change="validate" phx-submit="save" > + <.input field={@form[:first_name]} label="First Name" required /> + <.input field={@form[:last_name]} label="Last Name" required /> + <.input field={@form[:email]} label="Email" required type="email" /> + <.input field={@form[:birth_date]} label="Birth Date" type="date" /> + <.input field={@form[:paid]} label="Paid" type="checkbox" /> + <.input field={@form[:phone_number]} label="Phone Number" /> + <.input field={@form[:join_date]} label="Join Date" type="date" /> + <.input field={@form[:exit_date]} label="Exit Date" type="date" /> + <.input field={@form[:notes]} label="Notes" /> + <.input field={@form[:city]} label="City" /> + <.input field={@form[:street]} label="Street" /> + <.input field={@form[:house_number]} label="House Number" /> + <.input field={@form[:postal_code]} label="Postal Code" /> + +

Custom Properties

<.inputs_for :let={f_property} field={@form[:properties]}> <% type = Enum.find(@property_types, &(&1.id == f_property[:property_type_id].value)) %> <.inputs_for :let={value_form} field={f_property[:value]}> diff --git a/lib/mv_web/member_live/index.ex b/lib/mv_web/member_live/index.ex index 4e37429..96c7a41 100644 --- a/lib/mv_web/member_live/index.ex +++ b/lib/mv_web/member_live/index.ex @@ -18,7 +18,12 @@ defmodule MvWeb.MemberLive.Index do rows={@streams.members} row_click={fn {_id, member} -> JS.navigate(~p"/members/#{member}") end} > - <:col :let={{_id, member}} label="Id">{member.id} + + <:col :let={{_id, member}} label="First Name">{member.first_name} + <:col :let={{_id, member}} label="Last Name">{member.last_name} + <:col :let={{_id, member}} label="Email">{member.email} + <:col :let={{_id, member}} label="City">{member.city} + <:col :let={{_id, member}} label="Join Date">{member.join_date} <:action :let={{_id, member}}>
diff --git a/lib/mv_web/member_live/show.ex b/lib/mv_web/member_live/show.ex index 47e0f92..1608a9a 100644 --- a/lib/mv_web/member_live/show.ex +++ b/lib/mv_web/member_live/show.ex @@ -1,11 +1,12 @@ defmodule MvWeb.MemberLive.Show do use MvWeb, :live_view + import Ash.Query @impl true def render(assigns) do ~H""" <.header> - Member {@member.id} + {@member.first_name} {@member.last_name} <:subtitle>This is a member record from your database. <:actions> @@ -17,8 +18,30 @@ defmodule MvWeb.MemberLive.Show do <.list> <:item title="Id">{@member.id} + <:item title="First Name">{@member.first_name} + <:item title="Last Name">{@member.last_name} + <:item title="Email">{@member.email} + <:item title="Birth Date">{@member.birth_date} + <:item title="Paid">{if @member.paid, do: "Yes", else: "No"} + <:item title="Phone Number">{@member.phone_number} + <:item title="Join Date">{@member.join_date} + <:item title="Exit Date">{@member.exit_date} + <:item title="Notes">{@member.notes} + <:item title="City">{@member.city} + <:item title="Street">{@member.street} + <:item title="House Number">{@member.house_number} + <:item title="Postal Code">{@member.postal_code} +

Custom Properties

+ <.generic_list + items={Enum.map(@member.properties, fn p -> + { + p.property_type && p.property_type.name, # name + case p.value do %{value: v} -> v; v -> v end # value + } + end)} + /> <.back navigate={~p"/members"}>Back to members <.modal @@ -46,10 +69,17 @@ defmodule MvWeb.MemberLive.Show do @impl true def handle_params(%{"id" => id}, _, socket) do + query = + Mv.Membership.Member + |> filter(id == ^id) + |> load(properties: [:property_type]) + + member = Ash.read_one!(query) + {:noreply, socket |> assign(:page_title, page_title(socket.assigns.live_action)) - |> assign(:member, Ash.get!(Mv.Membership.Member, id))} + |> assign(:member, member)} end defp page_title(:show), do: "Show Member"