feat(admin): consolidate Users + Memberships into one filterable users page (BUNYIP-410) #407
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/BUNYIP-410-merge-users-memberships"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Merges the near-duplicate admin Users and Memberships pages into a single filterable users list, and removes the standalone Memberships page.
Users list
Server-side filtering (correct pagination)
UserRepository::list_paginatedgainstier(matched viaCOALESCE(subscription_tier,'standard')so NULL-tier rows count as standard) andverifiedfilters, threaded through/v1/admin/usersand the bunyip-web client. Both default to unfiltered, preserving pre-410 behaviour.Memberships page
/admin/membershipsredirects to the users list, preserving a tier filter as?tier=(old links/bookmarks still land somewhere sensible). The nav entry is removed./admin/memberships/{id}/grant|revoke) are kept, now redirecting to the user detail. The dead members-by-tier list fetch + itsAdminMembershipDTO are removed.Acceptance criteria
Verification
just check-containergreen: fmt + clippy-D warnings+ all test binaries (129 web tests). New tests: tier badge on the row, tier-label mapping, tri-state verified-filter parsing, and the/admin/memberships-> filtered-users redirect (tier preservation + junk-tier fallback).🤖 Generated with Claude Code
The admin panel had near-duplicate Users and Memberships pages. Merged them into a single users list that shows verification status and membership tier, with a filter bar, and removed the standalone Memberships page. Users list: - Each row now carries the membership-tier badge (Lifetime / Free / Early Adopter / Standard) alongside the existing verified/unverified indicator, so the tier the Memberships page showed is visible here at a glance. - A filter bar above the list filters by search, verification status, and tier. The verified/tier selects auto-submit on change; filters are preserved across the pager and the Active/Suspended tabs. Filtering is server-side for correct pagination: `UserRepository::list_paginated` gains `tier` (matched via `COALESCE(subscription_tier,'standard')` so NULL-tier rows count as standard) and `verified` filters, threaded through the `/v1/admin/users` query and the bunyip-web client. Both default to unfiltered, preserving pre-410 behaviour. Memberships page: - `/admin/memberships` now redirects to the users list, preserving a tier filter as `?tier=`, so old links/bookmarks land on the filtered view. The nav entry is removed. - No capability is lost: the grant/revoke lifetime actions already live on the user-detail page (BUNYIP-405), and the admin-override grant/revoke routes (`/admin/memberships/{id}/grant|revoke`) are kept, now redirecting to the user detail. The dead members-by-tier list fetch (`admin_api::memberships`) and its `AdminMembership` DTO are removed. Verified: `just check-container` green (fmt + clippy -D warnings + all test binaries, 129 web tests). New tests cover the tier badge on the row, the tier-label mapping, the tri-state verified-filter parsing, and the `/admin/memberships` -> filtered-users redirect (incl. tier preservation and junk-tier fallback). The tier/verified filter SQL (incl. COALESCE for NULL tiers and combined filters) was verified against a throwaway Postgres. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L5dcYueNHByRnWJDYoDX1W