Calculate selected_count, any_selected? and mailto_bcc once in assigns instead of recalculating Enum.any? and Enum.count multiple times in template. This improves render performance and makes the template code more readable.
275 lines
7.2 KiB
Text
275 lines
7.2 KiB
Text
<Layouts.app flash={@flash} current_user={@current_user}>
|
|
<.header>
|
|
{gettext("Members")}
|
|
<:actions>
|
|
<.button
|
|
class="secondary"
|
|
id="copy-emails-btn"
|
|
phx-hook="CopyToClipboard"
|
|
phx-click="copy_emails"
|
|
disabled={not @any_selected?}
|
|
aria-label={gettext("Copy email addresses of selected members")}
|
|
>
|
|
<.icon name="hero-clipboard-document" />
|
|
{gettext("Copy email addresses")} ({@selected_count})
|
|
</.button>
|
|
<.button
|
|
class="secondary"
|
|
id="open-email-btn"
|
|
href={"mailto:?bcc=" <> URI.encode(@mailto_bcc)}
|
|
disabled={not @any_selected?}
|
|
aria-label={gettext("Open email program with BCC recipients")}
|
|
>
|
|
<.icon name="hero-envelope" />
|
|
{gettext("Open in email program")}
|
|
</.button>
|
|
<.button variant="primary" navigate={~p"/members/new"}>
|
|
<.icon name="hero-plus" /> {gettext("New Member")}
|
|
</.button>
|
|
</:actions>
|
|
</.header>
|
|
|
|
<div class="flex flex-wrap gap-4 items-center">
|
|
<.live_component
|
|
module={MvWeb.Components.SearchBarComponent}
|
|
id="search-bar"
|
|
query={@query}
|
|
placeholder={gettext("Search...")}
|
|
/>
|
|
<.live_component
|
|
module={MvWeb.Components.PaymentFilterComponent}
|
|
id="payment-filter"
|
|
paid_filter={@paid_filter}
|
|
member_count={length(@members)}
|
|
/>
|
|
<.live_component
|
|
module={MvWeb.Components.FieldVisibilityDropdownComponent}
|
|
id="field-visibility-dropdown"
|
|
all_fields={@all_available_fields}
|
|
custom_fields={@all_custom_fields}
|
|
selected_fields={@user_field_selection}
|
|
/>
|
|
</div>
|
|
|
|
<.table
|
|
id="members"
|
|
rows={@members}
|
|
row_click={fn member -> JS.navigate(~p"/members/#{member}") end}
|
|
dynamic_cols={@dynamic_cols}
|
|
sort_field={@sort_field}
|
|
sort_order={@sort_order}
|
|
>
|
|
|
|
<!-- <:col :let={member} label="Id">{member.id}</:col> -->
|
|
<:col
|
|
:let={member}
|
|
col_click={&MvWeb.MemberLive.Index.checkbox_column_click/1}
|
|
label={
|
|
~H"""
|
|
<.input
|
|
type="checkbox"
|
|
name="select_all"
|
|
phx-click="select_all"
|
|
checked={MapSet.equal?(@selected_members, @members |> Enum.map(& &1.id) |> MapSet.new())}
|
|
aria-label={gettext("Select all members")}
|
|
role="checkbox"
|
|
/>
|
|
"""
|
|
}
|
|
>
|
|
<.input
|
|
type="checkbox"
|
|
name={member.id}
|
|
checked={MapSet.member?(@selected_members, member.id)}
|
|
aria-label={gettext("Select member")}
|
|
role="checkbox"
|
|
/>
|
|
</:col>
|
|
<:col
|
|
:let={member}
|
|
:if={:first_name in @member_fields_visible}
|
|
label={
|
|
~H"""
|
|
<.live_component
|
|
module={MvWeb.Components.SortHeaderComponent}
|
|
id={:sort_first_name}
|
|
field={:first_name}
|
|
label={gettext("First name")}
|
|
sort_field={@sort_field}
|
|
sort_order={@sort_order}
|
|
/>
|
|
"""
|
|
}
|
|
>
|
|
{member.first_name}
|
|
</:col>
|
|
<:col
|
|
:let={member}
|
|
:if={:last_name in @member_fields_visible}
|
|
label={
|
|
~H"""
|
|
<.live_component
|
|
module={MvWeb.Components.SortHeaderComponent}
|
|
id={:sort_last_name}
|
|
field={:last_name}
|
|
label={gettext("Last name")}
|
|
sort_field={@sort_field}
|
|
sort_order={@sort_order}
|
|
/>
|
|
"""
|
|
}
|
|
>
|
|
{member.last_name}
|
|
</:col>
|
|
<:col
|
|
:let={member}
|
|
:if={:email in @member_fields_visible}
|
|
label={
|
|
~H"""
|
|
<.live_component
|
|
module={MvWeb.Components.SortHeaderComponent}
|
|
id={:sort_email}
|
|
field={:email}
|
|
label={gettext("Email")}
|
|
sort_field={@sort_field}
|
|
sort_order={@sort_order}
|
|
/>
|
|
"""
|
|
}
|
|
>
|
|
{member.email}
|
|
</:col>
|
|
<:col
|
|
:let={member}
|
|
:if={:street in @member_fields_visible}
|
|
label={
|
|
~H"""
|
|
<.live_component
|
|
module={MvWeb.Components.SortHeaderComponent}
|
|
id={:sort_street}
|
|
field={:street}
|
|
label={gettext("Street")}
|
|
sort_field={@sort_field}
|
|
sort_order={@sort_order}
|
|
/>
|
|
"""
|
|
}
|
|
>
|
|
{member.street}
|
|
</:col>
|
|
<:col
|
|
:let={member}
|
|
:if={:house_number in @member_fields_visible}
|
|
label={
|
|
~H"""
|
|
<.live_component
|
|
module={MvWeb.Components.SortHeaderComponent}
|
|
id={:sort_house_number}
|
|
field={:house_number}
|
|
label={gettext("House Number")}
|
|
sort_field={@sort_field}
|
|
sort_order={@sort_order}
|
|
/>
|
|
"""
|
|
}
|
|
>
|
|
{member.house_number}
|
|
</:col>
|
|
<:col
|
|
:let={member}
|
|
:if={:postal_code in @member_fields_visible}
|
|
label={
|
|
~H"""
|
|
<.live_component
|
|
module={MvWeb.Components.SortHeaderComponent}
|
|
id={:sort_postal_code}
|
|
field={:postal_code}
|
|
label={gettext("Postal Code")}
|
|
sort_field={@sort_field}
|
|
sort_order={@sort_order}
|
|
/>
|
|
"""
|
|
}
|
|
>
|
|
{member.postal_code}
|
|
</:col>
|
|
<:col
|
|
:let={member}
|
|
:if={:city in @member_fields_visible}
|
|
label={
|
|
~H"""
|
|
<.live_component
|
|
module={MvWeb.Components.SortHeaderComponent}
|
|
id={:sort_city}
|
|
field={:city}
|
|
label={gettext("City")}
|
|
sort_field={@sort_field}
|
|
sort_order={@sort_order}
|
|
/>
|
|
"""
|
|
}
|
|
>
|
|
{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}
|
|
label={
|
|
~H"""
|
|
<.live_component
|
|
module={MvWeb.Components.SortHeaderComponent}
|
|
id={:sort_join_date}
|
|
field={:join_date}
|
|
label={gettext("Join Date")}
|
|
sort_field={@sort_field}
|
|
sort_order={@sort_order}
|
|
/>
|
|
"""
|
|
}
|
|
>
|
|
{MvWeb.MemberLive.Index.format_date(member.join_date)}
|
|
</:col>
|
|
<:col :let={member} :if={:paid in @member_fields_visible} label={gettext("Paid")}>
|
|
<span class={[
|
|
"badge",
|
|
if(member.paid == true, do: "badge-success", else: "badge-error")
|
|
]}>
|
|
{if member.paid == true, do: gettext("Yes"), else: gettext("No")}
|
|
</span>
|
|
</:col>
|
|
<:action :let={member}>
|
|
<div class="sr-only">
|
|
<.link navigate={~p"/members/#{member}"}>{gettext("Show")}</.link>
|
|
</div>
|
|
|
|
<.link navigate={~p"/members/#{member}/edit"}>{gettext("Edit")}</.link>
|
|
</:action>
|
|
|
|
<:action :let={member}>
|
|
<.link
|
|
phx-click={JS.push("delete", value: %{id: member.id}) |> hide("#row-#{member.id}")}
|
|
data-confirm={gettext("Are you sure?")}
|
|
>
|
|
{gettext("Delete")}
|
|
</.link>
|
|
</:action>
|
|
</.table>
|
|
</Layouts.app>
|