permission menu

This commit is contained in:
hamid zarghami
2026-02-26 10:05:44 +03:30
parent f466f03fea
commit 2398f455b0
6 changed files with 65 additions and 16 deletions
+3 -3
View File
@@ -32,9 +32,9 @@ export const Paths = {
update: '/admin/update/',
},
role: {
list: '/admin/role',
create: '/admin/role/create',
update: '/admin/role/update/',
list: '/role',
create: '/role/create',
update: '/role/update/',
},
formBuilder: {
list: '/form-builder/list/',
+7
View File
@@ -52,3 +52,10 @@ export const useDeleteAdmin = () => {
},
});
};
export const useGetAdminMe = () => {
return useQuery({
queryKey: ["adminMe"],
queryFn: api.getAdminMe,
});
};
+6
View File
@@ -4,6 +4,7 @@ import type {
CreateAdminType,
RolesResponseType,
AdminDetailResponseType,
AdminMeResponseType,
} from "../types/Types";
export const getAdmins = async (page: number, limit: number = 10) => {
@@ -46,3 +47,8 @@ export const deleteAdmin = async (adminId: string) => {
const { data } = await axios.delete(`/admin/admins/${adminId}`);
return data;
};
export const getAdminMe = async () => {
const { data } = await axios.get<AdminMeResponseType>("/admin/admins/me");
return data;
};
+6
View File
@@ -48,3 +48,9 @@ export type RoleItemType = {
export type RolesResponseType = BaseResponse<RoleItemType[]>;
export type AdminDetailResponseType = BaseResponse<AdminItemType>;
/** Admin "me" response: admin with full role including permissions */
export type AdminMeDataType = Omit<AdminItemType, "role"> & {
role: RoleItemType;
};
export type AdminMeResponseType = BaseResponse<AdminMeDataType>;
+15
View File
@@ -26,6 +26,7 @@ import { t } from '../locale';
import Button from '@/components/Button';
const SideBar: FC = () => {
const { openSidebar, setOpenSidebar } = useSharedStore();
const location = useLocation();
@@ -64,6 +65,7 @@ const SideBar: FC = () => {
title={t('sidebar.mainPage')}
isActive={isActive('/home')}
link={Paths.home}
activeName='dashboard'
/>
<SideBarItem
@@ -71,6 +73,7 @@ const SideBar: FC = () => {
title={'محصولات'}
isActive={isActive('product')}
link={Paths.product.list}
activeName='manage_products'
/>
<SideBarItem
@@ -78,6 +81,7 @@ const SideBar: FC = () => {
title={'درخواست ها'}
isActive={isActive('requests')}
link={Paths.requests.list}
activeName='view_requests'
/>
<SideBarItem
@@ -85,6 +89,7 @@ const SideBar: FC = () => {
title={'پیش فاکتور'}
isActive={isActive('/invoice')}
link={Paths.perfomaInvoice.list}
activeName='view_invoices'
/>
<SideBarItem
@@ -92,6 +97,7 @@ const SideBar: FC = () => {
title={'سفارشات'}
isActive={isActive('order')}
link={Paths.order.list}
activeName={['view_orders', 'view_assigned_orders']}
/>
@@ -101,6 +107,7 @@ const SideBar: FC = () => {
title={'مشتریان'}
isActive={isActive('users')}
link={Paths.users.list}
activeName='view_users'
/>
<SideBarItem
@@ -108,6 +115,7 @@ const SideBar: FC = () => {
title={'چاپ'}
isActive={isActive('print')}
link={Paths.print.list}
activeName='view_print'
/>
<SideBarItem
@@ -115,6 +123,7 @@ const SideBar: FC = () => {
title={'ادمین'}
isActive={isActive('admin')}
link={Paths.admin.list}
activeName='manage_admins'
/>
<SideBarItem
@@ -122,6 +131,7 @@ const SideBar: FC = () => {
title={'نقش‌ها'}
isActive={isActive('role')}
link={Paths.role.list}
activeName='manage_roles'
/>
</div>
@@ -134,6 +144,7 @@ const SideBar: FC = () => {
title={t('sidebar.tickets')}
isActive={isActive('/tickets')}
link={Paths.tickets.list}
activeName='manage_tickets'
/>
<SideBarItem
@@ -141,6 +152,7 @@ const SideBar: FC = () => {
title={t('sidebar.announcement')}
isActive={isActive('/announcement')}
link={Paths.announcement.list}
activeName='manage_announcements'
/>
<SideBarItem
@@ -148,6 +160,7 @@ const SideBar: FC = () => {
title={t('sidebar.criticisms')}
isActive={isActive('/criticisms')}
link={Paths.criticisms.list}
activeName='manage_criticisms'
/>
<SideBarItem
@@ -155,6 +168,7 @@ const SideBar: FC = () => {
title={t('sidebar.learning')}
isActive={isActive('/learning')}
link={Paths.learning.list}
activeName='manage_learnings'
/>
</div>
@@ -176,6 +190,7 @@ const SideBar: FC = () => {
title={t('sidebar.logout')}
isActive={isActive('logout')}
link={`#`}
activeName=''
isLogout
/>
</div>
+28 -13
View File
@@ -5,6 +5,8 @@ import { Paths } from '../config/Paths'
// import { useLogout } from '../pages/auth/hooks/useAuthData'
import { removeToken } from '../config/func'
import { removeRefreshToken } from '../config/func'
import { useGetAdminMe } from '@/pages/admin/hooks/useAdminData'
import type { PermissionItemType } from '@/pages/admin/types/Types'
type Props = {
icon: ReactNode,
@@ -12,11 +14,14 @@ type Props = {
isActive: boolean,
link: string,
isLogout?: boolean,
isWithoutLine?: boolean
isWithoutLine?: boolean,
activeName?: string | string[]
}
const SideBarItem: FC<Props> = (props: Props) => {
const { data:adminPermissions } = useGetAdminMe();
// const logout = useLogout()
const handleLogout = async () => {
@@ -25,21 +30,31 @@ const SideBarItem: FC<Props> = (props: Props) => {
removeRefreshToken()
window.location.href = Paths.auth.login
}
const permissions: PermissionItemType[] = adminPermissions?.data?.role?.permissions ?? []
const hasPermission =
props.activeName === '' ||
(Array.isArray(props.activeName)
? permissions.some((p) => (props.activeName as string[]).includes(p.name))
: !!props.activeName && permissions.some((p) => p.name === props.activeName))
if (hasPermission) {
return (
<Link onClick={props.isLogout ? handleLogout : undefined} to={props.link} className={clx(
'h-12 rounded-2xl flex gap-2 text-[#4F5260] px-4 text-[13px] items-center',
props.isActive && 'bg-[#F5F7FC]',
)}>
<div className='flex gap-3 items-center'>
{props.icon}
<div className={`text-[#4F5260]`}>
{props.title}
return (
<Link onClick={props.isLogout ? handleLogout : undefined} to={props.link} className={clx(
'h-12 rounded-2xl flex gap-2 text-[#4F5260] px-4 text-[13px] items-center',
props.isActive && 'bg-[#F5F7FC]',
)}>
<div className='flex gap-3 items-center'>
{props.icon}
<div className={`text-[#4F5260]`}>
{props.title}
</div>
</div>
</div>
</Link>
)
</Link>
)
}
return null
}
export default SideBarItem