forked from baron/baron-sso
린트 적용
This commit is contained in:
@@ -43,9 +43,15 @@ import {
|
||||
import { t } from "../../../lib/i18n";
|
||||
import { toast } from "sonner";
|
||||
|
||||
type UserGroupNode = GroupSummary & { children: UserGroupNode[]; isExpanded?: boolean };
|
||||
type UserGroupNode = GroupSummary & {
|
||||
children: UserGroupNode[];
|
||||
isExpanded?: boolean;
|
||||
};
|
||||
|
||||
function buildGroupTree(groups: GroupSummary[], parentId: string | null = null): UserGroupNode[] {
|
||||
function buildGroupTree(
|
||||
groups: GroupSummary[],
|
||||
parentId: string | null = null,
|
||||
): UserGroupNode[] {
|
||||
const nodes: UserGroupNode[] = [];
|
||||
const childrenOf = new Map<string, UserGroupNode[]>();
|
||||
|
||||
@@ -56,7 +62,10 @@ function buildGroupTree(groups: GroupSummary[], parentId: string | null = null):
|
||||
|
||||
// Second pass: Populate children
|
||||
groups.forEach((group) => {
|
||||
const node: UserGroupNode = { ...group, children: childrenOf.get(group.id)! };
|
||||
const node: UserGroupNode = {
|
||||
...group,
|
||||
children: childrenOf.get(group.id)!,
|
||||
};
|
||||
if (group.parentId === parentId) {
|
||||
nodes.push(node);
|
||||
} else {
|
||||
@@ -73,7 +82,7 @@ function buildGroupTree(groups: GroupSummary[], parentId: string | null = null):
|
||||
|
||||
// Sort children for consistent rendering (optional, but good for UI)
|
||||
nodes.sort((a, b) => a.name.localeCompare(b.name));
|
||||
nodes.forEach(node => {
|
||||
nodes.forEach((node) => {
|
||||
node.children.sort((a, b) => a.name.localeCompare(b.name));
|
||||
});
|
||||
|
||||
@@ -130,11 +139,16 @@ const UserGroupTreeNode: React.FC<UserGroupTreeNodeProps> = ({
|
||||
<ChevronRight size={16} />
|
||||
)}
|
||||
</Button>
|
||||
) : (level > 0 && (
|
||||
) : (
|
||||
level > 0 && (
|
||||
<span className="inline-block w-6 text-center">
|
||||
<ChevronRight size={16} className="text-muted-foreground inline-block align-middle" />
|
||||
<ChevronRight
|
||||
size={16}
|
||||
className="text-muted-foreground inline-block align-middle"
|
||||
/>
|
||||
</span>
|
||||
))}
|
||||
)
|
||||
)}
|
||||
<Users size={14} className="text-muted-foreground" />
|
||||
<span className="font-semibold">{node.name}</span>
|
||||
<Badge variant="secondary" className="text-[10px] font-mono">
|
||||
@@ -221,7 +235,12 @@ function TenantGroupsPage() {
|
||||
parentId: newGroupParentId || undefined,
|
||||
}),
|
||||
onSuccess: () => {
|
||||
toast.success(t("msg.admin.groups.list.create_success", "그룹이 성공적으로 생성되었습니다."));
|
||||
toast.success(
|
||||
t(
|
||||
"msg.admin.groups.list.create_success",
|
||||
"그룹이 성공적으로 생성되었습니다.",
|
||||
),
|
||||
);
|
||||
groupsQuery.refetch();
|
||||
setNewGroupName("");
|
||||
setNewGroupNameDesc("");
|
||||
@@ -229,21 +248,27 @@ function TenantGroupsPage() {
|
||||
setNewGroupParentId(null);
|
||||
},
|
||||
onError: (error: AxiosError<{ error?: string }>) => {
|
||||
toast.error(t("msg.admin.groups.list.create_error", "그룹 생성 실패"), { description: error.response?.data?.error || error.message });
|
||||
}
|
||||
toast.error(t("msg.admin.groups.list.create_error", "그룹 생성 실패"), {
|
||||
description: error.response?.data?.error || error.message,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// 그룹 삭제
|
||||
const deleteMutation = useMutation({
|
||||
mutationFn: (id: string) => deleteGroup(tenantId, id),
|
||||
onSuccess: () => {
|
||||
toast.success(t("msg.admin.groups.list.delete_success", "그룹이 삭제되었습니다."));
|
||||
toast.success(
|
||||
t("msg.admin.groups.list.delete_success", "그룹이 삭제되었습니다."),
|
||||
);
|
||||
groupsQuery.refetch();
|
||||
setSelectedGroupId(null);
|
||||
},
|
||||
onError: (error: AxiosError<{ error?: string }>) => {
|
||||
toast.error(t("msg.admin.groups.list.delete_error", "그룹 삭제 실패"), { description: error.response?.data?.error || error.message });
|
||||
}
|
||||
toast.error(t("msg.admin.groups.list.delete_error", "그룹 삭제 실패"), {
|
||||
description: error.response?.data?.error || error.message,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// 멤버 추가
|
||||
@@ -251,12 +276,16 @@ function TenantGroupsPage() {
|
||||
mutationFn: ({ groupId, userId }: { groupId: string; userId: string }) =>
|
||||
addGroupMember(tenantId, groupId, userId),
|
||||
onSuccess: () => {
|
||||
toast.success(t("msg.admin.groups.members.add_success", "멤버가 추가되었습니다."));
|
||||
toast.success(
|
||||
t("msg.admin.groups.members.add_success", "멤버가 추가되었습니다."),
|
||||
);
|
||||
groupsQuery.refetch();
|
||||
},
|
||||
onError: (error: AxiosError<{ error?: string }>) => {
|
||||
toast.error(t("msg.common.error", "오류 발생"), { description: error.response?.data?.error || error.message });
|
||||
}
|
||||
toast.error(t("msg.common.error", "오류 발생"), {
|
||||
description: error.response?.data?.error || error.message,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// 멤버 제거
|
||||
@@ -264,15 +293,21 @@ function TenantGroupsPage() {
|
||||
mutationFn: ({ groupId, userId }: { groupId: string; userId: string }) =>
|
||||
removeGroupMember(tenantId, groupId, userId),
|
||||
onSuccess: () => {
|
||||
toast.success(t("msg.admin.groups.members.remove_success", "멤버가 제거되었습니다."));
|
||||
toast.success(
|
||||
t("msg.admin.groups.members.remove_success", "멤버가 제거되었습니다."),
|
||||
);
|
||||
groupsQuery.refetch();
|
||||
},
|
||||
onError: (error: AxiosError<{ error?: string }>) => {
|
||||
toast.error(t("msg.common.error", "오류 발생"), { description: error.response?.data?.error || error.message });
|
||||
}
|
||||
toast.error(t("msg.common.error", "오류 발생"), {
|
||||
description: error.response?.data?.error || error.message,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const groupTree = groupsQuery.data ? buildGroupTree(groupsQuery.data, tenantId) : [];
|
||||
const groupTree = groupsQuery.data
|
||||
? buildGroupTree(groupsQuery.data, tenantId)
|
||||
: [];
|
||||
|
||||
const handleAddSubGroup = (parentId: string) => {
|
||||
setNewGroupParentId(parentId);
|
||||
@@ -304,7 +339,10 @@ function TenantGroupsPage() {
|
||||
{t("ui.admin.groups.create.title", "새 그룹 생성")}
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
{t("ui.admin.groups.create.description", "새로운 사용자 그룹을 생성하고 계층 구조를 설정합니다.")}
|
||||
{t(
|
||||
"ui.admin.groups.create.description",
|
||||
"새로운 사용자 그룹을 생성하고 계층 구조를 설정합니다.",
|
||||
)}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
@@ -425,8 +463,14 @@ function TenantGroupsPage() {
|
||||
)}
|
||||
{!groupsQuery.isLoading && groupTree.length === 0 && (
|
||||
<TableRow>
|
||||
<TableCell colSpan={3} className="text-center py-8 text-muted-foreground">
|
||||
{t("msg.admin.groups.list.empty", "아직 등록된 그룹이 없습니다.")}
|
||||
<TableCell
|
||||
colSpan={3}
|
||||
className="text-center py-8 text-muted-foreground"
|
||||
>
|
||||
{t(
|
||||
"msg.admin.groups.list.empty",
|
||||
"아직 등록된 그룹이 없습니다.",
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
@@ -438,9 +482,16 @@ function TenantGroupsPage() {
|
||||
onSelect={setSelectedGroupId}
|
||||
selectedGroupId={selectedGroupId}
|
||||
onDelete={(id) => {
|
||||
if (window.confirm(t("msg.admin.groups.list.delete_confirm", "그룹을 삭제하시겠습니까?"))) {
|
||||
deleteMutation.mutate(id);
|
||||
}
|
||||
if (
|
||||
window.confirm(
|
||||
t(
|
||||
"msg.admin.groups.list.delete_confirm",
|
||||
"그룹을 삭제하시겠습니까?",
|
||||
),
|
||||
)
|
||||
) {
|
||||
deleteMutation.mutate(id);
|
||||
}
|
||||
}}
|
||||
onAddSubGroup={handleAddSubGroup}
|
||||
addMemberMutation={addMemberMutation}
|
||||
@@ -464,15 +515,22 @@ function TenantGroupsPage() {
|
||||
})}
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
{t("ui.admin.groups.detail.members_subtitle", "그룹에 속한 멤버들을 확인하고 관리합니다.")}
|
||||
{t(
|
||||
"ui.admin.groups.detail.members_subtitle",
|
||||
"그룹에 속한 멤버들을 확인하고 관리합니다.",
|
||||
)}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex justify-end mb-4">
|
||||
<Button size="sm" onClick={() => handleAddMember(currentGroup.id)} disabled={addMemberMutation.isPending}>
|
||||
<UserPlus size={14} className="mr-1" />
|
||||
{t("ui.common.add", "멤버 추가")}
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => handleAddMember(currentGroup.id)}
|
||||
disabled={addMemberMutation.isPending}
|
||||
>
|
||||
<UserPlus size={14} className="mr-1" />
|
||||
{t("ui.common.add", "멤버 추가")}
|
||||
</Button>
|
||||
</div>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
|
||||
Reference in New Issue
Block a user