From d0a1d79fad292595a2381810054fb21f5ce4a1a0 Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Mon, 29 Jun 2026 16:28:26 +0330 Subject: [PATCH] update role + and fox --- .env | 4 +- src/config/Pages.ts | 1 + src/langs/fa.json | 1 + src/pages/users/RoleUpdate.tsx | 141 +++++++++ src/pages/users/RolesList.tsx | 11 +- src/pages/users/hooks/useUserData.ts | 15 + src/pages/users/service/UserService.ts | 10 + src/pages/users/types/UserTypes.ts | 12 + src/router/Main.tsx | 2 + src/shared/SideBar.tsx | 415 +++++++++++++++++++++---- 10 files changed, 545 insertions(+), 67 deletions(-) create mode 100644 src/pages/users/RoleUpdate.tsx diff --git a/.env b/.env index 78a7da3..c349e73 100644 --- a/.env +++ b/.env @@ -1,4 +1,4 @@ VITE_TOKEN_NAME = 'admin_token' VITE_REFRESH_TOKEN_NAME = 'admin_refresh_token' -VITE_BASE_URL = 'https://api.danakcorp.com' -# VITE_BASE_URL = 'http://10.73.49.88:3500' \ No newline at end of file +# VITE_BASE_URL = 'https://api.danakcorp.com' +VITE_BASE_URL = 'http://192.168.99.131:3500' \ No newline at end of file diff --git a/src/config/Pages.ts b/src/config/Pages.ts index fcd4026..45db021 100644 --- a/src/config/Pages.ts +++ b/src/config/Pages.ts @@ -81,6 +81,7 @@ export const Pages = { detail: "/users/detail/", roleList: "/users/roles-all", roleCreate: "/users/roles-add", + roleUpdate: "/users/roles-edit/", groupAdd: "/users/group-add", groupList: "/users/groups", }, diff --git a/src/langs/fa.json b/src/langs/fa.json index c6e956a..53a0510 100644 --- a/src/langs/fa.json +++ b/src/langs/fa.json @@ -696,6 +696,7 @@ "image": "تصویر حساب کاربری", "roles_list": "لیست نقش ها", "add_role": "افزودن نقش", + "update_role": "ویرایش نقش", "role_search": "جستجو در نقش ها", "title": "عنوان", "user": "کاربر", diff --git a/src/pages/users/RoleUpdate.tsx b/src/pages/users/RoleUpdate.tsx new file mode 100644 index 0000000..0c31375 --- /dev/null +++ b/src/pages/users/RoleUpdate.tsx @@ -0,0 +1,141 @@ +import { FC, useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' +import Button from '../../components/Button' +import { TickCircle } from 'iconsax-react' +import Input from '../../components/Input' +import CheckBoxComponent from '../../components/CheckBoxComponent' +import { useGetPermissions, useGetRoleDetail, useUpdateRole } from './hooks/useUserData' +import PageLoading from '../../components/PageLoading' +import { useFormik } from 'formik' +import { CreateRoleType, RolePermissionType } from './types/UserTypes' +import * as Yup from 'yup' +import { useNavigate, useParams } from 'react-router-dom' +import { Pages } from '../../config/Pages' +import { ErrorType } from '../../helpers/types' +import { toast } from 'react-toastify' + +const RoleUpdate: FC = () => { + + const { id } = useParams() + const { t } = useTranslation('global') + const navigate = useNavigate() + const [permissions, setPermissions] = useState([]) + const getPermissions = useGetPermissions() + const { data: roleDetail, isPending: isRoleDetailPending } = useGetRoleDetail(id || '') + const updateRole = useUpdateRole() + + const handleAdd = (permissionId: string) => { + if (permissions.includes(permissionId)) { + setPermissions(permissions.filter(permission => permission !== permissionId)) + } else { + setPermissions([...permissions, permissionId]) + } + } + + const formik = useFormik({ + initialValues: { + name: '', + permissions: [], + }, + validationSchema: Yup.object({ + name: Yup.string() + .required(t('errors.required')) + }), + onSubmit: (values) => { + if (permissions.length > 0) { + values.permissions = permissions + updateRole.mutate({ id: id || '', params: values }, { + onSuccess: () => { + toast.success(t('success')) + navigate(Pages.users.roleList) + }, + onError: (error: ErrorType) => { + toast.error(error.response?.data?.error?.message[0]) + } + }) + } else { + toast.error(t('user.error_count_permission')) + } + } + }) + + useEffect(() => { + const role = roleDetail?.data?.role + if (role) { + formik.setFieldValue('name', role.name) + const permissionIds = role.permissions?.map((permission: string | RolePermissionType) => + typeof permission === 'string' ? permission : permission.id + ) || [] + setPermissions(permissionIds) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [roleDetail]) + + if (getPermissions.isPending || isRoleDetailPending) { + return + } + + return ( +
+
+
+ {t('user.update_role')} +
+ +
+ +
+
+ + + +
+
+ {t('user.permissions')} +
+ +
+ { + getPermissions.data?.data?.permissions?.map((item: { id: string, name: string }) => { + return ( +
+ handleAdd(item.id)} + /> +
{item.name}
+
+ ) + }) + } +
+
+
+
+
+ +
+
+
+ ) +} + +export default RoleUpdate diff --git a/src/pages/users/RolesList.tsx b/src/pages/users/RolesList.tsx index a117591..8529fb7 100644 --- a/src/pages/users/RolesList.tsx +++ b/src/pages/users/RolesList.tsx @@ -1,10 +1,10 @@ import { FC, useState } from 'react' import { useTranslation } from 'react-i18next' import Button from '../../components/Button' -import { Add } from 'iconsax-react' +import { Add, Eye } from 'iconsax-react' import Input from '../../components/Input' import Td from '../../components/Td' -import { useNavigate } from 'react-router-dom' +import { Link, useNavigate } from 'react-router-dom' import { Pages } from '../../config/Pages' import { useGetRoles } from './hooks/useUserData' import { RoleItemType } from './types/UserTypes' @@ -57,6 +57,7 @@ const RolesList: FC = () => { + @@ -67,11 +68,11 @@ const RolesList: FC = () => { - {/* - + + - */} + ) }) diff --git a/src/pages/users/hooks/useUserData.ts b/src/pages/users/hooks/useUserData.ts index 97ed957..ccb28a0 100644 --- a/src/pages/users/hooks/useUserData.ts +++ b/src/pages/users/hooks/useUserData.ts @@ -26,6 +26,21 @@ export const useGetRoles = (search: string) => { }); }; +export const useGetRoleDetail = (id: string) => { + return useQuery({ + queryKey: ["role-detail", id], + queryFn: () => api.getRoleDetail(id), + enabled: !!id, + }); +}; + +export const useUpdateRole = () => { + return useMutation({ + mutationFn: ({ id, params }: { id: string; params: CreateRoleType }) => + api.updateRole(id, params), + }); +}; + export const useCreateUser = () => { return useMutation({ mutationFn: (variables: CreateUserType) => api.createUser(variables), diff --git a/src/pages/users/service/UserService.ts b/src/pages/users/service/UserService.ts index fa37190..0c2c5e9 100644 --- a/src/pages/users/service/UserService.ts +++ b/src/pages/users/service/UserService.ts @@ -20,6 +20,16 @@ export const getRoles = async (search: string) => { return data; }; +export const getRoleDetail = async (id: string) => { + const { data } = await axios.get(`/users/roles/${id}`); + return data; +}; + +export const updateRole = async (id: string, params: CreateRoleType) => { + const { data } = await axios.patch(`/users/roles/${id}`, params); + return data; +}; + export const createUser = async (params: CreateUserType) => { const { data } = await axios.post(`/users/admins`, params); return data; diff --git a/src/pages/users/types/UserTypes.ts b/src/pages/users/types/UserTypes.ts index 258f067..9582ea7 100644 --- a/src/pages/users/types/UserTypes.ts +++ b/src/pages/users/types/UserTypes.ts @@ -12,6 +12,18 @@ export type RoleItemType = { userCount: number; }; +export type RolePermissionType = { + id: string; + name: string; +}; + +export type RoleDetailType = { + id: string; + name: string; + isAdmin: boolean; + permissions: (string | RolePermissionType)[]; +}; + export type CreateUserType = { phone: string; firstName: string; diff --git a/src/router/Main.tsx b/src/router/Main.tsx index 1e7547e..7cb7399 100644 --- a/src/router/Main.tsx +++ b/src/router/Main.tsx @@ -92,6 +92,7 @@ import GroupCreate from "../pages/users/GroupCreate"; import GroupList from "../pages/users/GroupList"; import UsersList from "../pages/users/List"; import RoleCreate from "../pages/users/RoleCreate"; +import RoleUpdate from "../pages/users/RoleUpdate"; import RolesList from "../pages/users/RolesList"; import UpdateUser from "../pages/users/Update"; import Wallet from "../pages/wallet/Wallet"; @@ -167,6 +168,7 @@ const MainRouter: FC = () => { } /> } /> } /> + } /> } /> } /> } /> diff --git a/src/shared/SideBar.tsx b/src/shared/SideBar.tsx index fdc4d36..bcffa25 100644 --- a/src/shared/SideBar.tsx +++ b/src/shared/SideBar.tsx @@ -96,7 +96,12 @@ const SideBar: FC = () => { return ( <> - {openSidebar &&
setOpenSidebar(false)} />} + {openSidebar && ( +
setOpenSidebar(false)} + /> + )}
{ hasSubMenu && "w-24 !rounded-tl-none !rounded-bl-none", )} > -
{!hasSubMenu ? : }
+
+ {!hasSubMenu ? ( + + ) : ( + + )} +
{ {t("sidebar.menu")}
- +
} + icon={ + + } title={t("sidebar.mainpage")} isActive={isActive("dashboard")} link={Pages.dashboard} activeName="" /> } + icon={ + + } title={t("sidebar.services")} isActive={isActive("services")} link={Pages.services.list} @@ -136,7 +168,13 @@ const SideBar: FC = () => { /> } + icon={ + + } title={t("sidebar.support")} isActive={isActive("support")} link={Pages.support.list} @@ -144,21 +182,39 @@ const SideBar: FC = () => { /> } + icon={ + + } title={t("sidebar.customers")} isActive={isActive("customers")} link={Pages.customers.list} activeName="customers" /> } + icon={ + + } title={t("sidebar.representatives")} isActive={isActive("representatives")} link={Pages.representative.list} activeName="agents" /> } + icon={ + + } title={t("sidebar.developers")} isActive={isActive("developers")} link={Pages.developers.list} @@ -166,7 +222,13 @@ const SideBar: FC = () => { /> } + icon={ + + } title={t("sidebar.payments")} isActive={isActive("payments")} link={Pages.payment.list} @@ -174,26 +236,46 @@ const SideBar: FC = () => { /> } + icon={ + + } title={t("sidebar.code_referral")} isActive={isActive("referral-code")} link={Pages.referralCode.list} activeName="referralCode" /> } + icon={ + + } title={t("sidebar.users")} isActive={isActive("users")} link={Pages.users.list} activeName="admins" /> - } - title={t("sidebar.sliders")} - isActive={isActive("sliders")} - link={Pages.sliders.list} - activeName="blogs" - /> + {profile?.data?.user?.roles?.some((role: { name: string }) => role.name === "super_admin") && ( + + } + title={t("sidebar.sliders")} + isActive={isActive("sliders")} + link={Pages.sliders.list} + activeName="blogs" + /> + )}
{ @@ -204,13 +286,22 @@ const SideBar: FC = () => { {t("sidebar.financial")}
- +
}
} + icon={ + + } title={t("sidebar.subscriptions")} isActive={isActive("subscriptions")} link={Pages.subscriptions.list} @@ -218,7 +309,13 @@ const SideBar: FC = () => { /> } + icon={ + + } title={t("sidebar.receipt_list")} isActive={isActive("receipts")} link={Pages.receipts.index} @@ -226,7 +323,13 @@ const SideBar: FC = () => { /> } + icon={ + + } title={t("sidebar.transactions")} isActive={isActive("transactions")} link={Pages.transactions} @@ -234,7 +337,13 @@ const SideBar: FC = () => { /> } + icon={ + + } title={t("sidebar.discounts")} isActive={isActive("discounts")} link={Pages.discount.list} @@ -242,7 +351,13 @@ const SideBar: FC = () => { /> } + icon={ + + } title={t("sidebar.card")} isActive={isActive("card")} link={Pages.cardBank.list} @@ -258,14 +373,23 @@ const SideBar: FC = () => { {t("sidebar.other")}
- +
)}
} + icon={ + + } title={t("sidebar.ticket")} isActive={isActive("tickets")} link={Pages.ticket.list} @@ -273,7 +397,13 @@ const SideBar: FC = () => { /> } + icon={ + + } title={t("sidebar.feedback")} isActive={isActive("feedback")} link={Pages.feedback.list} @@ -282,7 +412,13 @@ const SideBar: FC = () => {
} + icon={ + + } title={t("sidebar.accessLogs")} isActive={isActive("access-logs")} link={Pages.accessLogs.list} @@ -293,7 +429,13 @@ const SideBar: FC = () => {
} + icon={ + + } title={t("sidebar.criticisms")} isActive={isActive("criticisms")} link={Pages.criticisms.list} @@ -310,13 +452,22 @@ const SideBar: FC = () => { {t("sidebar.taskmanager")}
- +
}
} + icon={ + + } title={t("sidebar.taskmanager")} isActive={isActive("taskmanager")} link={Pages.taskmanager.workspace + "dpage"} @@ -332,7 +483,10 @@ const SideBar: FC = () => { {t("sidebar.mnage_content")}
- +
)} @@ -346,13 +500,22 @@ const SideBar: FC = () => { {t("sidebar.reseller")}
- +
} + icon={ + + } title={t("sidebar.resellers")} isActive={isActive("reseller/list")} link={Pages.reseller.list} @@ -362,7 +525,13 @@ const SideBar: FC = () => {
} + icon={ + + } title={t("sidebar.withdraw")} isActive={isActive("reseller/withdraw")} link={Pages.reseller.withdraw} @@ -373,10 +542,16 @@ const SideBar: FC = () => { )} -
+
} + icon={ + + } title={t("sidebar.ads")} isActive={isActive("ads")} link={Pages.ads.list} @@ -386,7 +561,13 @@ const SideBar: FC = () => {
} + icon={ + + } title={t("sidebar.announcement")} isActive={isActive("announcement")} link={Pages.announcement.list} @@ -396,7 +577,13 @@ const SideBar: FC = () => {
} + icon={ + + } title={t("sidebar.blog")} isActive={isActive("blog")} link={Pages.blog.list} @@ -406,7 +593,13 @@ const SideBar: FC = () => {
} + icon={ + + } title={t("sidebar.learning")} isActive={isActive("learning")} link={Pages.learning.list} @@ -416,7 +609,13 @@ const SideBar: FC = () => {
} + icon={ + + } title={t("sidebar.messages")} isActive={isActive("messages")} link={Pages.messages.list} @@ -434,13 +633,22 @@ const SideBar: FC = () => { {t("sidebar.dmenu")}
- +
} + icon={ + + } title={t("sidebar.icons")} isActive={isActive("dmenu/icons/list")} link={Pages.dmenu.icons.list} @@ -450,7 +658,13 @@ const SideBar: FC = () => {
} + icon={ + + } title={t("sidebar.groups_icon")} isActive={isActive("dmenu/icons/group/list")} link={Pages.dmenu.icons.groupList} @@ -460,7 +674,13 @@ const SideBar: FC = () => {
} + icon={ + + } title={t("sidebar.reports")} isActive={isActive("dmenu/reports")} link={Pages.dmenu.warnings.list} @@ -470,7 +690,13 @@ const SideBar: FC = () => {
} + icon={ + + } title={t("sidebar.restaurants")} isActive={isActive("restaurants")} link={Pages.dmenu.restaurants.list} @@ -480,7 +706,13 @@ const SideBar: FC = () => {
} + icon={ + + } title={t("sidebar.sms_count")} isActive={isActive("sms-count")} link={Pages.dmenu.restaurants.smsCountList} @@ -500,13 +732,22 @@ const SideBar: FC = () => { {t("sidebar.dkala")}
- +
} + icon={ + + } title={t("sidebar.icons")} isActive={isActive("dkala/icons/list")} link={Pages.dkala.icons.list} @@ -516,7 +757,13 @@ const SideBar: FC = () => {
} + icon={ + + } title={t("sidebar.groups_icon")} isActive={isActive("dkala/icons/group")} link={Pages.dkala.icons.groupList} @@ -526,7 +773,13 @@ const SideBar: FC = () => {
} + icon={ + + } title={t("sidebar.reports")} isActive={isActive("dkala/reports")} link={Pages.dkala.warnings.list} @@ -536,7 +789,13 @@ const SideBar: FC = () => {
} + icon={ + + } title={t("sidebar.shops")} isActive={isActive("dkala/shops")} link={Pages.dkala.shops.list} @@ -546,7 +805,13 @@ const SideBar: FC = () => {
} + icon={ + + } title={t("sidebar.sms_count")} isActive={isActive("dkala/sms-count")} link={Pages.dkala.shops.smsCountList} @@ -565,13 +830,22 @@ const SideBar: FC = () => { {t("sidebar.dpage")}
- +
} + icon={ + + } title={t("sidebar.sticker")} isActive={isActive("dpage/stickers/list")} link={Pages.dpage.stickers.list} @@ -591,13 +865,22 @@ const SideBar: FC = () => { {t("sidebar.dmail")}
- +
} + icon={ + + } title={t("sidebar.domain")} isActive={isActive("dmail/domain/list")} link={Pages.dmail.list} @@ -612,7 +895,13 @@ const SideBar: FC = () => {
} + icon={ + + } title={t("sidebar.setting")} isActive={isActive("setting")} link={Pages.setting} @@ -621,7 +910,13 @@ const SideBar: FC = () => {
} + icon={ + + } title={t("sidebar.logout")} isActive={isActive("logout")} link={`#`}