feat(member): condense the overview into composite name and address cells
This commit is contained in:
parent
b79d7ac9ea
commit
af2cc2e0d4
17 changed files with 716 additions and 93 deletions
|
|
@ -149,6 +149,48 @@
|
|||
role="checkbox"
|
||||
/>
|
||||
</:col>
|
||||
<:col
|
||||
:let={member}
|
||||
:if={:name in @member_fields_visible}
|
||||
label={gettext("Name")}
|
||||
>
|
||||
<% full_name =
|
||||
[member.first_name, member.last_name]
|
||||
|> Enum.reject(&(&1 in [nil, ""]))
|
||||
|> Enum.join(" ") %>
|
||||
<div data-testid="member-name">
|
||||
<div class="font-medium truncate" title={full_name}>
|
||||
{full_name}
|
||||
</div>
|
||||
<div
|
||||
:if={member.email not in [nil, ""]}
|
||||
class="opacity-70 truncate"
|
||||
title={member.email}
|
||||
>
|
||||
{member.email}
|
||||
</div>
|
||||
</div>
|
||||
</:col>
|
||||
<:col
|
||||
:let={member}
|
||||
:if={:address in @member_fields_visible}
|
||||
label={gettext("Address")}
|
||||
>
|
||||
<% line1 =
|
||||
[member.street, member.house_number]
|
||||
|> Enum.reject(&(&1 in [nil, ""]))
|
||||
|> Enum.join(" ") %>
|
||||
<% line2 =
|
||||
[member.postal_code, member.city]
|
||||
|> Enum.reject(&(&1 in [nil, ""]))
|
||||
|> Enum.join(" ") %>
|
||||
<.maybe_value value={line1 <> line2} empty_sr_text={gettext("No address")}>
|
||||
<div data-testid="member-address">
|
||||
<div class="truncate" title={line1}>{line1}</div>
|
||||
<div class="opacity-70 truncate" title={line2}>{line2}</div>
|
||||
</div>
|
||||
</.maybe_value>
|
||||
</:col>
|
||||
<:col
|
||||
:let={member}
|
||||
:if={:first_name in @member_fields_visible}
|
||||
|
|
@ -280,7 +322,9 @@
|
|||
"""
|
||||
}
|
||||
>
|
||||
{member.city}
|
||||
<.maybe_value value={member.city} empty_sr_text={gettext("Not specified")}>
|
||||
{member.city}
|
||||
</.maybe_value>
|
||||
</:col>
|
||||
<:col
|
||||
:let={member}
|
||||
|
|
@ -298,7 +342,9 @@
|
|||
"""
|
||||
}
|
||||
>
|
||||
{member.street}
|
||||
<.maybe_value value={member.street} empty_sr_text={gettext("Not specified")}>
|
||||
{member.street}
|
||||
</.maybe_value>
|
||||
</:col>
|
||||
<:col
|
||||
:let={member}
|
||||
|
|
@ -316,7 +362,9 @@
|
|||
"""
|
||||
}
|
||||
>
|
||||
{member.house_number}
|
||||
<.maybe_value value={member.house_number} empty_sr_text={gettext("Not specified")}>
|
||||
{member.house_number}
|
||||
</.maybe_value>
|
||||
</:col>
|
||||
<:col
|
||||
:let={member}
|
||||
|
|
@ -334,7 +382,9 @@
|
|||
"""
|
||||
}
|
||||
>
|
||||
{member.postal_code}
|
||||
<.maybe_value value={member.postal_code} empty_sr_text={gettext("Not specified")}>
|
||||
{member.postal_code}
|
||||
</.maybe_value>
|
||||
</:col>
|
||||
<:col
|
||||
:let={member}
|
||||
|
|
@ -407,15 +457,17 @@
|
|||
}
|
||||
>
|
||||
<.maybe_value value={member.groups} empty_sr_text={gettext("No group assignment")}>
|
||||
<%= for group <- (member.groups || []) do %>
|
||||
<.badge
|
||||
variant="primary"
|
||||
style="outline"
|
||||
aria-label={gettext("Member of group %{name}", name: group.name)}
|
||||
>
|
||||
{group.name}
|
||||
</.badge>
|
||||
<% end %>
|
||||
<div class="flex flex-wrap gap-1 w-max">
|
||||
<%= for group <- (member.groups || []) do %>
|
||||
<.badge
|
||||
variant="primary"
|
||||
style="outline"
|
||||
aria-label={gettext("Member of group %{name}", name: group.name)}
|
||||
>
|
||||
{group.name}
|
||||
</.badge>
|
||||
<% end %>
|
||||
</div>
|
||||
</.maybe_value>
|
||||
</:col>
|
||||
<:action :let={member}>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,28 @@ defmodule MvWeb.MemberLive.Index.FieldVisibility do
|
|||
|
||||
# Single UI key for "Membership Fee Status"; only this appears in the dropdown.
|
||||
# Groups and membership_fee_type are also pseudo fields (not in member_fields(), displayed in the table).
|
||||
@pseudo_member_fields [:membership_fee_status, :membership_fee_type, :groups]
|
||||
# :name and :address are composite display-only columns (Name = name + email,
|
||||
# Address = street/house number over postal code/city).
|
||||
@pseudo_member_fields [:membership_fee_status, :membership_fee_type, :groups, :name, :address]
|
||||
|
||||
# Curated default-visible column set (§1.2): the columns shown on first visit
|
||||
# when there is no persisted selection and no global override. Everything else
|
||||
# (the individual name/address sub-fields, notes, dates other than join date)
|
||||
# defaults to hidden so the table fits common desktop widths.
|
||||
@default_visible_fields MapSet.new([
|
||||
:name,
|
||||
:address,
|
||||
:membership_fee_type,
|
||||
:membership_fee_status,
|
||||
:groups,
|
||||
:join_date
|
||||
])
|
||||
|
||||
@doc """
|
||||
The curated default-visible columns (member-field atoms) for a first visit.
|
||||
"""
|
||||
@spec default_visible_fields() :: [atom()]
|
||||
def default_visible_fields, do: MapSet.to_list(@default_visible_fields)
|
||||
|
||||
# Export/API may accept this as alias; must not appear in the UI options list.
|
||||
@export_only_alias :payment_status
|
||||
|
|
@ -276,13 +297,13 @@ defmodule MvWeb.MemberLive.Index.FieldVisibility do
|
|||
domain_map =
|
||||
Enum.reduce(domain_fields, %{}, fn field, acc ->
|
||||
field_string = Atom.to_string(field)
|
||||
default_visibility = if field == :exit_date, do: false, else: true
|
||||
default_visibility = MapSet.member?(@default_visible_fields, field)
|
||||
show_in_overview = Map.get(visibility_config, field, default_visibility)
|
||||
Map.put(acc, field_string, show_in_overview)
|
||||
end)
|
||||
|
||||
Enum.reduce(@pseudo_member_fields, domain_map, fn field, acc ->
|
||||
Map.put(acc, Atom.to_string(field), true)
|
||||
Map.put(acc, Atom.to_string(field), MapSet.member?(@default_visible_fields, field))
|
||||
end)
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue