feat(admin): list-plus-detail redesign of the admin users screen (BUNYIP-405) #403

Merged
longjacksonle merged 1 commit from feat/BUNYIP-405-admin-user-detail into main 2026-07-28 23:57:43 +02:00

What

Redesigns the admin users screen into the requested list-plus-detail pattern. The list was cluttered with 7 inline action buttons per row (View, Entitlements, Make Admin/Demote, Reset Password, Lifetime, Suspend, Delete); those actions now live only in the per-user detail view.

Key finding

The detail view (/admin/users/{id}) already existed and already hosts every management action - entitlements, promote/demote, reset password, lifetime grant/revoke, suspend, delete - plus identity/security and active-rate-limit cards. So no detail changes were needed; the work is the list.

List changes

Extracted a user_list_row helper (unit-testable):

  • Active rows are lightweight and the whole row links into the detail view. Each shows identity, the Admin badge, and an explicit verified/unverified indicator (green check "Verified" / amber "Unverified"), a disclosure chevron, and a hover highlight. No action buttons on the row.
  • Suspended rows keep their single inline Reactivate action and are intentionally not links: a soft-deleted user 404s on find_by_id (deleted_at IS NULL), so the detail view is unreachable for them. This matches the ticket, whose detail-action list omits reactivate and asks to keep the Active/Suspended split.
  • Active/Suspended tabs, search, and pagination are unchanged.

Added a chevron-right icon glyph.

Acceptance criteria

  • The users list shows verified/unverified status per user.
  • Clicking a user row opens a user detail view at its own route (active rows -> /admin/users/{id}).
  • Entitlements, make-admin/demote, reset-password, lifetime, and suspend live in the detail view, not on the list rows.
  • Each action still works from the detail view (unchanged handlers already reachable there; behaviour/redirects as before).
  • Active/Suspended tabs and pagination continue to work.

Verification

  • just check-container green: fmt + clippy -D warnings + all test binaries (119 web tests). Three new render tests: active row links to detail with no inline forms; unverified row shows the indicator; suspended row keeps Reactivate and is not a detail link.

🤖 Generated with Claude Code

## What Redesigns the admin users screen into the requested list-plus-detail pattern. The list was cluttered with 7 inline action buttons per row (View, Entitlements, Make Admin/Demote, Reset Password, Lifetime, Suspend, Delete); those actions now live only in the per-user detail view. ## Key finding The detail view (`/admin/users/{id}`) already existed and already hosts every management action - entitlements, promote/demote, reset password, lifetime grant/revoke, suspend, delete - plus identity/security and active-rate-limit cards. So no detail changes were needed; the work is the list. ## List changes Extracted a `user_list_row` helper (unit-testable): - **Active rows** are lightweight and the **whole row links** into the detail view. Each shows identity, the Admin badge, and an explicit **verified/unverified indicator** (green check "Verified" / amber "Unverified"), a disclosure chevron, and a hover highlight. No action buttons on the row. - **Suspended rows** keep their single inline **Reactivate** action and are intentionally **not** links: a soft-deleted user 404s on `find_by_id` (`deleted_at IS NULL`), so the detail view is unreachable for them. This matches the ticket, whose detail-action list omits reactivate and asks to keep the Active/Suspended split. - Active/Suspended tabs, search, and pagination are unchanged. Added a `chevron-right` icon glyph. ## Acceptance criteria - [x] The users list shows verified/unverified status per user. - [x] Clicking a user row opens a user detail view at its own route (active rows -> `/admin/users/{id}`). - [x] Entitlements, make-admin/demote, reset-password, lifetime, and suspend live in the detail view, not on the list rows. - [x] Each action still works from the detail view (unchanged handlers already reachable there; behaviour/redirects as before). - [x] Active/Suspended tabs and pagination continue to work. ## Verification - `just check-container` green: fmt + clippy `-D warnings` + all test binaries (119 web tests). Three new render tests: active row links to detail with no inline forms; unverified row shows the indicator; suspended row keeps Reactivate and is not a detail link. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(admin): list-plus-detail redesign of the admin users screen (BUNYIP-405)
All checks were successful
E2E / Playwright against deployment (pull_request) Successful in 1m24s
Check / fmt + clippy + build + tests (pull_request) Successful in 8m10s
Create release / Create release from merged PR (pull_request) Has been skipped
afe871b578
The admin users list rendered every management action inline on each row - View, Entitlements, Make Admin/Demote, Reset Password, Lifetime, Suspend, Delete - which was cluttered and gave no stable per-user URL. Reorganized into the requested list-plus-detail pattern.

The per-user detail view (`/admin/users/{id}`) already existed and already hosts every action (entitlements, promote/demote, reset password, lifetime grant/revoke, suspend, delete) plus the identity/security and active-rate-limit cards, so no detail changes were needed - the work is the list.

List changes (new `user_list_row` helper, so it is unit-testable):
- Active rows are now lightweight and the WHOLE row is a link into the detail view. Each shows identity, the Admin badge, and an explicit verified/unverified indicator (green check "Verified" / amber "Unverified"), with a disclosure chevron and a hover highlight. No action buttons on the row.
- Suspended rows keep their single inline Reactivate action and are intentionally NOT links: a soft-deleted user 404s on `find_by_id` (which filters `deleted_at IS NULL`), so the detail view is not reachable for them. This matches the ticket, whose detail-action list omits reactivate and asks to keep the Active/Suspended split.
- The Active/Suspended tabs, search, and pagination are unchanged.

Added a `chevron-right` icon glyph and three render tests: an active row links to the detail with no inline action forms, an unverified row shows the Unverified indicator, and a suspended row keeps Reactivate and is not a detail link.

Verified: `just check-container` green (fmt + clippy -D warnings + all test binaries, 119 web tests). Actions are unchanged handlers already reachable from the detail view, so their behaviour and redirects are as before.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L5dcYueNHByRnWJDYoDX1W
longjacksonle scheduled this pull request to auto merge when all checks succeed 2026-07-28 23:50:48 +02:00
longjacksonle deleted branch feat/BUNYIP-405-admin-user-detail 2026-07-28 23:57:43 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/bunyip!403
No description provided.