feat(overview): show suspended cycles separately in the payment tooltip

This commit is contained in:
Simon 2026-07-10 16:27:16 +02:00
parent e967cb59e9
commit 4d6294771a
7 changed files with 91 additions and 31 deletions

View file

@ -272,14 +272,32 @@ defmodule MvWeb.MemberLive.Index.PaymentAging do
|> Enum.sort_by(& &1.cycle_start, Date)
end
@doc """
Partitions a member's open cycles for the period into the unpaid cycles (which
drive the count and the badge) and the suspended cycles, which the tooltip
surfaces in their own labeled section rather than by color alone (§1.14).
Both lists stay in chronological order.
"""
@spec partition_open_cycles(map(), period()) :: %{unpaid: [map()], suspended: [map()]}
def partition_open_cycles(member, period) do
{unpaid, suspended} =
member
|> open_cycles(period)
|> Enum.split_with(&(&1.status == :unpaid))
%{unpaid: unpaid, suspended: suspended}
end
@tooltip_slots 5
@doc """
Partitions open cycles into the tooltip's fixed five-slot budget: at most
five badges total. Five or fewer cycles show in full with no overflow. More
than five collapse to the first four chronological cycles plus a single
overflow count (total 4), so the tooltip renders four cycle badges and one
grey overflow badge five items.
Partitions the tooltip's unpaid sub-list into a fixed five-slot budget: at
most five badges for the unpaid cycles. Five or fewer unpaid cycles show in
full with no overflow. More than five collapse to the first four chronological
cycles plus a single overflow count (total 4), so the unpaid sub-list
renders four cycle badges and one grey overflow badge five items. Suspended
cycles are listed separately (in their own labeled section) and are not capped
by this budget, so the tooltip's overall badge count can exceed five.
"""
@spec tooltip_cycles([map()]) :: {[map()], non_neg_integer()}
def tooltip_cycles(cycles) when is_list(cycles) do
@ -290,22 +308,6 @@ defmodule MvWeb.MemberLive.Index.PaymentAging do
end
end
@doc """
Static daisyUI badge color token for a cycle status, matching the codes used
on the member show page. Literal strings so Tailwind's content scanner keeps
them in the bundle (a runtime `badge-\#{status}` would be tree-shaken).
"""
@spec cycle_color_class(:paid | :unpaid | :suspended) :: String.t()
def cycle_color_class(:paid), do: "badge-success"
def cycle_color_class(:unpaid), do: "badge-error"
def cycle_color_class(:suspended), do: "badge-warning"
@doc """
Hero-icon name for a cycle status (reuses the established status icons).
"""
@spec cycle_icon(:paid | :unpaid | :suspended) :: String.t()
def cycle_icon(status), do: MembershipFeeHelpers.status_icon(status)
@doc """
Short, human-readable period label for a cycle, derived from its `cycle_start`
and the fee-type interval:
@ -313,7 +315,7 @@ defmodule MvWeb.MemberLive.Index.PaymentAging do
* yearly `"2025"`
* quarterly `"Q1 2026"`
* half-yearly `"H1 2026"`
* monthly `"März 2026"`
* monthly `"March 2026"`
Falls back to a `dd.MM.yyyydd.MM.yyyy` date range when the interval is not
loaded/known.