From ebd2c3c8f7aab2761d3eeebc506c0245149add10 Mon Sep 17 00:00:00 2001 From: hosseintaromi Date: Fri, 18 Jul 2025 14:03:04 +0330 Subject: [PATCH] feat(roles): add role permissions management page - Two-column layout for assigned vs available permissions - Real-time permission assignment and removal - Confirmation modals for destructive actions - Complete permissions list with descriptions - Visual distinction between assigned and available permissions --- .../role-permissions/RolePermissionsPage.tsx | 275 ++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 src/pages/roles/role-permissions/RolePermissionsPage.tsx diff --git a/src/pages/roles/role-permissions/RolePermissionsPage.tsx b/src/pages/roles/role-permissions/RolePermissionsPage.tsx new file mode 100644 index 0000000..7386315 --- /dev/null +++ b/src/pages/roles/role-permissions/RolePermissionsPage.tsx @@ -0,0 +1,275 @@ +import { useState } from "react"; +import { useNavigate, useParams } from "react-router-dom"; +import { useRole, useRolePermissions, usePermissions, useAssignPermission, useRemovePermission } from "../core/_hooks"; +import { Button } from "@/components/ui/Button"; +import { LoadingSpinner } from "@/components/ui/LoadingSpinner"; +import { Permission } from "@/types/auth"; +import { ArrowRight, Plus, Trash2, Check } from "lucide-react"; +import { Modal } from "@/components/ui/Modal"; + +const RolePermissionsPage = () => { + const navigate = useNavigate(); + const { id = "" } = useParams(); + const [showAssignModal, setShowAssignModal] = useState(false); + const [removePermissionId, setRemovePermissionId] = useState(null); + + const { data: role, isLoading: roleLoading } = useRole(id); + const { data: rolePermissions, isLoading: permissionsLoading } = useRolePermissions(id); + const { data: allPermissions, isLoading: allPermissionsLoading } = usePermissions(); + const { mutate: assignPermission, isPending: assigning } = useAssignPermission(); + const { mutate: removePermission, isPending: removing } = useRemovePermission(); + + const handleAssignPermission = (permissionId: number) => { + assignPermission({ + roleId: id, + permissionId: permissionId.toString(), + }); + }; + + const handleRemovePermission = (permissionId: number) => { + setRemovePermissionId(permissionId.toString()); + }; + + const confirmRemovePermission = () => { + if (removePermissionId) { + removePermission({ + roleId: id, + permissionId: removePermissionId, + }, { + onSuccess: () => { + setRemovePermissionId(null); + } + }); + } + }; + + const cancelRemovePermission = () => { + setRemovePermissionId(null); + }; + + const isLoading = roleLoading || permissionsLoading; + + if (isLoading) return ; + if (!role) return
نقش یافت نشد
; + + const assignedPermissionIds = rolePermissions?.map(p => p.id) || []; + const availablePermissions = allPermissions?.filter(p => !assignedPermissionIds.includes(p.id)) || []; + + return ( +
+
+
+
+ +
+

+ مدیریت دسترسی‌های نقش +

+

+ {role.title} +

+
+
+ + +
+
+ +
+ {/* دسترسی‌های تخصیص یافته */} +
+
+

+ دسترسی‌های تخصیص یافته ({assignedPermissionIds.length}) +

+
+ +
+ {permissionsLoading ? ( +
+ +
+ ) : ( +
+ {rolePermissions && rolePermissions.length > 0 ? ( + rolePermissions.map((permission: Permission) => ( +
+
+

+ {permission.title} +

+

+ {permission.description} +

+
+ +
+ )) + ) : ( +

+ هیچ دسترسی تخصیص داده نشده است +

+ )} +
+ )} +
+
+ + {/* دسترسی‌های در دسترس */} +
+
+

+ دسترسی‌های قابل تخصیص ({availablePermissions.length}) +

+
+ +
+ {allPermissionsLoading ? ( +
+ +
+ ) : ( +
+ {availablePermissions.length > 0 ? ( + availablePermissions.map((permission: Permission) => ( +
+
+

+ {permission.title} +

+

+ {permission.description} +

+
+ +
+ )) + ) : ( +

+ تمام دسترسی‌ها به این نقش تخصیص داده شده است +

+ )} +
+ )} +
+
+
+ + {/* Assign Permission Modal */} + setShowAssignModal(false)} + title="اختصاص دسترسی جدید" + size="lg" + > +
+

+ دسترسی مورد نظر را برای تخصیص به نقش "{role.title}" انتخاب کنید: +

+ +
+ {availablePermissions.map((permission: Permission) => ( +
+
+

+ {permission.title} +

+

+ {permission.description} +

+
+ +
+ ))} +
+ +
+ +
+
+
+ + {/* Remove Permission Confirmation Modal */} + +
+

+ آیا از حذف این دسترسی از نقش اطمینان دارید؟ +

+
+ + +
+
+
+
+ ); +}; + +export default RolePermissionsPage; \ No newline at end of file