diff --git a/adminfront/src/features/tenants/routes/TenantAdminsAndOwnersTab.tsx b/adminfront/src/features/tenants/routes/TenantAdminsAndOwnersTab.tsx index 38f3554c..f150d322 100644 --- a/adminfront/src/features/tenants/routes/TenantAdminsAndOwnersTab.tsx +++ b/adminfront/src/features/tenants/routes/TenantAdminsAndOwnersTab.tsx @@ -11,7 +11,7 @@ import { } from "lucide-react"; import { useState } from "react"; import { useAuth } from "react-oidc-context"; -import { useParams } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; import { Badge } from "../../../components/ui/badge"; import { Button } from "../../../components/ui/button"; import { @@ -66,6 +66,7 @@ function mergePendingMembers( export function TenantAdminsAndOwnersTab() { const auth = useAuth(); + const navigate = useNavigate(); const currentUserId = auth.user?.profile.sub; const { tenantId } = useParams<{ tenantId: string }>(); const queryClient = useQueryClient(); @@ -398,22 +399,19 @@ export function TenantAdminsAndOwnersTab() { {t("ui.admin.tenants.owners.table_email", "이메일")} - - {t("ui.admin.tenants.owners.table_actions", "액션")} - {ownersQuery.isLoading ? ( - +
) : currentOwners.length === 0 ? (
@@ -431,7 +429,8 @@ export function TenantAdminsAndOwnersTab() { currentOwners.map((owner) => ( navigate(`/users/${owner.id}`)} >
@@ -444,46 +443,6 @@ export function TenantAdminsAndOwnersTab() { {owner.email} - - - - - {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", - "소유자 권한 회수", - )} - - - )) )} @@ -529,22 +488,19 @@ export function TenantAdminsAndOwnersTab() { {t("ui.admin.tenants.admins.table_email", "이메일")} - - {t("ui.admin.tenants.admins.table_actions", "액션")} - {adminsQuery.isLoading ? ( - +
) : currentAdmins.length === 0 ? (
@@ -562,7 +518,8 @@ export function TenantAdminsAndOwnersTab() { currentAdmins.map((admin) => ( navigate(`/users/${admin.id}`)} >
@@ -575,46 +532,6 @@ export function TenantAdminsAndOwnersTab() { {admin.email} - - - - - {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", - "관리자 권한 회수", - )} - - - )) )} diff --git a/adminfront/src/features/tenants/routes/TenantSubTenantsPage.tsx b/adminfront/src/features/tenants/routes/TenantSubTenantsPage.tsx index e950bc9e..e83f3ce2 100644 --- a/adminfront/src/features/tenants/routes/TenantSubTenantsPage.tsx +++ b/adminfront/src/features/tenants/routes/TenantSubTenantsPage.tsx @@ -72,16 +72,13 @@ function TenantSubTenantsPage() { {t("ui.admin.tenants.sub.table.status", "STATUS")} - - {t("ui.admin.tenants.sub.table.action", "ACTION")} - {subTenants.length === 0 && ( {t( @@ -92,7 +89,11 @@ function TenantSubTenantsPage() { )} {subTenants.map((tenant) => ( - + navigate(`/tenants/${tenant.id}`)} + > {tenant.name} @@ -108,16 +109,6 @@ function TenantSubTenantsPage() { {t(`ui.common.status.${tenant.status}`, tenant.status)} - - - ))} diff --git a/adminfront/src/features/tenants/routes/TenantUsersPage.tsx b/adminfront/src/features/tenants/routes/TenantUsersPage.tsx index 2f91f404..fb288807 100644 --- a/adminfront/src/features/tenants/routes/TenantUsersPage.tsx +++ b/adminfront/src/features/tenants/routes/TenantUsersPage.tsx @@ -9,7 +9,7 @@ import { UserMinus, UserPlus, } from "lucide-react"; -import { Link, useParams } from "react-router-dom"; +import { Link, useNavigate, useParams } from "react-router-dom"; import { Badge } from "../../../components/ui/badge"; import { Button } from "../../../components/ui/button"; import { @@ -38,6 +38,7 @@ import { t } from "../../../lib/i18n"; function TenantUsersPage() { const params = useParams<{ tenantId: string }>(); + const navigate = useNavigate(); const tenantId = params.tenantId ?? ""; const queryClient = useQueryClient(); @@ -137,15 +138,12 @@ function TenantUsersPage() { {t("ui.admin.tenants.members.table.status", "STATUS")} - - {t("ui.admin.tenants.members.table.actions", "ACTIONS")} - {usersQuery.isLoading ? ( - +
{t( @@ -171,7 +169,11 @@ function TenantUsersPage() { ) : ( users.map((user) => ( - + navigate(`/users/${user.id}`)} + > {user.name} @@ -198,43 +200,6 @@ function TenantUsersPage() { {t(`ui.common.status.${user.status}`, user.status)} - - - - - - - - - - {t( - "ui.admin.tenants.members.view_profile", - "상세 정보", - )} - - - - handleRemoveMember(user.id, user.name) - } - disabled={removeTenantMutation.isPending} - > - - {t( - "ui.admin.tenants.members.remove", - "조직에서 제외", - )} - - - - )) )} diff --git a/adminfront/src/features/users/UserCreatePage.tsx b/adminfront/src/features/users/UserCreatePage.tsx index a024ed14..d9e6bb48 100644 --- a/adminfront/src/features/users/UserCreatePage.tsx +++ b/adminfront/src/features/users/UserCreatePage.tsx @@ -152,6 +152,7 @@ function UserCreatePage() { grade: "", position: "", jobTitle: "", + role: "user", metadata: {}, }, }); @@ -354,6 +355,7 @@ function UserCreatePage() { password: data.password, name: data.name, phone: data.phone, + role: data.role, metadata, }; @@ -632,6 +634,37 @@ function UserCreatePage() {
+
+ + +

+ {t( + "msg.admin.users.create.form.role_help", + "시스템 접근 권한을 결정합니다.", + )} +

+
+
+
+ +
+ +
+
{ + if (selectedUserIds.length === 0) return; + bulkUpdateMutation.mutate({ userIds: selectedUserIds, role }); + }; + const handleBulkDelete = () => { if (selectedUserIds.length === 0) return; if ( @@ -577,6 +582,15 @@ function UserListPage() { {getSortIcon("status")}
+ requestSort("role")} + > +
+ {t("ui.admin.users.list.table.role", "ROLE")} + {getSortIcon("role")} +
+
requestSort("tenant_dept")} @@ -721,6 +735,45 @@ function UserListPage() {
+ + +
@@ -797,6 +850,35 @@ function UserListPage() { )}
+ {profile?.role === "super_admin" && ( + <> + +
+ + )}