Inline filtering results, select-all across pages, country flags, settings RBAC, and inline role changes
- Round detail: add skeleton loading for filtering stats, inline results table with expandable rows, pagination, override/reinstate, CSV export, and tooltip on AI summaries button (removes need for separate results page) - Projects: add select-all-across-pages with Gmail-style banner, show country flags with tooltip instead of country codes (table + card views), add listAllIds backend endpoint - Settings: allow PROGRAM_ADMIN access to settings page, restrict infrastructure tabs (AI, Email, Storage, Security, Webhooks) to SUPER_ADMIN only - Members: add inline role change via dropdown submenu in user actions, enforce role hierarchy (only super admins can modify admin/super-admin roles) in both backend and UI Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -42,11 +42,16 @@ const TAB_ROLES: Record<TabKey, RoleValue[] | undefined> = {
|
||||
}
|
||||
|
||||
const statusColors: Record<string, 'default' | 'success' | 'secondary' | 'destructive'> = {
|
||||
NONE: 'secondary',
|
||||
ACTIVE: 'success',
|
||||
INVITED: 'secondary',
|
||||
SUSPENDED: 'destructive',
|
||||
}
|
||||
|
||||
const statusLabels: Record<string, string> = {
|
||||
NONE: 'Not Invited',
|
||||
}
|
||||
|
||||
const roleColors: Record<string, 'default' | 'outline' | 'secondary'> = {
|
||||
JURY_MEMBER: 'default',
|
||||
MENTOR: 'secondary',
|
||||
@@ -92,6 +97,9 @@ export function MembersContent() {
|
||||
|
||||
const roles = TAB_ROLES[tab]
|
||||
|
||||
const { data: currentUser } = trpc.user.me.useQuery()
|
||||
const currentUserRole = currentUser?.role as RoleValue | undefined
|
||||
|
||||
const { data, isLoading } = trpc.user.list.useQuery({
|
||||
roles: roles,
|
||||
search: search || undefined,
|
||||
@@ -216,7 +224,7 @@ export function MembersContent() {
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant={statusColors[user.status] || 'secondary'}>
|
||||
{user.status}
|
||||
{statusLabels[user.status] || user.status}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
@@ -233,6 +241,8 @@ export function MembersContent() {
|
||||
userId={user.id}
|
||||
userEmail={user.email}
|
||||
userStatus={user.status}
|
||||
userRole={user.role as RoleValue}
|
||||
currentUserRole={currentUserRole}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
@@ -263,7 +273,7 @@ export function MembersContent() {
|
||||
</div>
|
||||
</div>
|
||||
<Badge variant={statusColors[user.status] || 'secondary'}>
|
||||
{user.status}
|
||||
{statusLabels[user.status] || user.status}
|
||||
</Badge>
|
||||
</div>
|
||||
</CardHeader>
|
||||
@@ -305,6 +315,8 @@ export function MembersContent() {
|
||||
userId={user.id}
|
||||
userEmail={user.email}
|
||||
userStatus={user.status}
|
||||
userRole={user.role as RoleValue}
|
||||
currentUserRole={currentUserRole}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
Reference in New Issue
Block a user