Merge branch 'main' into feature/223_memberfields_settings
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
carla 2026-01-07 11:42:54 +01:00
commit df8c6a1854
23 changed files with 1274 additions and 176 deletions

View file

@ -0,0 +1,64 @@
defmodule MvWeb.Helpers.MemberHelpers do
@moduledoc """
Helper functions for member-related operations in the web layer.
Provides utilities for formatting and displaying member information.
"""
alias Mv.Membership.Member
@doc """
Returns a display name for a member.
Combines first_name and last_name if available, otherwise falls back to email.
This ensures that members without names still have a meaningful display name.
## Examples
iex> member = %Member{first_name: "John", last_name: "Doe", email: "john@example.com"}
iex> MvWeb.Helpers.MemberHelpers.display_name(member)
"John Doe"
iex> member = %Member{first_name: nil, last_name: nil, email: "john@example.com"}
iex> MvWeb.Helpers.MemberHelpers.display_name(member)
"john@example.com"
iex> member = %Member{first_name: "John", last_name: nil, email: "john@example.com"}
iex> MvWeb.Helpers.MemberHelpers.display_name(member)
"John"
"""
def display_name(%Member{} = member) do
name_parts =
[member.first_name, member.last_name]
|> Enum.reject(&blank?/1)
|> Enum.map_join(" ", &String.trim/1)
if name_parts == "" do
member.email
else
name_parts
end
end
@doc """
Checks if a value is blank (nil, empty string, or only whitespace).
## Examples
iex> MvWeb.Helpers.MemberHelpers.blank?(nil)
true
iex> MvWeb.Helpers.MemberHelpers.blank?("")
true
iex> MvWeb.Helpers.MemberHelpers.blank?(" ")
true
iex> MvWeb.Helpers.MemberHelpers.blank?("John")
false
"""
def blank?(nil), do: true
def blank?(""), do: true
def blank?(value) when is_binary(value), do: String.trim(value) == ""
def blank?(_), do: false
end

View file

@ -36,7 +36,7 @@ defmodule MvWeb.ContributionPeriodLive.Show do
<.mockup_warning />
<.header>
{gettext("Contributions for %{name}", name: "#{@member.first_name} #{@member.last_name}")}
{gettext("Contributions for %{name}", name: MvWeb.Helpers.MemberHelpers.display_name(@member))}
<:subtitle>
{gettext("Contribution type")}:
<span class="font-semibold">{@member.contribution_type}</span>

View file

@ -289,6 +289,6 @@ defmodule MvWeb.CustomFieldValueLive.Form do
end
defp member_options(members) do
Enum.map(members, &{"#{&1.first_name} #{&1.last_name}", &1.id})
Enum.map(members, &{MvWeb.Helpers.MemberHelpers.display_name(&1), &1.id})
end
end

View file

@ -43,7 +43,7 @@ defmodule MvWeb.MemberLive.Form do
<h1 class="text-2xl font-bold text-center flex-1">
<%= if @member do %>
{@member.first_name} {@member.last_name}
{MvWeb.Helpers.MemberHelpers.display_name(@member)}
<% else %>
{gettext("New Member")}
<% end %>
@ -82,10 +82,10 @@ defmodule MvWeb.MemberLive.Form do
<%!-- Name Row --%>
<div class="flex gap-4">
<div class="w-48">
<.input field={@form[:first_name]} label={gettext("First Name")} required />
<.input field={@form[:first_name]} label={gettext("First Name")} />
</div>
<div class="w-48">
<.input field={@form[:last_name]} label={gettext("Last Name")} required />
<.input field={@form[:last_name]} label={gettext("Last Name")} />
</div>
</div>
@ -110,11 +110,6 @@ defmodule MvWeb.MemberLive.Form do
<.input field={@form[:email]} label={gettext("Email")} required type="email" />
</div>
<%!-- Phone --%>
<div>
<.input field={@form[:phone_number]} label={gettext("Phone")} type="tel" />
</div>
<%!-- Membership Dates Row --%>
<div class="flex gap-4">
<div class="w-36">

View file

@ -239,24 +239,6 @@
>
{member.city}
</:col>
<:col
:let={member}
:if={:phone_number in @member_fields_visible}
label={
~H"""
<.live_component
module={MvWeb.Components.SortHeaderComponent}
id={:sort_phone_number}
field={:phone_number}
label={gettext("Phone Number")}
sort_field={@sort_field}
sort_order={@sort_order}
/>
"""
}
>
{member.phone_number}
</:col>
<:col
:let={member}
:if={:join_date in @member_fields_visible}

View file

@ -35,7 +35,7 @@ defmodule MvWeb.MemberLive.Show do
</.button>
<h1 class="text-2xl font-bold text-center flex-1">
{@member.first_name} {@member.last_name}
{MvWeb.Helpers.MemberHelpers.display_name(@member)}
</h1>
<.button variant="primary" navigate={~p"/members/#{@member}/edit?return_to=show"}>
@ -104,11 +104,6 @@ defmodule MvWeb.MemberLive.Show do
</.data_field>
</div>
<%!-- Phone --%>
<div>
<.data_field label={gettext("Phone")} value={@member.phone_number} />
</div>
<%!-- Membership Dates Row --%>
<div class="flex gap-6">
<.data_field

View file

@ -131,7 +131,7 @@ defmodule MvWeb.UserLive.Form do
<div class="flex items-center justify-between">
<div>
<p class="font-medium text-green-900">
{@user.member.first_name} {@user.member.last_name}
{MvWeb.Helpers.MemberHelpers.display_name(@user.member)}
</p>
<p class="text-sm text-green-700">{@user.member.email}</p>
</div>
@ -210,7 +210,7 @@ defmodule MvWeb.UserLive.Form do
)
]}
>
<p class="font-medium">{member.first_name} {member.last_name}</p>
<p class="font-medium">{MvWeb.Helpers.MemberHelpers.display_name(member)}</p>
<p class="text-sm text-base-content/70">{member.email}</p>
</div>
<% end %>
@ -438,7 +438,7 @@ defmodule MvWeb.UserLive.Form do
member_name =
if selected_member,
do: "#{selected_member.first_name} #{selected_member.last_name}",
do: MvWeb.Helpers.MemberHelpers.display_name(selected_member),
else: ""
# Store the selected member ID and name in socket state and clear unlink flag

View file

@ -51,7 +51,7 @@
</:col>
<:col :let={user} label={gettext("Linked Member")}>
<%= if user.member do %>
{user.member.first_name} {user.member.last_name}
{MvWeb.Helpers.MemberHelpers.display_name(user.member)}
<% else %>
<span class="text-base-content/50">{gettext("No member linked")}</span>
<% end %>

View file

@ -57,7 +57,7 @@ defmodule MvWeb.UserLive.Show do
class="text-blue-600 underline hover:text-blue-800"
>
<.icon name="hero-users" class="inline w-4 h-4 mr-1" />
{@user.member.first_name} {@user.member.last_name}
{MvWeb.Helpers.MemberHelpers.display_name(@user.member)}
</.link>
<% else %>
<span class="italic text-gray-500">{gettext("No member linked")}</span>

View file

@ -20,7 +20,6 @@ defmodule MvWeb.Translations.MemberFields do
def label(:first_name), do: gettext("First Name")
def label(:last_name), do: gettext("Last Name")
def label(:email), do: gettext("Email")
def label(:phone_number), do: gettext("Phone")
def label(:join_date), do: gettext("Join Date")
def label(:exit_date), do: gettext("Exit Date")
def label(:notes), do: gettext("Notes")