From 0b827ba990fafbf9613277564746c262832be5da Mon Sep 17 00:00:00 2001 From: karimaldeen Date: Sat, 14 Sep 2024 16:21:57 +0300 Subject: [PATCH] add new page "QuestionBank" --- .vscode/settings.json | 1 + .../ValidationField/View/TextField.tsx | 3 +- .../Admin/QuestionBank/Model/AddModel.tsx | 33 ++++++++ .../Admin/QuestionBank/Model/EditModel.tsx | 38 +++++++++ .../Admin/QuestionBank/Model/FilterForm.tsx | 20 +++++ .../Admin/QuestionBank/Model/ModelForm.tsx | 17 ++++ .../Admin/QuestionBank/Model/formUtil.ts | 19 +++++ src/Pages/Admin/QuestionBank/Page.tsx | 46 ++++++++++ src/Pages/Admin/QuestionBank/Table.tsx | 18 ++++ .../Admin/QuestionBank/useTableColumns.tsx | 83 +++++++++++++++++++ .../question/Model/Field/ChoiceFields.tsx | 1 + .../Model/Malty/ChoiceField/ChoiceFields.tsx | 1 + src/Pages/Admin/question/Model/Malty/Form.tsx | 1 + src/Pages/Admin/question/Model/ModelForm.tsx | 1 + src/Routes.tsx | 13 +++ src/enums/Model.ts | 7 ++ src/enums/abilities.ts | 1 + src/translate/ar.json | 12 ++- src/utils/hasAbilityFn.ts | 22 +++++ 19 files changed, 332 insertions(+), 5 deletions(-) create mode 100644 src/Pages/Admin/QuestionBank/Model/AddModel.tsx create mode 100644 src/Pages/Admin/QuestionBank/Model/EditModel.tsx create mode 100644 src/Pages/Admin/QuestionBank/Model/FilterForm.tsx create mode 100644 src/Pages/Admin/QuestionBank/Model/ModelForm.tsx create mode 100644 src/Pages/Admin/QuestionBank/Model/formUtil.ts create mode 100644 src/Pages/Admin/QuestionBank/Page.tsx create mode 100644 src/Pages/Admin/QuestionBank/Table.tsx create mode 100644 src/Pages/Admin/QuestionBank/useTableColumns.tsx diff --git a/.vscode/settings.json b/.vscode/settings.json index fae1ae1..54fb8c9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,6 +13,7 @@ "Popconfirm", "queryqlent", "registraion", + "Sellcast", "SENDNOTIFICATION", "setdateparams", "szhsin", diff --git a/src/Components/ValidationField/View/TextField.tsx b/src/Components/ValidationField/View/TextField.tsx index ae60405..35babba 100644 --- a/src/Components/ValidationField/View/TextField.tsx +++ b/src/Components/ValidationField/View/TextField.tsx @@ -25,6 +25,7 @@ const TextField = ({ ) => { formik.setFieldValue(name, e.target.value); }; + return (
diff --git a/src/Pages/Admin/QuestionBank/Model/AddModel.tsx b/src/Pages/Admin/QuestionBank/Model/AddModel.tsx new file mode 100644 index 0000000..348426b --- /dev/null +++ b/src/Pages/Admin/QuestionBank/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 { useAddGrade } from "../../../../api/grade"; + +const AddModel: React.FC = () => { + const { mutate, status } = useAddGrade(); + + const handleSubmit = (values: any) => { + mutate({ + ...values, + }); + }; + return ( + <> + + + + + ); +}; + +export default AddModel; diff --git a/src/Pages/Admin/QuestionBank/Model/EditModel.tsx b/src/Pages/Admin/QuestionBank/Model/EditModel.tsx new file mode 100644 index 0000000..a2e1fdb --- /dev/null +++ b/src/Pages/Admin/QuestionBank/Model/EditModel.tsx @@ -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 { useUpdateQuestion } from "../../../../api/Question"; +import { handelImageState } from "../../../../utils/DataToSendImageState"; + +const EditModel: React.FC = () => { + const { mutate, status } = useUpdateQuestion(); + const { objectToEdit } = useObjectToEdit((state) => state); + + const handleSubmit = (values: any) => { + const Data_to_send = { ...values }; + const handelImage = handelImageState(Data_to_send, "icon"); + mutate(handelImage); + }; + + return ( + <> + + + + + ); +}; + +export default EditModel; diff --git a/src/Pages/Admin/QuestionBank/Model/FilterForm.tsx b/src/Pages/Admin/QuestionBank/Model/FilterForm.tsx new file mode 100644 index 0000000..c870850 --- /dev/null +++ b/src/Pages/Admin/QuestionBank/Model/FilterForm.tsx @@ -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 ( +
+ + + + + +
+ ); +}; + +export default FilterForm; diff --git a/src/Pages/Admin/QuestionBank/Model/ModelForm.tsx b/src/Pages/Admin/QuestionBank/Model/ModelForm.tsx new file mode 100644 index 0000000..b18fe6f --- /dev/null +++ b/src/Pages/Admin/QuestionBank/Model/ModelForm.tsx @@ -0,0 +1,17 @@ +import { Col, Row } from "reactstrap"; +import ValidationField from "../../../../Components/ValidationField/ValidationField"; + +const Form = () => { + return ( + + + + + + + + + ); +}; + +export default Form; diff --git a/src/Pages/Admin/QuestionBank/Model/formUtil.ts b/src/Pages/Admin/QuestionBank/Model/formUtil.ts new file mode 100644 index 0000000..77f69bf --- /dev/null +++ b/src/Pages/Admin/QuestionBank/Model/formUtil.ts @@ -0,0 +1,19 @@ +import * as Yup from "yup"; +import { Grade, GradeInitialValues } from "../../../../types/Grade"; + +export const getInitialValues = ( + objectToEdit: Partial, +): GradeInitialValues => { + return { + id: objectToEdit?.id, + name: objectToEdit?.name ?? "", + icon: objectToEdit?.icon ?? "", + }; +}; + +export const getValidationSchema = () => { + // validate input + return Yup.object().shape({ + name: Yup.string().required("validation.required"), + }); +}; diff --git a/src/Pages/Admin/QuestionBank/Page.tsx b/src/Pages/Admin/QuestionBank/Page.tsx new file mode 100644 index 0000000..e905425 --- /dev/null +++ b/src/Pages/Admin/QuestionBank/Page.tsx @@ -0,0 +1,46 @@ +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 { useDeleteQuestion } from "../../../api/Question"; +import PageHeader from "../../../Layout/Dashboard/PageHeader"; +import FilterLayout from "../../../Layout/Dashboard/FilterLayout"; +import FilterForm from "./Model/FilterForm"; +import { canAddQuestionBank } from "../../../utils/hasAbilityFn"; + +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 = useDeleteQuestion(); + + useSetPageTitle(t(`page_header.QuestionBank`)); + + return ( +
+ }> + + } filterTitle="table.QuestionBank" /> + + + + + + + ); +}; + +export default TableHeader; diff --git a/src/Pages/Admin/QuestionBank/Table.tsx b/src/Pages/Admin/QuestionBank/Table.tsx new file mode 100644 index 0000000..37f483c --- /dev/null +++ b/src/Pages/Admin/QuestionBank/Table.tsx @@ -0,0 +1,18 @@ +import { useColumns } from "./useTableColumns"; +import React from "react"; +import DataTable from "../../../Layout/Dashboard/Table/DataTable"; +import { useGetAllQuestion } from "../../../api/Question"; +import { useFilterState } from "../../../Components/Utils/Filter/FilterState"; + +const App: React.FC = () => { + const { filterState } = useFilterState(); + + const response = useGetAllQuestion({ + pagination: true, + ...filterState, + }); + + return ; +}; + +export default App; diff --git a/src/Pages/Admin/QuestionBank/useTableColumns.tsx b/src/Pages/Admin/QuestionBank/useTableColumns.tsx new file mode 100644 index 0000000..da5680c --- /dev/null +++ b/src/Pages/Admin/QuestionBank/useTableColumns.tsx @@ -0,0 +1,83 @@ +import { TableColumnsType } from "antd"; +import { Question } from "../../../types/Item"; +import { FaPlus } from "react-icons/fa"; +import { ModalEnum } from "../../../enums/Model"; +import { useObjectToEdit } from "../../../zustand/ObjectToEditState"; +import { useTranslation } from "react-i18next"; +import { ABILITIES_ENUM } from "../../../enums/abilities"; +import { useNavigate } from "react-router-dom"; +import { useModalState } from "../../../zustand/Modal"; +import { + canAddQuestion, + canDeleteQuestion, + canEditQuestion, +} from "../../../utils/hasAbilityFn"; +import ActionButtons from "../../../Components/Table/ActionButtons"; + +export const useColumns = () => { + const { setObjectToEdit } = useObjectToEdit((state) => state); + const navigate = useNavigate(); + const { setIsOpen } = useModalState((state) => state); + + const handelAdd = () => { + setObjectToEdit({}); + navigate(`${ABILITIES_ENUM?.QUESTION}/add`); + }; + + const handelDelete = (data: any) => { + setObjectToEdit(data); + setIsOpen(ModalEnum?.QUESTION_DELETE); + }; + + const handleEdit = (record: any) => { + setObjectToEdit(record); + navigate(`${ABILITIES_ENUM?.QUESTION}/${record?.id}`); + }; + const [t] = useTranslation(); + + const columns: TableColumnsType = [ + { + title: t("columns.id"), + dataIndex: "id", + key: "id", + align: "center", + render: (text, record) => record?.id, + }, + { + title: `${t("columns.content")}`, + dataIndex: "name", + key: "name", + align: "center", + render: (text, record) => record?.content, + ellipsis: true, + }, + { + title: t("columns.isBase"), + dataIndex: "isBase", + key: "isBase", + align: "center", + render: (text, record) => + record?.isBase ? t("practical.yes") : t("practical.no"), + }, + + { + title: "#", + key: "actions", + align: "center", + + render: (_text, record, index) => { + return ( + handelDelete(record)} + onEdit={() => handleEdit(record)} + /> + ); + }, + }, + ]; + + return columns; +}; diff --git a/src/Pages/Admin/question/Model/Field/ChoiceFields.tsx b/src/Pages/Admin/question/Model/Field/ChoiceFields.tsx index 37630b6..552e7eb 100644 --- a/src/Pages/Admin/question/Model/Field/ChoiceFields.tsx +++ b/src/Pages/Admin/question/Model/Field/ChoiceFields.tsx @@ -70,6 +70,7 @@ const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => { type="TextArea" style={{ width: "100%" , height: 60,resize:"none" }} showCount={false} + autoSize={{ minRows: 2, maxRows: 10 }} /> diff --git a/src/Pages/Admin/question/Model/Malty/ChoiceField/ChoiceFields.tsx b/src/Pages/Admin/question/Model/Malty/ChoiceField/ChoiceFields.tsx index 4586fbb..46dac53 100644 --- a/src/Pages/Admin/question/Model/Malty/ChoiceField/ChoiceFields.tsx +++ b/src/Pages/Admin/question/Model/Malty/ChoiceField/ChoiceFields.tsx @@ -89,6 +89,7 @@ const ChoiceFields = ({ type="TextArea" style={{ width: "100%" , height: 60,resize:"none" }} showCount={false} + autoSize={{ minRows: 2, maxRows: 10 }} /> diff --git a/src/Pages/Admin/question/Model/Malty/Form.tsx b/src/Pages/Admin/question/Model/Malty/Form.tsx index fbb81f3..8effc15 100644 --- a/src/Pages/Admin/question/Model/Malty/Form.tsx +++ b/src/Pages/Admin/question/Model/Malty/Form.tsx @@ -142,6 +142,7 @@ const Form = () => { label="hint_question" type="TextArea" style={{ width: "100%" , height: 60,resize:"none" }} + autoSize={{ minRows: 2, maxRows: 10 }} showCount={false} /> diff --git a/src/Pages/Admin/question/Model/ModelForm.tsx b/src/Pages/Admin/question/Model/ModelForm.tsx index b104882..6de101f 100644 --- a/src/Pages/Admin/question/Model/ModelForm.tsx +++ b/src/Pages/Admin/question/Model/ModelForm.tsx @@ -77,6 +77,7 @@ const Form = () => { type="TextArea" style={{ width: "100%" , height: 60,resize:"none" }} showCount={false} + autoSize={{ minRows: 2, maxRows: 10 }} /> diff --git a/src/Routes.tsx b/src/Routes.tsx index 409c91c..93a9a74 100644 --- a/src/Routes.tsx +++ b/src/Routes.tsx @@ -32,6 +32,7 @@ const EditReSeller = React.lazy( 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")); /// RESELLER /// const Student_Package = React.lazy( @@ -129,6 +130,18 @@ export const menuItems: TMenuItem[] = [ 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, + }, + + /// RESELLER ///// { diff --git a/src/enums/Model.ts b/src/enums/Model.ts index 5a95bef..de37336 100644 --- a/src/enums/Model.ts +++ b/src/enums/Model.ts @@ -186,4 +186,11 @@ export enum ModalEnum { Student_Package_EDIT = "Student_Package.edit", Student_Package_ADD = "Student_Package.add", Student_Package_DELETE = "Student_Package.delete", + + + ///QuestionBank + + QUESTION_BANK_ADD = "QuestionBank.add", + QUESTION_BANK_EDIT = "QuestionBank.edit", + QUESTION_BANK_DELETE = "QuestionBank.delete", } diff --git a/src/enums/abilities.ts b/src/enums/abilities.ts index 427f62a..e84627a 100644 --- a/src/enums/abilities.ts +++ b/src/enums/abilities.ts @@ -47,6 +47,7 @@ export enum ABILITIES_ENUM { User = "user", RE_SELLER = "reseller", Student_Package = "student_package", + QUESTION_BANK = "QuestionBank" //// } diff --git a/src/translate/ar.json b/src/translate/ar.json index c2d428a..bd36428 100644 --- a/src/translate/ar.json +++ b/src/translate/ar.json @@ -753,7 +753,8 @@ "reseller": "البائعين", "param": "معامل", "student_package": "حزمة الطالب", - "quiz":"الاختبارات" + "quiz":"الاختبارات", + "QuestionBank":"بنك الأسئلة" }, "message": { "some_thing_went_wrong": "حدث خطأ ما", @@ -788,7 +789,8 @@ "grade": "الصفوف", "report": "تقرير", "tags": "كلمات مفتاحية", - "reseller":"البائعين" + "reseller":"البائعين", + "QuestionBank":"بنك الأسئلة" }, "page_header": { "dashboard": "لوحة القيادة / الصفحة الرئيسية", @@ -825,13 +827,15 @@ "reseller": " لوحة القيادة / البائعين", "add_reseller": " لوحة القيادة / البائعين / إضافة بائع ", "param": "معامل", - "student_package": "حزمة الطالب" + "student_package": "حزمة الطالب", + "QuestionBank":"لوحة القيادة / بنك الأسئلة" }, "table": { "student": "قائمة الطلاب", "reseller": "البائعين", "grade": "قائمة الصفوف", - "subjects": "مواد الصف" + "subjects": "مواد الصف", + "QuestionBank":"بنك الأسئلة" }, "alphabet": { "A": "A", diff --git a/src/utils/hasAbilityFn.ts b/src/utils/hasAbilityFn.ts index 221883b..dc4e751 100644 --- a/src/utils/hasAbilityFn.ts +++ b/src/utils/hasAbilityFn.ts @@ -677,3 +677,25 @@ export const canDeleteStudent_Package = hasAbility( ); + + +/// QuestionBank + +export const canAddQuestionBank = hasAbility( + ABILITIES_ENUM.QUESTION_BANK, + ABILITIES_VALUES_ENUM.STORE, +); + +export const canEditQuestionBank = hasAbility( + ABILITIES_ENUM.QUESTION_BANK, + ABILITIES_VALUES_ENUM.UPDATE, +); +export const canDeleteQuestionBank = hasAbility( + ABILITIES_ENUM.QUESTION_BANK, + ABILITIES_VALUES_ENUM.DELETE, +); + +export const canShowQuestionBank = hasAbility( + ABILITIES_ENUM.QUESTION_BANK, + ABILITIES_VALUES_ENUM.SHOW, +);