crud role
This commit is contained in:
@@ -31,6 +31,11 @@ export const Paths = {
|
|||||||
create: '/admin/create',
|
create: '/admin/create',
|
||||||
update: '/admin/update/',
|
update: '/admin/update/',
|
||||||
},
|
},
|
||||||
|
role: {
|
||||||
|
list: '/admin/role',
|
||||||
|
create: '/admin/role/create',
|
||||||
|
update: '/admin/role/update/',
|
||||||
|
},
|
||||||
formBuilder: {
|
formBuilder: {
|
||||||
list: '/form-builder/list/',
|
list: '/form-builder/list/',
|
||||||
create: '/form-builder/create/',
|
create: '/form-builder/create/',
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
import { useFormik } from "formik";
|
||||||
|
import { type FC } from "react";
|
||||||
|
import type { CreateRoleType } from "./types/Types";
|
||||||
|
import * as Yup from "yup";
|
||||||
|
import Button from "@/components/Button";
|
||||||
|
import { AddSquare } from "iconsax-react";
|
||||||
|
import Input from "@/components/Input";
|
||||||
|
import { useCreateRole, useGetPermissions } from "./hooks/useRoleData";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { toast } from "react-toastify";
|
||||||
|
import { extractErrorMessage } from "@/config/func";
|
||||||
|
import { Paths } from "@/config/Paths";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { clx } from "@/helpers/utils";
|
||||||
|
|
||||||
|
const CreateRole: FC = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { mutate: createRole, isPending } = useCreateRole();
|
||||||
|
const { data: permissionsData } = useGetPermissions();
|
||||||
|
|
||||||
|
const formik = useFormik<CreateRoleType>({
|
||||||
|
initialValues: {
|
||||||
|
name: "",
|
||||||
|
title: "",
|
||||||
|
permissionIds: [],
|
||||||
|
},
|
||||||
|
validationSchema: Yup.object({
|
||||||
|
name: Yup.string()
|
||||||
|
.required("نام اجباری می باشد")
|
||||||
|
.min(2, "نام باید حداقل 2 کاراکتر باشد"),
|
||||||
|
title: Yup.string(),
|
||||||
|
permissionIds: Yup.array().of(Yup.string()),
|
||||||
|
}),
|
||||||
|
onSubmit: (values) => {
|
||||||
|
createRole(values, {
|
||||||
|
onSuccess: () => {
|
||||||
|
toast.success("نقش با موفقیت ایجاد شد");
|
||||||
|
navigate(Paths.role.list);
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
toast.error(extractErrorMessage(error));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const permissions = permissionsData?.data ?? [];
|
||||||
|
|
||||||
|
const togglePermission = (permissionId: string) => {
|
||||||
|
const current = formik.values.permissionIds;
|
||||||
|
const next = current.includes(permissionId)
|
||||||
|
? current.filter((id) => id !== permissionId)
|
||||||
|
: [...current, permissionId];
|
||||||
|
formik.setFieldValue("permissionIds", next);
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectAll = () => {
|
||||||
|
if (formik.values.permissionIds.length === permissions.length) {
|
||||||
|
formik.setFieldValue("permissionIds", []);
|
||||||
|
} else {
|
||||||
|
formik.setFieldValue(
|
||||||
|
"permissionIds",
|
||||||
|
permissions.map((p) => p.id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-5">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<h1 className="text-lg font-light">ایجاد نقش جدید</h1>
|
||||||
|
<Button
|
||||||
|
className="w-fit px-6"
|
||||||
|
onClick={() => formik.handleSubmit()}
|
||||||
|
isLoading={isPending}
|
||||||
|
>
|
||||||
|
<div className="flex gap-1.5">
|
||||||
|
<AddSquare size={18} color="black" />
|
||||||
|
<div className="text-[13px] font-light">ایجاد نقش</div>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8 bg-white p-6 rounded-3xl flex-1">
|
||||||
|
<div className="rowTwoInput">
|
||||||
|
<Input
|
||||||
|
label="نام"
|
||||||
|
placeholder="نام را وارد کنید"
|
||||||
|
{...formik.getFieldProps("name")}
|
||||||
|
error_text={
|
||||||
|
formik.touched.name && formik.errors.name ? formik.errors.name : ""
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
label="عنوان"
|
||||||
|
placeholder="عنوان را وارد کنید"
|
||||||
|
{...formik.getFieldProps("title")}
|
||||||
|
error_text={
|
||||||
|
formik.touched.title && formik.errors.title
|
||||||
|
? formik.errors.title
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-6">
|
||||||
|
<div className="flex items-center justify-between mb-2">
|
||||||
|
<label className="block text-sm font-medium text-gray-700">
|
||||||
|
دسترسیها
|
||||||
|
</label>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={selectAll}
|
||||||
|
className="text-xs text-primary hover:underline"
|
||||||
|
>
|
||||||
|
{formik.values.permissionIds.length === permissions.length
|
||||||
|
? "حذف همه"
|
||||||
|
: "انتخاب همه"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={clx(
|
||||||
|
"border border-gray-200 rounded-xl p-4 max-h-64 overflow-y-auto",
|
||||||
|
"flex gap-6 flex-wrap"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{permissions.map((p) => (
|
||||||
|
<label
|
||||||
|
key={p.id}
|
||||||
|
className="flex items-center gap-2 cursor-pointer hover:bg-gray-50 p-2 rounded-lg"
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
checked={formik.values.permissionIds.includes(p.id)}
|
||||||
|
onCheckedChange={() => togglePermission(p.id)}
|
||||||
|
/>
|
||||||
|
<span className="text-sm">
|
||||||
|
{p.title || p.name}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CreateRole;
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
import { type FC } from "react";
|
||||||
|
import { useGetRoles, useDeleteRole } from "./hooks/useRoleData";
|
||||||
|
import Table from "@/components/Table";
|
||||||
|
import moment from "moment-jalaali";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import { Paths } from "@/config/Paths";
|
||||||
|
import Button from "@/components/Button";
|
||||||
|
import { AddSquare, Eye } from "iconsax-react";
|
||||||
|
import TrashWithConfrim from "@/components/TrashWithConfrim";
|
||||||
|
import type { RoleItemType } from "./types/Types";
|
||||||
|
|
||||||
|
const RoleList: FC = () => {
|
||||||
|
const { data, isLoading } = useGetRoles();
|
||||||
|
const deleteRoleMutation = useDeleteRole();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-5">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<h1 className="text-lg font-light">نقشها</h1>
|
||||||
|
<Link to={Paths.role.create}>
|
||||||
|
<Button className="w-fit px-6">
|
||||||
|
<div className="flex gap-1.5">
|
||||||
|
<AddSquare size={18} color="black" />
|
||||||
|
<div className="text-[13px] font-light">نقش جدید</div>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Table<RoleItemType>
|
||||||
|
columns={[
|
||||||
|
{
|
||||||
|
key: "name",
|
||||||
|
title: "نام",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "title",
|
||||||
|
title: "عنوان",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "isSystem",
|
||||||
|
title: "سیستمی",
|
||||||
|
render: (item) => (
|
||||||
|
<div>{item.isSystem ? "بله" : "خیر"}</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "permissionsCount",
|
||||||
|
title: "تعداد دسترسیها",
|
||||||
|
render: (item) => (
|
||||||
|
<div>{item.permissions?.length ?? 0}</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "createdAt",
|
||||||
|
title: "تاریخ ثبت",
|
||||||
|
render: (item) => (
|
||||||
|
<div>{moment(item.createdAt).format("jYYYY-jMM-jDD")}</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "actions",
|
||||||
|
title: "عملیات",
|
||||||
|
render: (item) => (
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Link to={`${Paths.role.update}${item.id}`}>
|
||||||
|
<Eye size={20} color="black" />
|
||||||
|
</Link>
|
||||||
|
{!item.isSystem && (
|
||||||
|
<TrashWithConfrim
|
||||||
|
onDelete={() => deleteRoleMutation.mutate(item.id)}
|
||||||
|
isloading={deleteRoleMutation.isPending}
|
||||||
|
colorIcon="#ef4444"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
data={data?.data}
|
||||||
|
isLoading={isLoading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RoleList;
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
import { useFormik } from "formik";
|
||||||
|
import { type FC, useEffect } from "react";
|
||||||
|
import type { CreateRoleType } from "./types/Types";
|
||||||
|
import * as Yup from "yup";
|
||||||
|
import Button from "@/components/Button";
|
||||||
|
import { Edit } from "iconsax-react";
|
||||||
|
import Input from "@/components/Input";
|
||||||
|
import { useGetRoleById, useGetPermissions, useUpdateRole } from "./hooks/useRoleData";
|
||||||
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
|
import { toast } from "react-toastify";
|
||||||
|
import { extractErrorMessage } from "@/config/func";
|
||||||
|
import { Paths } from "@/config/Paths";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { clx } from "@/helpers/utils";
|
||||||
|
|
||||||
|
const UpdateRole: FC = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { id: roleId } = useParams<{ id: string }>();
|
||||||
|
const { mutate: update, isPending: isUpdating } = useUpdateRole();
|
||||||
|
const { data: permissionsData } = useGetPermissions();
|
||||||
|
const { data: roleData, isLoading: isLoadingRole } = useGetRoleById(roleId);
|
||||||
|
|
||||||
|
const formik = useFormik<CreateRoleType>({
|
||||||
|
initialValues: {
|
||||||
|
name: "",
|
||||||
|
title: "",
|
||||||
|
permissionIds: [],
|
||||||
|
},
|
||||||
|
validationSchema: Yup.object({
|
||||||
|
name: Yup.string()
|
||||||
|
.required("نام اجباری می باشد")
|
||||||
|
.min(2, "نام باید حداقل 2 کاراکتر باشد"),
|
||||||
|
title: Yup.string(),
|
||||||
|
permissionIds: Yup.array().of(Yup.string()),
|
||||||
|
}),
|
||||||
|
onSubmit: (values) => {
|
||||||
|
if (!roleId) return;
|
||||||
|
|
||||||
|
update(
|
||||||
|
{ roleId, params: values },
|
||||||
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
toast.success("نقش با موفقیت ویرایش شد");
|
||||||
|
navigate(Paths.role.list);
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
toast.error(extractErrorMessage(error));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (roleData?.data) {
|
||||||
|
const role = roleData.data;
|
||||||
|
formik.setValues({
|
||||||
|
name: role.name ?? "",
|
||||||
|
title: role.title ?? "",
|
||||||
|
permissionIds: role.permissions?.map((p) => p.id) ?? [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [roleData]);
|
||||||
|
|
||||||
|
const permissions = permissionsData?.data ?? [];
|
||||||
|
|
||||||
|
const togglePermission = (permissionId: string) => {
|
||||||
|
const current = formik.values.permissionIds;
|
||||||
|
const next = current.includes(permissionId)
|
||||||
|
? current.filter((id) => id !== permissionId)
|
||||||
|
: [...current, permissionId];
|
||||||
|
formik.setFieldValue("permissionIds", next);
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectAll = () => {
|
||||||
|
if (formik.values.permissionIds.length === permissions.length) {
|
||||||
|
formik.setFieldValue("permissionIds", []);
|
||||||
|
} else {
|
||||||
|
formik.setFieldValue(
|
||||||
|
"permissionIds",
|
||||||
|
permissions.map((p) => p.id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isLoadingRole) {
|
||||||
|
return (
|
||||||
|
<div className="mt-5">
|
||||||
|
<div className="flex justify-center items-center h-64">
|
||||||
|
<div className="text-lg">در حال بارگذاری...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!roleData?.data) {
|
||||||
|
return (
|
||||||
|
<div className="mt-5">
|
||||||
|
<div className="flex justify-center items-center h-64">
|
||||||
|
<div className="text-lg text-red-500">نقش یافت نشد</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-5">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<h1 className="text-lg font-light">ویرایش نقش</h1>
|
||||||
|
<Button
|
||||||
|
className="w-fit px-6"
|
||||||
|
onClick={() => formik.handleSubmit()}
|
||||||
|
isLoading={isUpdating}
|
||||||
|
>
|
||||||
|
<div className="flex gap-1.5">
|
||||||
|
<Edit size={18} color="black" />
|
||||||
|
<div className="text-[13px] font-light">ویرایش نقش</div>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8 bg-white p-6 rounded-3xl flex-1">
|
||||||
|
<div className="rowTwoInput">
|
||||||
|
<Input
|
||||||
|
label="نام"
|
||||||
|
placeholder="نام را وارد کنید"
|
||||||
|
{...formik.getFieldProps("name")}
|
||||||
|
error_text={
|
||||||
|
formik.touched.name && formik.errors.name ? formik.errors.name : ""
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
label="عنوان"
|
||||||
|
placeholder="عنوان را وارد کنید"
|
||||||
|
{...formik.getFieldProps("title")}
|
||||||
|
error_text={
|
||||||
|
formik.touched.title && formik.errors.title
|
||||||
|
? formik.errors.title
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-6">
|
||||||
|
<div className="flex items-center justify-between mb-2">
|
||||||
|
<label className="block text-sm font-medium text-gray-700">
|
||||||
|
دسترسیها
|
||||||
|
</label>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={selectAll}
|
||||||
|
className="text-xs text-primary hover:underline"
|
||||||
|
>
|
||||||
|
{formik.values.permissionIds.length === permissions.length
|
||||||
|
? "حذف همه"
|
||||||
|
: "انتخاب همه"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={clx(
|
||||||
|
"border border-gray-200 rounded-xl p-4 max-h-64 overflow-y-auto",
|
||||||
|
"flex gap-6 flex-wrap"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{permissions.map((p) => (
|
||||||
|
<label
|
||||||
|
key={p.id}
|
||||||
|
className="flex items-center gap-2 cursor-pointer hover:bg-gray-50 p-2 rounded-lg"
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
checked={formik.values.permissionIds.includes(p.id)}
|
||||||
|
onCheckedChange={() => togglePermission(p.id)}
|
||||||
|
/>
|
||||||
|
<span className="text-sm">{p.title || p.name}</span>
|
||||||
|
</label>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UpdateRole;
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import * as api from "../service/RoleService";
|
||||||
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
|
import type { CreateRoleType } from "../types/Types";
|
||||||
|
|
||||||
|
export const useGetRoles = () => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["roles"],
|
||||||
|
queryFn: api.getRoles,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useGetPermissions = () => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["roles", "permissions"],
|
||||||
|
queryFn: api.getPermissions,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useGetRoleById = (roleId: string | undefined) => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["role", roleId],
|
||||||
|
queryFn: () => api.getRoleById(roleId!),
|
||||||
|
enabled: !!roleId,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useCreateRole = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: api.createRole,
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["roles"] });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useUpdateRole = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: ({
|
||||||
|
roleId,
|
||||||
|
params,
|
||||||
|
}: {
|
||||||
|
roleId: string;
|
||||||
|
params: CreateRoleType;
|
||||||
|
}) => api.updateRole(roleId, params),
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["roles"] });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useDeleteRole = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: api.deleteRole,
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["roles"] });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import axios from "@/config/axios";
|
||||||
|
import type {
|
||||||
|
RolesResponseType,
|
||||||
|
PermissionsResponseType,
|
||||||
|
RoleDetailResponseType,
|
||||||
|
CreateRoleType,
|
||||||
|
} from "../types/Types";
|
||||||
|
|
||||||
|
export const getRoles = async () => {
|
||||||
|
const { data } = await axios.get<RolesResponseType>("/admin/roles");
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getPermissions = async () => {
|
||||||
|
const { data } = await axios.get<PermissionsResponseType>(
|
||||||
|
"/admin/roles/permissions"
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getRoleById = async (roleId: string) => {
|
||||||
|
const { data } = await axios.get<RoleDetailResponseType>(
|
||||||
|
`/admin/roles/${roleId}`
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createRole = async (params: CreateRoleType) => {
|
||||||
|
const { data } = await axios.post("/admin/role", params);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateRole = async (roleId: string, params: CreateRoleType) => {
|
||||||
|
const { data } = await axios.patch(`/admin/roles/${roleId}`, params);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteRole = async (roleId: string) => {
|
||||||
|
const { data } = await axios.delete(`/admin/roles/${roleId}`);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import type { RowDataType } from "@/components/types/TableTypes";
|
||||||
|
import type { BaseResponse } from "@/shared/types/Types";
|
||||||
|
|
||||||
|
export interface PermissionItemType {
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
deletedAt: string | null;
|
||||||
|
name: string;
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RoleItemType extends RowDataType {
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
deletedAt: string | null;
|
||||||
|
name: string;
|
||||||
|
title: string;
|
||||||
|
isSystem: boolean;
|
||||||
|
permissions: PermissionItemType[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RolesResponseType = BaseResponse<RoleItemType[]>;
|
||||||
|
export type PermissionsResponseType = BaseResponse<PermissionItemType[]>;
|
||||||
|
export type RoleDetailResponseType = BaseResponse<RoleItemType>;
|
||||||
|
|
||||||
|
export type CreateRoleType = {
|
||||||
|
name: string;
|
||||||
|
title: string;
|
||||||
|
permissionIds: string[];
|
||||||
|
};
|
||||||
@@ -48,6 +48,9 @@ import UpdateUser from "@/pages/user/Update";
|
|||||||
import AdminList from "@/pages/admin/List";
|
import AdminList from "@/pages/admin/List";
|
||||||
import CreateAdmin from "@/pages/admin/Create";
|
import CreateAdmin from "@/pages/admin/Create";
|
||||||
import EditAdmin from "@/pages/admin/Update";
|
import EditAdmin from "@/pages/admin/Update";
|
||||||
|
import RoleList from "@/pages/role/List";
|
||||||
|
import CreateRole from "@/pages/role/Create";
|
||||||
|
import UpdateRole from "@/pages/role/Update";
|
||||||
import RequestDetail from "@/pages/requests/Detail";
|
import RequestDetail from "@/pages/requests/Detail";
|
||||||
import ConvertToOrders from "@/pages/order/ConvertToOrders";
|
import ConvertToOrders from "@/pages/order/ConvertToOrders";
|
||||||
import OrderPrint from "@/pages/order/Print";
|
import OrderPrint from "@/pages/order/Print";
|
||||||
@@ -112,6 +115,10 @@ const MainRouter: FC = () => {
|
|||||||
<Route path={Paths.admin.create} element={<CreateAdmin />} />
|
<Route path={Paths.admin.create} element={<CreateAdmin />} />
|
||||||
<Route path={Paths.admin.update + ":id"} element={<EditAdmin />} />
|
<Route path={Paths.admin.update + ":id"} element={<EditAdmin />} />
|
||||||
|
|
||||||
|
<Route path={Paths.role.list} element={<RoleList />} />
|
||||||
|
<Route path={Paths.role.create} element={<CreateRole />} />
|
||||||
|
<Route path={Paths.role.update + ":id"} element={<UpdateRole />} />
|
||||||
|
|
||||||
<Route path={Paths.features.list} element={<FeaturesList />} />
|
<Route path={Paths.features.list} element={<FeaturesList />} />
|
||||||
<Route path={Paths.features.create} element={<CreateFeature />} />
|
<Route path={Paths.features.create} element={<CreateFeature />} />
|
||||||
<Route path={Paths.service.print} element={<PrintService />} />
|
<Route path={Paths.service.print} element={<PrintService />} />
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
People,
|
People,
|
||||||
Printer,
|
Printer,
|
||||||
Receipt21,
|
Receipt21,
|
||||||
|
ShieldSecurity,
|
||||||
Teacher,
|
Teacher,
|
||||||
User,
|
User,
|
||||||
} from 'iconsax-react';
|
} from 'iconsax-react';
|
||||||
@@ -115,6 +116,13 @@ const SideBar: FC = () => {
|
|||||||
isActive={isActive('admin')}
|
isActive={isActive('admin')}
|
||||||
link={Paths.admin.list}
|
link={Paths.admin.list}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<SideBarItem
|
||||||
|
icon={<ShieldSecurity size={iconSizeSideBar} color="#4F5260" />}
|
||||||
|
title={'نقشها'}
|
||||||
|
isActive={isActive('role')}
|
||||||
|
link={Paths.role.list}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-10 px-6 text-description text-sm font-bold">{t('sidebar.other')}</div>
|
<div className="mt-10 px-6 text-description text-sm font-bold">{t('sidebar.other')}</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user