Refactor filters to use cycle status instead of paid field

Replace paid_filter with cycle_status_filter that filters based on
membership fee cycle status (last or current cycle). Update
PaymentFilterComponent to use new filter with options All, Paid, Unpaid.
Remove membership fee status filter dropdown. Extend
filter_members_by_cycle_status/3 to support both paid and unpaid filtering.
Update toggle_cycle_view to preserve filter state in URL.
This commit is contained in:
Moritz 2025-12-18 13:10:00 +01:00
parent 098b3b0a2a
commit c65b3808bf
Signed by: moritz
GPG key ID: 1020A035E5DD0824
10 changed files with 490 additions and 247 deletions

View file

@ -3,7 +3,7 @@ defmodule MvWeb.Components.PaymentFilterComponentTest do
Unit tests for the PaymentFilterComponent.
Tests cover:
- Rendering in all 3 filter states (nil, :paid, :not_paid)
- Rendering in all 3 filter states (nil, :paid, :unpaid)
- Event emission when selecting options
- ARIA attributes for accessibility
- Dropdown open/close behavior
@ -25,15 +25,15 @@ defmodule MvWeb.Components.PaymentFilterComponentTest do
test "renders with paid filter active", %{conn: conn} do
conn = conn_with_oidc_user(conn)
{:ok, view, _html} = live(conn, "/members?paid_filter=paid")
{:ok, view, _html} = live(conn, "/members?cycle_status_filter=paid")
# Should show badge when filter is active
assert has_element?(view, "#payment-filter .badge")
end
test "renders with not_paid filter active", %{conn: conn} do
test "renders with unpaid filter active", %{conn: conn} do
conn = conn_with_oidc_user(conn)
{:ok, view, _html} = live(conn, "/members?paid_filter=not_paid")
{:ok, view, _html} = live(conn, "/members?cycle_status_filter=unpaid")
# Should show badge when filter is active
assert has_element?(view, "#payment-filter .badge")
@ -82,7 +82,7 @@ defmodule MvWeb.Components.PaymentFilterComponentTest do
describe "filter selection" do
test "selecting 'All' clears the filter and updates URL", %{conn: conn} do
conn = conn_with_oidc_user(conn)
{:ok, view, _html} = live(conn, "/members?paid_filter=paid")
{:ok, view, _html} = live(conn, "/members?cycle_status_filter=paid")
# Open dropdown
view
@ -94,7 +94,7 @@ defmodule MvWeb.Components.PaymentFilterComponentTest do
|> element("#payment-filter button[phx-value-filter='']")
|> render_click()
# URL should not contain paid_filter param - wait for patch
# URL should not contain cycle_status_filter param - wait for patch
assert_patch(view)
end
@ -112,12 +112,12 @@ defmodule MvWeb.Components.PaymentFilterComponentTest do
|> element("#payment-filter button[phx-value-filter='paid']")
|> render_click()
# Wait for patch and check URL contains paid_filter=paid
# Wait for patch and check URL contains cycle_status_filter=paid
path = assert_patch(view)
assert path =~ "paid_filter=paid"
assert path =~ "cycle_status_filter=paid"
end
test "selecting 'Not paid' sets the filter and updates URL", %{conn: conn} do
test "selecting 'Unpaid' sets the filter and updates URL", %{conn: conn} do
conn = conn_with_oidc_user(conn)
{:ok, view, _html} = live(conn, "/members")
@ -126,14 +126,14 @@ defmodule MvWeb.Components.PaymentFilterComponentTest do
|> element("#payment-filter button[aria-haspopup='true']")
|> render_click()
# Select "Not paid" option
# Select "Unpaid" option
view
|> element("#payment-filter button[phx-value-filter='not_paid']")
|> element("#payment-filter button[phx-value-filter='unpaid']")
|> render_click()
# Wait for patch and check URL contains paid_filter=not_paid
# Wait for patch and check URL contains cycle_status_filter=unpaid
path = assert_patch(view)
assert path =~ "paid_filter=not_paid"
assert path =~ "cycle_status_filter=unpaid"
end
end
@ -166,7 +166,7 @@ defmodule MvWeb.Components.PaymentFilterComponentTest do
test "has aria-checked on selected option", %{conn: conn} do
conn = conn_with_oidc_user(conn)
{:ok, view, _html} = live(conn, "/members?paid_filter=paid")
{:ok, view, _html} = live(conn, "/members?cycle_status_filter=paid")
# Open dropdown
view