feat(ui): Improve UI for admins and owners

- Make 3 dots unclickable if there no available actions for an user.
- Remove "Add permissions" for admins because they have same permissions
as owner
This commit is contained in:
Vlad Vladov
2025-09-03 16:46:55 +03:00
parent a47a5f3b9e
commit 178ccb3f45

View File

@@ -86,6 +86,21 @@ export const ShowUsers = () => {
</TableHeader>
<TableBody>
{data?.map((member) => {
const canEditPermissions = member.role === "member";
const canDelete =
member.role !== "owner" &&
!isCloud &&
member.user.id !== session?.user?.id;
const canUnlink =
member.role !== "owner" &&
!(
member.role === "admin" &&
member.user.id === session?.user?.id
);
const hasAnyAction =
canEditPermissions || canDelete || canUnlink;
return (
<TableRow key={member.id}>
<TableCell className="w-[100px]">
@@ -114,122 +129,124 @@ export const ShowUsers = () => {
</TableCell>
<TableCell className="text-right flex justify-end">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
className="h-8 w-8 p-0"
>
<span className="sr-only">Open menu</span>
<MoreHorizontal className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuLabel>
Actions
</DropdownMenuLabel>
{hasAnyAction ? (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
className="h-8 w-8 p-0"
>
<span className="sr-only">
Open menu
</span>
<MoreHorizontal className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuLabel>
Actions
</DropdownMenuLabel>
{member.role !== "owner" && (
<AddUserPermissions
userId={member.user.id}
/>
)}
{canEditPermissions && (
<AddUserPermissions
userId={member.user.id}
/>
)}
{member.role !== "owner" && (
<>
{!isCloud &&
member.user.id !==
session?.user?.id && (
<DialogAction
title="Delete User"
description="Are you sure you want to delete this user?"
type="destructive"
onClick={async () => {
await mutateAsync({
userId: member.user.id,
})
.then(() => {
toast.success(
"User deleted successfully",
);
refetch();
})
.catch((err) => {
toast.error(
err?.message ||
"Error deleting user",
);
});
}}
>
<DropdownMenuItem
className="w-full cursor-pointer text-red-500 hover:!text-red-600"
onSelect={(e) =>
e.preventDefault()
}
>
Delete User
</DropdownMenuItem>
</DialogAction>
)}
{!(
member.role === "admin" &&
member.user.id === session?.user?.id
) && (
<DialogAction
title="Unlink User"
description="Are you sure you want to unlink this user?"
type="destructive"
onClick={async () => {
try {
if (!isCloud) {
const orgCount =
await utils.user.checkUserOrganizations.fetch(
{
userId: member.user.id,
},
);
if (orgCount === 1) {
await mutateAsync({
userId: member.user.id,
});
toast.success(
"User deleted successfully",
);
refetch();
return;
}
}
await removeMember({
memberId: member.id,
});
{canDelete && (
<DialogAction
title="Delete User"
description="Are you sure you want to delete this user?"
type="destructive"
onClick={async () => {
await mutateAsync({
userId: member.user.id,
})
.then(() => {
toast.success(
"User unlinked successfully",
"User deleted successfully",
);
refetch();
} catch (error: any) {
})
.catch((err) => {
toast.error(
error?.message ||
"Error unlinking user",
err?.message ||
"Error deleting user",
);
}
}}
});
}}
>
<DropdownMenuItem
className="w-full cursor-pointer text-red-500 hover:!text-red-600"
onSelect={(e) => e.preventDefault()}
>
<DropdownMenuItem
className="w-full cursor-pointer text-red-500 hover:!text-red-600"
onSelect={(e) =>
e.preventDefault()
Delete User
</DropdownMenuItem>
</DialogAction>
)}
{canUnlink && (
<DialogAction
title="Unlink User"
description="Are you sure you want to unlink this user?"
type="destructive"
onClick={async () => {
try {
if (!isCloud) {
const orgCount =
await utils.user.checkUserOrganizations.fetch(
{
userId: member.user.id,
},
);
if (orgCount === 1) {
await mutateAsync({
userId: member.user.id,
});
toast.success(
"User deleted successfully",
);
refetch();
return;
}
}
>
Unlink User
</DropdownMenuItem>
</DialogAction>
)}
</>
)}
</DropdownMenuContent>
</DropdownMenu>
await removeMember({
memberId: member.id,
});
toast.success(
"User unlinked successfully",
);
refetch();
} catch (error: any) {
toast.error(
error?.message ||
"Error unlinking user",
);
}
}}
>
<DropdownMenuItem
className="w-full cursor-pointer text-red-500 hover:!text-red-600"
onSelect={(e) => e.preventDefault()}
>
Unlink User
</DropdownMenuItem>
</DialogAction>
)}
</DropdownMenuContent>
</DropdownMenu>
) : (
<Button
variant="ghost"
className="h-8 w-8 p-0"
disabled
>
<span className="sr-only">
No actions available
</span>
<MoreHorizontal className="h-4 w-4 text-muted-foreground" />
</Button>
)}
</TableCell>
</TableRow>
);