diff --git a/src/Components/ValidationField/View/Default.tsx b/src/Components/ValidationField/View/Default.tsx
index 79753d3..8e5f561 100644
--- a/src/Components/ValidationField/View/Default.tsx
+++ b/src/Components/ValidationField/View/Default.tsx
@@ -14,13 +14,20 @@ const Default = ({
type,
no_label,
label_icon,
+ label2,
...props
}: ValidationFieldPropsInput) => {
const { errorMsg, isError, t } = useFormField(name, props);
return (
- {no_label ? (
+ {label2 ? (
+
+ )
+
+ :no_label ? (
diff --git a/src/Components/ValidationField/utils/types.ts b/src/Components/ValidationField/utils/types.ts
index 5535241..f2e2003 100644
--- a/src/Components/ValidationField/utils/types.ts
+++ b/src/Components/ValidationField/utils/types.ts
@@ -182,6 +182,7 @@ export interface ValidationFieldPropsInput
isDisabled?:boolean
no_label?:string
label_icon?:string
+label2?:string
}
diff --git a/src/Components/exercise/Header.tsx b/src/Components/exercise/Header.tsx
new file mode 100644
index 0000000..60c2876
--- /dev/null
+++ b/src/Components/exercise/Header.tsx
@@ -0,0 +1,38 @@
+import { useFormikContext } from 'formik';
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { GoArrowSwitch } from 'react-icons/go';
+import { useObjectToEdit } from '../../zustand/ObjectToEditState';
+
+const Header = () => {
+ const [t] = useTranslation();
+ const { values, setFieldValue,setValues } = useFormikContext
();
+ const {isBseQuestion,set_isBseQuestion} = useObjectToEdit()
+
+ const handleChange = () => {
+
+ if (isBseQuestion) {
+ set_isBseQuestion(false)
+ setValues(null)
+
+ } else {
+
+ set_isBseQuestion(true)
+ setValues(null)
+ }
+ };
+
+ return (
+
+
+ {t("practical.add")} {t("models.exercise")}{" "}
+
+
+
+ {isBseQuestion ? t("header.malty_exercise") :t("header.exercise") }
+
+
+ );
+};
+
+export default Header;
diff --git a/src/Pages/Auth/LoginForm.tsx b/src/Pages/Auth/LoginForm.tsx
index fa354fd..e1ac712 100644
--- a/src/Pages/Auth/LoginForm.tsx
+++ b/src/Pages/Auth/LoginForm.tsx
@@ -14,7 +14,7 @@ const LoginForm = () => {
const [t] = useTranslation();
const handelSubmit = (values: FormValues) => {
- mutate(values );
+ mutate(values);
};
const { login } = useAuthState();
diff --git a/src/Pages/Auth/formutils.ts b/src/Pages/Auth/formutils.ts
index b1ae058..bd6faa1 100644
--- a/src/Pages/Auth/formutils.ts
+++ b/src/Pages/Auth/formutils.ts
@@ -4,15 +4,9 @@ import { FormValues } from "../../types/Auth";
export const validationSchema = Yup.object().shape({
username: Yup.string().required("Username is required"),
password: Yup.string().required("Password is required"),
- cycle: Yup.string().required("Cycle is required"),
- branch: Yup.string().required("Branch is required"),
- term: Yup.string().required("Term is required"),
});
export const initialValues: FormValues = {
username: null,
password: null,
- cycle: null,
- branch: null,
- term: null,
};
diff --git a/src/Pages/Unit/Model/AddModel.tsx b/src/Pages/Unit/Model/AddModel.tsx
index af7a7e3..5a41c6b 100644
--- a/src/Pages/Unit/Model/AddModel.tsx
+++ b/src/Pages/Unit/Model/AddModel.tsx
@@ -38,7 +38,7 @@ const ModalForm: React.FC = () => {
{
-
-
-
);
};
diff --git a/src/Pages/Unit/Model/EditModel.tsx b/src/Pages/Unit/Model/EditModel.tsx
index 8105e4d..11a77e0 100644
--- a/src/Pages/Unit/Model/EditModel.tsx
+++ b/src/Pages/Unit/Model/EditModel.tsx
@@ -43,7 +43,7 @@ const ModalForm: React.FC = () => {
{
-
-
-
);
};
diff --git a/src/Pages/Unit/Model/formUtil.ts b/src/Pages/Unit/Model/formUtil.ts
index d411d79..365816f 100644
--- a/src/Pages/Unit/Model/formUtil.ts
+++ b/src/Pages/Unit/Model/formUtil.ts
@@ -4,8 +4,6 @@ export const getInitialValues = (objectToEdit: any): any => {
return {
id: objectToEdit?.id,
name: objectToEdit?.name ?? "",
- // subject_id:objectToEdit?.subject_id??null,
- term: objectToEdit?.term ?? null,
};
};
@@ -14,6 +12,5 @@ export const getValidationSchema = () => {
return Yup.object().shape({
name: Yup.string().required("validation.required"),
// subject_id: Yup.string().required('validation.required'),
- term: Yup.string().required("validation.required"),
});
};
diff --git a/src/Pages/Unit/useTableColumns.tsx b/src/Pages/Unit/useTableColumns.tsx
index 0af4eaf..d049c5a 100644
--- a/src/Pages/Unit/useTableColumns.tsx
+++ b/src/Pages/Unit/useTableColumns.tsx
@@ -69,20 +69,12 @@ export const useColumns = () => {
render: (text, record) => record?.name,
},
- {
- title: t("columns.term"),
- dataIndex: "term",
- key: "term",
- align: "center",
- render: (text, record) => record?.term,
- },
-
{
title: t("columns.lesson_count"),
dataIndex: "lesson_count",
key: "lesson_count",
align: "center",
- render: (text, record) => record?.lessons?.length,
+ render: (text, record) => record?.lessons_count,
},
{
diff --git a/src/Pages/lesson/Model/Add.tsx b/src/Pages/lesson/Model/Add.tsx
index 8236946..6337d8c 100644
--- a/src/Pages/lesson/Model/Add.tsx
+++ b/src/Pages/lesson/Model/Add.tsx
@@ -20,7 +20,7 @@ const Form = () => {
-
+
);
};
diff --git a/src/Pages/lesson/Model/AddModel.tsx b/src/Pages/lesson/Model/AddModel.tsx
index 98b5de5..3a1db52 100644
--- a/src/Pages/lesson/Model/AddModel.tsx
+++ b/src/Pages/lesson/Model/AddModel.tsx
@@ -42,7 +42,7 @@ const ModalForm: React.FC = () => {
{
-
+
);
};
diff --git a/src/Pages/lesson/Model/EditModel.tsx b/src/Pages/lesson/Model/EditModel.tsx
index f66ee08..95cfd27 100644
--- a/src/Pages/lesson/Model/EditModel.tsx
+++ b/src/Pages/lesson/Model/EditModel.tsx
@@ -46,7 +46,7 @@ const ModalForm: React.FC = () => {
{
align: "center",
render: (text, record) => record?.name,
},
-
- {
- title: t("columns.description"),
- dataIndex: "description",
- key: "description",
- align: "center",
- render: (text, record) => record?.description,
- },
-
{
title: can_add_Lesson ? (
- {/* */}
-
- {/* */}
{
diff --git a/src/Pages/question/Model/AddModel.tsx b/src/Pages/question/Model/AddModel.tsx
deleted file mode 100644
index 0f867da..0000000
--- a/src/Pages/question/Model/AddModel.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-import React, { useEffect } from "react";
-import { Modal, Spin } from "antd";
-import FormikForm from "../../../Layout/Dashboard/FormikFormModel";
-import ModelBody from "./Add";
-import { getInitialValues, getValidationSchema } from "./formUtil";
-import { useAddQuestion } from "../../../api/Question";
-import { useQueryClient } from "react-query";
-import { useTranslation } from "react-i18next";
-import { useNavigate, useParams } from "react-router-dom";
-import { ParamsEnum } from "../../../enums/params";
-import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
-
-const ModalForm: React.FC = () => {
-
- const queryClient = useQueryClient();
-
- const { mutate, isSuccess, isLoading } = useAddQuestion();
- const {object_to_edit} = useObjectToEdit()
-
- const {subject_id} = useParams()
-
-
- const handleSubmit = (values: any) => {
- console.log(values,"values");
-
- mutate({ ...values, subject_id:subject_id });
- };
- const navigate = useNavigate()
- useEffect(() => {
- if(isSuccess){
- navigate(-1)
-
- }
- }, [isSuccess])
-
- const handleCancel = () => {
- navigate(-1)
- };
-
- const [t] = useTranslation();
-
- return (
-
-
-
-
-
-
- {" "}
- {t("practical.add")} {t("models.exercise")}{" "}
-
-
-
-
{t("practical.back")}
-
- {t("practical.add")}
-
- {isLoading && (
-
-
-
- )}
-
-
-
-
-
-
- );
-};
-
-export default ModalForm;
diff --git a/src/Pages/question/Model/Edit.tsx b/src/Pages/question/Model/Edit.tsx
index acd5247..dba5338 100644
--- a/src/Pages/question/Model/Edit.tsx
+++ b/src/Pages/question/Model/Edit.tsx
@@ -46,7 +46,6 @@ const Form = () => {
{/* */}
-
diff --git a/src/Pages/question/Model/EditModel.tsx b/src/Pages/question/Model/EditModel.tsx
deleted file mode 100644
index e5f8b8f..0000000
--- a/src/Pages/question/Model/EditModel.tsx
+++ /dev/null
@@ -1,86 +0,0 @@
-import React, { useEffect } from "react";
-import { Modal, Spin } from "antd";
-import FormikForm from "../../../Layout/Dashboard/FormikFormModel";
-import ModelBody from "./Add";
-import { getInitialValues, getValidationSchema } from "./formUtil";
-import { useGetAllQuestion, useUpdateQuestion } from "../../../api/Question";
-import { useQueryClient } from "react-query";
-import { useTranslation } from "react-i18next";
-import { useNavigate, useParams } from "react-router-dom";
-import { ParamsEnum } from "../../../enums/params";
-import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
-import { removeStringKeys } from "../../../utils/removeStringKeys";
-import SpinContainer from "../../../Components/Layout/SpinContainer";
-
-const ModalForm: React.FC = () => {
-
- const {question_id,subject_id} = useParams()
-
- const { mutate, isSuccess, isLoading } = useUpdateQuestion();
- const {data,isLoading:dataLoading}= useGetAllQuestion({show:question_id})
-
- const object_to_edit = data?.data ;
-
- const handleSubmit = (values: any) => {
- console.log(values, "values");
- const DataToSend = structuredClone(values);
-
- const keysToRemove = ['image', 'answer_image'];
- const updatedObject = removeStringKeys(DataToSend, keysToRemove);
-
- mutate({ ...updatedObject });
- };
-
- const navigate = useNavigate()
- const handleCancel = () => {
- navigate(-1)
- };
-
- const [t] = useTranslation();
-
- useEffect(() => {
- if(isSuccess){
- navigate(-1)
- }
- }, [isSuccess])
-
-
- if(dataLoading){
- return
- }
-
- return (
-
-
-
-
-
-
- {" "}
- {t("practical.edit")} {t("models.exercise")}{" "}
-
-
-
-
{t("practical.back")}
-
- {t("practical.edit")}
-
- {isLoading && (
-
-
-
- )}
-
-
-
-
-
-
- );
-};
-
-export default ModalForm;
diff --git a/src/Pages/question/Model/Malty/Add.tsx b/src/Pages/question/Model/Malty/Add.tsx
new file mode 100644
index 0000000..673f784
--- /dev/null
+++ b/src/Pages/question/Model/Malty/Add.tsx
@@ -0,0 +1,121 @@
+ import { Col, Row } from "reactstrap";
+import React, { useEffect } from "react";
+import ValidationField from "../../../../Components/ValidationField/ValidationField";
+import { useFormikContext } from "formik";
+import { useModalState } from "../../../../zustand/Modal";
+import PdfUploader from "../../../../Components/CustomFields/PdfUploader";
+import ChoiceFields from "./ChoiceField/ChoiceFields";
+import { FaCirclePlus } from "react-icons/fa6";
+import { Choice } from "../../../../types/Item";
+import { useTranslation } from "react-i18next";
+import DynamicTags from "./Tags/DynamicTags";
+import { useGetAllQuestion } from "../../../../api/Question";
+import QuestionFIeld from "./QuestionFIeld/QuestionFIeld";
+
+const Form = () => {
+ const formik = useFormikContext();
+ const { isOpen } = useModalState((state) => state);
+ // const {data} = useGetAllQuestion();
+
+ useEffect(() => {
+ if (isOpen === "") {
+ formik.setErrors({});
+ formik.resetForm();
+ }
+ }, [isOpen]);
+
+ // console.log(formik?.errors);
+
+
+ const handleAddChoice = (parent_index:number) => {
+ console.log(parent_index);
+
+ formik.setFieldValue(`Questions.[${parent_index}].QuestionOptions`, [...(formik?.values as any)?.Questions?.[parent_index].QuestionOptions as Choice[],
+
+ {
+ answer:null,
+ answer_image:null,
+ isCorrect:0
+ }])
+ }
+
+
+ const handleAddQuestion = () => {
+ formik.setFieldValue('Questions', [...(formik?.values as any)?.Questions as Choice[],
+
+ {
+ content: "",
+ image: "",
+ parent: '',
+ isBase: 0,
+ max_mark: 1,
+ min_mark_to_pass: 1,
+ QuestionOptions: [{ answer: null, answer_image: null, isCorrect: 0 }],
+ tags: []
+ }])
+
+ const max_mark = formik?.values?.max_mark + 1
+
+ formik.setFieldValue('max_mark', max_mark)
+}
+ const [t] = useTranslation()
+ console.log(formik.errors);
+
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ (((formik?.values as any)?.Questions as Choice[])||[]) .map((item:Choice,parent_index:number)=>{
+
+ return (
+
+
+
+
+
+
+ {
+ (((formik?.values as any)?.Questions?.[parent_index]?.QuestionOptions as Choice[])||[]) .map((item:Choice,index:number)=>{
+
+ return
+ }
+ )
+ }
+
+ handleAddChoice(parent_index)} size={23} /> {t("header.add_new_choice")}
+
+
+
+
+ )
+ }
+ )
+ }
+
+
+ {t("header.add_new_question")}
+
+
+ );
+};
+
+export default Form;
diff --git a/src/Pages/question/Model/Malty/ChoiceField/CheckboxField.tsx b/src/Pages/question/Model/Malty/ChoiceField/CheckboxField.tsx
new file mode 100644
index 0000000..630ecb6
--- /dev/null
+++ b/src/Pages/question/Model/Malty/ChoiceField/CheckboxField.tsx
@@ -0,0 +1,37 @@
+import React from "react";
+import useFormField from "../../../../../Hooks/useFormField";
+import { Checkbox, Form } from "antd";
+import { useFormik, useFormikContext } from "formik";
+import { useTranslation } from "react-i18next";
+const CheckboxField = ({
+ name,
+ label,
+ isDisabled,
+ onChange,
+ Group,
+ className,
+ parent_index,
+ props,
+}: any) => {
+ const formik = useFormikContext()
+ const [t] = useTranslation()
+ const CheckboxhandleChange = (value: any) => {
+ console.log(value?.target?.checked);
+
+ formik.setFieldValue(`Questions[${parent_index}].QuestionOptions[${name}].isCorrect`, value?.target?.checked ? 1 : 0);
+ };
+ return (
+
+
+ {t(`input.${label ? label : name}`)}
+
+
+ );
+};
+
+export default CheckboxField;
diff --git a/src/Pages/question/Model/Malty/ChoiceField/ChoiceFields.tsx b/src/Pages/question/Model/Malty/ChoiceField/ChoiceFields.tsx
new file mode 100644
index 0000000..426850e
--- /dev/null
+++ b/src/Pages/question/Model/Malty/ChoiceField/ChoiceFields.tsx
@@ -0,0 +1,28 @@
+import React from 'react'
+import { Choice } from '../../../../../types/Item'
+import ValidationField from '../../../../../Components/ValidationField/ValidationField'
+import { useFormikContext } from 'formik';
+import { useTranslation } from 'react-i18next';
+import { getCharFromNumber } from '../../../../../utils/getCharFromNumber';
+import CheckboxField from './CheckboxField';
+import TextField from './TextField';
+import File from './File';
+
+const ChoiceFields = ({index,parent_index,data}:{index:number ,parent_index:number, data :Choice }) => {
+ const formik = useFormikContext();
+
+ const [t] = useTranslation()
+ return (
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default ChoiceFields
\ No newline at end of file
diff --git a/src/Pages/question/Model/Malty/ChoiceField/File.tsx b/src/Pages/question/Model/Malty/ChoiceField/File.tsx
new file mode 100644
index 0000000..f5d4c88
--- /dev/null
+++ b/src/Pages/question/Model/Malty/ChoiceField/File.tsx
@@ -0,0 +1,86 @@
+import { Button, Upload, UploadFile } from "antd";
+import useFormField from "../../../../../Hooks/useFormField";
+import { UploadOutlined } from "@ant-design/icons";
+import { useMemo } from "react";
+
+const File = ({
+ name,
+ label,
+ onChange,
+ isDisabled,
+ placholder,
+ className,
+ parent_index,
+ props,
+}: any) => {
+
+ const newName = `Questions[${parent_index}].QuestionOptions[${name}].answer_image`
+
+ const { formik, t, isError,errorMsg } = useFormField(newName, props);
+ let imageUrl = formik?.values?.Questions?.[parent_index]?.QuestionOptions[name]?.answer_image ?? null;
+ // console.log(imageUrl);
+
+ const fileList: UploadFile[] = useMemo(() => {
+ if (!imageUrl) return [];
+
+ return [
+ typeof imageUrl === 'string'
+ ? {
+ uid: '-1',
+ name: 'uploaded-image',
+ status: 'done',
+ url: imageUrl,
+ thumbUrl: imageUrl,
+ }
+ : {
+ uid: imageUrl.uid || '-1',
+ name: imageUrl.name || 'uploaded-image',
+ status: 'done',
+ originFileObj: imageUrl,
+ },
+ ];
+ }, [imageUrl]);
+ // console.log(1);
+
+ const FilehandleChange = (value: any) => {
+ // console.log(value,"filevalue");
+ if (value.fileList.length === 0) {
+ formik.setFieldValue(newName, null);
+ } else {
+ formik.setFieldValue(`Questions[${parent_index}].QuestionOptions[${name}].answer_image`, value?.file?.originFileObj);
+
+ }
+ };
+ const customRequest = async ({ onSuccess, no_label, label_icon }: any) => {
+ onSuccess();
+ };
+ return (
+
+
+
+
+ }
+ >
+ {placholder ?? t("input.Click_to_upload_the_image")}
+
+
+ {isError ? "required" : ""}
+ {errorMsg}
+
+
+ );
+};
+
+export default File;
diff --git a/src/Pages/question/Model/Malty/ChoiceField/TextField.tsx b/src/Pages/question/Model/Malty/ChoiceField/TextField.tsx
new file mode 100644
index 0000000..b65fdd8
--- /dev/null
+++ b/src/Pages/question/Model/Malty/ChoiceField/TextField.tsx
@@ -0,0 +1,72 @@
+import { Form, Input } from "antd";
+import React from "react";
+import useFormField from "../../../../../Hooks/useFormField";
+import { MdOutlineEdit } from "react-icons/md";
+import { Field } from "formik";
+const { TextArea } = Input;
+
+const TextField = ({
+ name,
+ label,
+ label2,
+ placeholder,
+ isDisabled,
+ onChange,
+ props,
+ no_label,
+ label_icon,
+ parent_index,
+ className
+}: any) => {
+ const newName = `Questions[${parent_index}].QuestionOptions[${name}].answer`
+ const { formik, isError, errorMsg, t } = useFormField(newName, props);
+ const TextFilehandleChange = (
+ e: React.ChangeEvent,
+ ) => {
+ // console.log('Change:', e.target.value);
+ formik.setFieldValue(newName, e.target.value);
+ };
+
+ return (
+
+ {no_label ? (
+
+ ) : label_icon ? (
+
+
+
+
+ ) : (
+
+ )}
+
+
+
+
+
+ );
+};
+
+export default React.memo(TextField);
diff --git a/src/Pages/question/Model/Malty/Edit.tsx b/src/Pages/question/Model/Malty/Edit.tsx
new file mode 100644
index 0000000..d7a1359
--- /dev/null
+++ b/src/Pages/question/Model/Malty/Edit.tsx
@@ -0,0 +1,121 @@
+import { Col, Row } from "reactstrap";
+import React, { useEffect } from "react";
+import ValidationField from "../../../../Components/ValidationField/ValidationField";
+import { useFormikContext } from "formik";
+import { useModalState } from "../../../../zustand/Modal";
+import PdfUploader from "../../../../Components/CustomFields/PdfUploader";
+import ChoiceFields from "./ChoiceField/ChoiceFields";
+import { FaCirclePlus } from "react-icons/fa6";
+import { Choice } from "../../../../types/Item";
+import { useTranslation } from "react-i18next";
+import DynamicTags from "./Tags/DynamicTags";
+import { useGetAllQuestion } from "../../../../api/Question";
+import QuestionFIeld from "./QuestionFIeld/QuestionFIeld";
+
+const Form = () => {
+ const formik = useFormikContext();
+ const { isOpen } = useModalState((state) => state);
+ // const {data} = useGetAllQuestion();
+
+ useEffect(() => {
+ if (isOpen === "") {
+ formik.setErrors({});
+ formik.resetForm();
+ }
+ }, [isOpen]);
+
+ // console.log(formik?.errors);
+ const [t] = useTranslation()
+
+
+ const handleAddChoice = (parent_index:number) => {
+ console.log(parent_index);
+
+ formik.setFieldValue(`Questions.[${parent_index}].QuestionOptions`, [...(formik?.values as any)?.Questions?.[parent_index].QuestionOptions,
+
+ {
+ answer:null,
+ answer_image:null,
+ isCorrect:0
+ }])
+ }
+
+
+ const handleAddQuestion = () => {
+ formik.setFieldValue('Questions', [...(formik?.values as any)?.Questions,
+
+ {
+ content: "",
+ image: "",
+ parent: '',
+ isBase: 0,
+ max_mark: 1,
+ min_mark_to_pass: 1,
+ QuestionOptions: [{ answer: null, answer_image: null, isCorrect: 0 }],
+ tags: []
+ }])
+
+ const max_mark = formik?.values?.max_mark + 1
+
+ formik.setFieldValue('max_mark', max_mark)
+ }
+ console.log(formik?.values);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ (((formik?.values as any)?.Questions)||[])?.map((item:Choice,parent_index:number)=>{
+
+ return (
+
+
+
+
+
+
+
+ {
+ (((formik?.values as any)?.Questions?.[parent_index]?.QuestionOptions)||[]) .map((item:Choice,index:number)=>{
+
+ return
+ }
+ )
+ }
+
+ handleAddChoice(parent_index)} size={23} /> {t("header.add_new_choice")}
+
+
+
+
+ )
+ }
+ )
+ }
+
+
+ {t("header.add_new_question")}
+
+
+ );
+};
+
+export default Form;
diff --git a/src/Pages/question/Model/Malty/QuestionFIeld/File.tsx b/src/Pages/question/Model/Malty/QuestionFIeld/File.tsx
new file mode 100644
index 0000000..457e1a5
--- /dev/null
+++ b/src/Pages/question/Model/Malty/QuestionFIeld/File.tsx
@@ -0,0 +1,85 @@
+import { Button, Upload, UploadFile } from "antd";
+import useFormField from "../../../../../Hooks/useFormField";
+import { UploadOutlined } from "@ant-design/icons";
+import { useMemo } from "react";
+
+const File = ({
+ name,
+ label,
+ onChange,
+ isDisabled,
+ placholder,
+ className,
+ props,
+}: any) => {
+
+ const newName = `Questions[${name}].image`
+
+ const { formik, t, isError,errorMsg } = useFormField(newName, props);
+ let imageUrl = formik?.values?.Questions?.[name]?.image ?? null;
+ // console.log(imageUrl);
+
+ const fileList: UploadFile[] = useMemo(() => {
+ if (!imageUrl) return [];
+
+ return [
+ typeof imageUrl === 'string'
+ ? {
+ uid: '-1',
+ name: 'uploaded-image',
+ status: 'done',
+ url: imageUrl,
+ thumbUrl: imageUrl,
+ }
+ : {
+ uid: imageUrl.uid || '-1',
+ name: imageUrl.name || 'uploaded-image',
+ status: 'done',
+ originFileObj: imageUrl,
+ },
+ ];
+ }, [imageUrl]);
+ // console.log(1);
+
+ const FilehandleChange = (value: any) => {
+ // console.log(value,"filevalue");
+ if (value.fileList.length === 0) {
+ formik.setFieldValue(newName, null);
+ } else {
+ formik.setFieldValue(`Questions[${name}].image`, value?.file?.originFileObj);
+
+ }
+ };
+ const customRequest = async ({ onSuccess, no_label, label_icon }: any) => {
+ onSuccess();
+ };
+ return (
+
+
+
+
+ }
+ >
+ {placholder ?? t("input.Click_to_upload_the_image")}
+
+
+ {isError ? "required" : ""}
+ {errorMsg}
+
+
+ );
+};
+
+export default File;
diff --git a/src/Pages/question/Model/Malty/QuestionFIeld/QuestionFIeld.tsx b/src/Pages/question/Model/Malty/QuestionFIeld/QuestionFIeld.tsx
new file mode 100644
index 0000000..47ec2f1
--- /dev/null
+++ b/src/Pages/question/Model/Malty/QuestionFIeld/QuestionFIeld.tsx
@@ -0,0 +1,25 @@
+import React from 'react'
+import { Choice } from '../../../../../types/Item'
+import ValidationField from '../../../../../Components/ValidationField/ValidationField'
+import { useFormikContext } from 'formik';
+import { useTranslation } from 'react-i18next';
+import { getCharFromNumber } from '../../../../../utils/getCharFromNumber';
+import TextField from './TextField';
+import File from './File';
+
+const QuestionFIeld = ({index,data}:{index:number , data :Choice }) => {
+ const formik = useFormikContext();
+ console.log(index);
+
+ const [t] = useTranslation()
+ return (
+
+
+
+
+
+
+ )
+}
+
+export default QuestionFIeld
\ No newline at end of file
diff --git a/src/Pages/question/Model/Malty/QuestionFIeld/TextField.tsx b/src/Pages/question/Model/Malty/QuestionFIeld/TextField.tsx
new file mode 100644
index 0000000..db669f2
--- /dev/null
+++ b/src/Pages/question/Model/Malty/QuestionFIeld/TextField.tsx
@@ -0,0 +1,71 @@
+import { Form, Input } from "antd";
+import React from "react";
+import useFormField from "../../../../../Hooks/useFormField";
+import { MdOutlineEdit } from "react-icons/md";
+import { Field } from "formik";
+const { TextArea } = Input;
+
+const TextField = ({
+ name,
+ label,
+ label2,
+ placeholder,
+ isDisabled,
+ onChange,
+ props,
+ no_label,
+ label_icon,
+ className
+}: any) => {
+ const newName = `Questions[${name}].content`
+ const { formik, isError, errorMsg, t } = useFormField(newName, props);
+ const TextFilehandleChange = (
+ e: React.ChangeEvent,
+ ) => {
+ // console.log('Change:', e.target.value);
+ formik.setFieldValue(newName, e.target.value);
+ };
+
+ return (
+
+ {no_label ? (
+
+ ) : label_icon ? (
+
+
+
+
+ ) : (
+
+ )}
+
+
+
+
+
+ );
+};
+
+export default React.memo(TextField);
diff --git a/src/Pages/question/Model/Malty/Tags/DynamicTags.tsx b/src/Pages/question/Model/Malty/Tags/DynamicTags.tsx
new file mode 100644
index 0000000..375fe4c
--- /dev/null
+++ b/src/Pages/question/Model/Malty/Tags/DynamicTags.tsx
@@ -0,0 +1,107 @@
+import { useFormikContext } from 'formik'
+import React from 'react'
+import { useTranslation } from 'react-i18next'
+import { FaCirclePlus } from 'react-icons/fa6'
+import Tag from './Tag'
+import { useObjectToEdit } from '../../../../../zustand/ObjectToEditState'
+import { useGetAllTag } from '../../../../../api/tags'
+
+const DynamicTags = ({parent_index}:{parent_index:number}) => {
+
+ const formik = useFormikContext()
+ const [t] = useTranslation()
+ const { Tags_search ,set_Tags_search,currentTag,current_parent_index} = useObjectToEdit();
+ const {data} = useGetAllTag({
+ name : Tags_search
+ })
+ const suggests = data?.data
+
+
+ const handleAddChoice = () => {
+ const length = formik?.values?.Questions?.[parent_index]?.tags.length;
+ const lastElement = formik?.values?.Questions?.[parent_index]?.tags[length - 1]?.name;
+
+ if(lastElement !== ""){
+ formik.setFieldValue(`Questions.[${parent_index}].tags`, [...(formik?.values as any)?.Questions?.[parent_index]?.tags as any[],
+
+ {
+ id:length +"_new",
+ name:"",
+ key:length
+ }])
+ }else{
+
+ }
+
+
+}
+// console.log(formik?.values);
+// console.log(currentTag);
+
+const handleChoice = (item: any) => {
+
+ const length = formik.values.tags.length;
+ console.log(currentTag);
+
+ formik.setFieldValue(`Questions.[${parent_index}].tags[${currentTag}]`, {...item,key:length});
+ set_Tags_search(null);
+}
+
+
+
+// console.log(formik?.values?.tags?.length);
+
+ return (
+
+ {formik?.values?.tags?.length < 1 &&
+
+
+ {t("header.add_tag")}
+
+ }
+
+
+
+
+{
+(((formik?.values as any)?.Questions?.[parent_index]?.tags as any[])||[]) .map((item:any,index:number)=>{
+
+return (
+
+
+
+)
+}
+)
+}
+
+
+ {formik?.values?.Questions?.[parent_index]?.tags?.length > 0 &&
+
+
+
+
+
+ }
+
+
+ {Tags_search && current_parent_index === parent_index &&
+
+ {suggests?.map((item:any,index:number)=>{
+ console.log(current_parent_index === parent_index);
+
+ return (
+
handleChoice(item)}>
+ {item?.name}
+
+ )
+ })}
+
+ }
+
+
+
+ )
+}
+
+export default DynamicTags
\ No newline at end of file
diff --git a/src/Pages/question/Model/Malty/Tags/Tag.tsx b/src/Pages/question/Model/Malty/Tags/Tag.tsx
new file mode 100644
index 0000000..09ed75f
--- /dev/null
+++ b/src/Pages/question/Model/Malty/Tags/Tag.tsx
@@ -0,0 +1,71 @@
+import { useFormikContext } from 'formik';
+import React, { useRef, useEffect } from 'react';
+import { useObjectToEdit } from '../../../../../zustand/ObjectToEditState';
+import { FaTrash } from 'react-icons/fa';
+
+const Tag = ({ data, index,parent_index }: { data: any, index: number,parent_index:number }) => {
+ const inputRef = useRef(null);
+ const timeoutRef = useRef(null);
+ const DEBOUNCE_DELAY = 500;
+ const formik = useFormikContext();
+ const { set_Tags_search ,set_currentTag,set_current_parent_index} = useObjectToEdit();
+
+ useEffect(() => {
+ if (inputRef.current) {
+ inputRef.current.style.width = `${(formik?.values?.Questions?.[parent_index]?.tags[index]?.name?.length + 1) * 8}px`;
+ }
+ }, [formik?.values?.Questions?.[parent_index]?.tags[index]?.name]);
+
+ const handleEditInputChange = (e: React.ChangeEvent) => {
+ // console.log(e.target.value);
+ formik.setFieldValue(`Questions.[${parent_index}].tags[${index}].name`, e.target.value);
+ set_currentTag(index)
+ set_current_parent_index(parent_index)
+ if (timeoutRef.current) {
+ clearTimeout(timeoutRef.current);
+ }
+
+ timeoutRef.current = setTimeout(() => {
+ set_Tags_search(e.target.value)
+ }, DEBOUNCE_DELAY);
+ };
+
+ const handleDeleteChoice = () => {
+ console.log(data);
+
+ // Create a copy of current tags array
+ const currentTags = [...formik.values.tags];
+
+ // Remove the item at the specified index from the array
+ currentTags.splice(index, 1);
+
+ console.log(currentTags); // Log the updated tags array
+
+ // Update formik field value with the updated tags array
+ formik.setFieldValue(`Questions.[${parent_index}].tags`, currentTags);
+
+ // Reset search state if needed
+ set_Tags_search(null);
+ };
+
+
+
+ return (
+
+
+
+
+ );
+};
+
+export default Tag;
+
+
+
diff --git a/src/Pages/question/Model/Tags/Tag.tsx b/src/Pages/question/Model/Tags/Tag.tsx
index 70e87bb..09de022 100644
--- a/src/Pages/question/Model/Tags/Tag.tsx
+++ b/src/Pages/question/Model/Tags/Tag.tsx
@@ -7,7 +7,8 @@ const Tag = ({ data, index }: { data: any, index: number }) => {
const inputRef = useRef(null);
const formik = useFormikContext();
const { set_Tags_search ,set_currentTag} = useObjectToEdit();
-
+ const timeoutRef = useRef(null);
+ const DEBOUNCE_DELAY = 500;
useEffect(() => {
if (inputRef.current) {
inputRef.current.style.width = `${(formik?.values?.tags[index]?.name?.length + 1) * 8}px`;
@@ -17,9 +18,15 @@ const Tag = ({ data, index }: { data: any, index: number }) => {
const handleEditInputChange = (e: React.ChangeEvent) => {
// console.log(e.target.value);
formik.setFieldValue(`tags[${index}].name`, e.target.value);
- set_Tags_search(e.target.value)
+ // set_Tags_search(e.target.value)
set_currentTag(index)
-
+ if (timeoutRef.current) {
+ clearTimeout(timeoutRef.current);
+ }
+
+ timeoutRef.current = setTimeout(() => {
+ set_Tags_search(e.target.value)
+ }, DEBOUNCE_DELAY);
};
const handleInputBlur = () => {
diff --git a/src/Pages/question/Model/formUtil.ts b/src/Pages/question/Model/formUtil.ts
index cc833d2..3afca5c 100644
--- a/src/Pages/question/Model/formUtil.ts
+++ b/src/Pages/question/Model/formUtil.ts
@@ -3,26 +3,24 @@ import { Question } from "../../../types/Item";
export const getInitialValues = (objectToEdit: Question): any => {
- const tags = objectToEdit?.tags?.map((item:any,index:number)=>{
- return {...item,key:index}
-});
- console.log(objectToEdit,"objectToEdit");
+ const tags = objectToEdit?.tags?.map((item: any, index: number) => {
+ return { ...item, key: index }
+ });
return {
id: objectToEdit?.id ?? null,
content: objectToEdit?.content ?? "",
image: objectToEdit?.image ?? "",
- subject_id:objectToEdit?.subject_id??'',
- isBase:objectToEdit?.isBase??'',
- max_mark:objectToEdit?.max_mark??null,
- min_mark_to_pass:1,
- parent:objectToEdit?.parent??'',
- QuestionOptions: objectToEdit?.QuestionOptions ?? [{answer:null,answer_image:null,isCorrect:0}],
- tags : tags ??[]
+ subject_id: objectToEdit?.subject_id ?? '',
+ isBase: objectToEdit?.isBase,
+ max_mark: 1,
+ min_mark_to_pass: 1,
+ parent: objectToEdit?.parent ?? '',
+ QuestionOptions: objectToEdit?.QuestionOptions ?? [],
+ tags: tags ?? [],
};
};
-
export const getValidationSchema = () => {
// validate input
return Yup.object().shape({
@@ -30,13 +28,63 @@ export const getValidationSchema = () => {
content: Yup.string().required("validation.required"),
max_mark: Yup.number().required("validation.required").min(Yup.ref("min_mark_to_pass"),"validation.max_mark_must_be_greater_than_min_mark_to_pass"),
min_mark_to_pass: Yup.number().required("validation.required"),
-
QuestionOptions: Yup.array().of(
Yup.object().shape({
- answer: Yup.string().required('details name is required'),
+ answer: Yup.string().required("validation.required"),
answer_image: Yup.string().nullable(),
isCorrect: Yup.boolean()
})
- ).required('Params are required')
+ ).nullable('Params are required')
+ });
+};
+
+
+
+export const getInitialValuesBase = (objectToEdit: Question): any => {
+ const tags = objectToEdit?.tags?.map((item: any, index: number) => {
+ return { ...item, key: index }
+ });
+ console.log(objectToEdit);
+
+ const questions = objectToEdit?.Questions ?? [];
+
+
+ return {
+ id: objectToEdit?.id ?? null,
+ content: objectToEdit?.content ?? "",
+ image: objectToEdit?.image ?? "",
+ subject_id: objectToEdit?.subject_id ?? '',
+ isBase: objectToEdit?.isBase,
+ max_mark: questions.length ?? 1,
+ min_mark_to_pass: 1,
+ parent: objectToEdit?.parent ?? '',
+ tags: tags ?? [],
+ Questions: questions,
+ };
+};
+
+export const getValidationSchemaBase = () => {
+ // validate input
+ return Yup.object().shape({
+ image: Yup.string().nullable(),
+ content: Yup.string().required("validation.required"),
+ max_mark: Yup.number().required("validation.required").min(Yup.ref("min_mark_to_pass"),"validation.max_mark_must_be_greater_than_min_mark_to_pass"),
+ min_mark_to_pass: Yup.number().required("validation.required"),
+ Questions: Yup.array().of(
+ Yup.object().shape({
+ image: Yup.string().nullable(),
+ content: Yup.string().required("validation.required"),
+ max_mark: Yup.number().required("validation.required").min(Yup.ref("min_mark_to_pass"),"validation.max_mark_must_be_greater_than_min_mark_to_pass"),
+ min_mark_to_pass: Yup.number().required("validation.required"),
+ QuestionOptions: Yup.array().of(
+ Yup.object().shape({
+ answer: Yup.string().required("validation.required"),
+ answer_image: Yup.string().nullable(),
+ isCorrect: Yup.boolean()
+ })
+ ).nullable('required')
+ })
+ ),
+
});
};
diff --git a/src/Pages/question/Table.tsx b/src/Pages/question/Table.tsx
index b1d3fcb..cd26b77 100644
--- a/src/Pages/question/Table.tsx
+++ b/src/Pages/question/Table.tsx
@@ -6,10 +6,10 @@ import { useParams } from "react-router-dom";
import { ParamsEnum } from "../../enums/params";
const App: React.FC = () => {
- const {unit_id} = useParams()
- const response = useGetAllQuestion({ unit_id:unit_id, pagination: true});
+ const {subject_id} = useParams()
+ const response = useGetAllQuestion({ subject_id:subject_id, pagination: true});
- return ;
+ return ;
};
export default App;
diff --git a/src/Pages/subject/Model/Add.tsx b/src/Pages/subject/Model/Add.tsx
index 963ead1..97e1a52 100644
--- a/src/Pages/subject/Model/Add.tsx
+++ b/src/Pages/subject/Model/Add.tsx
@@ -8,13 +8,7 @@ import { useModalState } from "../../../zustand/Modal";
import useSearchQuery from "../../../api/utils/useSearchQuery";
const Form = () => {
- const [searchQuery] = useSearchQuery("techer_name");
- const { data , isLoading } = useGetAllTeacher({
- name: searchQuery,
-
- });
- const SelectData = useFormatDataToSelect(data?.data);
const { isOpen } = useModalState((state) => state);
const formik = useFormikContext();
useEffect(() => {
@@ -28,15 +22,7 @@ const Form = () => {
-
+
diff --git a/src/Pages/subject/Model/AddModel.tsx b/src/Pages/subject/Model/AddModel.tsx
index 2f5ace1..55266ea 100644
--- a/src/Pages/subject/Model/AddModel.tsx
+++ b/src/Pages/subject/Model/AddModel.tsx
@@ -12,7 +12,6 @@ import { useTranslation } from "react-i18next";
const ModalForm: React.FC = () => {
const { isOpen, setIsOpen } = useModalState((state) => state);
- const { course_id } = useParams();
const { mutate, isSuccess, isLoading } = useAddSubject();
const { set_object_to_edit } = useObjectToEdit();
@@ -27,7 +26,7 @@ const ModalForm: React.FC = () => {
// console.log(values,"values");
mutate({
...values,
- course_id: course_id,
+
});
};
diff --git a/src/Pages/subject/Model/Edit.tsx b/src/Pages/subject/Model/Edit.tsx
index 7c3d4c0..8edf7a1 100644
--- a/src/Pages/subject/Model/Edit.tsx
+++ b/src/Pages/subject/Model/Edit.tsx
@@ -8,12 +8,6 @@ import { useFormikContext } from "formik";
import useSearchQuery from "../../../api/utils/useSearchQuery";
const Form = () => {
- const [searchQuery] = useSearchQuery("techer_name");
-
- const { data , isLoading } = useGetAllTeacher({
- name: searchQuery,
- });
- const SelectData = useFormatDataToSelect(data?.data);
const { isOpen } = useModalState((state) => state);
const formik = useFormikContext();
@@ -27,15 +21,7 @@ const Form = () => {
-
+
diff --git a/src/Pages/subject/show/Tables/Contents/Model/AddModel.tsx b/src/Pages/subject/show/Tables/Contents/Model/AddModel.tsx
index f4c94ba..ad0e8d1 100644
--- a/src/Pages/subject/show/Tables/Contents/Model/AddModel.tsx
+++ b/src/Pages/subject/show/Tables/Contents/Model/AddModel.tsx
@@ -38,7 +38,7 @@ const ModalForm: React.FC = () => {
{
import("./Pages/Tags/Page"));
const Unit = React.lazy(() => import("./Pages/Unit/Page"));
const Lesson = React.lazy(() => import("./Pages/lesson/Page"));
const Question = React.lazy(() => import('./Pages/question/Page'))
-const AddQuestion = React.lazy(() => import('./Pages/question/Model/AddModel'))
-const EditQuestion = React.lazy(() => import('./Pages/question/Model/EditModel'))
+const AddQuestionPage = React.lazy(() => import('./Pages/question/AddPage'))
+const EditQuestionPage = React.lazy(() => import('./Pages/question/EditPage'))
// const QuestionChildren = React.lazy(() => import('./Pages/question/children/Page'))
@@ -90,14 +90,14 @@ export const CrudRoute: TCrudRoute[] = [
},
{
header: "page_header.add_Question",
- element: ,
+ element: ,
path: `/${ABILITIES_ENUM?.SUBJECT}/:${ParamsEnum?.SUBJECT_ID}/${ABILITIES_ENUM?.UNIT}/:${ParamsEnum?.UNIT_ID}/${ABILITIES_ENUM?.LESSON}/:${ParamsEnum?.LESSON_ID}/${ABILITIES_ENUM?.QUESTION}/add`,
abilities: ABILITIES_ENUM?.QUESTION,
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
},
{
header: "page_header.edit_Question",
- element: ,
+ element: ,
path: `/${ABILITIES_ENUM?.SUBJECT}/:${ParamsEnum?.SUBJECT_ID}/${ABILITIES_ENUM?.UNIT}/:${ParamsEnum?.UNIT_ID}/${ABILITIES_ENUM?.LESSON}/:${ParamsEnum?.LESSON_ID}/${ABILITIES_ENUM?.QUESTION}/:${ParamsEnum?.QUESTION_ID}`,
abilities: ABILITIES_ENUM?.QUESTION,
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
diff --git a/src/Styles/Pages/exercise.scss b/src/Styles/Pages/exercise.scss
index 39adbe7..1c3b1d0 100644
--- a/src/Styles/Pages/exercise.scss
+++ b/src/Styles/Pages/exercise.scss
@@ -107,4 +107,14 @@
}
+}
+
+.exercise_add_header{
+ display: flex;
+ justify-content: space-between;
+ width: 90%;
+}
+
+.inputSmall{
+ width: 100px;
}
\ No newline at end of file
diff --git a/src/api/config.ts b/src/api/config.ts
index 9c2df36..0b90ec0 100644
--- a/src/api/config.ts
+++ b/src/api/config.ts
@@ -1,4 +1,6 @@
-export const BaseURL = "http://192.168.1.108:8000/api/";
+// export const BaseURL = "http://192.168.1.108:8000/api/";
+export const BaseURL = "http://127.0.0.1:8000/api/";
+
// export const BaseURL = "https://school-back-dev.point-dev.net/api/";
export const ImageBaseURL = "http://192.168.1.9:8000/";
diff --git a/src/translate/ar.json b/src/translate/ar.json
index 9e5863b..2ec741b 100644
--- a/src/translate/ar.json
+++ b/src/translate/ar.json
@@ -99,10 +99,13 @@
"change_your_current_password": "تغير كلمة السر الحالية",
"view_cycle_for_this_branch": "مشاهدة الدورات في هذا الفرع",
"view_term_for_this_cycle": "مشاهدة الفصول في هذة السنة دراسية",
- "add_new_choice":"إضافة خيار آخر",
+ "add_new_choice":"إضافة خيار ",
"add_tag":"إضافة كلمة مفتاحية",
"add_synonyms":"إضافة مرادفات",
- "add_Question":"إضافة اسئلة"
+ "add_Question":"إضافة اسئلة",
+ "malty_exercise":"تمرين متعدد",
+ "add_new_question":"اضافة سؤال جديد",
+ "exercise":"تمارين"
},
"columns": {
@@ -331,7 +334,9 @@
"exercise":"تمارين",
"max_mark":"العلامة الكاملة",
"min_mark_to_pass" : "علامة النجاح",
- "isBase":"سؤال رئيسي"
+ "isBase":"سؤال رئيسي",
+ "main_question":"النص الأساسي ",
+ "question":"السؤال"
},
diff --git a/src/types/Auth.ts b/src/types/Auth.ts
index 5fc3359..47deeff 100644
--- a/src/types/Auth.ts
+++ b/src/types/Auth.ts
@@ -1,7 +1,4 @@
export interface FormValues {
username: string | null;
password: string | null;
- cycle: string | null;
- branch: string | null;
- term: string | null;
}
diff --git a/src/types/Item.ts b/src/types/Item.ts
index 18c7fab..088f0ae 100644
--- a/src/types/Item.ts
+++ b/src/types/Item.ts
@@ -34,6 +34,7 @@ export interface Unit {
description: string | null;
subject_id: number;
term: term_type;
+ lessons_count:number;
lessons: Lesson[];
}
@@ -313,6 +314,7 @@ export interface Question {
max_mark: number;
min_mark_to_pass: number;
image: string | null;
+ Questions?:any[]
QuestionOptions: QuestionOption[];
tags: tags[]; // Assuming tags are strings, adjust as per actual data type
}
\ No newline at end of file
diff --git a/src/zustand/AuthState.ts b/src/zustand/AuthState.ts
index 732572a..d994b5d 100644
--- a/src/zustand/AuthState.ts
+++ b/src/zustand/AuthState.ts
@@ -21,7 +21,7 @@ const useAuthState = create((set) => {
const storedAbilities = localStorage.getItem(ABILITIES_KEY);
return {
- isAuthenticated: !!storedToken && !!storedAbilities,
+ isAuthenticated: !!storedToken,
token: storedToken,
abilities: storedAbilities,
diff --git a/src/zustand/ObjectToEditState.ts b/src/zustand/ObjectToEditState.ts
index 182801c..ea3461c 100644
--- a/src/zustand/ObjectToEditState.ts
+++ b/src/zustand/ObjectToEditState.ts
@@ -15,7 +15,10 @@ interface ModelState {
set_Tags_query: (data: any) => void;
currentTag: any;
set_currentTag: (data: any) => void;
-
+ current_parent_index: any;
+ set_current_parent_index: (data: any) => void;
+ isBseQuestion: boolean;
+ set_isBseQuestion: (data: any) => void;
}
export const useObjectToEdit = create((set) => ({
@@ -33,4 +36,8 @@ export const useObjectToEdit = create((set) => ({
set_Tags_query: (data) => set(() => ({ Tags_query: data })),
currentTag: null,
set_currentTag: (data) => set(() => ({ currentTag: data })),
+ current_parent_index: null,
+ set_current_parent_index: (data) => set(() => ({ current_parent_index: data })),
+ isBseQuestion: false,
+ set_isBseQuestion: (data) => set(() => ({ isBseQuestion: data })),
}));