Skip to content

feat(dashboard): add Users settings page#800

Merged
aaight merged 1 commit intodevfrom
feature/users-settings-page
Mar 14, 2026
Merged

feat(dashboard): add Users settings page#800
aaight merged 1 commit intodevfrom
feature/users-settings-page

Conversation

@aaight
Copy link
Copy Markdown
Collaborator

@aaight aaight commented Mar 14, 2026

Summary

  • Adds /settings/users route page that loads users via trpc.users.list with loading/error states
  • Adds UsersTable component with Name, Email, Role (Badge), Created columns and Edit/Delete actions with AlertDialog confirmation
  • Adds UserFormDialog supporting Create and Edit modes (Name, Email, Password, Role); password optional in Edit mode
  • Registers settingsUsersRoute in route-tree.ts
  • Adds Users nav link (with Users icon from lucide-react) to the Settings section in sidebar.tsx

Closes: https://trello.com/c/taDscRmL/323-as-an-admin-i-want-a-users-settings-page-in-the-dashboard-so-that-i-can-manage-org-users-via-the-web-ui

Test plan

  • Navigate to /settings/users — page loads with user list or loading/error states
  • Sidebar shows "Users" link under Settings section
  • Clicking "New User" opens dialog with Name, Email, Password, Role fields; submitting creates user
  • Clicking Edit opens dialog pre-filled; password field optional; submitting updates user
  • Clicking Delete shows AlertDialog; confirming deletes user
  • Role selector offers member / admin / superadmin options
  • TypeScript: npm run typecheck and cd web && npx tsc --noEmit both pass
  • Linting: npm run lint passes

🤖 Generated with Claude Code

Copy link
Copy Markdown
Collaborator

@nhopeatall nhopeatall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

LGTM — Clean implementation that follows the established credentials page pattern exactly. CI passes, route registration is correct, backend authorization is solid (admin-only via adminProcedure, superadmin escalation guards).

Should Fix (non-blocking)

  • web/src/components/settings/user-form-dialog.tsx:26-31 — Stale form state on reopen: The UserFormDialog in users.tsx is rendered unconditionally (always mounted). After creating a user and closing the dialog, reopening "New User" will show the previously entered name/email/role because useState only initializes on mount. A useEffect that resets fields when open transitions to true (or adding key={createOpen ? 'open' : 'closed'} on the dialog) would fix this. Note: this is the same pattern as the existing CredentialFormDialog, so it's a pre-existing issue — not introduced by this PR.

  • web/src/components/settings/user-form-dialog.tsx:116-121 — The <select> uses raw HTML with hand-rolled Tailwind classes instead of the project's Select/SelectTrigger/SelectItem components from @/components/ui/select.js. Using the existing UI component would give consistent focus-ring behavior, keyboard navigation, and dark mode styling for free.

🕵️ claude-code · claude-opus-4-6 · run details

@aaight aaight merged commit 5a32a00 into dev Mar 14, 2026
6 checks passed
@nhopeatall
Copy link
Copy Markdown
Collaborator

Inline feedback on web/src/components/settings/user-form-dialog.tsx

Line 26-31 — [SHOULD_FIX] Stale form state on reopen

This dialog is always mounted in users.tsx (not conditionally rendered). After creating a user and closing, reopening "New User" will show the previously entered name/email/role because useState only initializes on mount.

Add a reset effect:

useEffect(() => {
  if (open) {
    setName(user?.name ?? '');
    setEmail(user?.email ?? '');
    setPassword('');
    setRole((user?.role as 'member' | 'admin' | 'superadmin') ?? 'member');
  }
}, [open, user]);

Note: The existing CredentialFormDialog has the same issue, so this is a pre-existing pattern — but worth fixing.


Line 116 — [SHOULD_FIX] Raw <select> instead of UI component

This uses a raw <select> with hand-rolled Tailwind classes. The project has a Select/SelectTrigger/SelectContent/SelectItem component set in @/components/ui/select.js that provides consistent focus rings, keyboard navigation, and dark mode styling. Consider using those instead for visual consistency.

🕵️ claude-code · claude-opus-4-6 · run details

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants