feat(overview): rework filter builder with editable chips and native date ranges

Editable filter chips, uniformly-sized value controls, working field-picker
search, and native date-range inputs with relative presets in place of the
vendored calendar — native inputs give year-jump, manual entry and keyboard
accessibility for free.
This commit is contained in:
Simon 2026-07-10 16:27:15 +02:00
parent c0d1550401
commit 8303a39041
23 changed files with 1905 additions and 565 deletions

View file

@ -81,7 +81,7 @@ defmodule MvWeb.MemberLive.Index.PaymentAging do
(at least N unpaid cycles in the period)
* anything else `nil` (no payment-count filter)
"""
@spec parse_filter(term()) :: filter()
@spec parse_filter(term()) :: nil | :fully_paid | {:has_unpaid, 1..3}
def parse_filter("fully_paid"), do: :fully_paid
def parse_filter("unpaid_1"), do: {:has_unpaid, 1}
def parse_filter("unpaid_2"), do: {:has_unpaid, 2}
@ -212,17 +212,31 @@ defmodule MvWeb.MemberLive.Index.PaymentAging do
@doc """
Human-readable tooltip naming the active payment period with locally formatted
(`dd.MM.yyyy`) bounds (§1.28). The all-outstanding default names all
outstanding cycles; open-ended periods render an open bound as an ellipsis.
(`dd.MM.yyyy`) bounds (§1.28). Explains that the shown figures refer to the
filtered contribution period, then names it: the all-outstanding default
names all outstanding cycles; open-ended periods render an open bound as an
ellipsis.
"""
@spec period_tooltip(period()) :: String.t()
def period_tooltip(%{from: nil, to: nil}), do: gettext("Fees across all outstanding cycles")
def period_tooltip(%{from: nil, to: nil}),
do:
gettext(
"The values refer to the filtered contribution period. Fees across all outstanding cycles"
)
def period_tooltip(%{from: from, to: to}) do
gettext("Fees in period %{from}%{to}", from: period_bound(from), to: period_bound(to))
gettext(
"The values refer to the filtered contribution period. Fees in period %{from}%{to}",
from: period_bound(from),
to: period_bound(to)
)
end
def period_tooltip(_), do: gettext("Fees across all outstanding cycles")
def period_tooltip(_),
do:
gettext(
"The values refer to the filtered contribution period. Fees across all outstanding cycles"
)
defp period_bound(%Date{} = d), do: DateFormatter.format_date(d)
defp period_bound(_), do: ""