report index page , show page and notification page
This commit is contained in:
parent
547f71f840
commit
ecbcbf67cb
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
|
@ -25,6 +25,7 @@
|
||||||
"Viewelement",
|
"Viewelement",
|
||||||
"webp",
|
"webp",
|
||||||
"Xmark",
|
"Xmark",
|
||||||
|
"ZAKER",
|
||||||
"zustand",
|
"zustand",
|
||||||
"مطلوب"
|
"مطلوب"
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
/>
|
/>
|
||||||
<script type="module" src="/src/index.tsx"></script>
|
<script type="module" src="/src/index.tsx"></script>
|
||||||
|
|
||||||
<title>NERD DASHBOARD</title>
|
<title>ZAKER DASHBOARD</title>
|
||||||
</head>
|
</head>
|
||||||
<body dir="rtl">
|
<body dir="rtl">
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ const NavBarRightSide = () => {
|
||||||
icon={<CiCirclePlus size={25} />}
|
icon={<CiCirclePlus size={25} />}
|
||||||
/>
|
/>
|
||||||
<TooltipComp
|
<TooltipComp
|
||||||
// onClick={()=>(Navigate('/notifications'))}
|
onClick={()=>(Navigate('/notifications'))}
|
||||||
className="NotificationsIcon"
|
className="NotificationsIcon"
|
||||||
note="notification"
|
note="notification"
|
||||||
color="#E0E0E0"
|
color="#E0E0E0"
|
||||||
|
|
|
||||||
|
|
@ -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 { useAddNotification } from "../../../../../api/notification";
|
||||||
|
|
||||||
|
const AddModel: React.FC = () => {
|
||||||
|
const { mutate, status } = useAddNotification();
|
||||||
|
|
||||||
|
const handleSubmit = (values: any) => {
|
||||||
|
mutate({
|
||||||
|
...values,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<LayoutModel
|
||||||
|
status={status as QueryStatusEnum}
|
||||||
|
ModelEnum={ModalEnum.NOTIFICATION_ADD}
|
||||||
|
modelTitle="notification"
|
||||||
|
handleSubmit={handleSubmit}
|
||||||
|
getInitialValues={getInitialValues({})}
|
||||||
|
getValidationSchema={getValidationSchema}
|
||||||
|
>
|
||||||
|
<ModelForm />
|
||||||
|
</LayoutModel>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddModel;
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
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 { handelImageState } from "../../../../../utils/DataToSendImageState";
|
||||||
|
import { useUpdateNotification } from "../../../../../api/notification";
|
||||||
|
|
||||||
|
const EditModel: React.FC = () => {
|
||||||
|
const { mutate, status } = useUpdateNotification();
|
||||||
|
const { objectToEdit } = useObjectToEdit((state) => state);
|
||||||
|
|
||||||
|
const handleSubmit = (values: any) => {
|
||||||
|
const Data_to_send = { ...values };
|
||||||
|
const handelImage = handelImageState(Data_to_send, "icon");
|
||||||
|
mutate(handelImage);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<LayoutModel
|
||||||
|
status={status as QueryStatusEnum}
|
||||||
|
ModelEnum={ModalEnum.NOTIFICATION_EDIT}
|
||||||
|
modelTitle="notification"
|
||||||
|
handleSubmit={handleSubmit}
|
||||||
|
getInitialValues={getInitialValues(objectToEdit)}
|
||||||
|
getValidationSchema={getValidationSchema}
|
||||||
|
isAddModal={false}
|
||||||
|
>
|
||||||
|
<ModelForm />
|
||||||
|
</LayoutModel>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditModel;
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import React from "react";
|
||||||
|
import ValidationField from "../../../../../Components/ValidationField/ValidationField";
|
||||||
|
import { Col, Row } from "reactstrap";
|
||||||
|
import { useFormikContext } from "formik";
|
||||||
|
|
||||||
|
const FilterForm = () => {
|
||||||
|
const formik = useFormikContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<ValidationField placeholder="name" label="name" name="name" />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FilterForm;
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { Col, Row } from "reactstrap";
|
||||||
|
import ValidationField from "../../../../../Components/ValidationField/ValidationField";
|
||||||
|
|
||||||
|
const Form = () => {
|
||||||
|
return (
|
||||||
|
<Row className="w-100">
|
||||||
|
<Col>
|
||||||
|
<ValidationField name="title" placeholder="title" label="title" />
|
||||||
|
<ValidationField name="body" placeholder="body" label="body" />
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<ValidationField name="seen" placeholder="seen" label="seen" />
|
||||||
|
<ValidationField name="notifiable_type" placeholder="notifiable_type" label="notifiable_type" />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Form;
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
import * as Yup from "yup";
|
||||||
|
import { Grade, GradeInitialValues } from "../../../../../types/Grade";
|
||||||
|
import { Notification } from "../../../../../types/Notification";
|
||||||
|
|
||||||
|
export const getInitialValues = (
|
||||||
|
objectToEdit: Partial<Notification>,
|
||||||
|
): any => {
|
||||||
|
return {
|
||||||
|
id: objectToEdit?.id,
|
||||||
|
title: objectToEdit?.title ?? "",
|
||||||
|
seen: objectToEdit?.seen ?? "",
|
||||||
|
body: objectToEdit?.body ?? "",
|
||||||
|
notifiable_type: objectToEdit?.notifiable_type ?? "",
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getValidationSchema = () => {
|
||||||
|
// validate input
|
||||||
|
return Yup.object().shape({
|
||||||
|
title: Yup.string().required("validation.required"),
|
||||||
|
seen: Yup.string().required("validation.required"),
|
||||||
|
body: Yup.string().required("validation.required"),
|
||||||
|
notifiable_type: Yup.string().required("validation.required"),
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
49
src/Pages/Admin/Notifications/AddNotification/Page.tsx
Normal file
49
src/Pages/Admin/Notifications/AddNotification/Page.tsx
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
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 FilterLayout from "../../../../Layout/Dashboard/FilterLayout";
|
||||||
|
import FilterForm from "./Model/FilterForm";
|
||||||
|
import { canAddNotification } from "../../../../utils/hasAbilityFn";
|
||||||
|
import { useDeleteNotification } from "../../../../api/notification";
|
||||||
|
|
||||||
|
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 = useDeleteNotification();
|
||||||
|
|
||||||
|
useSetPageTitle([
|
||||||
|
{name:`${t(`page_header.home`)}`, path:"/"},
|
||||||
|
{name:`${t(`page_header.notification`)}`, path:"notification"}
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="TableWithHeader">
|
||||||
|
<Suspense fallback={<Spin />}>
|
||||||
|
<PageHeader
|
||||||
|
pageTitle="notification"
|
||||||
|
ModelAbility={ModalEnum?.NOTIFICATION_ADD}
|
||||||
|
canAdd={canAddNotification}
|
||||||
|
/>
|
||||||
|
<FilterLayout sub_children={<FilterForm />} filterTitle="table.notification" />
|
||||||
|
<Table />
|
||||||
|
<AddModalForm />
|
||||||
|
<EditModalForm />
|
||||||
|
<DeleteModalForm
|
||||||
|
deleteMutation={deleteMutation}
|
||||||
|
ModelEnum={ModalEnum?.NOTIFICATION_DELETE}
|
||||||
|
/>
|
||||||
|
</Suspense>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TableHeader;
|
||||||
24
src/Pages/Admin/Notifications/AddNotification/Table.tsx
Normal file
24
src/Pages/Admin/Notifications/AddNotification/Table.tsx
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
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 { useGetAllNotification } from "../../../../api/notification";
|
||||||
|
|
||||||
|
const App: React.FC = () => {
|
||||||
|
const { filterState } = useFilterState();
|
||||||
|
const { Filter } = useFilterStateState();
|
||||||
|
const name = Filter?.name ;
|
||||||
|
const sort_by = Filter?.sort_by ;
|
||||||
|
|
||||||
|
const response = useGetAllNotification({
|
||||||
|
pagination: true,
|
||||||
|
...filterState,
|
||||||
|
name:filterState.name || name,
|
||||||
|
sort_by
|
||||||
|
});
|
||||||
|
|
||||||
|
return <DataTable response={response} useColumns={useColumns} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default App;
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
import { TableColumnsType } from "antd";
|
||||||
|
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 {
|
||||||
|
canDeleteNotification,
|
||||||
|
canEditNotification,
|
||||||
|
} from "../../../../utils/hasAbilityFn";
|
||||||
|
import ActionButtons from "../../../../Components/Table/ActionButtons";
|
||||||
|
import ColumnsImage from "../../../../Components/Columns/ColumnsImage";
|
||||||
|
import { useFilterStateState } from "../../../../zustand/Filter";
|
||||||
|
import { Notification } from "../../../../types/Notification";
|
||||||
|
|
||||||
|
export const useColumns = () => {
|
||||||
|
const { handel_open_model } = useModalHandler();
|
||||||
|
|
||||||
|
const { setObjectToEdit } = useObjectToEdit((state) => state);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { setFilter } = useFilterStateState();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const handelShow = (record: Notification) => {
|
||||||
|
setFilter({})
|
||||||
|
navigate(`${record?.id}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handelDelete = (data: Notification) => {
|
||||||
|
setObjectToEdit(data);
|
||||||
|
handel_open_model(ModalEnum?.NOTIFICATION_DELETE);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEdit = (record: Notification) => {
|
||||||
|
setObjectToEdit(record);
|
||||||
|
handel_open_model(ModalEnum?.NOTIFICATION_EDIT);
|
||||||
|
};
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
const columns: TableColumnsType<Notification> = [
|
||||||
|
{
|
||||||
|
title: t("columns.id"),
|
||||||
|
dataIndex: "id",
|
||||||
|
key: "id",
|
||||||
|
align: "center",
|
||||||
|
render: (_text, record) => record?.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: `${t("columns.body")}`,
|
||||||
|
dataIndex: "body",
|
||||||
|
key: "body",
|
||||||
|
align: "center",
|
||||||
|
render: (_text, record) => record?.body,
|
||||||
|
ellipsis:true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: `${t("columns.seen")}`,
|
||||||
|
dataIndex: "seen",
|
||||||
|
key: "seen",
|
||||||
|
align: "center",
|
||||||
|
render: (_text, record) => record?.seen,
|
||||||
|
ellipsis:true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: `${t("columns.notifiable_type")}`,
|
||||||
|
dataIndex: "notifiable_type",
|
||||||
|
key: "notifiable_type",
|
||||||
|
align: "center",
|
||||||
|
render: (_text, record) => record?.notifiable_type,
|
||||||
|
ellipsis:true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
title: t("columns.procedure"),
|
||||||
|
key: "actions",
|
||||||
|
align: "center",
|
||||||
|
width: "25vw",
|
||||||
|
render: (_text, record, index) => {
|
||||||
|
return (
|
||||||
|
<ActionButtons
|
||||||
|
canDelete={canDeleteNotification}
|
||||||
|
canEdit={canEditNotification}
|
||||||
|
index={index}
|
||||||
|
onDelete={() => handelDelete(record)}
|
||||||
|
onEdit={() => handleEdit(record)}
|
||||||
|
onShow={() => handelShow(record)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return columns;
|
||||||
|
};
|
||||||
|
|
@ -1,19 +1,31 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ValidationField from "../../../../Components/ValidationField/ValidationField";
|
import ValidationField from "../../../../Components/ValidationField/ValidationField";
|
||||||
import { Col, Row } from "reactstrap";
|
import { Col, Row } from "reactstrap";
|
||||||
|
import { useGetAllStudent } from "../../../../api/student";
|
||||||
|
import { useGetAllQuestion } from "../../../../api/Question";
|
||||||
|
|
||||||
const FilterForm = () => {
|
const FilterForm = () => {
|
||||||
|
const {data:StudentData} = useGetAllStudent();
|
||||||
|
const {data:QuestionData} = useGetAllQuestion();
|
||||||
|
|
||||||
|
console.log(QuestionData?.data);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<ValidationField placeholder="name" label="name" name="name" />
|
<ValidationField placeholder="content" label="content" name="content" />
|
||||||
<ValidationField placeholder="name" label="name" name="name" />
|
<ValidationField placeholder="student_name" label="student_name" name="student_id" type="Select"
|
||||||
</Col>
|
option={StudentData?.data?.map((e: any) => ({
|
||||||
<Col>
|
...e,
|
||||||
<ValidationField placeholder="name" label="name" name="name" />
|
fullName: `${e.first_name} ${e.last_name}`
|
||||||
<ValidationField placeholder="name" label="name" name="name" />
|
}))}
|
||||||
|
fieldNames={{
|
||||||
|
label: "fullName",
|
||||||
|
value: "id"
|
||||||
|
}}/>
|
||||||
</Col>
|
</Col>
|
||||||
|
<ValidationField placeholder="question_content" label="question_content" name="question_id" type="Select" option={QuestionData?.data} fieldNames={{label:"content" ,value:"id"}} />
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,8 @@ const TableHeader = () => {
|
||||||
<Suspense fallback={<Spin />}>
|
<Suspense fallback={<Spin />}>
|
||||||
<PageHeader
|
<PageHeader
|
||||||
pageTitle="report"
|
pageTitle="report"
|
||||||
ModelAbility={ModalEnum?.REPORT_ADD}
|
// ModelAbility={ModalEnum?.REPORT_ADD}
|
||||||
canAdd={canAddReport}
|
// canAdd={canAddReport}
|
||||||
/>
|
/>
|
||||||
<FilterLayout
|
<FilterLayout
|
||||||
sub_children={<FilterForm />}
|
sub_children={<FilterForm />}
|
||||||
|
|
|
||||||
15
src/Pages/Admin/Report/Show/Page.tsx
Normal file
15
src/Pages/Admin/Report/Show/Page.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import React from 'react'
|
||||||
|
import ReportInfo from './ReportInfo';
|
||||||
|
const EditQuestionPage = React.lazy(
|
||||||
|
() => import("../../question/EditPage"),
|
||||||
|
);
|
||||||
|
const Page = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ReportInfo/>
|
||||||
|
<EditQuestionPage/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Page
|
||||||
25
src/Pages/Admin/Report/Show/ReportInfo.tsx
Normal file
25
src/Pages/Admin/Report/Show/ReportInfo.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { useGetAllReport } from '../../../../api/report'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { ParamsEnum } from '../../../../enums/params';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
|
const ReportInfo = () => {
|
||||||
|
const {report_id} = useParams<ParamsEnum>();
|
||||||
|
|
||||||
|
const {data} = useGetAllReport({
|
||||||
|
show:report_id
|
||||||
|
})
|
||||||
|
const {t} = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='report_info'>
|
||||||
|
<div>
|
||||||
|
<h4>{t("practical.student_name")} : <p>{!!data?.data?.student?.first_name ?data?.data?.student?.first_name + " " + data?.data?.student?.last_name: " "}</p> </h4>
|
||||||
|
<h4>{t("practical.report_content")} : <p>{data?.data?.content}</p> </h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ReportInfo
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
import { TableColumnsType } from "antd";
|
import { TableColumnsType } from "antd";
|
||||||
import { report } from "../../../types/Item";
|
|
||||||
import { ModalEnum } from "../../../enums/Model";
|
import { ModalEnum } from "../../../enums/Model";
|
||||||
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
||||||
import { useModalState } from "../../../zustand/Modal";
|
import { useModalState } from "../../../zustand/Modal";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { canDeleteReport, canEditReport } from "../../../utils/hasAbilityFn";
|
import { canDeleteReport, canEditReport, canShowReport } from "../../../utils/hasAbilityFn";
|
||||||
import ActionButtons from "../../../Components/Table/ActionButtons";
|
import ActionButtons from "../../../Components/Table/ActionButtons";
|
||||||
|
import ColumnsImage from "../../../Components/Columns/ColumnsImage";
|
||||||
|
import { useFilterStateState } from "../../../zustand/Filter";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { Report } from "../../../types/Report";
|
||||||
|
|
||||||
export const useColumns = () => {
|
export const useColumns = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
@ -13,26 +16,57 @@ export const useColumns = () => {
|
||||||
const { setIsOpen } = useModalState((state) => state);
|
const { setIsOpen } = useModalState((state) => state);
|
||||||
|
|
||||||
const { setObjectToEdit } = useObjectToEdit((state) => state);
|
const { setObjectToEdit } = useObjectToEdit((state) => state);
|
||||||
const handelDelete = (record: any) => {
|
|
||||||
setObjectToEdit(record);
|
const navigate = useNavigate();
|
||||||
setIsOpen(ModalEnum?.REPORT_DELETE);
|
const { setFilter } = useFilterStateState();
|
||||||
};
|
|
||||||
const handleEdit = (record: any) => {
|
const handelShow = (record: any) => {
|
||||||
setObjectToEdit(record);
|
setFilter({})
|
||||||
setIsOpen(ModalEnum?.REPORT_EDIT);
|
navigate(`${record?.id+"/"+record?.question?.id}`);
|
||||||
|
console.log(record);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const columns: TableColumnsType<report> = [
|
const columns: TableColumnsType<Report> = [
|
||||||
|
|
||||||
{
|
{
|
||||||
title: t("columns.id"),
|
title: t("columns.content"),
|
||||||
dataIndex: "id",
|
dataIndex: "content",
|
||||||
key: "id",
|
key: "content",
|
||||||
align: "center",
|
align: "center",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t("columns.name"),
|
title: t("columns.created_at"),
|
||||||
dataIndex: "name",
|
dataIndex: "created_at",
|
||||||
key: "name",
|
key: "created_at",
|
||||||
|
align: "center",
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// title: t("columns.image"),
|
||||||
|
// dataIndex: "image",
|
||||||
|
// key: "image",
|
||||||
|
// align: "center",
|
||||||
|
// render: (_text: any, record: Report) => {
|
||||||
|
// let str = record?.image;
|
||||||
|
|
||||||
|
// return <ColumnsImage src={str}/> ;
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
title: t("columns.question_name"),
|
||||||
|
dataIndex: "question_id",
|
||||||
|
key: "question_id",
|
||||||
|
render: (_text: any, record: any) => record?.question?.content,
|
||||||
|
ellipsis:true,
|
||||||
|
align: "center",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: t("columns.student_name"),
|
||||||
|
dataIndex: "student_id",
|
||||||
|
key: "student_id",
|
||||||
|
render: (_text: any, record: any) => !!record?.student?.first_name ? record?.student?.first_name + " " +record?.student?.last_name : "" ,
|
||||||
align: "center",
|
align: "center",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -42,14 +76,15 @@ export const useColumns = () => {
|
||||||
align: "center",
|
align: "center",
|
||||||
width: "25vw",
|
width: "25vw",
|
||||||
render: (_text, record, index) => {
|
render: (_text, record, index) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
!!record?.question?.id ?
|
||||||
<ActionButtons
|
<ActionButtons
|
||||||
canDelete={canEditReport}
|
canShow={canShowReport}
|
||||||
canEdit={canDeleteReport}
|
|
||||||
index={index}
|
index={index}
|
||||||
onDelete={() => handelDelete(record)}
|
onShow={() => handelShow(record)}
|
||||||
onEdit={() => handleEdit(record)}
|
|
||||||
/>
|
/>
|
||||||
|
: " "
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,9 @@ const EditReSeller = React.lazy(() => import("./Pages/Admin/Reseller/Edit/Page")
|
||||||
|
|
||||||
const User = React.lazy(() => import("./Pages/Admin/User/Page"));
|
const User = React.lazy(() => import("./Pages/Admin/User/Page"));
|
||||||
const QuestionBank = React.lazy(() => import("./Pages/Admin/QuestionBank/Page"));
|
const QuestionBank = React.lazy(() => import("./Pages/Admin/QuestionBank/Page"));
|
||||||
const Notifications = React.lazy(() => import("./Pages/Admin/Notifications/Page"));
|
const AllNotifications = React.lazy(() => import("./Pages/Admin/Notifications/Page"));
|
||||||
|
const Notifications = React.lazy(() => import("./Pages/Admin/Notifications/AddNotification/Page"));
|
||||||
|
|
||||||
const Profile = React.lazy(() => import("./Pages/Admin/Profile/Page"));
|
const Profile = React.lazy(() => import("./Pages/Admin/Profile/Page"));
|
||||||
const Setting = React.lazy(() => import("./Pages/Admin/Setting/Page"));
|
const Setting = React.lazy(() => import("./Pages/Admin/Setting/Page"));
|
||||||
|
|
||||||
|
|
@ -51,6 +53,7 @@ const Roles = React.lazy(() => import("./Pages/Admin/Roles/Page"));
|
||||||
const Coupon = React.lazy(() => import("./Pages/Admin/Coupon/Page"));
|
const Coupon = React.lazy(() => import("./Pages/Admin/Coupon/Page"));
|
||||||
|
|
||||||
const Report = React.lazy(() => import("./Pages/Admin/Report/Page"));
|
const Report = React.lazy(() => import("./Pages/Admin/Report/Page"));
|
||||||
|
const ShowReport = React.lazy(() => import("./Pages/Admin/Report/Show/Page"));
|
||||||
const Param = React.lazy(() => import("./Pages/Admin/Param/Page"));
|
const Param = React.lazy(() => import("./Pages/Admin/Param/Page"));
|
||||||
|
|
||||||
/// RESELLER ///
|
/// RESELLER ///
|
||||||
|
|
@ -69,6 +72,7 @@ import { TbCategory } from "react-icons/tb";
|
||||||
import { UserTypeEnum } from "./enums/UserType";
|
import { UserTypeEnum } from "./enums/UserType";
|
||||||
import { FaTags } from "react-icons/fa6";
|
import { FaTags } from "react-icons/fa6";
|
||||||
import { CiSquareQuestion } from "react-icons/ci";
|
import { CiSquareQuestion } from "react-icons/ci";
|
||||||
|
import { IoNotifications } from "react-icons/io5";
|
||||||
|
|
||||||
export const menuItems: TMenuItem[] = [
|
export const menuItems: TMenuItem[] = [
|
||||||
{
|
{
|
||||||
|
|
@ -156,17 +160,26 @@ export const menuItems: TMenuItem[] = [
|
||||||
prevPath: 0,
|
prevPath: 0,
|
||||||
},
|
},
|
||||||
|
|
||||||
// {
|
{
|
||||||
// header: "page_header.report",
|
header: "page_header.report",
|
||||||
// element: <Report />,
|
element: <Report />,
|
||||||
// icon: <FaPaperclip />,
|
icon: <FaPaperclip />,
|
||||||
// text: "sidebar.report",
|
text: "sidebar.report",
|
||||||
// path: `/${ABILITIES_ENUM?.Report}`,
|
path: `/${ABILITIES_ENUM?.Report}`,
|
||||||
// abilities: ABILITIES_ENUM?.Report,
|
abilities: ABILITIES_ENUM?.Report,
|
||||||
// abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
||||||
// prevPath: 0,
|
prevPath: 0,
|
||||||
// },
|
},
|
||||||
|
{
|
||||||
|
header: "page_header.add_notification",
|
||||||
|
element: <Notifications />,
|
||||||
|
icon: <IoNotifications />,
|
||||||
|
text: "sidebar.notification",
|
||||||
|
path: `/add_${ABILITIES_ENUM?.NOTIFICATIONS}`,
|
||||||
|
abilities: ABILITIES_ENUM?.NOTIFICATIONS,
|
||||||
|
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
||||||
|
prevPath: 0,
|
||||||
|
},
|
||||||
// {
|
// {
|
||||||
// header: "page_header.param",
|
// header: "page_header.param",
|
||||||
// element: <Param />,
|
// element: <Param />,
|
||||||
|
|
@ -358,7 +371,7 @@ export const CrudRoute: TCrudRoute[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: "page_header.notifications",
|
header: "page_header.notifications",
|
||||||
element: <Notifications />,
|
element: <AllNotifications />,
|
||||||
path: `/${ABILITIES_ENUM?.NOTIFICATIONS}`,
|
path: `/${ABILITIES_ENUM?.NOTIFICATIONS}`,
|
||||||
abilities: ABILITIES_ENUM?.NOTIFICATIONS,
|
abilities: ABILITIES_ENUM?.NOTIFICATIONS,
|
||||||
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
||||||
|
|
@ -416,6 +429,16 @@ export const CrudRoute: TCrudRoute[] = [
|
||||||
type:UserTypeEnum.RE_SELLER
|
type:UserTypeEnum.RE_SELLER
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
header: "page_header.report",
|
||||||
|
element: <ShowReport />,
|
||||||
|
path: `/${ABILITIES_ENUM?.Report}/:${ParamsEnum?.REPORT_ID}/:${ParamsEnum?.QUESTION_ID}`,
|
||||||
|
abilities: ABILITIES_ENUM?.Report,
|
||||||
|
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
||||||
|
prevPath: 0,
|
||||||
|
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const AppRoutes: Record<string, string> = Object.fromEntries(
|
export const AppRoutes: Record<string, string> = Object.fromEntries(
|
||||||
|
|
|
||||||
24
src/Styles/Pages/Report.scss
Normal file
24
src/Styles/Pages/Report.scss
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
.report_info{
|
||||||
|
display: flex;align-items: center;
|
||||||
|
width: 98%;
|
||||||
|
margin-inline: auto;
|
||||||
|
margin-block: 10px;
|
||||||
|
div{
|
||||||
|
padding: 20px;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
// align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
h4{
|
||||||
|
color: var(--text);
|
||||||
|
display: flex;align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
p{
|
||||||
|
font-size: 20px;
|
||||||
|
color: var(--subtext) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,3 +16,5 @@
|
||||||
@import './collections.scss';
|
@import './collections.scss';
|
||||||
@import './setting.scss';
|
@import './setting.scss';
|
||||||
@import './sales.scss';
|
@import './sales.scss';
|
||||||
|
@import './Report.scss';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export const BaseURL = "https://nerd-back.point-dev.net/api/";
|
// export const BaseURL = "https://nerd-back.point-dev.net/api/";
|
||||||
// export const BaseURL = "http://192.168.1.106:8000/api/";
|
export const BaseURL = "http://192.168.43.153:8080/api/";
|
||||||
|
|
||||||
export const HEADER_KEY = "X-Custom-Query-Key";
|
export const HEADER_KEY = "X-Custom-Query-Key";
|
||||||
|
|
|
||||||
20
src/api/notification.ts
Normal file
20
src/api/notification.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
import useAddMutation from "./helper/useAddMutation";
|
||||||
|
import useDeleteMutation from "./helper/useDeleteMutation";
|
||||||
|
import useGetQuery from "./helper/useGetQuery";
|
||||||
|
import useUpdateMutation from "./helper/useUpdateMutation";
|
||||||
|
|
||||||
|
const API = {
|
||||||
|
GET: "/notification",
|
||||||
|
ADD: "/notification",
|
||||||
|
DELETE: "/notification",
|
||||||
|
UPDATE: "/notification",
|
||||||
|
};
|
||||||
|
|
||||||
|
const KEY = "notification";
|
||||||
|
|
||||||
|
export const useGetAllNotification = (params?: any, options?: any) =>
|
||||||
|
useGetQuery(KEY, API.GET, params, options);
|
||||||
|
export const useAddNotification = () => useAddMutation(KEY, API.ADD);
|
||||||
|
export const useUpdateNotification = (params?: any) => useUpdateMutation(KEY, API.GET);
|
||||||
|
export const useDeleteNotification = (params?: any) =>
|
||||||
|
useDeleteMutation(KEY, API.DELETE);
|
||||||
|
|
@ -14,6 +14,9 @@ const KEY = "report";
|
||||||
|
|
||||||
export const useGetAllReport = (params?: any, options?: any) =>
|
export const useGetAllReport = (params?: any, options?: any) =>
|
||||||
useGetQuery(KEY, API.GET, params, options);
|
useGetQuery(KEY, API.GET, params, options);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const useAddReport = () => useAddMutation(KEY, API.ADD);
|
export const useAddReport = () => useAddMutation(KEY, API.ADD);
|
||||||
export const useUpdateReport = (params?: any) =>
|
export const useUpdateReport = (params?: any) =>
|
||||||
useUpdateMutation(KEY, API.GET);
|
useUpdateMutation(KEY, API.GET);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export const PROJECT_NAME = "SCHOOL_DASHBOARD_EXERCISE";
|
export const PROJECT_NAME = "ZAKER_EXERCISE";
|
||||||
|
|
||||||
export const LANGUAGE_KEY = PROJECT_NAME + "_LANGUAGE";
|
export const LANGUAGE_KEY = PROJECT_NAME + "_LANGUAGE";
|
||||||
export const Currency = "ل.س";
|
export const Currency = "ل.س";
|
||||||
|
|
|
||||||
|
|
@ -249,4 +249,11 @@ export enum ModalEnum {
|
||||||
Financial_Collection_EDIT = "Financial_Collection.edit",
|
Financial_Collection_EDIT = "Financial_Collection.edit",
|
||||||
Financial_Collection_ADD = "Financial_Collection.add",
|
Financial_Collection_ADD = "Financial_Collection.add",
|
||||||
Financial_Collection_DELETE = "Financial_Collection.delete",
|
Financial_Collection_DELETE = "Financial_Collection.delete",
|
||||||
|
|
||||||
|
///NOTIFICATION
|
||||||
|
|
||||||
|
NOTIFICATION_EDIT = "NOTIFICATION.edit",
|
||||||
|
NOTIFICATION_ADD = "NOTIFICATION.add",
|
||||||
|
NOTIFICATION_DELETE = "NOTIFICATION.delete",
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ export enum ParamsEnum {
|
||||||
CITY_ID = "city_id",
|
CITY_ID = "city_id",
|
||||||
Collection_ID = "collection_id",
|
Collection_ID = "collection_id",
|
||||||
Manager_ID = "manager_id",
|
Manager_ID = "manager_id",
|
||||||
|
REPORT_ID = "report_id"
|
||||||
// RESELLER_ID = "reseller_id",
|
// RESELLER_ID = "reseller_id",
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -243,7 +243,8 @@
|
||||||
"unit":"الوحدة",
|
"unit":"الوحدة",
|
||||||
"lesson":"الدرس",
|
"lesson":"الدرس",
|
||||||
"code":"رمز",
|
"code":"رمز",
|
||||||
"due_to":"صالح الى"
|
"due_to":"صالح الى",
|
||||||
|
"question_name":"اسم السؤال"
|
||||||
},
|
},
|
||||||
"practical": {
|
"practical": {
|
||||||
"to_confirm_deletion_please_re_enter": "لتأكيد الحذف، يرجى إعادة الإدخال",
|
"to_confirm_deletion_please_re_enter": "لتأكيد الحذف، يرجى إعادة الإدخال",
|
||||||
|
|
@ -326,7 +327,9 @@
|
||||||
"sale":"بيع",
|
"sale":"بيع",
|
||||||
"financial_collection":"التحصيلات",
|
"financial_collection":"التحصيلات",
|
||||||
"show_collection":"حصيلة",
|
"show_collection":"حصيلة",
|
||||||
"does_not_exist_notification":"عذرا لا يوجد إشعارات..."
|
"does_not_exist_notification":"عذرا لا يوجد إشعارات...",
|
||||||
|
"student_name":"اسم الطالب",
|
||||||
|
"report_content":"محتوى التقرير"
|
||||||
},
|
},
|
||||||
"Table": {
|
"Table": {
|
||||||
"header": "",
|
"header": "",
|
||||||
|
|
@ -422,7 +425,8 @@
|
||||||
"financial_collection":"التحصيلات",
|
"financial_collection":"التحصيلات",
|
||||||
"show_collection":"حصيلة",
|
"show_collection":"حصيلة",
|
||||||
"city":"مدينة",
|
"city":"مدينة",
|
||||||
"financialCollection":"التحصيلات"
|
"financialCollection":"التحصيلات",
|
||||||
|
"notification":"الاشعارات"
|
||||||
},
|
},
|
||||||
"education_class_actions": {
|
"education_class_actions": {
|
||||||
"Student_Records": "سجلات الطلاب",
|
"Student_Records": "سجلات الطلاب",
|
||||||
|
|
@ -565,7 +569,8 @@
|
||||||
"activation_date":"تاريخ التنشيط",
|
"activation_date":"تاريخ التنشيط",
|
||||||
"expiration_date":"تاريخ الالغاء",
|
"expiration_date":"تاريخ الالغاء",
|
||||||
"package":"حزمة",
|
"package":"حزمة",
|
||||||
"contact_number":"رقم الهاتف"
|
"contact_number":"رقم الهاتف",
|
||||||
|
"question_content":"محتوى السؤال"
|
||||||
},
|
},
|
||||||
"select": {
|
"select": {
|
||||||
"enums": {
|
"enums": {
|
||||||
|
|
@ -904,7 +909,8 @@
|
||||||
"Area":"المنطقة",
|
"Area":"المنطقة",
|
||||||
"city":"مدينة",
|
"city":"مدينة",
|
||||||
"coupon":"قسيمة",
|
"coupon":"قسيمة",
|
||||||
"financial_collection":"التحصيلات"
|
"financial_collection":"التحصيلات",
|
||||||
|
"notification":"الاشعارات"
|
||||||
},
|
},
|
||||||
"message": {
|
"message": {
|
||||||
"some_thing_went_wrong": "حدث خطأ ما",
|
"some_thing_went_wrong": "حدث خطأ ما",
|
||||||
|
|
@ -956,7 +962,8 @@
|
||||||
"edit_reseller":"تعديل البائع",
|
"edit_reseller":"تعديل البائع",
|
||||||
"Coupon":"قسيمة",
|
"Coupon":"قسيمة",
|
||||||
"financial_collection":"التحصيلات",
|
"financial_collection":"التحصيلات",
|
||||||
"show_collection":"حصيلة"
|
"show_collection":"حصيلة",
|
||||||
|
"notification":"الاشعارات"
|
||||||
},
|
},
|
||||||
"page_header": {
|
"page_header": {
|
||||||
"home": "لوحة القيادة",
|
"home": "لوحة القيادة",
|
||||||
|
|
@ -1014,7 +1021,8 @@
|
||||||
"city":"مدينة",
|
"city":"مدينة",
|
||||||
"questionBank":"بنك الأسئلة",
|
"questionBank":"بنك الأسئلة",
|
||||||
"roles":"الدور",
|
"roles":"الدور",
|
||||||
"coupon":"قسيمة"
|
"coupon":"قسيمة",
|
||||||
|
"notification":"الاشعارات"
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
"student": "قائمة الطلاب",
|
"student": "قائمة الطلاب",
|
||||||
|
|
|
||||||
|
|
@ -320,11 +320,7 @@ export interface Question {
|
||||||
meta?:{}
|
meta?:{}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type report = {
|
|
||||||
id: number;
|
|
||||||
key?: number;
|
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type user = {
|
export type user = {
|
||||||
id: number;
|
id: number;
|
||||||
|
|
|
||||||
14
src/types/Notification.ts
Normal file
14
src/types/Notification.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { Nullable } from "./App";
|
||||||
|
|
||||||
|
// Define the Teacher interface
|
||||||
|
|
||||||
|
export interface Notification {
|
||||||
|
id: number; // Unique identifier for the user
|
||||||
|
name: string; // Name of the user
|
||||||
|
title:string;
|
||||||
|
body:string;
|
||||||
|
seen:string;
|
||||||
|
notifiable_type:string;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
13
src/types/Report.ts
Normal file
13
src/types/Report.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { Nullable } from "./App";
|
||||||
|
|
||||||
|
// Define the Teacher interface
|
||||||
|
|
||||||
|
|
||||||
|
export type Report = {
|
||||||
|
id: number; // Unique identifier for the user
|
||||||
|
content: string; // Name of the user
|
||||||
|
image: any; // URL of the user's icon
|
||||||
|
question_id: number; // URL of the user's icon
|
||||||
|
student_id: number; // URL of the user's icon
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -547,12 +547,7 @@ export const canAddStatus =
|
||||||
hasAbility(ABILITIES_ENUM.ABSENCE, ABILITIES_VALUES_ENUM.STORE) &&
|
hasAbility(ABILITIES_ENUM.ABSENCE, ABILITIES_VALUES_ENUM.STORE) &&
|
||||||
hasAbility(ABILITIES_ENUM.LATE_ARRIVAL, ABILITIES_VALUES_ENUM.STORE);
|
hasAbility(ABILITIES_ENUM.LATE_ARRIVAL, ABILITIES_VALUES_ENUM.STORE);
|
||||||
|
|
||||||
/// notification
|
|
||||||
|
|
||||||
export const canAddNotification = hasAbility(
|
|
||||||
ABILITIES_ENUM.NOTE,
|
|
||||||
ABILITIES_VALUES_ENUM.STORE,
|
|
||||||
);
|
|
||||||
|
|
||||||
/// MarksReport
|
/// MarksReport
|
||||||
|
|
||||||
|
|
@ -694,6 +689,10 @@ export const canDeleteReport = hasAbility(
|
||||||
ABILITIES_ENUM.Report,
|
ABILITIES_ENUM.Report,
|
||||||
ABILITIES_VALUES_ENUM.DELETE,
|
ABILITIES_VALUES_ENUM.DELETE,
|
||||||
);
|
);
|
||||||
|
export const canShowReport = hasAbility(
|
||||||
|
ABILITIES_ENUM.Report,
|
||||||
|
ABILITIES_VALUES_ENUM.SHOW,
|
||||||
|
);
|
||||||
|
|
||||||
/// User
|
/// User
|
||||||
|
|
||||||
|
|
@ -845,3 +844,30 @@ export const canShowCollection = hasAbility(
|
||||||
ABILITIES_ENUM.Collections,
|
ABILITIES_ENUM.Collections,
|
||||||
ABILITIES_VALUES_ENUM.SHOW,
|
ABILITIES_VALUES_ENUM.SHOW,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///// Notification
|
||||||
|
|
||||||
|
export const canAddNotification = hasAbility(
|
||||||
|
ABILITIES_ENUM.EDUCATION_CLASS,
|
||||||
|
ABILITIES_VALUES_ENUM.STORE,
|
||||||
|
);
|
||||||
|
export const canEditNotification = hasAbility(
|
||||||
|
ABILITIES_ENUM.EDUCATION_CLASS,
|
||||||
|
ABILITIES_VALUES_ENUM.UPDATE,
|
||||||
|
);
|
||||||
|
export const canDeleteNotification = hasAbility(
|
||||||
|
ABILITIES_ENUM.EDUCATION_CLASS,
|
||||||
|
ABILITIES_VALUES_ENUM.DELETE,
|
||||||
|
);
|
||||||
|
export const canShowNotification = hasAbility(
|
||||||
|
ABILITIES_ENUM.EDUCATION_CLASS,
|
||||||
|
ABILITIES_VALUES_ENUM.SHOW,
|
||||||
|
);
|
||||||
|
export const canIndexNotification = hasAbility(
|
||||||
|
ABILITIES_ENUM.EDUCATION_CLASS,
|
||||||
|
ABILITIES_VALUES_ENUM.INDEX,
|
||||||
|
);
|
||||||
Loading…
Reference in New Issue
Block a user