Make cycle button match PaymentFilterComponent and Columns button style. Show 'Current Cycle Payment Status' or 'Last Cycle Payment Status' based on active state. Button shows active state when current cycle is selected.
329 lines
8.7 KiB
Text
329 lines
8.7 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=" <> @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"
|
|
cycle_status_filter={@cycle_status_filter}
|
|
member_count={length(@members)}
|
|
/>
|
|
<button
|
|
type="button"
|
|
phx-click="toggle_cycle_view"
|
|
class={[
|
|
"btn gap-2",
|
|
@show_current_cycle && "btn-active"
|
|
]}
|
|
aria-label={
|
|
if(@show_current_cycle,
|
|
do: gettext("Current Cycle Payment Status"),
|
|
else: gettext("Last Cycle Payment Status")
|
|
)
|
|
}
|
|
title={
|
|
if(@show_current_cycle,
|
|
do: gettext("Current Cycle Payment Status"),
|
|
else: gettext("Last Cycle Payment Status")
|
|
)
|
|
}
|
|
>
|
|
<.icon name="hero-arrow-path" class="h-5 w-5" />
|
|
<span class="hidden sm:inline">
|
|
{if(@show_current_cycle,
|
|
do: gettext("Current Cycle Payment Status"),
|
|
else: gettext("Last Cycle Payment Status")
|
|
)}
|
|
</span>
|
|
</button>
|
|
<.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}
|
|
label={
|
|
~H"""
|
|
<div class="flex items-center gap-2">
|
|
<span>{gettext("Membership Fee Status")}</span>
|
|
<button
|
|
type="button"
|
|
phx-click="toggle_cycle_view"
|
|
class="btn btn-xs btn-ghost"
|
|
title={
|
|
if(@show_current_cycle,
|
|
do: gettext("Switch to last completed cycle"),
|
|
else: gettext("Switch to current cycle")
|
|
)
|
|
}
|
|
>
|
|
<.icon name="hero-arrow-path" class="size-3" />
|
|
</button>
|
|
</div>
|
|
"""
|
|
}
|
|
>
|
|
<%= if badge = MvWeb.MemberLive.Index.MembershipFeeStatus.format_cycle_status_badge(
|
|
MvWeb.MemberLive.Index.MembershipFeeStatus.get_cycle_status_for_member(member, @show_current_cycle)
|
|
) do %>
|
|
<span class={["badge", badge.color]}>
|
|
<.icon name={badge.icon} class="size-4" />
|
|
{badge.label}
|
|
</span>
|
|
<% else %>
|
|
<span class="badge badge-ghost">{gettext("No cycle")}</span>
|
|
<% end %>
|
|
</: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>
|