From abca3f3ad7fb9ccbedd82300ae9d758539a112bf Mon Sep 17 00:00:00 2001 From: Levi Gomes Date: Fri, 10 Jul 2026 00:50:39 -0300 Subject: [PATCH 1/2] feat(users): show role tag (member/manager/admin) on user cards Every user card on the Users page now displays exactly one role badge with a distinct color, instead of only platform admins having a tag. - Add UserRole type and optional role field to UserListResponse, matching the derived role exposed by the backend (US-14.2); the field is optional so older API responses still work - Add manager and member Badge variants with Shema tokens - UserCard renders the role badge via a role -> {variant, icon, label} map with precedence platform_admin > manager > member, falling back to is_platform_admin when the API does not send role --- src/components/pages/UsersPage/UserCard.tsx | 32 +++++++++++++++------ src/components/ui/badge.tsx | 2 ++ src/types/index.ts | 1 + src/types/user.ts | 3 ++ 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/components/pages/UsersPage/UserCard.tsx b/src/components/pages/UsersPage/UserCard.tsx index 704f0c0..38871d3 100644 --- a/src/components/pages/UsersPage/UserCard.tsx +++ b/src/components/pages/UsersPage/UserCard.tsx @@ -1,6 +1,13 @@ import { useNavigate } from "react-router" -import { Calendar, Shield, ChevronRight } from "lucide-react" -import type { UserListResponse, UserRoleResponse, AppResponse } from "@/types" +import { + Calendar, + Shield, + ChevronRight, + UserCog, + User as UserIcon, + type LucideIcon, +} from "lucide-react" +import type { UserListResponse, UserRoleResponse, AppResponse, UserRole } from "@/types" import { cn } from "@/utils/cn" import { Badge } from "@/components/ui/badge" import { card } from "@/styles" @@ -13,6 +20,15 @@ interface UserCardProps { apps: AppResponse[] } +const roleBadge: Record< + UserRole, + { variant: "admin" | "manager" | "member"; icon: LucideIcon; label: string } +> = { + platform_admin: { variant: "admin", icon: Shield, label: "Admin" }, + manager: { variant: "manager", icon: UserCog, label: "Manager" }, + member: { variant: "member", icon: UserIcon, label: "Member" }, +} + function getUniqueApps(roles: UserRoleResponse[], apps: AppResponse[]) { const appKeys = [...new Set(roles.map((r) => r.app_key))] return appKeys.map((key) => { @@ -24,6 +40,8 @@ function getUniqueApps(roles: UserRoleResponse[], apps: AppResponse[]) { export function UserCard({ user, roles, apps }: UserCardProps) { const navigate = useNavigate() const userApps = getUniqueApps(roles, apps) + const role = user.role ?? (user.is_platform_admin ? "platform_admin" : "member") + const { variant, icon: RoleIcon, label } = roleBadge[role] return (
{user.is_active ? "Active" : "Inactive"} - {user.is_platform_admin && ( - - - Admin - - )} + + + {label} +
diff --git a/src/components/ui/badge.tsx b/src/components/ui/badge.tsx index c636ffe..d36597b 100644 --- a/src/components/ui/badge.tsx +++ b/src/components/ui/badge.tsx @@ -13,6 +13,8 @@ const badgeVariants = cva( active: "bg-verde-claro/20 text-verde-claro", inactive: "bg-areia/30 text-verde", admin: "bg-telha/15 text-telha border border-telha/30", + manager: "bg-azul/25 text-verde border border-azul/60", + member: "bg-areia/30 text-verde border border-areia", }, }, defaultVariants: { diff --git a/src/types/index.ts b/src/types/index.ts index e343aa0..0ce331d 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -9,6 +9,7 @@ export type { } from "./auth" export type { + UserRole, UserListResponse, UserUpdate, UserRoleResponse, diff --git a/src/types/user.ts b/src/types/user.ts index 42c8b33..af24575 100644 --- a/src/types/user.ts +++ b/src/types/user.ts @@ -1,3 +1,5 @@ +export type UserRole = "member" | "manager" | "platform_admin"; + export interface UserListResponse { id: string email: string @@ -5,6 +7,7 @@ export interface UserListResponse { avatar_url: string | null is_active: boolean is_platform_admin: boolean + role?: UserRole; created_at: string } From d4c64cf304594675164c8f4e25603e6db6dafdd9 Mon Sep 17 00:00:00 2001 From: Levi Gomes Date: Wed, 15 Jul 2026 17:00:42 -0300 Subject: [PATCH 2/2] chore(ci): empty commit to re-trigger CI checks Co-Authored-By: Claude Opus 4.8 (1M context)