fix question
This commit is contained in:
parent
084762e51e
commit
6e1e79465f
|
|
@ -56,6 +56,7 @@
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
"@types/node": "^20.14.0",
|
"@types/node": "^20.14.0",
|
||||||
"@types/react": "^18.3.3",
|
"@types/react": "^18.3.3",
|
||||||
|
"@types/react-beautiful-dnd": "^13.1.8",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@types/react-helmet": "^6.1.11",
|
"@types/react-helmet": "^6.1.11",
|
||||||
"@vitejs/plugin-legacy": "^5.4.1",
|
"@vitejs/plugin-legacy": "^5.4.1",
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,9 @@ importers:
|
||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: ^18.3.3
|
specifier: ^18.3.3
|
||||||
version: 18.3.3
|
version: 18.3.3
|
||||||
|
'@types/react-beautiful-dnd':
|
||||||
|
specifier: ^13.1.8
|
||||||
|
version: 13.1.8
|
||||||
'@types/react-dom':
|
'@types/react-dom':
|
||||||
specifier: ^18.3.0
|
specifier: ^18.3.0
|
||||||
version: 18.3.0
|
version: 18.3.0
|
||||||
|
|
@ -1342,6 +1345,9 @@ packages:
|
||||||
'@types/prop-types@15.7.12':
|
'@types/prop-types@15.7.12':
|
||||||
resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==}
|
resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==}
|
||||||
|
|
||||||
|
'@types/react-beautiful-dnd@13.1.8':
|
||||||
|
resolution: {integrity: sha512-E3TyFsro9pQuK4r8S/OL6G99eq7p8v29sX0PM7oT8Z+PJfZvSQTx4zTQbUJ+QZXioAF0e7TGBEcA1XhYhCweyQ==}
|
||||||
|
|
||||||
'@types/react-dom@18.3.0':
|
'@types/react-dom@18.3.0':
|
||||||
resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==}
|
resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==}
|
||||||
|
|
||||||
|
|
@ -4997,7 +5003,7 @@ snapshots:
|
||||||
'@jridgewell/trace-mapping@0.3.9':
|
'@jridgewell/trace-mapping@0.3.9':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/resolve-uri': 3.1.2
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
'@jridgewell/sourcemap-codec': 1.4.15
|
'@jridgewell/sourcemap-codec': 1.5.0
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@popperjs/core@2.11.8': {}
|
'@popperjs/core@2.11.8': {}
|
||||||
|
|
@ -5252,6 +5258,10 @@ snapshots:
|
||||||
|
|
||||||
'@types/prop-types@15.7.12': {}
|
'@types/prop-types@15.7.12': {}
|
||||||
|
|
||||||
|
'@types/react-beautiful-dnd@13.1.8':
|
||||||
|
dependencies:
|
||||||
|
'@types/react': 18.3.3
|
||||||
|
|
||||||
'@types/react-dom@18.3.0':
|
'@types/react-dom@18.3.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/react': 18.3.3
|
'@types/react': 18.3.3
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,9 @@ const ImageBoxField = ({ name }: any) => {
|
||||||
const value = getNestedValue(formik.values, name);
|
const value = getNestedValue(formik.values, name);
|
||||||
const [imagePreview, setImagePreview] = useState<string | null>(null);
|
const [imagePreview, setImagePreview] = useState<string | null>(null);
|
||||||
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
||||||
|
console.log(formik.values);
|
||||||
|
|
||||||
|
console.log(value,name);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (value instanceof File) {
|
if (value instanceof File) {
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ const AddPage: React.FC = () => {
|
||||||
isBseQuestion,
|
isBseQuestion,
|
||||||
setTagsSearch,
|
setTagsSearch,
|
||||||
setObjectToEdit,
|
setObjectToEdit,
|
||||||
|
objectToEdit,
|
||||||
setSuccess,
|
setSuccess,
|
||||||
SavedQuestionData,
|
SavedQuestionData,
|
||||||
} = useObjectToEdit();
|
} = useObjectToEdit();
|
||||||
|
|
@ -102,8 +103,6 @@ const AddPage: React.FC = () => {
|
||||||
{ resetForm }: { resetForm: () => void },
|
{ resetForm }: { resetForm: () => void },
|
||||||
) => {
|
) => {
|
||||||
const DataToSend = structuredClone(values);
|
const DataToSend = structuredClone(values);
|
||||||
console.log(DataToSend);
|
|
||||||
|
|
||||||
setTagsSearch(null);
|
setTagsSearch(null);
|
||||||
const canAnswersBeShuffled = DataToSend?.canAnswersBeShuffled ? 1 : 0;
|
const canAnswersBeShuffled = DataToSend?.canAnswersBeShuffled ? 1 : 0;
|
||||||
if (isBseQuestion || DataToSend?.isBase === 1) {
|
if (isBseQuestion || DataToSend?.isBase === 1) {
|
||||||
|
|
@ -166,51 +165,54 @@ const AddPage: React.FC = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
// console.log(SavedQuestionData);
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
if (
|
// if (
|
||||||
isSuccessAsync &&
|
// isSuccessAsync &&
|
||||||
(SavedQuestionData?.Questions?.length > 0 ? isSuccess : true)
|
// (SavedQuestionData?.Questions?.length > 0 ? isSuccess : true)
|
||||||
) {
|
// ) {
|
||||||
setObjectToEdit(null);
|
// setObjectToEdit(null);
|
||||||
setSuccess(true);
|
// setSuccess(true);
|
||||||
localStorage.removeItem(QUESTION_OBJECT_KEY);
|
// localStorage.removeItem(QUESTION_OBJECT_KEY);
|
||||||
}
|
// }
|
||||||
if (isSuccess && !SavedQuestionData?.Questions?.length) {
|
// if (isSuccess && !SavedQuestionData?.Questions?.length) {
|
||||||
toast.success(t("validation.the_possess_done_successful"));
|
// toast.success(t("validation.the_possess_done_successful"));
|
||||||
setObjectToEdit(null);
|
// setObjectToEdit(null);
|
||||||
setSuccess(true);
|
// setSuccess(true);
|
||||||
localStorage.removeItem(QUESTION_OBJECT_KEY);
|
// localStorage.removeItem(QUESTION_OBJECT_KEY);
|
||||||
}
|
// }
|
||||||
}, [isSuccess, isSuccessAsync]);
|
// }, [isSuccess, isSuccessAsync]);
|
||||||
|
|
||||||
let cleanedAnswers = cleanObject(SavedQuestionData);
|
// let cleanedAnswers = cleanObject(SavedQuestionData);
|
||||||
let noChange = hasItems(cleanedAnswers);
|
// let noChange = hasItems(cleanedAnswers);
|
||||||
|
// console.log(SavedQuestionData);
|
||||||
|
|
||||||
useSaveOnDisconnect(noChange, QUESTION_OBJECT_KEY, SavedQuestionData);
|
// useSaveOnDisconnect(noChange, QUESTION_OBJECT_KEY, SavedQuestionData);
|
||||||
|
|
||||||
const SavedData = getLocalStorageQuestions(QUESTION_OBJECT_KEY);
|
// const SavedData = getLocalStorageQuestions(QUESTION_OBJECT_KEY);
|
||||||
|
// console.log(SavedData);
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
if (!noChange) {
|
navigate(-1);
|
||||||
navigate(-1);
|
// if (!noChange) {
|
||||||
localStorage.removeItem(QUESTION_OBJECT_KEY);
|
// localStorage.removeItem(QUESTION_OBJECT_KEY);
|
||||||
} else {
|
// } else {
|
||||||
setIsOpen(ModalEnum?.QUESTION_ACCEPT);
|
// setIsOpen(ModalEnum?.QUESTION_ACCEPT);
|
||||||
}
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isBseQuestion || SavedData?.isBase === 1) {
|
if (isBseQuestion ) {
|
||||||
return (
|
return (
|
||||||
<div className="exercise_add">
|
<div className="exercise_add">
|
||||||
<FormikForm
|
<FormikForm
|
||||||
handleSubmit={handleSubmit}
|
handleSubmit={handleSubmit}
|
||||||
initialValues={getInitialValuesBase(SavedData)}
|
initialValues={getInitialValuesBase(objectToEdit)}
|
||||||
validationSchema={getValidationSchemaBase}
|
validationSchema={getValidationSchemaBase}
|
||||||
>
|
>
|
||||||
<main className="w-100 exercise_add_main">
|
<main className="w-100 exercise_add_main">
|
||||||
<Header/>
|
<Header />
|
||||||
<ModelForm/>
|
<BaseForm />
|
||||||
|
|
||||||
<div className="exercise_add_buttons">
|
<div className="exercise_add_buttons">
|
||||||
<div onClick={handleCancel}>{t("practical.back")}</div>
|
<div onClick={handleCancel}>{t("practical.back")}</div>
|
||||||
|
|
@ -236,7 +238,7 @@ const AddPage: React.FC = () => {
|
||||||
<div className="exercise_add">
|
<div className="exercise_add">
|
||||||
<FormikForm
|
<FormikForm
|
||||||
handleSubmit={handleSubmit}
|
handleSubmit={handleSubmit}
|
||||||
initialValues={getInitialValues(SavedData)}
|
initialValues={getInitialValues(objectToEdit)}
|
||||||
validationSchema={getValidationSchema}
|
validationSchema={getValidationSchema}
|
||||||
>
|
>
|
||||||
<main className="w-100 exercise_add_main">
|
<main className="w-100 exercise_add_main">
|
||||||
|
|
|
||||||
|
|
@ -15,18 +15,18 @@ const CheckboxField = ({
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const CheckboxhandleChange = (value: any, index: number) => {
|
const CheckboxhandleChange = (value: any, index: number) => {
|
||||||
const allAreZero = formik?.values?.QuestionOptions?.some(
|
const allAreZero = formik?.values?.answers?.some(
|
||||||
(item: any) => item.isCorrect === 1,
|
(item: any) => item.isCorrect === 1,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (allAreZero) {
|
if (allAreZero) {
|
||||||
formik?.values.QuestionOptions.forEach((item: any, index: number) => {
|
formik?.values.answers.forEach((item: any, index: number) => {
|
||||||
formik.setFieldValue(`QuestionOptions[${index}].isCorrect`, 0);
|
formik.setFieldValue(`answers[${index}].isCorrect`, 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`QuestionOptions[${name}].isCorrect`,
|
`answers[${name}].isCorrect`,
|
||||||
value?.target?.checked ? 1 : 0,
|
value?.target?.checked ? 1 : 0,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -35,9 +35,8 @@ const CheckboxField = ({
|
||||||
<Checkbox
|
<Checkbox
|
||||||
onChange={onChange || CheckboxhandleChange}
|
onChange={onChange || CheckboxhandleChange}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
checked={formik.values?.QuestionOptions?.[name]?.isCorrect === 1}
|
checked={formik.values?.answers?.[name]?.isCorrect === 1}
|
||||||
className={className}
|
className={className}
|
||||||
|
|
||||||
>
|
>
|
||||||
{t(`input.${label ? label : name}`)}
|
{t(`input.${label ? label : name}`)}
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,8 @@ import { useTranslation } from "react-i18next";
|
||||||
import { getCharFromNumber } from "../../../../../utils/getCharFromNumber";
|
import { getCharFromNumber } from "../../../../../utils/getCharFromNumber";
|
||||||
import CheckboxField from "./CheckboxField";
|
import CheckboxField from "./CheckboxField";
|
||||||
import TextField from "./TextField";
|
import TextField from "./TextField";
|
||||||
import File from "./File";
|
|
||||||
import { FaCirclePlus, FaDeleteLeft } from "react-icons/fa6";
|
|
||||||
import { GoTrash } from "react-icons/go";
|
|
||||||
import { LuImagePlus } from "react-icons/lu";
|
|
||||||
import ImageBoxField from "../../../../../Components/CustomFields/ImageBoxField/ImageBoxField";
|
import ImageBoxField from "../../../../../Components/CustomFields/ImageBoxField/ImageBoxField";
|
||||||
|
import { GoTrash } from "react-icons/go";
|
||||||
|
|
||||||
const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => {
|
const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
|
|
@ -19,50 +16,56 @@ const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
|
|
||||||
const handleDeleteChoice = () => {
|
const handleDeleteChoice = () => {
|
||||||
console.log(index);
|
console.log(index);
|
||||||
console.log(formik.values.QuestionOptions[index]);
|
console.log(formik.values.answers[index]);
|
||||||
|
|
||||||
const updatedQuestionOptions = formik.values.QuestionOptions.filter(
|
const updatedAnswers = formik.values.answers.filter(
|
||||||
(_: any, i: any) => i !== index,
|
(_: any, i: any) => i !== index,
|
||||||
);
|
);
|
||||||
|
|
||||||
formik.setFieldValue("QuestionOptions", updatedQuestionOptions);
|
formik.setFieldValue("answers", updatedAnswers);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ChoiceFields">
|
<>
|
||||||
<TextField
|
<div className="ChoiceFields">
|
||||||
className="textarea_exercise"
|
<TextField
|
||||||
placeholder={"choice"}
|
className="textarea_exercise"
|
||||||
label2={t(`input.choice`) + ` ` + `( ${t(`alphabet.${getCharFromNumber(index)}`)} )`}
|
placeholder={"choice"}
|
||||||
name={index}
|
label2={t(`input.choice`) + ` ` + `( ${t(`alphabet.${getCharFromNumber(index)}`)} )`}
|
||||||
id={`choice_${index + 1}`}
|
name={index}
|
||||||
type="TextArea"
|
id={`choice_${index + 1}`}
|
||||||
/>
|
type="TextArea"
|
||||||
{/* <File
|
/>
|
||||||
className="file_exercise"
|
|
||||||
label={"attachment"}
|
|
||||||
name={index}
|
|
||||||
type="File"
|
|
||||||
placeholder=""
|
|
||||||
icon={<LuImagePlus/>}
|
|
||||||
/> */}
|
|
||||||
<ImageBoxField name={`QuestionOptions.${index}.answer_image`} />
|
|
||||||
|
|
||||||
<div className="answer_status">
|
<ImageBoxField name={`answers.${index}.answer_image`} />
|
||||||
|
|
||||||
<CheckboxField
|
<div className="answer_status">
|
||||||
className=""
|
|
||||||
label="The_correct_answer"
|
|
||||||
name={index}
|
|
||||||
type="Checkbox"
|
|
||||||
|
|
||||||
/>
|
<CheckboxField
|
||||||
<p className="delete_question_options">
|
className=""
|
||||||
{t("header.delete_choice")}
|
label="The_correct_answer"
|
||||||
<GoTrash className="trash_icon" onClick={handleDeleteChoice} size={17} />
|
name={index}
|
||||||
</p>
|
type="Checkbox"
|
||||||
|
|
||||||
|
/>
|
||||||
|
<p className="delete_question_options">
|
||||||
|
{t("header.delete_choice")}
|
||||||
|
<GoTrash className="trash_icon" onClick={handleDeleteChoice} size={17} />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="exercise_form_width">
|
||||||
|
|
||||||
|
<ValidationField
|
||||||
|
className=" "
|
||||||
|
placeholder="_"
|
||||||
|
name={`answers.${index}.hint`}
|
||||||
|
label="hint_question"
|
||||||
|
type="text"
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ const Choices = () => {
|
||||||
return (
|
return (
|
||||||
<DragDropContext onDragEnd={handleDragEnd}>
|
<DragDropContext onDragEnd={handleDragEnd}>
|
||||||
<Droppable droppableId="choices">
|
<Droppable droppableId="choices">
|
||||||
{(provided:any) => (
|
{(provided) => (
|
||||||
<div {...provided.droppableProps} ref={provided.innerRef}>
|
<div {...provided.droppableProps} ref={provided.innerRef}>
|
||||||
{formik?.values?.answers?.map(
|
{formik?.values?.answers?.map(
|
||||||
(item: Choice, index: number) => {
|
(item: Choice, index: number) => {
|
||||||
|
|
@ -50,7 +50,7 @@ const Choices = () => {
|
||||||
draggableId={draggableId}
|
draggableId={draggableId}
|
||||||
index={index}
|
index={index}
|
||||||
>
|
>
|
||||||
{(provided:any) => (
|
{(provided) => (
|
||||||
<div
|
<div
|
||||||
ref={provided.innerRef}
|
ref={provided.innerRef}
|
||||||
{...provided.draggableProps}
|
{...provided.draggableProps}
|
||||||
|
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
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,
|
|
||||||
placeholder,
|
|
||||||
className,
|
|
||||||
props,
|
|
||||||
icon,
|
|
||||||
}: any) => {
|
|
||||||
const newName = `QuestionOptions[${name}].answer_image`;
|
|
||||||
|
|
||||||
const { formik, t, isError, errorMsg } = useFormField(newName, props);
|
|
||||||
let imageUrl = formik?.values?.QuestionOptions[name]?.answer_image ?? null;
|
|
||||||
// console.log(imageUrl);
|
|
||||||
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(
|
|
||||||
`QuestionOptions[${name}].answer_image`,
|
|
||||||
value?.file?.originFileObj,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const customRequest = async ({ onSuccess, no_label, label_icon }: any) => {
|
|
||||||
onSuccess();
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<div className={`ValidationField upload_image_button ${className ?? ""} `}>
|
|
||||||
<label htmlFor={name} className="text">
|
|
||||||
{t(`input.${label || name}`)}
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<Upload
|
|
||||||
disabled={isDisabled}
|
|
||||||
listType="picture"
|
|
||||||
maxCount={1}
|
|
||||||
fileList={[...fileList]}
|
|
||||||
onChange={onChange || FilehandleChange}
|
|
||||||
customRequest={customRequest}
|
|
||||||
className={` w-100`}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
className={isError ? "isError w-100 " : " w-100"}
|
|
||||||
icon={icon ? icon : <UploadOutlined />}
|
|
||||||
>
|
|
||||||
{placeholder ?? t("input.Click_to_upload_the_image")}
|
|
||||||
</Button>
|
|
||||||
<div className="Error_color"> {isError ? "required" : ""}</div>
|
|
||||||
{errorMsg}
|
|
||||||
</Upload>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default File;
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
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 HintField = ({
|
|
||||||
name,
|
|
||||||
label,
|
|
||||||
label2,
|
|
||||||
placeholder,
|
|
||||||
isDisabled,
|
|
||||||
onChange,
|
|
||||||
props,
|
|
||||||
no_label,
|
|
||||||
label_icon,
|
|
||||||
id,
|
|
||||||
className,
|
|
||||||
}: any) => {
|
|
||||||
const newName = `answers[${name}].hint`;
|
|
||||||
const { formik, isError, errorMsg, t } = useFormField(newName, props);
|
|
||||||
const TextFilehandleChange = (
|
|
||||||
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
|
||||||
) => {
|
|
||||||
// console.log('Change:', e.target.value);
|
|
||||||
formik.setFieldValue(newName, e.target.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={`ValidationField w-100 ${className ?? ""} `}>
|
|
||||||
{no_label ? (
|
|
||||||
<label htmlFor={name} className="text">
|
|
||||||
<span>empty</span>
|
|
||||||
</label>
|
|
||||||
) : label_icon ? (
|
|
||||||
<div className="LabelWithIcon">
|
|
||||||
<label htmlFor={name} className="text">
|
|
||||||
{label2 ? label2 : t(`input.${label ? label : name}`)}
|
|
||||||
</label>
|
|
||||||
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<label htmlFor={name} className="text">
|
|
||||||
{label2 ? label2 : t(`input.${label ? label : name}`)}
|
|
||||||
</label>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
hasFeedback
|
|
||||||
validateStatus={isError ? "error" : ""}
|
|
||||||
help={isError ? errorMsg : ""}
|
|
||||||
>
|
|
||||||
<Field
|
|
||||||
as={Input}
|
|
||||||
placeholder={t(`input.${placeholder ? placeholder : name}`)}
|
|
||||||
name={newName}
|
|
||||||
disabled={isDisabled}
|
|
||||||
size="large"
|
|
||||||
onChange={onChange || TextFilehandleChange}
|
|
||||||
style={{ width: 200 }}
|
|
||||||
id={id}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default React.memo(HintField);
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Form, Input } from "antd";
|
import { Form, Input } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import useFormField from "../../../../../Hooks/useFormField";
|
||||||
import { MdOutlineEdit } from "react-icons/md";
|
import { MdOutlineEdit } from "react-icons/md";
|
||||||
import { Field } from "formik";
|
import { Field } from "formik";
|
||||||
import useFormField from "../../../../../Hooks/useFormField";
|
|
||||||
const { TextArea } = Input;
|
const { TextArea } = Input;
|
||||||
|
|
||||||
const TextField = ({
|
const TextField = ({
|
||||||
|
|
@ -18,7 +18,7 @@ const TextField = ({
|
||||||
id,
|
id,
|
||||||
className,
|
className,
|
||||||
}: any) => {
|
}: any) => {
|
||||||
const newName = `QuestionOptions[${name}].answer`;
|
const newName = `answers[${name}].content`;
|
||||||
const { formik, isError, errorMsg, t } = useFormField(newName, props);
|
const { formik, isError, errorMsg, t } = useFormField(newName, props);
|
||||||
const TextFilehandleChange = (
|
const TextFilehandleChange = (
|
||||||
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import ValidationField from '../../../../Components/ValidationField/ValidationField'
|
|
||||||
import { Col, Row } from "reactstrap";
|
|
||||||
|
|
||||||
const FilterForm = () => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Row>
|
|
||||||
<Col>
|
|
||||||
<ValidationField placeholder="name" label="name" name="name" />
|
|
||||||
<ValidationField placeholder="name" label="name" name="name" />
|
|
||||||
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<ValidationField placeholder="name" label="name" name="name" />
|
|
||||||
<ValidationField placeholder="name" label="name" name="name" />
|
|
||||||
|
|
||||||
</Col>
|
|
||||||
|
|
||||||
</Row>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default FilterForm
|
|
||||||
|
|
@ -10,17 +10,14 @@ import { useTranslation } from "react-i18next";
|
||||||
import DynamicTags from "./Tags/DynamicTags";
|
import DynamicTags from "./Tags/DynamicTags";
|
||||||
import QuestionFIeld from "./QuestionFIeld/QuestionFIeld";
|
import QuestionFIeld from "./QuestionFIeld/QuestionFIeld";
|
||||||
import { useObjectToEdit } from "../../../../../zustand/ObjectToEditState";
|
import { useObjectToEdit } from "../../../../../zustand/ObjectToEditState";
|
||||||
|
import Choices from "./ChoiceField/Choices";
|
||||||
|
|
||||||
const Form = () => {
|
const Form = () => {
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
const { isOpen } = useModalState((state) => state);
|
|
||||||
// const {data} = useGetAllQuestion();
|
|
||||||
const { setSuccess, Success, setSavedQuestionData } = useObjectToEdit();
|
const { setSuccess, Success, setSavedQuestionData } = useObjectToEdit();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Success) {
|
if (Success) {
|
||||||
console.log(1);
|
|
||||||
|
|
||||||
formik.setErrors({});
|
formik.setErrors({});
|
||||||
formik.resetForm({ values: {} });
|
formik.resetForm({ values: {} });
|
||||||
setSuccess(false);
|
setSuccess(false);
|
||||||
|
|
@ -32,14 +29,13 @@ const Form = () => {
|
||||||
}, [formik?.values]);
|
}, [formik?.values]);
|
||||||
|
|
||||||
// console.log(formik?.errors);
|
// console.log(formik?.errors);
|
||||||
console.log(formik?.values?.Questions, "formik?.values?.Questions");
|
|
||||||
|
|
||||||
const handleAddChoice = (parent_index: number) => {
|
const handleAddChoice = (parent_index: number) => {
|
||||||
console.log(parent_index);
|
console.log(parent_index);
|
||||||
|
|
||||||
formik.setFieldValue(`Questions.[${parent_index}].QuestionOptions`, [
|
formik.setFieldValue(`Questions.[${parent_index}].answers`, [
|
||||||
...((formik?.values as any)?.Questions?.[parent_index]
|
...((formik?.values as any)?.Questions?.[parent_index]
|
||||||
.QuestionOptions as Choice[]),
|
.answers as Choice[]),
|
||||||
|
|
||||||
{
|
{
|
||||||
answer: null,
|
answer: null,
|
||||||
|
|
@ -58,9 +54,9 @@ const Form = () => {
|
||||||
image: "",
|
image: "",
|
||||||
parent: "",
|
parent: "",
|
||||||
isBase: 0,
|
isBase: 0,
|
||||||
max_mark: 1,
|
// max_mark: 1,
|
||||||
min_mark_to_pass: 1,
|
// min_mark_to_pass: 1,
|
||||||
QuestionOptions: [{ answer: null, answer_image: null, isCorrect: 0 }],
|
answers: [{ answer: null, answer_image: null, isCorrect: 0 }],
|
||||||
tags: [],
|
tags: [],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
@ -70,7 +66,6 @@ const Form = () => {
|
||||||
formik.setFieldValue("max_mark", max_mark);
|
formik.setFieldValue("max_mark", max_mark);
|
||||||
};
|
};
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
console.log(formik.errors);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row className="w-100">
|
<Row className="w-100">
|
||||||
|
|
@ -109,21 +104,9 @@ const Form = () => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{(
|
<Choices parent_index={parent_index} />
|
||||||
(formik?.values as any)?.Questions?.[parent_index]
|
|
||||||
?.QuestionOptions || []
|
|
||||||
).map((item: Choice, index: number) => {
|
|
||||||
return (
|
|
||||||
<ChoiceFields
|
|
||||||
key={index}
|
|
||||||
parent_index={parent_index}
|
|
||||||
index={index}
|
|
||||||
data={item}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
|
|
||||||
{formik?.values?.Questions?.[parent_index]?.QuestionOptions
|
{formik?.values?.Questions?.[parent_index]?.answers
|
||||||
?.length < 5 && (
|
?.length < 5 && (
|
||||||
<p className="add_new_button">
|
<p className="add_new_button">
|
||||||
<FaCirclePlus
|
<FaCirclePlus
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import useFormField from "../../../../../../Hooks/useFormField";
|
||||||
import { Checkbox, Form } from "antd";
|
import { Checkbox, Form } from "antd";
|
||||||
import { useFormik, useFormikContext } from "formik";
|
import { useFormik, useFormikContext } from "formik";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
@ -15,16 +16,15 @@ const CheckboxField = ({
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const CheckboxhandleChange = (value: any) => {
|
const CheckboxhandleChange = (value: any) => {
|
||||||
console.log(value?.target?.checked);
|
|
||||||
|
|
||||||
const allAreZero = formik?.values?.Questions?.[
|
const allAreZero = formik?.values?.Questions?.[
|
||||||
parent_index
|
parent_index
|
||||||
]?.QuestionOptions?.some((item: any) => item.isCorrect === 1);
|
]?.answers?.some((item: any) => item.isCorrect === 1);
|
||||||
if (allAreZero) {
|
if (allAreZero) {
|
||||||
formik?.values?.Questions?.[parent_index]?.QuestionOptions.forEach(
|
formik?.values?.Questions?.[parent_index]?.answers.forEach(
|
||||||
(item: any, index: number) => {
|
(item: any, index: number) => {
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`Questions[${parent_index}].QuestionOptions[${index}].isCorrect`,
|
`Questions[${parent_index}].answers[${index}].isCorrect`,
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
@ -32,7 +32,7 @@ const CheckboxField = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`Questions[${parent_index}].QuestionOptions[${name}].isCorrect`,
|
`Questions[${parent_index}].answers[${name}].isCorrect`,
|
||||||
value?.target?.checked ? 1 : 0,
|
value?.target?.checked ? 1 : 0,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -42,7 +42,7 @@ const CheckboxField = ({
|
||||||
onChange={onChange || CheckboxhandleChange}
|
onChange={onChange || CheckboxhandleChange}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
checked={
|
checked={
|
||||||
formik.values?.Questions?.[parent_index]?.QuestionOptions?.[name]
|
formik.values?.Questions?.[parent_index]?.answers?.[name]
|
||||||
?.isCorrect === 1
|
?.isCorrect === 1
|
||||||
}
|
}
|
||||||
className={className}
|
className={className}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import TextField from "./TextField";
|
||||||
import File from "./File";
|
import File from "./File";
|
||||||
import { FaTrash } from "react-icons/fa";
|
import { FaTrash } from "react-icons/fa";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
|
import HintField from "./HintField";
|
||||||
|
|
||||||
const ChoiceFields = ({
|
const ChoiceFields = ({
|
||||||
index,
|
index,
|
||||||
|
|
@ -25,7 +26,7 @@ const ChoiceFields = ({
|
||||||
|
|
||||||
const handleDeleteChoice = () => {
|
const handleDeleteChoice = () => {
|
||||||
const arrayLength =
|
const arrayLength =
|
||||||
formik.values.Questions?.[parent_index].QuestionOptions?.length;
|
formik.values.Questions?.[parent_index].answers?.length;
|
||||||
|
|
||||||
console.log(arrayLength);
|
console.log(arrayLength);
|
||||||
|
|
||||||
|
|
@ -36,15 +37,16 @@ const ChoiceFields = ({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedQuestionOptions = formik.values.Questions?.[
|
const updatedAnswers = formik.values.Questions?.[
|
||||||
parent_index
|
parent_index
|
||||||
].QuestionOptions.filter((_: any, i: any) => i !== index);
|
].answers.filter((_: any, i: any) => i !== index);
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`Questions[${parent_index}].QuestionOptions`,
|
`Questions[${parent_index}].answers`,
|
||||||
updatedQuestionOptions,
|
updatedAnswers,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<div className="ChoiceFields">
|
<div className="ChoiceFields">
|
||||||
<TextField
|
<TextField
|
||||||
className="textarea_exercise"
|
className="textarea_exercise"
|
||||||
|
|
@ -73,6 +75,18 @@ const ChoiceFields = ({
|
||||||
<FaTrash onClick={handleDeleteChoice} size={17} />
|
<FaTrash onClick={handleDeleteChoice} size={17} />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<HintField
|
||||||
|
className=""
|
||||||
|
label="hint"
|
||||||
|
placeholder="hint"
|
||||||
|
name={index}
|
||||||
|
|
||||||
|
parent_index={parent_index}
|
||||||
|
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,11 @@ const File = ({
|
||||||
parent_index,
|
parent_index,
|
||||||
props,
|
props,
|
||||||
}: any) => {
|
}: any) => {
|
||||||
const newName = `Questions[${parent_index}].QuestionOptions[${name}].answer_image`;
|
const newName = `Questions[${parent_index}].answers[${name}].answer_image`;
|
||||||
|
|
||||||
const { formik, t, isError, errorMsg } = useFormField(newName, props);
|
const { formik, t, isError, errorMsg } = useFormField(newName, props);
|
||||||
let imageUrl =
|
let imageUrl =
|
||||||
formik?.values?.Questions?.[parent_index]?.QuestionOptions[name]
|
formik?.values?.Questions?.[parent_index]?.answers[name]
|
||||||
?.answer_image ?? null;
|
?.answer_image ?? null;
|
||||||
// console.log(imageUrl);
|
// console.log(imageUrl);
|
||||||
|
|
||||||
|
|
@ -49,7 +49,7 @@ const File = ({
|
||||||
formik.setFieldValue(newName, null);
|
formik.setFieldValue(newName, null);
|
||||||
} else {
|
} else {
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
`Questions[${parent_index}].QuestionOptions[${name}].answer_image`,
|
`Questions[${parent_index}].answers[${name}].answer_image`,
|
||||||
value?.file?.originFileObj,
|
value?.file?.originFileObj,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ const TextField = ({
|
||||||
parent_index,
|
parent_index,
|
||||||
className,
|
className,
|
||||||
}: any) => {
|
}: any) => {
|
||||||
const newName = `Questions[${parent_index}].QuestionOptions[${name}].answer`;
|
const newName = `Questions[${parent_index}].answers[${name}].content`;
|
||||||
const { formik, isError, errorMsg, t } = useFormField(newName, props);
|
const { formik, isError, errorMsg, t } = useFormField(newName, props);
|
||||||
const TextFilehandleChange = (
|
const TextFilehandleChange = (
|
||||||
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import React, { useEffect } from "react";
|
||||||
import ValidationField from "../../../../../Components/ValidationField/ValidationField";
|
import ValidationField from "../../../../../Components/ValidationField/ValidationField";
|
||||||
import { useFormikContext } from "formik";
|
import { useFormikContext } from "formik";
|
||||||
import { useModalState } from "../../../../../zustand/Modal";
|
import { useModalState } from "../../../../../zustand/Modal";
|
||||||
|
import PdfUploader from "../../../../../Components/CustomFields/PdfUploader";
|
||||||
import ChoiceFields from "./ChoiceField/ChoiceFields";
|
import ChoiceFields from "./ChoiceField/ChoiceFields";
|
||||||
import { FaCirclePlus } from "react-icons/fa6";
|
import { FaCirclePlus } from "react-icons/fa6";
|
||||||
import { Choice } from "../../../../../types/Item";
|
import { Choice } from "../../../../../types/Item";
|
||||||
|
|
@ -29,9 +30,9 @@ const Form = () => {
|
||||||
const handleAddChoice = (parent_index: number) => {
|
const handleAddChoice = (parent_index: number) => {
|
||||||
console.log(parent_index);
|
console.log(parent_index);
|
||||||
console.log(formik?.values?.Questions);
|
console.log(formik?.values?.Questions);
|
||||||
formik.setFieldValue(`Questions.[${parent_index}].QuestionOptions`, [
|
formik.setFieldValue(`Questions.[${parent_index}].answers`, [
|
||||||
...((formik?.values as any)?.Questions?.[parent_index]
|
...((formik?.values as any)?.Questions?.[parent_index]
|
||||||
.QuestionOptions as Choice[]),
|
.answers as Choice[]),
|
||||||
|
|
||||||
{
|
{
|
||||||
answer: null,
|
answer: null,
|
||||||
|
|
@ -52,7 +53,7 @@ const Form = () => {
|
||||||
isBase: 0,
|
isBase: 0,
|
||||||
max_mark: 1,
|
max_mark: 1,
|
||||||
min_mark_to_pass: 1,
|
min_mark_to_pass: 1,
|
||||||
QuestionOptions: [{ answer: null, answer_image: null, isCorrect: 0 }],
|
answers: [{ answer: null, answer_image: null, isCorrect: 0 }],
|
||||||
tags: [],
|
tags: [],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
@ -102,7 +103,7 @@ const Form = () => {
|
||||||
|
|
||||||
{(
|
{(
|
||||||
(formik?.values as any)?.Questions?.[parent_index]
|
(formik?.values as any)?.Questions?.[parent_index]
|
||||||
?.QuestionOptions || []
|
?.answers || []
|
||||||
).map((item: Choice, index: number) => {
|
).map((item: Choice, index: number) => {
|
||||||
return (
|
return (
|
||||||
<ChoiceFields
|
<ChoiceFields
|
||||||
|
|
@ -113,7 +114,7 @@ const Form = () => {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
{formik?.values?.Questions?.[parent_index]?.QuestionOptions
|
{formik?.values?.Questions?.[parent_index]?.answers
|
||||||
?.length < 5 && (
|
?.length < 5 && (
|
||||||
<p className="add_new_button">
|
<p className="add_new_button">
|
||||||
<FaCirclePlus
|
<FaCirclePlus
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,11 @@ import File from "./File";
|
||||||
import { FaTrash } from "react-icons/fa";
|
import { FaTrash } from "react-icons/fa";
|
||||||
import { useObjectToEdit } from "../../../../../../zustand/ObjectToEditState";
|
import { useObjectToEdit } from "../../../../../../zustand/ObjectToEditState";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
|
import CheckboxField from "./CheckboxField";
|
||||||
|
import HintField from "./HintField";
|
||||||
|
|
||||||
const QuestionFIeld = ({ index, data }: { index: number; data: Choice }) => {
|
const QuestionFIeld = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
console.log(index);
|
|
||||||
const { setDeletedQuestions, DeletedQuestions } = useObjectToEdit();
|
const { setDeletedQuestions, DeletedQuestions } = useObjectToEdit();
|
||||||
|
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
@ -25,13 +26,14 @@ const QuestionFIeld = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
if (DeleteQuestionId?.id) {
|
if (DeleteQuestionId?.id) {
|
||||||
setDeletedQuestions([...DeletedQuestions, DeleteQuestionId]);
|
setDeletedQuestions([...DeletedQuestions, DeleteQuestionId]);
|
||||||
}
|
}
|
||||||
const updatedQuestionOptions = formik.values.Questions.filter(
|
const updatedAnswers = formik.values.Questions.filter(
|
||||||
(_: any, i: any) => i !== index,
|
(_: any, i: any) => i !== index,
|
||||||
);
|
);
|
||||||
formik.setFieldValue(`Questions`, updatedQuestionOptions);
|
formik.setFieldValue(`Questions`, updatedAnswers);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div className="d-c">
|
||||||
<div className="ChoiceFields">
|
<div className="ChoiceFields">
|
||||||
<TextField
|
<TextField
|
||||||
className="textarea_exercise"
|
className="textarea_exercise"
|
||||||
|
|
@ -46,10 +48,24 @@ const QuestionFIeld = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
name={index}
|
name={index}
|
||||||
type="File"
|
type="File"
|
||||||
/>
|
/>
|
||||||
|
<CheckboxField
|
||||||
|
className="canAnswersBeShuffled"
|
||||||
|
label={"canAnswersBeShuffled"}
|
||||||
|
name={index}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<p className="delete_question_options">
|
<p className="delete_question_options">
|
||||||
<FaTrash onClick={handleDeleteQuestion} size={17} />
|
<FaTrash onClick={handleDeleteQuestion} size={17} />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<HintField placeholder={"hint"} name={index} label="hint" id={`hint`} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
import React, { useState } from "react";
|
|
||||||
import MathJax from "react-mathjax";
|
|
||||||
|
|
||||||
const MathInput: React.FC = () => {
|
|
||||||
const [input, setInput] = useState<string>(
|
|
||||||
"a^2+b^2=c^2 (x+a)^n=x=(-b±√(b^2-4ac))/2a ∑_(k=0)^n▒〖(n¦k) x^k a^(n-k) 〗",
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
const formattedInput = event.target.value.replace("_", " _ ");
|
|
||||||
console.log(event.target.value);
|
|
||||||
|
|
||||||
setInput(formattedInput);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<MathJax.Provider>
|
|
||||||
<div>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
id="mathInput"
|
|
||||||
value={input}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
<div>
|
|
||||||
<MathJax.Node formula={input} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</MathJax.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MathInput;
|
|
||||||
|
|
@ -8,12 +8,12 @@ import { useTranslation } from "react-i18next";
|
||||||
import DynamicTags from "./Tags/DynamicTags";
|
import DynamicTags from "./Tags/DynamicTags";
|
||||||
import { useObjectToEdit } from "../../../../zustand/ObjectToEditState";
|
import { useObjectToEdit } from "../../../../zustand/ObjectToEditState";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { LuImagePlus } from "react-icons/lu";
|
import Choices from "./Field/Choices";
|
||||||
import ImageBoxField from "../../../../Components/CustomFields/ImageBoxField/ImageBoxField";
|
import ImageBoxField from "../../../../Components/CustomFields/ImageBoxField/ImageBoxField";
|
||||||
import SelectTag from "./Tags/SelectTag";
|
import SelectTag from "../../../../Components/CustomFields/SelectTag";
|
||||||
|
|
||||||
const Form = () => {
|
const Form = () => {
|
||||||
const [t] = useTranslation()
|
const [t] = useTranslation();
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
const { setSuccess, Success, setSavedQuestionData } = useObjectToEdit();
|
const { setSuccess, Success, setSavedQuestionData } = useObjectToEdit();
|
||||||
|
|
||||||
|
|
@ -26,41 +26,50 @@ const Form = () => {
|
||||||
}, [Success]);
|
}, [Success]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSavedQuestionData(formik.values)
|
console.log(formik.values,"formik.values");
|
||||||
}, [formik?.values])
|
|
||||||
|
|
||||||
|
|
||||||
|
setSavedQuestionData(formik.values);
|
||||||
|
}, [formik?.values]);
|
||||||
|
|
||||||
const handleAddChoice = () => {
|
const handleAddChoice = () => {
|
||||||
formik.setFieldValue('QuestionOptions', [...(formik?.values as any)?.QuestionOptions as Choice[],
|
formik.setFieldValue("answers", [
|
||||||
{
|
...((formik?.values as any)?.answers as Choice[]),
|
||||||
answer:null,
|
{
|
||||||
answer_image:null,
|
content: null,
|
||||||
isCorrect:0,
|
answer_image: null,
|
||||||
}])
|
isCorrect: 0,
|
||||||
}
|
},
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(formik?.values);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row className="w-100 exercise_form_container">
|
<Row className="w-100 exercise_form_container">
|
||||||
<div className="exercise_form">
|
<div className="exercise_form">
|
||||||
<ValidationField className="textarea_exercise" name="answer_content" label="answer_content" type="TextArea" />
|
<ValidationField className="textarea_exercise" name="content" label="answer_content" type="TextArea" />
|
||||||
<ImageBoxField name="image" />
|
<ImageBoxField name="image" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{
|
|
||||||
(((formik?.values as any)?.QuestionOptions as Choice[])||[]) .map((item:Choice,index:number)=>{
|
<Choices />
|
||||||
return <ChoiceFields key={index} index={index} data={item}/>
|
{formik?.values?.answers?.length < 5 && (
|
||||||
})}
|
<p className="add_new_button">
|
||||||
{formik?.values?.QuestionOptions?.length < 5 && (
|
<FaCirclePlus onClick={handleAddChoice} size={23} />{" "}
|
||||||
<p className="add_new_button" >
|
{t("header.add_new_choice")}
|
||||||
<FaCirclePlus onClick={handleAddChoice} size={23} /> {t("header.add_new_choice")}
|
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{/* <DynamicTags/> */}
|
|
||||||
<div className="exercise_form_width">
|
<div className="exercise_form_width">
|
||||||
|
|
||||||
|
<ValidationField
|
||||||
<SelectTag/>
|
className=" "
|
||||||
|
placeholder="_"
|
||||||
|
name="hint"
|
||||||
|
label="hint"
|
||||||
|
type="text"
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
/>
|
||||||
|
<SelectTag />
|
||||||
</div>
|
</div>
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
import React, { useState, useMemo } from 'react';
|
|
||||||
import { Select, Spin } from 'antd';
|
|
||||||
import { useGetAllTag } from '../../../../../api/tags';
|
|
||||||
import { useDebounce } from '../../../../../utils/useDebounce';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
const SelectTag: React.FC = () => {
|
|
||||||
const [searchValue, setSearchValue] = useState<string>('');
|
|
||||||
const [fieldValue, setFieldValue] = useState<string>('');
|
|
||||||
|
|
||||||
const handleChange = (value: string[]) => {
|
|
||||||
setSearchValue('');
|
|
||||||
setFieldValue('');
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSearch = useDebounce((value: string) => {
|
|
||||||
setSearchValue(value);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleFieldChange = (value: string) => {
|
|
||||||
setFieldValue(value);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleBlur = () => {
|
|
||||||
setSearchValue('');
|
|
||||||
setFieldValue('');
|
|
||||||
};
|
|
||||||
|
|
||||||
const { data, isLoading } = useGetAllTag({
|
|
||||||
name: searchValue,
|
|
||||||
});
|
|
||||||
|
|
||||||
const [t] = useTranslation();
|
|
||||||
|
|
||||||
const options = data?.data ?? []
|
|
||||||
console.log(options,"options");
|
|
||||||
const additionalData = options?.length < 1 && searchValue.length > 1 && !isLoading ? [{id:`new_${searchValue}`,name:searchValue}] :[];
|
|
||||||
console.log(additionalData);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='SelectTag'>
|
|
||||||
|
|
||||||
<label htmlFor="">
|
|
||||||
{t("models.tag")}
|
|
||||||
</label>
|
|
||||||
<Select
|
|
||||||
mode="multiple"
|
|
||||||
allowClear
|
|
||||||
style={{ width: '100%' ,height:"40px"}}
|
|
||||||
placeholder=""
|
|
||||||
fieldNames={{ label: 'name', value: 'id' }}
|
|
||||||
onChange={handleChange}
|
|
||||||
options={[...options,...additionalData]}
|
|
||||||
filterOption={false}
|
|
||||||
loading={isLoading}
|
|
||||||
notFoundContent={isLoading ? <Spin /> : t("practical.not_found")}
|
|
||||||
onSearch={(value) => {
|
|
||||||
handleSearch(value);
|
|
||||||
handleFieldChange(value);
|
|
||||||
}}
|
|
||||||
searchValue={fieldValue}
|
|
||||||
onDropdownVisibleChange={(open) => {
|
|
||||||
if (!open) {
|
|
||||||
handleBlur();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SelectTag;
|
|
||||||
|
|
@ -7,15 +7,18 @@ export const getInitialValues = (objectToEdit: Question): any => {
|
||||||
const tags = objectToEdit?.tags?.map((item: any, index: number) => {
|
const tags = objectToEdit?.tags?.map((item: any, index: number) => {
|
||||||
return { ...item, key: index };
|
return { ...item, key: index };
|
||||||
});
|
});
|
||||||
|
console.log(objectToEdit);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: objectToEdit?.id ?? null,
|
id: objectToEdit?.id ?? null,
|
||||||
content: objectToEdit?.content ?? "",
|
content: objectToEdit?.content ?? "",
|
||||||
image: objectToEdit?.image ?? "",
|
image: objectToEdit?.image ?? "",
|
||||||
subject_id: objectToEdit?.subject_id ?? "",
|
subject_id: objectToEdit?.subject_id ?? "",
|
||||||
|
canAnswersBeShuffled: objectToEdit?.canAnswersBeShuffled ? 1 : 0,
|
||||||
|
hint: objectToEdit?.hint ?? "",
|
||||||
isBase: 0,
|
isBase: 0,
|
||||||
parent_id: objectToEdit?.parent_id ?? "",
|
parent_id: objectToEdit?.parent_id ?? "",
|
||||||
QuestionOptions: objectToEdit?.QuestionOptions ?? [],
|
answers: objectToEdit?.answers ?? [],
|
||||||
tags: tags ?? [],
|
tags: tags ?? [],
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -25,10 +28,10 @@ export const getValidationSchema = () => {
|
||||||
return Yup.object().shape({
|
return Yup.object().shape({
|
||||||
image: Yup.string().nullable(),
|
image: Yup.string().nullable(),
|
||||||
content: Yup.string().required("validation.required"),
|
content: Yup.string().required("validation.required"),
|
||||||
QuestionOptions: Yup.array()
|
answers: Yup.array()
|
||||||
.of(
|
.of(
|
||||||
Yup.object().shape({
|
Yup.object().shape({
|
||||||
answer: Yup.string().required("validation.required"),
|
content: Yup.string().required("validation.required"),
|
||||||
answer_image: Yup.string().nullable(),
|
answer_image: Yup.string().nullable(),
|
||||||
isCorrect: Yup.boolean(),
|
isCorrect: Yup.boolean(),
|
||||||
}),
|
}),
|
||||||
|
|
@ -38,11 +41,6 @@ export const getValidationSchema = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getInitialValuesBase = (objectToEdit: Question): any => {
|
export const getInitialValuesBase = (objectToEdit: Question): any => {
|
||||||
const tags = objectToEdit?.tags?.map((item: any, index: number) => {
|
|
||||||
return { ...item, key: index };
|
|
||||||
});
|
|
||||||
console.log(objectToEdit);
|
|
||||||
|
|
||||||
const newQuestions = objectToEdit?.Questions?.map((item: any) => {
|
const newQuestions = objectToEdit?.Questions?.map((item: any) => {
|
||||||
const tags = item?.tags?.map((tag: any) => ({
|
const tags = item?.tags?.map((tag: any) => ({
|
||||||
id: tag?.id,
|
id: tag?.id,
|
||||||
|
|
@ -52,6 +50,8 @@ export const getInitialValuesBase = (objectToEdit: Question): any => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
|
canAnswersBeShuffled: objectToEdit?.canAnswersBeShuffled ? 1 : 0,
|
||||||
|
hint: item?.hint ?? "",
|
||||||
tags,
|
tags,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
@ -65,6 +65,8 @@ export const getInitialValuesBase = (objectToEdit: Question): any => {
|
||||||
subject_id: objectToEdit?.subject_id ?? "",
|
subject_id: objectToEdit?.subject_id ?? "",
|
||||||
isBase: 1,
|
isBase: 1,
|
||||||
parent_id: objectToEdit?.parent_id ?? "",
|
parent_id: objectToEdit?.parent_id ?? "",
|
||||||
|
canAnswersBeShuffled: objectToEdit?.canAnswersBeShuffled ? 1 : 0,
|
||||||
|
hint: objectToEdit?.hint ?? "",
|
||||||
Questions: questions,
|
Questions: questions,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -78,10 +80,10 @@ export const getValidationSchemaBase = () => {
|
||||||
Yup.object().shape({
|
Yup.object().shape({
|
||||||
image: Yup.string().nullable(),
|
image: Yup.string().nullable(),
|
||||||
content: Yup.string().required("validation.required"),
|
content: Yup.string().required("validation.required"),
|
||||||
QuestionOptions: Yup.array()
|
answers: Yup.array()
|
||||||
.of(
|
.of(
|
||||||
Yup.object().shape({
|
Yup.object().shape({
|
||||||
answer: Yup.string().required("validation.required"),
|
content: Yup.string().required("validation.required"),
|
||||||
answer_image: Yup.string().nullable(),
|
answer_image: Yup.string().nullable(),
|
||||||
isCorrect: Yup.boolean(),
|
isCorrect: Yup.boolean(),
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,6 @@ import { ModalEnum } from "../../../enums/Model";
|
||||||
import { useGetAllSubject } from "../../../api/subject";
|
import { useGetAllSubject } from "../../../api/subject";
|
||||||
import { useGetAllGrade } from "../../../api/grade";
|
import { useGetAllGrade } from "../../../api/grade";
|
||||||
import { useGetAllCurriculum } from "../../../api/curriculum";
|
import { useGetAllCurriculum } from "../../../api/curriculum";
|
||||||
import PageHeader from "../../../Layout/Dashboard/PageHeader";
|
|
||||||
import FilterLayout from "../../../Layout/Dashboard/FilterLayout";
|
|
||||||
import FilterForm from "./Model/FilterForm";
|
|
||||||
import { canAddQuestion } from "../../../utils/hasAbilityFn";
|
|
||||||
import { ABILITIES_ENUM } from "../../../enums/abilities";
|
|
||||||
const Table = lazy(() => import("./Table"));
|
const Table = lazy(() => import("./Table"));
|
||||||
|
|
||||||
const TableHeader = () => {
|
const TableHeader = () => {
|
||||||
|
|
@ -74,15 +69,9 @@ const TableHeader = () => {
|
||||||
return (
|
return (
|
||||||
<div className="TableWithHeader">
|
<div className="TableWithHeader">
|
||||||
<Suspense fallback={<Spin />}>
|
<Suspense fallback={<Spin />}>
|
||||||
<PageHeader
|
<header>
|
||||||
pageTitle="question"
|
<h6>{t("models.Question")}</h6>
|
||||||
ModelAbility={ModalEnum?.QUESTION_ACCEPT}
|
</header>
|
||||||
canAdd={canAddQuestion}
|
|
||||||
locationToNavigate={`${ABILITIES_ENUM?.QUESTION}/add`}
|
|
||||||
openModel={false}/>
|
|
||||||
<FilterLayout
|
|
||||||
sub_children={<FilterForm/>}
|
|
||||||
filterTitle="sidebar.question"/>
|
|
||||||
<Table />
|
<Table />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
<DeleteModels
|
<DeleteModels
|
||||||
|
|
|
||||||
|
|
@ -69,16 +69,15 @@ export const useColumns = () => {
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
// canAddQuestion ? (
|
title: canAddQuestion ? (
|
||||||
// <button onClick={() => handelAdd()} className="add_button">
|
<button onClick={() => handelAdd()} className="add_button">
|
||||||
// {t("practical.add")} {t("models.Question")} <FaPlus />
|
{t("practical.add")} {t("models.Question")} <FaPlus />
|
||||||
// </button>
|
</button>
|
||||||
// ) : (
|
) : (
|
||||||
// ""
|
""
|
||||||
// ),
|
),
|
||||||
title: t("columns.procedure"),
|
|
||||||
key: "actions",
|
key: "actions",
|
||||||
align: "center",
|
align: "end",
|
||||||
width: "25vw",
|
width: "25vw",
|
||||||
render: (_text, record, index) => {
|
render: (_text, record, index) => {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -182,10 +182,10 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
margin-block: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.exercise_form_width{
|
.exercise_form_width{
|
||||||
|
margin-block: 20px;
|
||||||
|
|
||||||
max-width: 50vw;
|
max-width: 50vw;
|
||||||
>*{
|
>*{
|
||||||
|
|
|
||||||
|
|
@ -373,7 +373,10 @@
|
||||||
"question": "السؤال",
|
"question": "السؤال",
|
||||||
"id": "الرقم التعريفي",
|
"id": "الرقم التعريفي",
|
||||||
"icon": "الايقونة",
|
"icon": "الايقونة",
|
||||||
"answer_content":"نص السؤال"
|
"answer_content":"نص السؤال",
|
||||||
|
"hint":"شرح السؤال",
|
||||||
|
"hint_question":"شرح الاختيار",
|
||||||
|
"_":""
|
||||||
},
|
},
|
||||||
"select": {
|
"select": {
|
||||||
"Payments": {
|
"Payments": {
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@ export const setLocalStorageQuestions = async (key: string, data: any) => {
|
||||||
data.image = await convertFileToBase64(data.image);
|
data.image = await convertFileToBase64(data.image);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for QuestionOptions array and convert answer_image if it's a File
|
// Check for answers array and convert answer_image if it's a File
|
||||||
if (Array.isArray(data.QuestionOptions)) {
|
if (Array.isArray(data.answers)) {
|
||||||
for (const option of data.QuestionOptions) {
|
for (const option of data.answers) {
|
||||||
if (option.answer_image instanceof File) {
|
if (option.answer_image instanceof File) {
|
||||||
option.answer_image = await convertFileToBase64(option.answer_image);
|
option.answer_image = await convertFileToBase64(option.answer_image);
|
||||||
}
|
}
|
||||||
|
|
@ -18,14 +18,14 @@ export const setLocalStorageQuestions = async (key: string, data: any) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for Questions array and convert image if it's a File
|
// Check for Questions array and convert image if it's a File
|
||||||
if (Array.isArray(data.Questions)) {
|
if (Array.isArray(data.answers)) {
|
||||||
for (const question of data.Questions) {
|
for (const question of data.answers) {
|
||||||
if (question.image instanceof File) {
|
if (question.image instanceof File) {
|
||||||
question.image = await convertFileToBase64(question.image);
|
question.image = await convertFileToBase64(question.image);
|
||||||
}
|
}
|
||||||
// Check for nested QuestionOptions and convert answer_image if it's a File
|
// Check for nested answers and convert answer_image if it's a File
|
||||||
if (Array.isArray(question.QuestionOptions)) {
|
if (Array.isArray(question.answers)) {
|
||||||
for (const option of question.QuestionOptions) {
|
for (const option of question.answers) {
|
||||||
if (option.answer_image instanceof File) {
|
if (option.answer_image instanceof File) {
|
||||||
option.answer_image = await convertFileToBase64(
|
option.answer_image = await convertFileToBase64(
|
||||||
option.answer_image,
|
option.answer_image,
|
||||||
|
|
@ -55,9 +55,9 @@ export const getLocalStorageQuestions = (key: string): any | null => {
|
||||||
data.image = base64StringToFile(data.image);
|
data.image = base64StringToFile(data.image);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for QuestionOptions array and convert answer_image if it's a base64 string
|
// Check for answers array and convert answer_image if it's a base64 string
|
||||||
if (Array.isArray(data.QuestionOptions)) {
|
if (Array.isArray(data.answers)) {
|
||||||
for (const option of data.QuestionOptions) {
|
for (const option of data.answers) {
|
||||||
if (
|
if (
|
||||||
typeof option.answer_image === "string" &&
|
typeof option.answer_image === "string" &&
|
||||||
option.answer_image.length > 0
|
option.answer_image.length > 0
|
||||||
|
|
@ -68,14 +68,14 @@ export const getLocalStorageQuestions = (key: string): any | null => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for Questions array and convert image if it's a base64 string
|
// Check for Questions array and convert image if it's a base64 string
|
||||||
if (Array.isArray(data.Questions)) {
|
if (Array.isArray(data.answers)) {
|
||||||
for (const question of data.Questions) {
|
for (const question of data.answers) {
|
||||||
if (typeof question.image === "string" && question.image.length > 0) {
|
if (typeof question.image === "string" && question.image.length > 0) {
|
||||||
question.image = base64StringToFile(question.image);
|
question.image = base64StringToFile(question.image);
|
||||||
}
|
}
|
||||||
// Check for nested QuestionOptions and convert answer_image if it's a base64 string
|
// Check for nested answers and convert answer_image if it's a base64 string
|
||||||
if (Array.isArray(question.QuestionOptions)) {
|
if (Array.isArray(question.answers)) {
|
||||||
for (const option of question.QuestionOptions) {
|
for (const option of question.answers) {
|
||||||
if (
|
if (
|
||||||
typeof option.answer_image === "string" &&
|
typeof option.answer_image === "string" &&
|
||||||
option.answer_image.length > 0
|
option.answer_image.length > 0
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user