1
0
forked from baron/baron-sso

feat: disable remove button for self and last admin/owner in UI

This commit is contained in:
2026-03-19 11:21:03 +09:00
parent a6c552236f
commit 4d11d3e554

View File

@@ -10,6 +10,7 @@ import {
Users, Users,
} from "lucide-react"; } from "lucide-react";
import { useState } from "react"; import { useState } from "react";
import { useAuth } from "react-oidc-context";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { toast } from "sonner"; import { toast } from "sonner";
import { Badge } from "../../../components/ui/badge"; import { Badge } from "../../../components/ui/badge";
@@ -52,6 +53,8 @@ import { t } from "../../../lib/i18n";
type DialogMode = "owner" | "admin"; type DialogMode = "owner" | "admin";
export function TenantAdminsAndOwnersTab() { export function TenantAdminsAndOwnersTab() {
const auth = useAuth();
const currentUserId = auth.user?.profile.sub;
const { tenantId } = useParams<{ tenantId: string }>(); const { tenantId } = useParams<{ tenantId: string }>();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const [searchTerm, setSearchTerm] = useState(""); const [searchTerm, setSearchTerm] = useState("");
@@ -289,15 +292,36 @@ export function TenantAdminsAndOwnersTab() {
<Button <Button
variant="ghost" variant="ghost"
size="icon" size="icon"
className="opacity-0 group-hover:opacity-100 text-destructive hover:text-destructive hover:bg-destructive/10 transition-all" className={`opacity-0 group-hover:opacity-100 transition-all ${
owner.id === currentUserId ||
currentOwners.length <= 1
? "opacity-50 cursor-not-allowed"
: "text-destructive hover:text-destructive hover:bg-destructive/10"
}`}
onClick={() => onClick={() =>
handleRemoveOwner(owner.id, owner.name) handleRemoveOwner(owner.id, owner.name)
} }
disabled={removeOwnerMutation.isPending} disabled={
title={t( removeOwnerMutation.isPending ||
"ui.admin.tenants.owners.remove_title", owner.id === currentUserId ||
"소유자 권한 회수", currentOwners.length <= 1
)} }
title={
owner.id === currentUserId
? t(
"msg.admin.tenants.owners.remove_self",
"본인의 권한은 회수할 수 없습니다.",
)
: currentOwners.length <= 1
? t(
"msg.admin.tenants.owners.remove_last",
"마지막 소유자는 회수할 수 없습니다.",
)
: t(
"ui.admin.tenants.owners.remove_title",
"소유자 권한 회수",
)
}
> >
<Trash2 className="h-4 w-4" /> <Trash2 className="h-4 w-4" />
</Button> </Button>
@@ -395,15 +419,36 @@ export function TenantAdminsAndOwnersTab() {
<Button <Button
variant="ghost" variant="ghost"
size="icon" size="icon"
className="opacity-0 group-hover:opacity-100 text-destructive hover:text-destructive hover:bg-destructive/10 transition-all" className={`opacity-0 group-hover:opacity-100 transition-all ${
admin.id === currentUserId ||
currentAdmins.length <= 1
? "opacity-50 cursor-not-allowed"
: "text-destructive hover:text-destructive hover:bg-destructive/10"
}`}
onClick={() => onClick={() =>
handleRemoveAdmin(admin.id, admin.name) handleRemoveAdmin(admin.id, admin.name)
} }
disabled={removeAdminMutation.isPending} disabled={
title={t( removeAdminMutation.isPending ||
"ui.admin.tenants.admins.remove_title", admin.id === currentUserId ||
"관리자 권한 회수", currentAdmins.length <= 1
)} }
title={
admin.id === currentUserId
? t(
"msg.admin.tenants.admins.remove_self",
"본인의 권한은 회수할 수 없습니다.",
)
: currentAdmins.length <= 1
? t(
"msg.admin.tenants.admins.remove_last",
"마지막 관리자는 회수할 수 없습니다.",
)
: t(
"ui.admin.tenants.admins.remove_title",
"관리자 권한 회수",
)
}
> >
<Trash2 className="h-4 w-4" /> <Trash2 className="h-4 w-4" />
</Button> </Button>