From edd50bafad3c0deae010edbc24a23d97f78bcfdb Mon Sep 17 00:00:00 2001 From: Moaz Dawalibi Date: Mon, 16 Sep 2024 17:05:10 +0300 Subject: [PATCH] manager page design and fixes --- src/Components/Layout/SideBar/MenuItem.tsx | 4 +- src/Layout/Dashboard/FilterLayout.tsx | 2 +- src/Layout/Ui/NotFoundPage.tsx | 2 +- src/Pages/Admin/Manager/Add/Page.tsx | 52 ++++++ .../Admin/Manager/Form/AttachmentForm.tsx | 23 +++ src/Pages/Admin/Manager/Form/FilterForm.tsx | 25 +++ .../Form/ImageBoxField/ImageBoxField.scss | 38 ++++ .../Form/ImageBoxField/ImageBoxField.tsx | 87 +++++++++ .../Form/ImageBoxField/ImageCancelIcon.tsx | 18 ++ .../Manager/Form/ImageBoxField/ImageIcon.tsx | 18 ++ .../ImageBoxField/generateImagePreview.ts | 10 + .../Manager/Form/PersonalDetailsForm.tsx | 76 ++++++++ .../Admin/Manager/Form/TitleDetailsForm.tsx | 30 +++ src/Pages/Admin/Manager/Form/formUtils.ts | 13 ++ src/Pages/Admin/Manager/Model/AddModel.tsx | 33 ++++ src/Pages/Admin/Manager/Model/EditModel.tsx | 36 ++++ src/Pages/Admin/Manager/Model/FilterForm.tsx | 26 +++ src/Pages/Admin/Manager/Model/ModelForm.tsx | 71 ++++++++ src/Pages/Admin/Manager/Model/formUtil.ts | 26 +++ src/Pages/Admin/Manager/Page.tsx | 54 ++++++ src/Pages/Admin/Manager/Table.tsx | 27 +++ src/Pages/Admin/Manager/useTableColumns.tsx | 92 ++++++++++ .../Admin/Roles/Permissions/Model/formUtil.ts | 13 ++ src/Pages/Admin/Roles/Permissions/Page.tsx | 43 +++++ src/Pages/Admin/Roles/Permissions/Table.tsx | 25 +++ .../Roles/Permissions/useTableColumns.tsx | 95 ++++++++++ src/Pages/Admin/Roles/useTableColumns.tsx | 9 + src/Pages/Admin/Student/Page.tsx | 4 +- src/Pages/Admin/Student/show/Page.tsx | 5 +- src/Routes.tsx | 171 +++++++++++------- src/Styles/App/App.scss | 36 +--- src/Styles/Layout/FilterLayout.scss | 4 +- src/Styles/Layout/SideBar.scss | 2 +- src/Styles/Pages/Classes.scss | 5 + src/api/manager.ts | 31 ++++ src/enums/Model.ts | 20 +- src/enums/abilities.ts | 4 +- src/translate/ar.json | 39 +++- src/types/Manager.ts | 14 ++ src/utils/hasAbilityFn.ts | 20 ++ 40 files changed, 1179 insertions(+), 124 deletions(-) create mode 100644 src/Pages/Admin/Manager/Add/Page.tsx create mode 100644 src/Pages/Admin/Manager/Form/AttachmentForm.tsx create mode 100644 src/Pages/Admin/Manager/Form/FilterForm.tsx create mode 100644 src/Pages/Admin/Manager/Form/ImageBoxField/ImageBoxField.scss create mode 100644 src/Pages/Admin/Manager/Form/ImageBoxField/ImageBoxField.tsx create mode 100644 src/Pages/Admin/Manager/Form/ImageBoxField/ImageCancelIcon.tsx create mode 100644 src/Pages/Admin/Manager/Form/ImageBoxField/ImageIcon.tsx create mode 100644 src/Pages/Admin/Manager/Form/ImageBoxField/generateImagePreview.ts create mode 100644 src/Pages/Admin/Manager/Form/PersonalDetailsForm.tsx create mode 100644 src/Pages/Admin/Manager/Form/TitleDetailsForm.tsx create mode 100644 src/Pages/Admin/Manager/Form/formUtils.ts create mode 100644 src/Pages/Admin/Manager/Model/AddModel.tsx create mode 100644 src/Pages/Admin/Manager/Model/EditModel.tsx create mode 100644 src/Pages/Admin/Manager/Model/FilterForm.tsx create mode 100644 src/Pages/Admin/Manager/Model/ModelForm.tsx create mode 100644 src/Pages/Admin/Manager/Model/formUtil.ts create mode 100644 src/Pages/Admin/Manager/Page.tsx create mode 100644 src/Pages/Admin/Manager/Table.tsx create mode 100644 src/Pages/Admin/Manager/useTableColumns.tsx create mode 100644 src/Pages/Admin/Roles/Permissions/Model/formUtil.ts create mode 100644 src/Pages/Admin/Roles/Permissions/Page.tsx create mode 100644 src/Pages/Admin/Roles/Permissions/Table.tsx create mode 100644 src/Pages/Admin/Roles/Permissions/useTableColumns.tsx create mode 100644 src/api/manager.ts create mode 100644 src/types/Manager.ts diff --git a/src/Components/Layout/SideBar/MenuItem.tsx b/src/Components/Layout/SideBar/MenuItem.tsx index 4a8e9d4..bdcd0a7 100644 --- a/src/Components/Layout/SideBar/MenuItem.tsx +++ b/src/Components/Layout/SideBar/MenuItem.tsx @@ -37,14 +37,14 @@ export const MenuItem = ({ item, location, index, isOpen }: any) => { className="DropDownIcon" onClick={() => handleDropdown(index)} > - + ) : (
handleDropdown(index)} > - +
)} diff --git a/src/Layout/Dashboard/FilterLayout.tsx b/src/Layout/Dashboard/FilterLayout.tsx index 7a519f7..e529f3f 100644 --- a/src/Layout/Dashboard/FilterLayout.tsx +++ b/src/Layout/Dashboard/FilterLayout.tsx @@ -20,7 +20,7 @@ const FilterLayout = ({ haveOrder = true }: { filterTitle: string; - sub_children: any; + sub_children?: any; search_by?:string; width?:string; haveFilter?:boolean; diff --git a/src/Layout/Ui/NotFoundPage.tsx b/src/Layout/Ui/NotFoundPage.tsx index 6a3ec1f..8762dd6 100644 --- a/src/Layout/Ui/NotFoundPage.tsx +++ b/src/Layout/Ui/NotFoundPage.tsx @@ -12,7 +12,7 @@ function NotFoundPage() {
- Error 404 + Error 404

{t("practical.sorry_something_went_wrong")}

{t("practical.error_404_Page_not_found._Sorry,_the_page_you_are_looking_for_does_not_exist")}

+ +
+ + + + + + ); +}; + +export default TableHeader; diff --git a/src/Pages/Admin/Manager/Form/AttachmentForm.tsx b/src/Pages/Admin/Manager/Form/AttachmentForm.tsx new file mode 100644 index 0000000..a4f7a7a --- /dev/null +++ b/src/Pages/Admin/Manager/Form/AttachmentForm.tsx @@ -0,0 +1,23 @@ +import React from "react"; +import { useTranslation } from "react-i18next"; +import { FaImage } from "react-icons/fa"; +import ImageBoxField from "./ImageBoxField/ImageBoxField"; + +const AttachmentForm = () => { + const [t] = useTranslation(); + + return ( +
+
+ +

{t("header.attachment")}

+
+
+ + +
+
+ ); +}; + +export default AttachmentForm; diff --git a/src/Pages/Admin/Manager/Form/FilterForm.tsx b/src/Pages/Admin/Manager/Form/FilterForm.tsx new file mode 100644 index 0000000..0857f55 --- /dev/null +++ b/src/Pages/Admin/Manager/Form/FilterForm.tsx @@ -0,0 +1,25 @@ +import React from "react"; +import ValidationField from "../../../../Components/ValidationField/ValidationField"; +import { Col, Row } from "reactstrap"; + +const FilterForm = () => { + return ( +
+ + + + {/* */} + + {/* + + */} + +
+ ); +}; + +export default FilterForm; diff --git a/src/Pages/Admin/Manager/Form/ImageBoxField/ImageBoxField.scss b/src/Pages/Admin/Manager/Form/ImageBoxField/ImageBoxField.scss new file mode 100644 index 0000000..66e2f2f --- /dev/null +++ b/src/Pages/Admin/Manager/Form/ImageBoxField/ImageBoxField.scss @@ -0,0 +1,38 @@ +.ImageBoxField { + .ImageBox { + width: 120px; + height: 120px; + display: flex; + align-items: center; + justify-content: center; + border: max(1.5px, 0.1vw) dashed #a9c3f1; + margin-block: 10px; + border-radius: 5px; + z-index: 9999999 !important; + .ImageBoxIcon { + cursor: pointer; + } + .imagePreview { + max-width: 99%; + height: auto; + max-height: 99%; + object-fit: contain; + border-radius: 5px; + } + } + .ImageHeader { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 10px; + } + + .ImageCancelIcon { + width: 16px !important; + height: 16px !important; + } + .ImageBoxIcon { + width: 20px !important; + height: 20px !important; + } +} diff --git a/src/Pages/Admin/Manager/Form/ImageBoxField/ImageBoxField.tsx b/src/Pages/Admin/Manager/Form/ImageBoxField/ImageBoxField.tsx new file mode 100644 index 0000000..d163048 --- /dev/null +++ b/src/Pages/Admin/Manager/Form/ImageBoxField/ImageBoxField.tsx @@ -0,0 +1,87 @@ +import { useFormikContext } from "formik"; +import { useState, useRef, useEffect } from "react"; +import "./ImageBoxField.scss"; +import ImageIcon from "./ImageIcon"; +import ImageCancelIcon from "./ImageCancelIcon"; +import { generateImagePreview } from "./generateImagePreview"; +import { getNestedValue } from "../../../../../utils/getNestedValue"; +import { useTranslation } from "react-i18next"; + +// Helper function to generate image preview from a File + +const ImageBoxField = ({ name }: any) => { + const formik = useFormikContext(); + const value = getNestedValue(formik.values, name); + const [imagePreview, setImagePreview] = useState(null); + const fileInputRef = useRef(null); + + useEffect(() => { + if (value instanceof File) { + generateImagePreview(value, setImagePreview); + } else if (typeof value === "string") { + setImagePreview(value); + } else { + setImagePreview(null); + } + }, [value]); + + const handleFileChange = (event: any) => { + const file = event.target.files[0]; + if (file) { + generateImagePreview(file, setImagePreview); + formik.setFieldValue(name, file); + } + }; + + const handleButtonClick = () => { + const fileInput = fileInputRef.current; + if (fileInput) { + fileInput.click(); + } + }; + + const handleCancel = () => { + setImagePreview(""); + formik.setFieldValue(name, ""); + + if (fileInputRef.current) { + fileInputRef.current.value = ""; + } + }; + const [t] = useTranslation(); + return ( +
+
{t(`input.${name}`)}
+
+ {imagePreview ? ( + <> + + + + ) : ( +
hidden
+ )} +
+
+ {imagePreview ? ( + Preview + ) : ( + + )} +
+ +
+ ); +}; + +export default ImageBoxField; diff --git a/src/Pages/Admin/Manager/Form/ImageBoxField/ImageCancelIcon.tsx b/src/Pages/Admin/Manager/Form/ImageBoxField/ImageCancelIcon.tsx new file mode 100644 index 0000000..d42ba53 --- /dev/null +++ b/src/Pages/Admin/Manager/Form/ImageBoxField/ImageCancelIcon.tsx @@ -0,0 +1,18 @@ +import React from "react"; + +interface ImageCancelIconProps extends React.HTMLAttributes {} + +const ImageCancelIcon: React.FC = (props) => { + return ( +
+ + + +
+ ); +}; + +export default ImageCancelIcon; diff --git a/src/Pages/Admin/Manager/Form/ImageBoxField/ImageIcon.tsx b/src/Pages/Admin/Manager/Form/ImageBoxField/ImageIcon.tsx new file mode 100644 index 0000000..4ca597a --- /dev/null +++ b/src/Pages/Admin/Manager/Form/ImageBoxField/ImageIcon.tsx @@ -0,0 +1,18 @@ +import React from "react"; + +interface ImageIconProps extends React.HTMLAttributes {} + +const ImageIcon: React.FC = (props) => { + return ( +
+ + + +
+ ); +}; + +export default ImageIcon; diff --git a/src/Pages/Admin/Manager/Form/ImageBoxField/generateImagePreview.ts b/src/Pages/Admin/Manager/Form/ImageBoxField/generateImagePreview.ts new file mode 100644 index 0000000..3f754d3 --- /dev/null +++ b/src/Pages/Admin/Manager/Form/ImageBoxField/generateImagePreview.ts @@ -0,0 +1,10 @@ +export const generateImagePreview = ( + file: File, + setImagePreview: (result: string) => void, +) => { + const reader = new FileReader(); + reader.onloadend = () => { + setImagePreview(reader.result as string); + }; + reader.readAsDataURL(file); +}; diff --git a/src/Pages/Admin/Manager/Form/PersonalDetailsForm.tsx b/src/Pages/Admin/Manager/Form/PersonalDetailsForm.tsx new file mode 100644 index 0000000..5815b15 --- /dev/null +++ b/src/Pages/Admin/Manager/Form/PersonalDetailsForm.tsx @@ -0,0 +1,76 @@ +import React from "react"; +import { useTranslation } from "react-i18next"; +import { FaStore } from "react-icons/fa"; +import ValidationField from "../../../../Components/ValidationField/ValidationField"; +import { convert_data_to_select } from "../../../../Layout/app/Const"; +import { userTypeOptions } from "../../../../config/userTypeOptions"; +import { statusType } from "../../../../config/statusType"; + +const PersonalDetailsForm = () => { + const [t] = useTranslation(); + return ( +
+
+ +

{t("header.personal_information")}

+
+
+ + + + + + + + + + + +
+
+ ); +}; + +export default PersonalDetailsForm; diff --git a/src/Pages/Admin/Manager/Form/TitleDetailsForm.tsx b/src/Pages/Admin/Manager/Form/TitleDetailsForm.tsx new file mode 100644 index 0000000..e7faa2a --- /dev/null +++ b/src/Pages/Admin/Manager/Form/TitleDetailsForm.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import { useTranslation } from "react-i18next"; +import { FaRegAddressBook } from "react-icons/fa"; +import ValidationField from "../../../../Components/ValidationField/ValidationField"; +import { nationalities } from "../../../../types/App"; + +const TitleDetailsForm = () => { + const [t] = useTranslation(); + + return ( +
+
+ +

{t("header.address")}

+
+
+ + +
+
+ ); +}; + +export default TitleDetailsForm; diff --git a/src/Pages/Admin/Manager/Form/formUtils.ts b/src/Pages/Admin/Manager/Form/formUtils.ts new file mode 100644 index 0000000..b14915a --- /dev/null +++ b/src/Pages/Admin/Manager/Form/formUtils.ts @@ -0,0 +1,13 @@ +import * as Yup from "yup"; + +export const getInitialValues = (objectToEdit: Partial) => { + return { + id: objectToEdit?.id ?? null, + name: objectToEdit?.name ?? null, + }; +}; + +export const getValidationSchema = () => { + // validate input + return Yup.object().shape({}); +}; diff --git a/src/Pages/Admin/Manager/Model/AddModel.tsx b/src/Pages/Admin/Manager/Model/AddModel.tsx new file mode 100644 index 0000000..b9bf3fd --- /dev/null +++ b/src/Pages/Admin/Manager/Model/AddModel.tsx @@ -0,0 +1,33 @@ +import React from "react"; +import { getInitialValues, getValidationSchema } from "./formUtil"; +import { ModalEnum } from "../../../../enums/Model"; +import LayoutModel from "../../../../Layout/Dashboard/LayoutModel"; +import { QueryStatusEnum } from "../../../../enums/QueryStatus"; +import ModelForm from "./ModelForm"; +import { useAddManager } from "../../../../api/manager"; + +const AddModel: React.FC = () => { + const { mutate, status } = useAddManager(); + + const handleSubmit = (values: any) => { + mutate({ + ...values, + }); + }; + return ( + <> + + + + + ); +}; + +export default AddModel; diff --git a/src/Pages/Admin/Manager/Model/EditModel.tsx b/src/Pages/Admin/Manager/Model/EditModel.tsx new file mode 100644 index 0000000..2710154 --- /dev/null +++ b/src/Pages/Admin/Manager/Model/EditModel.tsx @@ -0,0 +1,36 @@ +import React from "react"; +import { getInitialValues, getValidationSchema } from "./formUtil"; +import { ModalEnum } from "../../../../enums/Model"; +import LayoutModel from "../../../../Layout/Dashboard/LayoutModel"; +import ModelForm from "./ModelForm"; +import { QueryStatusEnum } from "../../../../enums/QueryStatus"; +import { useObjectToEdit } from "../../../../zustand/ObjectToEditState"; +import { useUpdateManager } from "../../../../api/manager"; + +const EditModel: React.FC = () => { + const { mutate, status } = useUpdateManager(); + const { objectToEdit } = useObjectToEdit((state) => state); + + const handleSubmit = (values: any) => { + const Data_to_send = { ...values }; + mutate(Data_to_send); + }; + + return ( + <> + + + + + ); +}; + +export default EditModel; diff --git a/src/Pages/Admin/Manager/Model/FilterForm.tsx b/src/Pages/Admin/Manager/Model/FilterForm.tsx new file mode 100644 index 0000000..7db83f6 --- /dev/null +++ b/src/Pages/Admin/Manager/Model/FilterForm.tsx @@ -0,0 +1,26 @@ +import React from "react"; +import ValidationField from "../../../../Components/ValidationField/ValidationField"; +import { Col, Row } from "reactstrap"; + +const FilterForm = () => { + return ( +
+ + + + + + +
+ ); +}; + +export default FilterForm; diff --git a/src/Pages/Admin/Manager/Model/ModelForm.tsx b/src/Pages/Admin/Manager/Model/ModelForm.tsx new file mode 100644 index 0000000..cbc4fcf --- /dev/null +++ b/src/Pages/Admin/Manager/Model/ModelForm.tsx @@ -0,0 +1,71 @@ +import { Col, Row } from "reactstrap"; +import ValidationField from "../../../../Components/ValidationField/ValidationField"; +import { useGetAllGrade } from "../../../../api/grade"; +import { useValidationValidationParamState } from "../../../../Components/ValidationField/state/ValidationValidationParamState"; + +const Form = ({ isEdit = false }: { isEdit?: boolean }) => { + const { ValidationParamState } = useValidationValidationParamState(); + const { GradeName, GradeCurrentPage } = ValidationParamState; + + const { data: Grade, isLoading: isLoadingGrade } = useGetAllGrade({ + name: GradeName, + page: GradeCurrentPage, + }); + const GradeOption = Grade?.data ?? []; + const canChangeGradePage = !!Grade?.links?.next; + const GradePage = Grade?.meta?.currentPage; + + const sex = [ + { name: "male", id: "male" }, + { name: "female", id: "female" }, + ]; + return ( + + + + + + {!isEdit && ( + + )} + + + + + + + + ); +}; + +export default Form; diff --git a/src/Pages/Admin/Manager/Model/formUtil.ts b/src/Pages/Admin/Manager/Model/formUtil.ts new file mode 100644 index 0000000..3914abe --- /dev/null +++ b/src/Pages/Admin/Manager/Model/formUtil.ts @@ -0,0 +1,26 @@ +import * as Yup from "yup"; +import { Student, StudentInitialValues } from "../../../../types/Student"; + +export const getInitialValues = ( + objectToEdit: Partial, +): StudentInitialValues => { + return { + id: objectToEdit?.user_id, + first_name: objectToEdit?.first_name ?? "", + last_name: objectToEdit?.last_name ?? "", + // address: objectToEdit?.address ?? "", + // birthday: objectToEdit?.birthday ?? "", + // city: objectToEdit?.city ?? "", + grade_id: objectToEdit?.grade_id, + // image: objectToEdit?.image ?? "", + sex: objectToEdit?.sex, + }; +}; + +export const getValidationSchema = () => { + // validate input + return Yup.object().shape({ + first_name: Yup.string().required("validation.required"), + last_name: Yup.string().required("validation.required"), + }); +}; diff --git a/src/Pages/Admin/Manager/Page.tsx b/src/Pages/Admin/Manager/Page.tsx new file mode 100644 index 0000000..cc2a683 --- /dev/null +++ b/src/Pages/Admin/Manager/Page.tsx @@ -0,0 +1,54 @@ +import { useTranslation } from "react-i18next"; +import { lazy, Suspense } from "react"; +import { Spin } from "antd"; +import useSetPageTitle from "../../../Hooks/useSetPageTitle"; +import { ModalEnum } from "../../../enums/Model"; +import PageHeader from "../../../Layout/Dashboard/PageHeader"; +import { canAddManager } from "../../../utils/hasAbilityFn"; +import FilterLayout from "../../../Layout/Dashboard/FilterLayout"; +import FilterForm from "./Model/FilterForm"; +import { useDeleteManager } from "../../../api/manager"; + +const Table = lazy(() => import("./Table")); +const AddModalForm = lazy(() => import("./Model/AddModel")); +const EditModalForm = lazy(() => import("./Model/EditModel")); +const DeleteModalForm = lazy( + () => import("../../../Layout/Dashboard/DeleteModels"), +); + +const TableHeader = () => { + const [t] = useTranslation(); + const deleteMutation = useDeleteManager(); + + useSetPageTitle([ + {name:`${t(`page_header.home`)}`, path:"/"}, + {name:`${t(`page_header.users`)}`, path:"user"}, + {name:`${t(`page_header.managers`)}`, path:"managers"}, + ]); + return ( +
+ }> + + } + filterTitle="table.managers_list" + /> + + + + + + + ); +}; + +export default TableHeader; diff --git a/src/Pages/Admin/Manager/Table.tsx b/src/Pages/Admin/Manager/Table.tsx new file mode 100644 index 0000000..7b306fc --- /dev/null +++ b/src/Pages/Admin/Manager/Table.tsx @@ -0,0 +1,27 @@ +import { useColumns } from "./useTableColumns"; +import React from "react"; +import DataTable from "../../../Layout/Dashboard/Table/DataTable"; +import { useFilterState } from "../../../Components/Utils/Filter/FilterState"; +import { useFilterStateState } from "../../../zustand/Filter"; +import { useGetAllManager } from "../../../api/manager"; + +const App: React.FC = () => { + const { filterState } = useFilterState(); + + const { Filter } = useFilterStateState(); + + const name = Filter?.name ; + const sort_by = Filter?.sort_by ; + + + const response = useGetAllManager({ + name, + sort_by, + pagination: true, + ...filterState, + }); + + return ; +}; + +export default App; diff --git a/src/Pages/Admin/Manager/useTableColumns.tsx b/src/Pages/Admin/Manager/useTableColumns.tsx new file mode 100644 index 0000000..fe78e63 --- /dev/null +++ b/src/Pages/Admin/Manager/useTableColumns.tsx @@ -0,0 +1,92 @@ +import { TableColumnsType } from "antd"; +import { Student } from "../../../types/Student"; +import useModalHandler from "../../../utils/useModalHandler"; +import { ModalEnum } from "../../../enums/Model"; +import { useObjectToEdit } from "../../../zustand/ObjectToEditState"; +import { useTranslation } from "react-i18next"; +import { useNavigate } from "react-router-dom"; +import { + canDeleteManager, + canDeleteStudent, + canEditManager, + canEditStudent, + canShowManager, + canShowStudent, +} from "../../../utils/hasAbilityFn"; +import ActionButtons from "../../../Components/Table/ActionButtons"; +import { Manager } from "../../../types/Manager"; + +export const useColumns = () => { + const { handel_open_model } = useModalHandler(); + + const { setObjectToEdit } = useObjectToEdit((state) => state); + const navigate = useNavigate(); + + const handelShow = (record: Manager) => { + navigate(`${record?.user_id}`); + }; + + const handelDelete = (data: Manager) => { + setObjectToEdit(data); + handel_open_model(ModalEnum?.MANAGER_DELETE); + }; + + const handleEdit = (record: Student) => { + setObjectToEdit(record); + handel_open_model(ModalEnum?.MANAGER_EDIT); + }; + const [t] = useTranslation(); + + const columns: TableColumnsType = [ + { + title: t("columns.id"), + dataIndex: "id", + key: "id", + align: "center", + render: (_text, record) => record?.user_id, + }, + { + title: `${t("columns.first_name")}`, + dataIndex: "first_name", + key: "first_name", + align: "center", + render: (_text, record) => record?.first_name, + }, + { + title: `${t("columns.last_name")}`, + dataIndex: "last_name", + key: "last_name", + align: "center", + render: (_text, record) => record?.last_name, + }, + { + title: `${t("columns.sex")}`, + dataIndex: "sex", + key: "sex", + align: "center", + render: (_text, record) => record?.sex, + }, + + { + title: "", + + key: "actions", + align: "center", + render: (_text, record, index) => { + return ( + handelDelete(record)} + onEdit={() => handleEdit(record)} + onShow={() => handelShow(record)} + /> + ); + }, + }, + ]; + + return columns; +}; diff --git a/src/Pages/Admin/Roles/Permissions/Model/formUtil.ts b/src/Pages/Admin/Roles/Permissions/Model/formUtil.ts new file mode 100644 index 0000000..9ae0147 --- /dev/null +++ b/src/Pages/Admin/Roles/Permissions/Model/formUtil.ts @@ -0,0 +1,13 @@ +import * as Yup from "yup"; +export const getInitialValues = (objectToEdit: any): any => { + return { + id: objectToEdit?.id ?? null, + name: objectToEdit?.name ?? null, + }; +}; + +export const getValidationSchema = () => { + return Yup.object().shape({ + name: Yup.string().required("validation.required"), + }); +}; diff --git a/src/Pages/Admin/Roles/Permissions/Page.tsx b/src/Pages/Admin/Roles/Permissions/Page.tsx new file mode 100644 index 0000000..59d3c2c --- /dev/null +++ b/src/Pages/Admin/Roles/Permissions/Page.tsx @@ -0,0 +1,43 @@ +import { useTranslation } from "react-i18next"; +import { lazy, Suspense } from "react"; +import { Spin } from "antd"; +import useSetPageTitle from "../../../../Hooks/useSetPageTitle"; +import PageHeader from "../../../../Layout/Dashboard/PageHeader"; +import FilterLayout from "../../../../Layout/Dashboard/FilterLayout"; +import FormikForm from "../../../../Layout/Dashboard/FormikForm"; +import { getInitialValues } from "./Model/formUtil"; +const Table = lazy(() => import("./Table")); + +const TableHeader = () => { + const [t] = useTranslation(); + + useSetPageTitle([ + {name:`${t(`page_header.home`)}`, path:"/"}, + {name:`${t(`page_header.role`)}`, path:"role"}, + {name:`${t(`page_header.permissions`)}`, path:"permissions"} + ]); + + return ( +
+ }> + + + (console.log(1))}> +
+ + + + + ); +}; + +export default TableHeader; diff --git a/src/Pages/Admin/Roles/Permissions/Table.tsx b/src/Pages/Admin/Roles/Permissions/Table.tsx new file mode 100644 index 0000000..cd122f4 --- /dev/null +++ b/src/Pages/Admin/Roles/Permissions/Table.tsx @@ -0,0 +1,25 @@ +import React from "react"; +import DataTable from "../../../../Layout/Dashboard/Table/DataTable"; +import { useColumns } from "./useTableColumns"; +import { useFilterState } from "../../../../Components/Utils/Filter/FilterState"; +import { useFilterStateState } from "../../../../zustand/Filter"; +import { useGetAllRole } from "../../../../api/role"; +import { useGetAllTag } from "../../../../api/tags"; +const App: React.FC = () => { + + const { filterState } = useFilterState(); + const { Filter } = useFilterStateState(); + const name = Filter?.name ; + const sort_by = Filter?.sort_by ; + + const response = useGetAllTag({ + pagination: true, + name, + sort_by, + ...filterState, + }); + + return ; +}; + +export default App; diff --git a/src/Pages/Admin/Roles/Permissions/useTableColumns.tsx b/src/Pages/Admin/Roles/Permissions/useTableColumns.tsx new file mode 100644 index 0000000..bfd2313 --- /dev/null +++ b/src/Pages/Admin/Roles/Permissions/useTableColumns.tsx @@ -0,0 +1,95 @@ +import { TableColumnsType } from "antd"; +import { useObjectToEdit } from "../../../../zustand/ObjectToEditState"; +import { useModalState } from "../../../../zustand/Modal"; +import { useTranslation } from "react-i18next"; +import { Role } from "../../../../types/App"; +import { ModalEnum } from "../../../../enums/Model"; +import ValidationField from "../../../../Components/ValidationField/ValidationField"; + +export const useColumns = () => { + const [t] = useTranslation(); + + const { setIsOpen } = useModalState((state) => state); + + const { setObjectToEdit } = useObjectToEdit((state) => state); + const handleEdit = (record: any) => { + setObjectToEdit(record); + setIsOpen(ModalEnum?.ROLE_EDIT); + }; + const columns: TableColumnsType = [ + // { + // title: , + // dataIndex: "id", + // key: "id", + // align: "center", + // render: (_text) => { + // return ( + // + // ); + // }, + // }, + { + title: t("columns.units"), + dataIndex: "name", + key: "name", + align: "center", + }, + { + title: t("columns.add"), + dataIndex: "id", + key: "id", + align: "center", + render: (_text) => { + return ( + + ); + }, + }, + { + title: t("columns.read"), + dataIndex: "id", + key: "id", + align: "center", + render: (_text) => { + return ( + + ); + }, + }, + { + title: t("columns.edit"), + dataIndex: "id", + key: "id", + align: "center", + render: (_text) => { + return ( + + ); + }, + }, + { + title: t("columns.delete"), + dataIndex: "id", + key: "id", + align: "center", + render: (_text) => { + return ( + + ); + }, + }, + { + title: t("columns.allow_everyone"), + dataIndex: "id", + key: "id", + align: "center", + render: (_text) => { + return ( + + ); + }, + }, + ]; + + return columns; +}; diff --git a/src/Pages/Admin/Roles/useTableColumns.tsx b/src/Pages/Admin/Roles/useTableColumns.tsx index 20908b4..b0ccdd6 100644 --- a/src/Pages/Admin/Roles/useTableColumns.tsx +++ b/src/Pages/Admin/Roles/useTableColumns.tsx @@ -6,6 +6,8 @@ import { useTranslation } from "react-i18next"; import { canDeleteRole,canEditRole } from "../../../utils/hasAbilityFn"; import ActionButtons from "../../../Components/Table/ActionButtons"; import { Role } from "../../../types/App"; +import { useNavigate } from "react-router-dom"; +import { ABILITIES_ENUM } from "../../../enums/abilities"; export const useColumns = () => { const [t] = useTranslation(); @@ -13,6 +15,12 @@ export const useColumns = () => { const { setIsOpen } = useModalState((state) => state); const { setObjectToEdit } = useObjectToEdit((state) => state); + const navigate = useNavigate(); + + const handelShow = (record: Role) => { + navigate(`/${record?.id}`); + }; + const handelDelete = (record: any) => { setObjectToEdit(record); setIsOpen(ModalEnum?.ROLE_DELETE); @@ -22,6 +30,7 @@ export const useColumns = () => { setIsOpen(ModalEnum?.ROLE_EDIT); }; + const columns: TableColumnsType = [ { title: t("columns.id"), diff --git a/src/Pages/Admin/Student/Page.tsx b/src/Pages/Admin/Student/Page.tsx index cc7b8a5..9f817f8 100644 --- a/src/Pages/Admin/Student/Page.tsx +++ b/src/Pages/Admin/Student/Page.tsx @@ -22,13 +22,13 @@ const TableHeader = () => { useSetPageTitle([ {name:`${t(`page_header.home`)}`, path:"/"}, - {name:`${t(`page_header.student`)}`, path:"student"} + {name:`${t(`page_header.student`)}`, path:"student"}, ]); return (
}> diff --git a/src/Pages/Admin/Student/show/Page.tsx b/src/Pages/Admin/Student/show/Page.tsx index f597de2..fe06816 100644 --- a/src/Pages/Admin/Student/show/Page.tsx +++ b/src/Pages/Admin/Student/show/Page.tsx @@ -17,9 +17,10 @@ const TableHeader = () => { const {student_id} = useParams(); useSetPageTitle([ - { name: `${t(`page_header.users`)}`, path: "/" }, + { name: `${t(`page_header.home`)}`, path: "" }, + { name: `${t(`page_header.users`)}`, path: "user" }, { name: `${t(`PageTitle.students`)}`, path: "students" }, - { name: `${t(`PageTitle.students_details`)}`, path: `reseller/${student_id}` }, + { name: `${t(`PageTitle.students_details`)}`, path: `reseller/${student_id}` , }, ]); return ( diff --git a/src/Routes.tsx b/src/Routes.tsx index 20011e4..8f6c45e 100644 --- a/src/Routes.tsx +++ b/src/Routes.tsx @@ -1,6 +1,6 @@ import { TCrudRoute, TMenuItem } from "./types/App"; -import { FaCashRegister, FaHome, FaMoneyBill, FaPaperclip, FaSellcast, FaTag, FaUser,FaUserShield } from "react-icons/fa"; -import { CiSquareQuestion } from "react-icons/ci"; +import { FaCashRegister, FaHome, FaMoneyBill, FaPaperclip, FaSellcast, FaTag, FaUser, FaUserShield } from "react-icons/fa"; +import { GoDotFill } from "react-icons/go"; import { GrGroup } from "react-icons/gr"; import React from "react"; @@ -21,24 +21,27 @@ const EditQuestionPage = React.lazy( () => import("./Pages/Admin/question/EditPage"), ); -const Report = React.lazy(() => import("./Pages/Admin/Report/Page")); const Student = React.lazy(() => import("./Pages/Admin/Student/Page")); const ShowStudent = React.lazy(() => import("./Pages/Admin/Student/show/Page")); +const Manager = React.lazy(() => import("./Pages/Admin/Manager/Page")); +const AddManager = React.lazy(() => import("./Pages/Admin/Manager/Add/Page")); + const ReSeller = React.lazy(() => import("./Pages/Admin/Reseller/Page")); const ShowReSeller = React.lazy(() => import("./Pages/Admin/Reseller/show/Page")); const AddReSeller = React.lazy(() => import("./Pages/Admin/Reseller/Add/Page")); -const EditReSeller = React.lazy( - () => import("./Pages/Admin/Reseller/Edit/Page"), -); +const EditReSeller = React.lazy(() => import("./Pages/Admin/Reseller/Edit/Page"),); const User = React.lazy(() => import("./Pages/Admin/User/Page")); - -const Param = React.lazy(() => import("./Pages/Admin/Param/Page")); const QuestionBank = React.lazy(() => import("./Pages/Admin/QuestionBank/Page")); const Notifications = React.lazy(() => import("./Pages/Admin/Notifications/Page")); const Profile = React.lazy(() => import("./Pages/Admin/Profile/Page")); + const Roles = React.lazy(() => import("./Pages/Admin/Roles/Page")); +const Permissions = React.lazy(() => import("./Pages/Admin/Roles/Permissions/Page")); + +const Report = React.lazy(() => import("./Pages/Admin/Report/Page")); +const Param = React.lazy(() => import("./Pages/Admin/Param/Page")); /// RESELLER /// const Student_Package = React.lazy( @@ -51,7 +54,6 @@ import { ParamsEnum } from "./enums/params"; import { TbCategory } from "react-icons/tb"; import { UserTypeEnum } from "./enums/UserType"; import { FaTags } from "react-icons/fa6"; -import { MdGrade } from "react-icons/md"; export const menuItems: TMenuItem[] = [ { @@ -62,8 +64,8 @@ export const menuItems: TMenuItem[] = [ path: "/", abilities: ABILITIES_ENUM?.PASS, abilities_value: ABILITIES_VALUES_ENUM.INDEX, - prevPath: 0, type: UserTypeEnum?.PASS, + prevPath: 0, }, { header: "page_header.grade", @@ -75,6 +77,38 @@ export const menuItems: TMenuItem[] = [ abilities_value: ABILITIES_VALUES_ENUM.INDEX, prevPath: 0, }, + { + header: "page_header.user", + element: , + icon: , + text: "sidebar.users", + path: `/${ABILITIES_ENUM?.USER}`, + abilities: ABILITIES_ENUM?.USER, + abilities_value: ABILITIES_VALUES_ENUM.INDEX, + prevPath: 0, + children: [ + { + header: "page_header.student", + element: , + icon: , + text: "sidebar.student", + path: `/${ABILITIES_ENUM?.STUDENT}`, + abilities: ABILITIES_ENUM?.STUDENT, + abilities_value: ABILITIES_VALUES_ENUM.INDEX, + prevPath: 0, + }, + // { + // header: "page_header.managers", + // element: , + // icon: , + // text: "sidebar.managers", + // path: `/${ABILITIES_ENUM?.MANAGERS}`, + // abilities: ABILITIES_ENUM?.MANAGERS, + // abilities_value: ABILITIES_VALUES_ENUM.INDEX, + // prevPath: 0, + // }, + ] + }, { header: "page_header.tags", element: , @@ -85,26 +119,6 @@ export const menuItems: TMenuItem[] = [ abilities_value: ABILITIES_VALUES_ENUM.INDEX, prevPath: 0, }, - { - header: "page_header.report", - element: , - icon: , - text: "sidebar.report", - path: `/${ABILITIES_ENUM?.Report}`, - abilities: ABILITIES_ENUM?.Report, - abilities_value: ABILITIES_VALUES_ENUM.INDEX, - prevPath: 0, - }, - { - header: "page_header.student", - element: , - icon: , - text: "sidebar.student", - path: `/${ABILITIES_ENUM?.STUDENT}`, - abilities: ABILITIES_ENUM?.STUDENT, - abilities_value: ABILITIES_VALUES_ENUM.INDEX, - prevPath: 0, - }, { header: "page_header.reSeller", element: , @@ -115,47 +129,48 @@ export const menuItems: TMenuItem[] = [ abilities_value: ABILITIES_VALUES_ENUM.INDEX, prevPath: 0, }, - { - header: "page_header.user", - element: , - icon: , - text: "sidebar.user", - path: `/${ABILITIES_ENUM?.USER}`, - abilities: ABILITIES_ENUM?.USER, - abilities_value: ABILITIES_VALUES_ENUM.INDEX, - prevPath: 0, - }, - { - header: "page_header.param", - element: , - icon: , - text: "sidebar.param", - path: `/${ABILITIES_ENUM?.PARAM}`, - abilities: ABILITIES_ENUM?.PARAM, - abilities_value: ABILITIES_VALUES_ENUM.INDEX, - prevPath: 0, - }, + // { + // header: "page_header.report", + // element: , + // icon: , + // text: "sidebar.report", + // path: `/${ABILITIES_ENUM?.Report}`, + // abilities: ABILITIES_ENUM?.Report, + // abilities_value: ABILITIES_VALUES_ENUM.INDEX, + // prevPath: 0, + // }, - { - header: "page_header.questionBank", - element: , - icon: , - text: "sidebar.questionBank", - path: `/${ABILITIES_ENUM?.QUESTION}`, - abilities: ABILITIES_ENUM?.QUESTION, - abilities_value: ABILITIES_VALUES_ENUM.INDEX, - prevPath: 0, - }, - { - header: "page_header.roles", - element: , - icon: , - text: "sidebar.role", - path: `/${ABILITIES_ENUM?.ROLE}`, - abilities: ABILITIES_ENUM?.ROLE, - abilities_value: ABILITIES_VALUES_ENUM.INDEX, - prevPath: 0, - }, + // { + // header: "page_header.param", + // element: , + // icon: , + // text: "sidebar.param", + // path: `/${ABILITIES_ENUM?.PARAM}`, + // abilities: ABILITIES_ENUM?.PARAM, + // abilities_value: ABILITIES_VALUES_ENUM.INDEX, + // prevPath: 0, + // }, + + // { + // header: "page_header.questionBank", + // element: , + // icon: , + // text: "sidebar.questionBank", + // path: `/${ABILITIES_ENUM?.QUESTION}`, + // abilities: ABILITIES_ENUM?.QUESTION, + // abilities_value: ABILITIES_VALUES_ENUM.INDEX, + // prevPath: 0, + // }, + // { + // header: "page_header.roles", + // element: , + // icon: , + // text: "sidebar.role", + // path: `/${ABILITIES_ENUM?.ROLE}`, + // abilities: ABILITIES_ENUM?.ROLE, + // abilities_value: ABILITIES_VALUES_ENUM.INDEX, + // prevPath: 0, + // }, /// RESELLER ///// @@ -274,6 +289,22 @@ export const CrudRoute: TCrudRoute[] = [ abilities_value: ABILITIES_VALUES_ENUM.INDEX, prevPath: 0, }, + { + header: "page_header.permissions", + element: , + path: `/${ABILITIES_ENUM?.PERMISSIONS}`, + abilities: ABILITIES_ENUM?.PERMISSIONS, + abilities_value: ABILITIES_VALUES_ENUM.INDEX, + prevPath: 0, + }, + { + header: "page_header.add_manager", + element: , + path: `/${ABILITIES_ENUM?.MANAGERS}/add`, + abilities: ABILITIES_ENUM?.MANAGERS, + abilities_value: ABILITIES_VALUES_ENUM.INDEX, + prevPath: 0, + }, ]; export const AppRoutes: Record = Object.fromEntries( diff --git a/src/Styles/App/App.scss b/src/Styles/App/App.scss index f2f303b..b6acaf2 100644 --- a/src/Styles/App/App.scss +++ b/src/Styles/App/App.scss @@ -68,35 +68,6 @@ svg { } } } - // p { - // color: white; - // display: inline; - // } - // h6 { - // display: inline; - // margin-inline: 20px; - // height: 140px !important; - - // width: 20px; - // } - // .container-not-found { - // display: flex; - // flex-direction: column; - // align-items: center; - // div { - // display: flex; - // justify-content: center; - // align-items: center; - // } - // button { - // border: none; - // outline: none; - // padding: 8px; - // border-radius: 10px; - - // margin-inline: 30px; - // } - // } } /* Username */ @@ -108,3 +79,10 @@ svg { #password { font-size: 1vw; } + +.DropDownIcon{ + .sidebar_menu_icaon{ + background: transparent !important; + color: var(--primary) !important; + } +} \ No newline at end of file diff --git a/src/Styles/Layout/FilterLayout.scss b/src/Styles/Layout/FilterLayout.scss index 118b05f..0db96bf 100644 --- a/src/Styles/Layout/FilterLayout.scss +++ b/src/Styles/Layout/FilterLayout.scss @@ -97,8 +97,8 @@ padding-bottom: 30px; } .ant-select-selection-search{ - color: #6A7287 !important; - display: none !important; + // color: #6A7287 !important; + // display: none !important; } :where(.css-dev-only-do-not-override-oad6qy).ant-select-single.ant-select-lg .ant-select-selector .ant-select-selection-search{ diff --git a/src/Styles/Layout/SideBar.scss b/src/Styles/Layout/SideBar.scss index 17209b1..afa62cb 100644 --- a/src/Styles/Layout/SideBar.scss +++ b/src/Styles/Layout/SideBar.scss @@ -70,12 +70,12 @@ flex: 1; gap: 0.5vw; padding-inline: 7%; - // overflow-y: auto; scroll-behavior: smooth; scroll-padding: 10rem; @include Scrollbar; position: relative; padding-top: 20px; + margin-block: 10px; > p { font-size: 18px; margin-bottom: 5px; diff --git a/src/Styles/Pages/Classes.scss b/src/Styles/Pages/Classes.scss index 1e3fcab..28e5736 100644 --- a/src/Styles/Pages/Classes.scss +++ b/src/Styles/Pages/Classes.scss @@ -96,3 +96,8 @@ .pointer { cursor: pointer; } + +.transparent_bg{ + background: transparent !important; + color: #fff !important; +} \ No newline at end of file diff --git a/src/api/manager.ts b/src/api/manager.ts new file mode 100644 index 0000000..37351bb --- /dev/null +++ b/src/api/manager.ts @@ -0,0 +1,31 @@ +import useAddMutation from "./helper/useAddMutation"; +import useDeleteMutation from "./helper/useDeleteMutation"; +import useGetQuery from "./helper/useGetQuery"; +import useUpdateMutation from "./helper/useUpdateMutation"; + +const API = { + GET: "/manager", + ADD: "/manager", + DELETE: "/manager", + UPDATE: "/manager", + MOVE: "/manager/moveManagers", + IMPORT: "/manager/importManagers", +}; + +const KEY = "manager"; + +export const useGetAllManager = (params?: any, options?: any) => + useGetQuery(KEY, API.GET, params); + +export const useGetManager = (params?: any, options?: any) => + useGetQuery(KEY, API.GET, params, options); + +export const useAddManager = () => useAddMutation(KEY, API.ADD); +export const useUpdateManager = (params?: any) => + useUpdateMutation(KEY, API.GET); + +export const useDeleteManager = (params?: any) => + useDeleteMutation(KEY, API.DELETE); + +export const useMoveManager = () => useAddMutation(KEY, API.MOVE); +export const useImportManager = () => useAddMutation(KEY, API.IMPORT); diff --git a/src/enums/Model.ts b/src/enums/Model.ts index 75f16b5..f3f1739 100644 --- a/src/enums/Model.ts +++ b/src/enums/Model.ts @@ -31,6 +31,12 @@ export enum ModalEnum { STUDENT_DELETE = "student.delete", STUDENT_SENDNOTIFICATION = "student.sendnotification", + ////manager + + MANAGER_ADD = "manager.add", + MANAGER_EDIT = "manager.edit", + MANAGER_DELETE = "manager.delete", + MANAGER_SENDNOTIFICATION = "manager.sendnotification", ////subject SUBJECT_ADD = "subject.add", @@ -193,9 +199,15 @@ export enum ModalEnum { Student_Package_DELETE = "Student_Package.delete", - ///QuestionBank + ///QuestionBank - QUESTION_BANK_ADD = "QuestionBank.add", - QUESTION_BANK_EDIT = "QuestionBank.edit", - QUESTION_BANK_DELETE = "QuestionBank.delete", + QUESTION_BANK_ADD = "QuestionBank.add", + QUESTION_BANK_EDIT = "QuestionBank.edit", + QUESTION_BANK_DELETE = "QuestionBank.delete", + + /// permission + PERMISSION_EDIT = "PERMISSION.edit", + PERMISSION_ADD = "PERMISSION.add", + PERMISSION_DELETE = "PERMISSION.delete", + } diff --git a/src/enums/abilities.ts b/src/enums/abilities.ts index 0414158..929b3ea 100644 --- a/src/enums/abilities.ts +++ b/src/enums/abilities.ts @@ -49,7 +49,9 @@ export enum ABILITIES_ENUM { Student_Package = "student_package", QUESTION_BANK = "QuestionBank", NOTIFICATIONS = "Notifications", - PROFILE = "profile" + PROFILE = "profile", + PERMISSIONS = "permissions", + MANAGERS = "managers", //// } diff --git a/src/translate/ar.json b/src/translate/ar.json index 58b5100..acb5cb5 100644 --- a/src/translate/ar.json +++ b/src/translate/ar.json @@ -136,7 +136,8 @@ "password": "كلمة المرور", "edit": "تعديل", "change": "تغيير", - "role_list": "قائمة الأدوار" + "role_list": "قائمة الأدوار", + "managers":"مدراء" }, "columns": { "id": "الرقم التعريفي", @@ -212,7 +213,14 @@ "residual": "المتبقي", "date_of_receipt": "تاريخ الاستلام", "amount": "مبلغ", - "created_at": "تم إنشاؤه في" + "created_at": "تم إنشاؤه في", + "units":"وحدات", + "allow_everyone":"السماح للجميع", + "add":"إضافة", + "edit":"تعديل", + "delete":"حذف", + "read":"قراءة", + "managers":"مدراء" }, "practical": { "to_confirm_deletion_please_re_enter": "لتأكيد الحذف، يرجى إعادة الإدخال", @@ -345,7 +353,9 @@ "collection": "تحصيل", "profile": "الملف الشخصي", "role_details": "تفاصيل الأدوار", - "created_at": "تم إنشاؤه في" + "created_at": "تم إنشاؤه في", + "managers":"مدراء", + "manager":"مدير" }, "education_class_actions": { "Student_Records": "سجلات الطلاب", @@ -469,7 +479,9 @@ "amount_value": "قيمة المبلغ", "email_address": "عنوان البريد الإلكتروني", "current_password": "كلمة المرور الحالية", - "created_at": "تم إنشاؤه في" + "created_at": "تم إنشاؤه في", + "empty":"", + "role":"الدور" }, "select": { "enums": { @@ -800,7 +812,9 @@ "quiz": "الاختبارات", "questionBank": "بنك الأسئلة", "notifications": "الإشعارات", - "profile": "الملف الشخصي" + "profile": "الملف الشخصي", + "users":"المستخدمون", + "managers":"مدراء" }, "message": { "some_thing_went_wrong": "حدث خطأ ما", @@ -839,7 +853,10 @@ "QuestionBank": "بنك الأسئلة", "reseller_details": "تفاصيل البائع", "notifications": "الإشعارات", - "profile": "الملف الشخصي" + "profile": "الملف الشخصي", + "permissions":"اذونات", + "managers":"مدراء", + "add_manager":"إضافة مدير" }, "page_header": { "home": "لوحة القيادة", @@ -848,7 +865,7 @@ "payment": " الدفعات", "branch": " الفروع", "role": " الأدوار", - "student": " قائمة الطلاب ", + "student": "الطلاب", "admin": " المسؤولون", "student_details": "تفاصيل الطالب", "create_student": "إنشاء طالب", @@ -881,14 +898,18 @@ "reseller_details": "تفاصيل البائع", "notifications": "الإشعارات", "profile": "الملف الشخصي", - "user": "مستخدم" + "user": "مستخدم", + "permissions":"اذونات", + "managers":"مدراء" }, "table": { "student": "قائمة الطلاب", "reseller": "البائعين", "grade": "قائمة الصفوف", "subjects": "مواد الصف", - "QuestionBank": "بنك الأسئلة" + "QuestionBank": "بنك الأسئلة", + "managers":"مدراء", + "managers_list":"قائمة المدراء" }, "alphabet": { "A": "A", diff --git a/src/types/Manager.ts b/src/types/Manager.ts new file mode 100644 index 0000000..8154688 --- /dev/null +++ b/src/types/Manager.ts @@ -0,0 +1,14 @@ +import { DateType } from "./App"; + +export interface Manager { + first_name: string; // The first name of the user + last_name: string; // The last name of the user + city: string | null; // The city of the user, can be null + sex: string; // The sex of the user, using a union type for possible values + image: string | null; // The URL of the user's image, can be null + address: string | null; // The address of the user, can be null + card: string | null; // The card information, can be null + birthday: DateType; // The birthday of the user, can be null + grade_id: number | string; // The ID of the user's grade + user_id: number; // The unique ID of the user + } \ No newline at end of file diff --git a/src/utils/hasAbilityFn.ts b/src/utils/hasAbilityFn.ts index dc4e751..e6de73d 100644 --- a/src/utils/hasAbilityFn.ts +++ b/src/utils/hasAbilityFn.ts @@ -278,6 +278,26 @@ export const canMoveStudent = hasAbility( ABILITIES_VALUES_ENUM.MOVE_STUDENTS, ); + +/// Manager + +export const canAddManager = hasAbility( + ABILITIES_ENUM.MANAGERS, + ABILITIES_VALUES_ENUM.STORE, +); + +export const canEditManager = hasAbility( + ABILITIES_ENUM.MANAGERS, + ABILITIES_VALUES_ENUM.UPDATE, +); +export const canDeleteManager = hasAbility( + ABILITIES_ENUM.MANAGERS, + ABILITIES_VALUES_ENUM.DELETE, +); +export const canShowManager = hasAbility( + ABILITIES_ENUM.MANAGERS, + ABILITIES_VALUES_ENUM.SHOW, +); /// EarlyDeparture export const canAddEarlyDeparture = hasAbility(