end mml input

This commit is contained in:
karimaldeen 2024-09-21 09:12:01 +03:00
parent c49f498309
commit efb687b742
27 changed files with 327 additions and 171 deletions

View File

@ -6,7 +6,7 @@ import { convertMathMLToLaTeX } from '../../utils/convertMathMLToLaTeX';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
const LaTexModal = ({name,setLatex,Latex,setIsModalOpen,isModalOpen}:{ const AddLaTexModal = ({name,setLatex,Latex,setIsModalOpen,isModalOpen}:{
name:string, name:string,
setLatex: (value:string)=> void, setLatex: (value:string)=> void,
Latex:string, Latex:string,
@ -66,13 +66,12 @@ const LaTexModal = ({name,setLatex,Latex,setIsModalOpen,isModalOpen}:{
<div className="back_button pointer" onClick={handleCancel}> <div className="back_button pointer" onClick={handleCancel}>
{t("practical.cancel")} {t("practical.cancel")}
</div> </div>
<button <div
className="add_button" className="add_button"
type="submit"
onClick={handleOk} onClick={handleOk}
> >
{t(`practical.${ "add"}`)} {t(`practical.${ "add"}`)}
</button> </div>
</div> </div>
</div> </div>
</Modal> </Modal>
@ -80,4 +79,4 @@ const LaTexModal = ({name,setLatex,Latex,setIsModalOpen,isModalOpen}:{
) )
} }
export default LaTexModal export default AddLaTexModal

View File

@ -0,0 +1,89 @@
import { Modal } from 'antd'
import TextArea from 'antd/es/input/TextArea'
import { useFormikContext } from 'formik';
import React, { useState } from 'react'
import { convertMathMLToLaTeX } from '../../utils/convertMathMLToLaTeX';
import { useTranslation } from 'react-i18next';
import { toast } from 'react-toastify';
import { parseTextAndLatex } from '../../utils/parseTextAndLatex';
const EditLaTexModal = ({name,setLatex,Latex,setIsModalOpen,isModalOpen}:{
name:string,
setLatex: (value:string)=> void,
Latex:any,
setIsModalOpen: (value:boolean)=> void ,
isModalOpen:boolean,
}) => {
const {values} = useFormikContext<any>()
const [Value, setValue] = useState(Latex?.text ?? Latex)
const handleOk = () => {
console.log(1);
const oldValue = values?.[name];
const currentKey = Latex?.key ;
const Preview = parseTextAndLatex(oldValue ?? "") ;
console.log(Latex);
const newLatex = convertMathMLToLaTeX(Latex);
console.log(newLatex);
if(newLatex){
const newArray = Preview?.map((item:any,index:number)=>{
if(item?.key)
return item
})
}else{
toast.error(t("validation.that_is_not_a_valid_mml"))
}
};
const handleCancel = () => {
setIsModalOpen(false);
setLatex("")
};
const handleChangeInputLatex = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => {
const newValue = e.target.value;
console.log(newValue,"newValue");
setValue(newValue)
};
const [t] = useTranslation()
return (
<Modal footer={false} open={isModalOpen} onOk={handleOk} onCancel={handleCancel}>
<div className='latexModal'>
<label className='mb-3'> {t("header.past_your_MMl_text")} </label>
<TextArea
size="large"
showCount
maxLength={1000}
autoSize={{ minRows: 4, maxRows: 10 }}
style={{height:"400px"}}
onChange={handleChangeInputLatex}
value={Value
}
/>
<div className="buttons">
<div className="back_button pointer" onClick={handleCancel}>
{t("practical.cancel")}
</div>
<div
className="add_button"
onClick={handleOk}
>
{t(`practical.${ "edit"}`)}
</div>
</div>
</div>
</Modal>
)
}
export default EditLaTexModal

View File

@ -1,24 +1,27 @@
import TextArea from 'antd/es/input/TextArea' import TextArea from 'antd/es/input/TextArea'
import { useFormikContext } from 'formik'; import { useFormikContext } from 'formik';
import React, { useState } from 'react' import React, { Suspense, useState } from 'react'
import { convertMathMLToLaTeX } from '../../utils/convertMathMLToLaTeX';
import { parseTextAndLatex } from '../../utils/parseTextAndLatex'; import { parseTextAndLatex } from '../../utils/parseTextAndLatex';
import LatexPreview from '../../Components/CustomFields/MathComponent'; import LatexPreview from '../../Components/CustomFields/MathComponent';
import { Checkbox, Modal } from 'antd'; import { Checkbox } from 'antd';
import { CheckboxProps } from 'antd/lib'; import { CheckboxProps } from 'antd/lib';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import LaTexModal from './LaTexModal';
import { FaPlus } from 'react-icons/fa'; import { FaPlus } from 'react-icons/fa';
import { useObjectToEdit } from '../../zustand/ObjectToEditState';
const LaTeXInput = ({name}:{name:string}) => { import { TextAreaProps } from 'antd/lib/input';
import SpinContainer from '../Layout/SpinContainer';
const AddLazyModal = React.lazy(()=> import("./AddLaTexModal"));
const EditLazyModal = React.lazy(()=> import("./EditLaTexModal"));
interface ILaTeXInput extends TextAreaProps {
name:string,label:string
}
const LaTeXInput = ({name,label,...props}:ILaTeXInput) => {
const {values,setFieldValue} = useFormikContext<any>() const {values,setFieldValue,getFieldProps} = useFormikContext<any>()
const { ShowLatexOption } = useObjectToEdit();
const [showPreview, setShowPreview] = useState(false) ; const [showPreview, setShowPreview] = useState(false) ;
const value = getFieldProps(name)?.value
console.log(values?.[name]);
const handleChangeInput = const handleChangeInput =
( (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>, e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
@ -26,7 +29,7 @@ const LaTeXInput = ({name}:{name:string}) => {
setFieldValue(name,e.target.value); setFieldValue(name,e.target.value);
}; };
const Preview = parseTextAndLatex(values?.[name]) ; const Preview = parseTextAndLatex(value ?? "") ;
const onPreviewChange: CheckboxProps['onChange'] = (e) => { const onPreviewChange: CheckboxProps['onChange'] = (e) => {
const value = e.target.checked const value = e.target.checked
@ -35,6 +38,8 @@ const LaTeXInput = ({name}:{name:string}) => {
const [t] = useTranslation() const [t] = useTranslation()
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
const [Latex, setLatex] = useState<string>("") const [Latex, setLatex] = useState<string>("")
@ -43,9 +48,19 @@ const LaTeXInput = ({name}:{name:string}) => {
}; };
const handelEditModal = (item:any)=>{
console.log(item);
setLatex(item)
setIsEditModalOpen(true)
}
return ( return (
<div className='LaTeXInput'> <div className='LaTeXInput'>
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
<div className='LaTeXInputArea'> <div className='LaTeXInputArea'>
<TextArea <TextArea
size="large" size="large"
@ -54,19 +69,24 @@ const LaTeXInput = ({name}:{name:string}) => {
autoSize={{ minRows: 6, maxRows: 10 }} autoSize={{ minRows: 6, maxRows: 10 }}
style={{height:"400px"}} style={{height:"400px"}}
onChange={handleChangeInput} onChange={handleChangeInput}
value={values?.[name]} value={value}
{...props}
/> />
{ShowLatexOption &&
<div className='LaTeXInputOptions'> <div className='LaTeXInputOptions'>
<Checkbox onChange={onPreviewChange}>{t("header.show_preview")}</Checkbox> <Checkbox onChange={onPreviewChange}>{t("header.show_preview")}</Checkbox>
<button className='addMML' onClick={showModal}> <FaPlus/> {t("MML")} </button> <button type='button' className='addMML' onClick={showModal}> <FaPlus/> {t("MML")} </button>
</div> </div>
}
{showPreview && {showPreview &&
<div className='showPreviewInput'> <div className='showPreviewInput'>
{Preview?.map((item:any,index:number)=>{ {Preview?.map((item:any,index:number)=>{
if(item?.isLatex){ if(item?.isLatex){
return <div key={index} className='LatexPreview'> <LatexPreview Latex={item?.text} /> </div> return <div key={index} onClick={()=>handelEditModal(item)} className='LatexPreview'> <LatexPreview Latex={item?.text} /> </div>
} }
return <div key={index}> return <div key={index}>
{item?.text} {item?.text}
@ -77,9 +97,11 @@ const LaTeXInput = ({name}:{name:string}) => {
</div> </div>
<LaTexModal name={name} Latex={Latex} isModalOpen={isModalOpen} setIsModalOpen={setIsModalOpen} setLatex={setLatex} /> <Suspense fallback={<SpinContainer/>}>
<AddLazyModal name={name} Latex={Latex} isModalOpen={isModalOpen} setIsModalOpen={setIsModalOpen} setLatex={setLatex} />
<EditLazyModal name={name} Latex={Latex} isModalOpen={isEditModalOpen} setIsModalOpen={setIsEditModalOpen} setLatex={setLatex} />
</Suspense>
</div> </div>
) )

View File

@ -38,7 +38,8 @@ const TextField = ({
/> />
<ValidationFieldContainer isError={isError} errorMsg={errorMsg}> <ValidationFieldContainer isError={isError} errorMsg={errorMsg}>
<TextArea <Field
as={TextArea}
placeholder={t(`input.${placeholder ? placeholder : name}`)} placeholder={t(`input.${placeholder ? placeholder : name}`)}
name={name} name={name}
disabled={isDisabled} disabled={isDisabled}

View File

@ -7,11 +7,12 @@ import { Checkbox, CheckboxProps, Popconfirm, Popover } from "antd";
import { CombinationKeyEnum } from "../../enums/CombinationKeyEnum"; import { CombinationKeyEnum } from "../../enums/CombinationKeyEnum";
import { PopconfirmProps } from "antd/lib"; import { PopconfirmProps } from "antd/lib";
import { SettingFilled } from "@ant-design/icons"; import { SettingFilled } from "@ant-design/icons";
import { LocalStorageEnum } from "../../enums/LocalStorageEnum";
const Header = () => { const Header = () => {
const [t] = useTranslation(); const [t] = useTranslation();
const { values, setValues } = useFormikContext<any>(); const { values, setValues } = useFormikContext<any>();
const { isBseQuestion, setIsBseQuestion,ShowHint,setShowHint } = useObjectToEdit(); const { isBseQuestion, setIsBseQuestion,ShowHint,setShowHint,ShowLatexOption,setShowLatexOption } = useObjectToEdit();
// const [Setting, setSetting] = useState(false) // const [Setting, setSetting] = useState(false)
const isEdited = ()=>{ const isEdited = ()=>{
@ -73,24 +74,32 @@ const Header = () => {
); );
const handleOpenChange = (newOpen: boolean) => { const onChangeHint: CheckboxProps['onChange'] = (e) => {
// setSetting(newOpen);
};
const onChange: CheckboxProps['onChange'] = (e) => {
setShowHint(e.target.checked); setShowHint(e.target.checked);
localStorage?.setItem(LocalStorageEnum.HINT_INPUT,e.target.checked ? "true" : "false" )
};
const onChangeLatexOption: CheckboxProps['onChange'] = (e) => {
setShowLatexOption(e.target.checked);
localStorage?.setItem(LocalStorageEnum.LATEX_OPTION_INPUT,e.target.checked ? "true" : "false" )
}; };
const contentSetting = ( const contentSetting = (
<div> <div>
<Checkbox checked={ShowHint} onChange={onChange}> <Checkbox checked={ShowHint} onChange={onChangeHint}>
{ t("header.show_hint")} { t("header.show_hint")}
</Checkbox> </Checkbox>
<Checkbox checked={ShowLatexOption} onChange={onChangeLatexOption}>
{ t("header.show_MMl")}
</Checkbox>
</div> </div>
); );
return ( return (
<header className="exercise_add_header mb-4"> <header className="exercise_add_header mb-4">
<article> <article>
@ -105,7 +114,7 @@ const Header = () => {
<div> <div>
<div className="question_header_setting"> <div className="question_header_setting">
<Popover onOpenChange={handleOpenChange} trigger="click" content={contentSetting}> <Popover trigger="click" content={contentSetting}>
<SettingFilled/> <SettingFilled/>
</Popover> </Popover>

View File

@ -53,6 +53,7 @@ export const useColumns = () => {
key: "name", key: "name",
align: "center", align: "center",
render: (_text, record) => record?.name, render: (_text, record) => record?.name,
ellipsis:true
}, },
{ {
title: t("columns.image"), title: t("columns.image"),

View File

@ -34,6 +34,7 @@ export const useColumns = () => {
dataIndex: "name", dataIndex: "name",
key: "name", key: "name",
align: "center", align: "center",
ellipsis:true
}, },
{ {

View File

@ -66,6 +66,7 @@ export const useColumns = () => {
key: "name", key: "name",
align: "center", align: "center",
render: (text) => text, render: (text) => text,
ellipsis:true
}, },
{ {

View File

@ -61,6 +61,7 @@ export const useColumns = () => {
key: "name", key: "name",
align: "center", align: "center",
render: (text, record) => record?.name, render: (text, record) => record?.name,
ellipsis:true
}, },
{ {
// canAddLesson ? ( // canAddLesson ? (

View File

@ -32,7 +32,7 @@ const AddPage: React.FC = () => {
const [t] = useTranslation(); const [t] = useTranslation();
const { subject_id, lesson_id } = useParams<ParamsEnum>(); const { subject_id, lesson_id } = useParams<ParamsEnum>();
const handleSubmit = ( values: any) => { const handleFormSubmit = ( values: any) => {
const DataToSend = structuredClone(values); const DataToSend = structuredClone(values);
setTagsSearch(null); setTagsSearch(null);
@ -99,14 +99,14 @@ const AddPage: React.FC = () => {
mutate(NewQuestion); mutate(NewQuestion);
} }
}; };
const handleValidateSingleQuestion = (values:any)=>{
const handleValidateSingleQuestion = (values:any,isValid:boolean,handleSubmit:any)=>{
const haveMoreThanOneAnswer = values?.answers?.length > 1; const haveMoreThanOneAnswer = values?.answers?.length > 1;
const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item:any)=> item?.isCorrect === 1 || item.isCorrect === true ) const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item:any)=> item?.isCorrect === 1 || item.isCorrect === true )
const haveImageOrContent = haveOneAnswerRight && values?.answers?.some((item:any)=> !(item?.content) && !(item.content_image) ) const haveImageOrContent = haveOneAnswerRight && values?.answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
const content = values.content ; const content = values.content ;
const content_image = values.content_image ; const content_image = values.content_image ;
const haveContentOrContentImage = !!content || !!content_image ; const haveContentOrContentImage = !!content || !!content_image ;
console.log(haveImageOrContent,"haveImageOrContent"); console.log(haveImageOrContent,"haveImageOrContent");
if(!haveContentOrContentImage){ if(!haveContentOrContentImage){
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`); toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
@ -122,22 +122,30 @@ const AddPage: React.FC = () => {
return false ; return false ;
} }
if(haveImageOrContent){ if(haveImageOrContent){
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer_in_answer")) toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
return false return false
} }
console.log(1);
if(isValid){
handleSubmit(values)
} }
const handleValidateBaseQuestion = (values: any) => {
}
const handleValidateBaseQuestion = (values: any,isValid:boolean,handleSubmit:any) => {
const content = values.content ; const content = values.content ;
const content_image = values.content_image ; const content_image = values.content_image ;
const haveContentOrContentImage = !!content || !!content_image ; const haveContentOrContentImage = !!content || !!content_image ;
console.log(2);
if(!haveContentOrContentImage){ if(!haveContentOrContentImage){
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`); toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
return false; return false;
} }
console.log(1);
values?.Questions?.every((Question: any, QuestionsIndex: number) => { const isValidate = values?.Questions?.every((Question: any, QuestionsIndex: number) => {
const content = Question.content ; const content = Question.content ;
@ -179,9 +187,15 @@ const AddPage: React.FC = () => {
return false return false
} }
return true; return true
}); });
console.log(1);
if(isValid && isValidate){
console.log(2);
handleSubmit(values)
}
}; };
@ -212,12 +226,13 @@ const AddPage: React.FC = () => {
<div className="exercise_add"> <div className="exercise_add">
<Formik <Formik
onSubmit={handleSubmit} onSubmit={handleFormSubmit}
initialValues={getInitialValuesBase({} as any)} initialValues={getInitialValuesBase({} as any)}
validationSchema={getValidationSchemaBase} validationSchema={getValidationSchemaBase}
enableReinitialize enableReinitialize
> >
{({ values,handleSubmit }) => ( {({ values,isValid,handleSubmit }) => (
<Form className="w-100"> <Form className="w-100">
<main className="w-100 exercise_add_main"> <main className="w-100 exercise_add_main">
@ -226,9 +241,9 @@ const AddPage: React.FC = () => {
<div className="exercise_add_buttons"> <div className="exercise_add_buttons">
<div onClick={handleCancel}>{t("practical.back")}</div> <div onClick={handleCancel}>{t("practical.back")}</div>
<button disabled={Loading} className="relative" type="submit" <button disabled={Loading} className="relative" type="button"
onClick={()=>{handleValidateBaseQuestion(values) ;handleSubmit(values)}} onClick={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit) }}
onSubmit={()=>{handleValidateBaseQuestion(values) ;handleSubmit(values) }} onSubmit={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit) }}
> >
{t("practical.add")} {t("practical.add")}
@ -261,11 +276,12 @@ const AddPage: React.FC = () => {
enableReinitialize={true} enableReinitialize={true}
initialValues={getInitialValues({} as any)} initialValues={getInitialValues({} as any)}
validationSchema={getValidationSchema} validationSchema={getValidationSchema}
validateOnMount={true}
onSubmit={(values) => { onSubmit={(values) => {
handleSubmit(values); handleFormSubmit(values);
}} }}
> >
{({ values,handleSubmit }) => ( {({ values,isValid ,handleSubmit}) => (
<Form className="w-100"> <Form className="w-100">
<main className="w-100 exercise_add_main"> <main className="w-100 exercise_add_main">
<Header /> <Header />
@ -273,12 +289,9 @@ const AddPage: React.FC = () => {
<div className="exercise_add_buttons"> <div className="exercise_add_buttons">
<div onClick={handleCancel}>{t("practical.back")}</div> <div onClick={handleCancel}>{t("practical.back")}</div>
<button <div
disabled={Loading}
className="relative" className="relative"
onClick={()=>{handleValidateSingleQuestion(values) ;handleSubmit(values)}} onClick={()=>{ Loading ? ()=>{} : handleValidateSingleQuestion(values,isValid,handleSubmit) }}
onSubmit={()=>{handleValidateSingleQuestion(values) ;handleSubmit(values) }}
type="submit"
> >
{t("practical.add")} {t("practical.add")}
@ -287,7 +300,7 @@ const AddPage: React.FC = () => {
<Spin /> <Spin />
</span> </span>
)} )}
</button> </div>
</div> </div>
</main> </main>
</Form> </Form>

View File

@ -28,10 +28,11 @@ import { Form, Formik } from "formik";
import { MdOutlineArrowForwardIos } from "react-icons/md"; import { MdOutlineArrowForwardIos } from "react-icons/md";
import { SettingFilled } from "@ant-design/icons"; import { SettingFilled } from "@ant-design/icons";
import { CheckboxProps } from "antd/lib"; import { CheckboxProps } from "antd/lib";
import { LocalStorageEnum } from "../../../enums/LocalStorageEnum";
const EditPage: React.FC = () => { const EditPage: React.FC = () => {
const { subject_id, lesson_id, question_id } = useParams<ParamsEnum>(); const { subject_id, lesson_id, question_id } = useParams<ParamsEnum>();
const { isBseQuestion, setIsBseQuestion, setTagsSearch, DeletedQuestions , ShowHint,setShowHint } = const { isBseQuestion, setIsBseQuestion, setTagsSearch, DeletedQuestions , ShowHint,setShowHint , ShowLatexOption,setShowLatexOption } =
useObjectToEdit(); useObjectToEdit();
const { mutate, isSuccess, isLoading } = useUpdateQuestion(); const { mutate, isSuccess, isLoading } = useUpdateQuestion();
@ -45,7 +46,7 @@ const EditPage: React.FC = () => {
const { data: Questions, isLoading: QuestionsDataLoading } = const { data: Questions, isLoading: QuestionsDataLoading } =
useGetAllQuestion({ useGetAllQuestion({
parent_id: question_id, parent_id: question_id,
paginate:false isPaginated:false
}); });
const objectToEdit = { ...data?.data, Questions: Questions?.data }; const objectToEdit = { ...data?.data, Questions: Questions?.data };
@ -190,20 +191,19 @@ const EditPage: React.FC = () => {
navigate(-1); navigate(-1);
}; };
const handleValidateSingleQuestion = (values:any,isValid:boolean,handleSubmit:any)=>{
const handleValidateSingleQuestion = (values:any)=>{
const haveMoreThanOneAnswer = values?.answers?.length > 1; const haveMoreThanOneAnswer = values?.answers?.length > 1;
const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item:any)=> item?.isCorrect === 1 || item.isCorrect === true ) const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item:any)=> item?.isCorrect === 1 || item.isCorrect === true )
const haveImageOrContent = haveOneAnswerRight && values?.answers?.some((item:any)=> !(item?.content) && !(item.content_image) ) const haveImageOrContent = haveOneAnswerRight && values?.answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
const content = values.content ; const content = values.content ;
const content_image = values.content_image ; const content_image = values.content_image ;
const haveContentOrContentImage = !!content || !!content_image ; const haveContentOrContentImage = !!content || !!content_image ;
console.log(haveImageOrContent,"haveImageOrContent"); console.log(haveImageOrContent,"haveImageOrContent");
if(!haveContentOrContentImage){ if(!haveContentOrContentImage){
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`); toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
return false; return false;
} }
if(!haveMoreThanOneAnswer){ if(!haveMoreThanOneAnswer){
toast.error(t("validation.it_should_have_more_than_one_answers")) ; toast.error(t("validation.it_should_have_more_than_one_answers")) ;
return false ; return false ;
@ -217,10 +217,26 @@ const EditPage: React.FC = () => {
return false return false
} }
console.log(1);
if(isValid){
handleSubmit(values)
} }
const handleValidateBaseQuestion = (values: any) => { }
const haveAnswers = values?.Questions?.every((Question: any, QuestionsIndex: number) => { const handleValidateBaseQuestion = (values: any,isValid:boolean,handleSubmit:any) => {
const content = values.content ;
const content_image = values.content_image ;
const haveContentOrContentImage = !!content || !!content_image ;
console.log(2);
if(!haveContentOrContentImage){
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
return false;
}
console.log(1);
const isValidate = values?.Questions?.every((Question: any, QuestionsIndex: number) => {
const content = Question.content ; const content = Question.content ;
@ -236,10 +252,12 @@ const handleValidateBaseQuestion = (values: any) => {
const answers = Question?.answers; const answers = Question?.answers;
const haveAnswers = answers?.length > 0; const haveAnswers = answers?.length > 0;
const haveMoreThanOneAnswer = haveAnswers && answers?.length > 1; const haveMoreThanOneAnswer = haveAnswers && answers?.length > 1;
const haveOneAnswerRight = const haveOneAnswerRight = haveMoreThanOneAnswer && answers?.some((item: any) => item?.isCorrect === 1 || item.isCorrect === true);
haveMoreThanOneAnswer && answers?.some((item: any) => item?.isCorrect === 1 || item.isCorrect === true);
const haveImageOrContent = haveOneAnswerRight && answers?.some((item:any)=> !(item?.content) && !(item.content_image) ) const haveImageOrContent = haveOneAnswerRight && answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
if (!haveAnswers) { if (!haveAnswers) {
toast.error(t("validation.it_should_have_more_than_one_answers")); toast.error(t("validation.it_should_have_more_than_one_answers"));
return false; return false;
@ -260,13 +278,17 @@ const handleValidateBaseQuestion = (values: any) => {
return false return false
} }
return true
return true;
}); });
console.log(haveAnswers, "haveAnswers"); console.log(1);
};
if(isValid && isValidate){
console.log(2);
handleSubmit(values)
}
};
const handleNavigateToPage = () => { const handleNavigateToPage = () => {
const cleanedUrl = location.pathname.replace(/\/Question\/\d+$/, ""); const cleanedUrl = location.pathname.replace(/\/Question\/\d+$/, "");
@ -280,17 +302,29 @@ const handleNavigateToPage = () => {
} }
}, [isSuccess]); }, [isSuccess]);
const onChange: CheckboxProps['onChange'] = (e) => { const onChangeHint: CheckboxProps['onChange'] = (e) => {
setShowHint(e.target.checked); setShowHint(e.target.checked);
localStorage?.setItem(LocalStorageEnum.HINT_INPUT,e.target.checked ? "true" : "false" )
}; };
const onChangeLatexOption: CheckboxProps['onChange'] = (e) => {
setShowLatexOption(e.target.checked);
localStorage?.setItem(LocalStorageEnum.LATEX_OPTION_INPUT,e.target.checked ? "true" : "false" )
};
const contentSetting = ( const contentSetting = (
<div> <div>
<Checkbox checked={ShowHint} onChange={onChange}> <Checkbox checked={ShowHint} onChange={onChangeHint}>
{ t("header.show_hint")} { t("header.show_hint")}
</Checkbox> </Checkbox>
<Checkbox checked={ShowLatexOption} onChange={onChangeLatexOption}>
{ t("header.show_MMl")}
</Checkbox>
</div> </div>
); );
@ -317,7 +351,7 @@ const handleNavigateToPage = () => {
validationSchema={getValidationSchemaBase} validationSchema={getValidationSchemaBase}
enableReinitialize enableReinitialize
> >
{({ values,handleSubmit }) => ( {({ values,isValid,handleSubmit }) => (
<Form className="w-100"> <Form className="w-100">
<main className="w-100 exercise_add_main"> <main className="w-100 exercise_add_main">
@ -337,9 +371,9 @@ const handleNavigateToPage = () => {
<BaseForm /> <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>
<button disabled={Loading} className="relative" type="submit" <button disabled={Loading} className="relative" type="button"
onClick={()=>{handleValidateBaseQuestion(values) ;handleSubmit(values)}} onClick={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit) }}
onSubmit={()=>{handleValidateBaseQuestion(values) ;handleSubmit(values) }} onSubmit={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit) }}
> {t("practical.edit")} > {t("practical.edit")}
{Loading && ( {Loading && (
@ -376,7 +410,7 @@ const handleNavigateToPage = () => {
handleSubmit(values); handleSubmit(values);
}} }}
> >
{({ values,handleSubmit , dirty }) => ( {({ values , dirty,isValid,handleSubmit }) => (
<Form className="w-100"> <Form className="w-100">
<main className="w-100 exercise_add_main"> <main className="w-100 exercise_add_main">
{/* <Header/> */} {/* <Header/> */}
@ -384,25 +418,28 @@ const handleNavigateToPage = () => {
<div> <div>
{t("practical.edit")} {t("models.exercise")}{" "} {t("practical.edit")} {t("models.exercise")}{" "}
</div> </div>
<div className="SettingEdit">
<Popover trigger="click" content={contentSetting}>
<SettingFilled/>
</Popover>
<div>{t("header.exercise")}</div> <div>{t("header.exercise")}</div>
</div>
</header> </header>
<ModelForm /> <ModelForm />
<div className="exercise_add_buttons"> <div className="exercise_add_buttons">
<div onClick={handleCancel}>{t("practical.back")}</div> <div onClick={handleCancel}>{t("practical.back")}</div>
<button <div
disabled={Loading || !dirty}
className="relative" className="relative"
onClick={()=>{handleValidateSingleQuestion(values) ;handleSubmit(values)}} onClick={()=>{ Loading ? ()=>{} : handleValidateSingleQuestion(values,isValid,handleSubmit) }}
onSubmit={()=>{handleValidateSingleQuestion(values) ;handleSubmit(values) }}
type="submit"
> {t("practical.edit")} > {t("practical.edit")}
{Loading && ( {Loading && (
<span className="Spinier_Div"> <span className="Spinier_Div">
<Spin /> <Spin />
</span> </span>
)} )}
</button> </div>
</div> </div>
</main> </main>

View File

@ -10,6 +10,7 @@ import ImageBoxField from "../../../../../Components/CustomFields/ImageBoxField/
import { GoTrash } from "react-icons/go"; import { GoTrash } from "react-icons/go";
import { Popconfirm } from "antd"; import { Popconfirm } from "antd";
import { useObjectToEdit } from "../../../../../zustand/ObjectToEditState"; import { useObjectToEdit } from "../../../../../zustand/ObjectToEditState";
import LaTeXInput from "../../../../../Components/LatextInput/LaTeXInput";
const ChoiceFields = ({ index }: { index: number; data: Choice }) => { const ChoiceFields = ({ index }: { index: number; data: Choice }) => {
const formik = useFormikContext<any>(); const formik = useFormikContext<any>();
@ -43,20 +44,7 @@ const ChoiceFields = ({ index }: { index: number; data: Choice }) => {
return ( return (
<> <>
<div id={`ChoiceField_${index}`} className="ChoiceFields"> <div id={`ChoiceField_${index}`} className="ChoiceFields">
<TextField <LaTeXInput id={`choice_${index + 1}`} name={`answers.${index}.content`} label={t(`input.choice`) + ` ` +`( ${index + 1} )`}/>
className="textarea_exercise"
placeholder={"choice"}
label2={
t(`input.choice`) +
` ` +
`( ${t(`alphabet.${getCharFromNumber(index)}`)} )`
}
name={index}
id={`choice_${index + 1}`}
type="TextArea"
/>
<ImageBoxField name={`answers.${index}.content_image`} /> <ImageBoxField name={`answers.${index}.content_image`} />
<div className="answer_status"> <div className="answer_status">

View File

@ -16,7 +16,7 @@ const CheckboxField = ({
const [t] = useTranslation(); const [t] = useTranslation();
const CheckboxhandleChange = (value: any) => { const CheckboxhandleChange = (value: any) => {
const allAreZero = formik?.values?.Questions?.[parent_index]?.answers?.some( const allAreZero = formik?.values?.Questions?.[parent_index]?.answers?.some(
(item: any) => item.isCorrect === 1, (item: any) => item.isCorrect === 1 || item.isCorrect === true,
); );
if (allAreZero) { if (allAreZero) {
formik?.values?.Questions?.[parent_index]?.answers.forEach( formik?.values?.Questions?.[parent_index]?.answers.forEach(

View File

@ -11,6 +11,7 @@ import ImageBoxField from "../../../../../../Components/CustomFields/ImageBoxFie
import { GoTrash } from "react-icons/go"; import { GoTrash } from "react-icons/go";
import { Popconfirm } from "antd"; import { Popconfirm } from "antd";
import { useObjectToEdit } from "../../../../../../zustand/ObjectToEditState"; import { useObjectToEdit } from "../../../../../../zustand/ObjectToEditState";
import LaTeXInput from "../../../../../../Components/LatextInput/LaTeXInput";
const ChoiceFields = ({ const ChoiceFields = ({
index, index,
@ -53,7 +54,7 @@ const ChoiceFields = ({
return ( return (
<> <>
<div id={`ChoiceField_${parent_index}_${index}`} className="ChoiceFields"> <div id={`ChoiceField_${parent_index}_${index}`} className="ChoiceFields">
<TextField {/* <TextField
className="textarea_exercise" className="textarea_exercise"
placeholder={"choice"} placeholder={"choice"}
label2={ label2={
@ -64,8 +65,12 @@ const ChoiceFields = ({
name={index} name={index}
parent_index={parent_index} parent_index={parent_index}
type="TextArea" type="TextArea"
/> /> */}
<LaTeXInput name={`Questions[${parent_index}].answers[${index}].content`} label={
t(`input.choice`) +
` ` +
`( ${index + 1} )`
}/>
<ImageBoxField <ImageBoxField
name={`Questions.${parent_index}.answers.${index}.content_image`} name={`Questions.${parent_index}.answers.${index}.content_image`}
/> />

View File

@ -13,6 +13,7 @@ import MaltySelectTag from "./Tags/MaltySelectTag";
import useKeyCombination from "../../../../../Hooks/useKeyCombination"; import useKeyCombination from "../../../../../Hooks/useKeyCombination";
import { CombinationKeyEnum } from "../../../../../enums/CombinationKeyEnum"; import { CombinationKeyEnum } from "../../../../../enums/CombinationKeyEnum";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import LaTeXInput from "../../../../../Components/LatextInput/LaTeXInput";
const Form = () => { const Form = () => {
const formik = useFormikContext<any>(); const formik = useFormikContext<any>();
@ -101,12 +102,7 @@ const Form = () => {
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 <LaTeXInput name={"content"} label={t("input.main_question")}/>
className="textarea_exercise"
name="content"
label="main_question"
type="TextArea"
/>
<ImageBoxField name="content_image" /> <ImageBoxField name="content_image" />
<div></div> <div></div>

View File

@ -8,6 +8,7 @@ import { useObjectToEdit } from "../../../../../../zustand/ObjectToEditState";
import ImageBoxField from "../../../../../../Components/CustomFields/ImageBoxField/ImageBoxField"; import ImageBoxField from "../../../../../../Components/CustomFields/ImageBoxField/ImageBoxField";
import { GoTrash } from "react-icons/go"; import { GoTrash } from "react-icons/go";
import { Popconfirm } from "antd"; import { Popconfirm } from "antd";
import LaTeXInput from "../../../../../../Components/LatextInput/LaTeXInput";
const QuestionFIeld = ({ index, data }: { index: number; data: Choice }) => { const QuestionFIeld = ({ index, data }: { index: number; data: Choice }) => {
const formik = useFormikContext<any>(); const formik = useFormikContext<any>();
@ -48,19 +49,11 @@ const QuestionFIeld = ({ index, data }: { index: number; data: Choice }) => {
<> <>
<div className="exercise_forms"> <div className="exercise_forms">
<div className="ChoiceFields"> <div className="ChoiceFields">
<TextField <LaTeXInput id={`question_${index + 1}`} name={`Questions[${index}].content`} label={
className="textarea_exercise"
placeholder={"question"}
label2={
t(`input.question`) + t(`input.question`) +
` ` + ` ` +
`( ${t(`alphabet.${getCharFromNumber(index)}`)} )` `( ${index + 1} )`
} }/>
name={index}
id={`question_${index + 1}`}
type="TextArea"
/>
<ImageBoxField name={`Questions.${index}.content_image`} /> <ImageBoxField name={`Questions.${index}.content_image`} />
{handelCanDeleteAnswers() ? {handelCanDeleteAnswers() ?

View File

@ -11,6 +11,7 @@ import SelectTag from "../../../../Components/CustomFields/SelectTag";
import useKeyCombination from "../../../../Hooks/useKeyCombination"; import useKeyCombination from "../../../../Hooks/useKeyCombination";
import { CombinationKeyEnum } from "../../../../enums/CombinationKeyEnum"; import { CombinationKeyEnum } from "../../../../enums/CombinationKeyEnum";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import LaTeXInput from "../../../../Components/LatextInput/LaTeXInput";
const Form = () => { const Form = () => {
const [t] = useTranslation(); const [t] = useTranslation();
@ -50,14 +51,8 @@ const Form = () => {
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="content"
label="answer_content"
type="TextArea"
/>
<LaTeXInput name={"content"} label={t("input.answer_content")}/>
<ImageBoxField name="content_image" /> <ImageBoxField name="content_image" />
</div> </div>

View File

@ -47,6 +47,8 @@ export const getValidationSchema = () => {
"content-or-image-required", "content-or-image-required",
"At least one of content or content_image must be provided", "At least one of content or content_image must be provided",
(obj:any) => { (obj:any) => {
console.log(obj);
const isValid = !!obj.content || !!obj.content_image; const isValid = !!obj.content || !!obj.content_image;
console.log(isValid,"isValid"); console.log(isValid,"isValid");
@ -80,10 +82,11 @@ export const getInitialValuesBase = (objectToEdit: Question): any => {
}); });
const questions = newQuestions ?? [{answers:[]}]; const questions = newQuestions ?? [{answers:[]}];
console.log(objectToEdit,"objectToEdit");
return { return {
id: objectToEdit?.id ?? null, id: objectToEdit?.id ?? null,
content: objectToEdit?.content ?? "", content: objectToEdit?.content ?? null,
content_image: objectToEdit?.content_image ?? "", content_image: objectToEdit?.content_image ?? "",
subject_id: objectToEdit?.subject_id ?? "", subject_id: objectToEdit?.subject_id ?? "",
isBase: 1, isBase: 1,

View File

@ -25,7 +25,6 @@ const TableWithHeader = () => {
const deleteMutation = useDeleteSubject(); const deleteMutation = useDeleteSubject();
const { grade_id } = useParams<ParamsEnum>(); const { grade_id } = useParams<ParamsEnum>();
console.log(grade_id);
const { data: grade } = useGetAllGrade({ const { data: grade } = useGetAllGrade({
show: grade_id, show: grade_id,

View File

@ -49,6 +49,7 @@ export const useColumns = () => {
dataIndex: "name", dataIndex: "name",
key: "name", key: "name",
align: "center", align: "center",
ellipsis:true
}, },
{ {
title: t("columns.icon"), title: t("columns.icon"),

View File

@ -1,31 +1,11 @@
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import useFilter from "../../Components/FilterField/components/useFilter";
import { Select } from "antd";
import { Form, Formik } from "formik";
import LaTeXInput from "../../Components/LatextInput/LaTeXInput";
const Dummy = () => { const Dummy = () => {
const [t] = useTranslation(); const [t] = useTranslation();
// const { FilterButton, FilterBody } = useFilter();
return ( return (
<div className="DummyHomePage"> <div className="DummyHomePage">
{/* <FilterButton/>
<FilterBody>
karim
</FilterBody>
<Select
style={{width:"200px"}}
showSearch
/>
*/}
<Formik initialValues={{name:""}} onSubmit={()=>{}}>
<Form>
<LaTeXInput name={"name"}/>
</Form>
</Formik>
</div> </div>
); );

View File

@ -176,7 +176,7 @@
.answer_status { .answer_status {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between;
padding-block: 30px; padding-block: 30px;
align-items: flex-end; align-items: flex-end;
} }

View File

@ -3,8 +3,12 @@
} }
.LaTeXInputArea{ .LaTeXInputArea{
width: 600px;
width: 50vw;
position: relative; position: relative;
margin-bottom: 10px;
} }
.showPreviewInput{ .showPreviewInput{
background-color: var(--bg); background-color: var(--bg);
@ -60,3 +64,11 @@
display: flex; display: flex;
padding: 10px; padding: 10px;
} }
.text{
margin-bottom: 7px !important;
font-weight: bold;
font-size: 19px;
> span {
color: transparent;
}
}

View File

@ -3,4 +3,6 @@ export enum LocalStorageEnum {
LANGUAGE_KEY = LocalStorageEnum.PROJECT_NAME + "_LANGUAGE", LANGUAGE_KEY = LocalStorageEnum.PROJECT_NAME + "_LANGUAGE",
TOKEN_KEY = LocalStorageEnum.PROJECT_NAME + "_TOKEN_KEY", TOKEN_KEY = LocalStorageEnum.PROJECT_NAME + "_TOKEN_KEY",
USER_KEY = LocalStorageEnum.PROJECT_NAME + "_USER_KEY", USER_KEY = LocalStorageEnum.PROJECT_NAME + "_USER_KEY",
HINT_INPUT = LocalStorageEnum.PROJECT_NAME + "HINT_INPUT",
LATEX_OPTION_INPUT = LocalStorageEnum.PROJECT_NAME + "LATEX_OPTION_INPUT",
} }

View File

@ -146,7 +146,8 @@
"show_hint":"عرض الشرح", "show_hint":"عرض الشرح",
"past_your_MMl_text":"ضع نص MMl الخاص بك", "past_your_MMl_text":"ضع نص MMl الخاص بك",
"add_MML":"إضافة MML", "add_MML":"إضافة MML",
"show_preview":"عرض المعاينة" "show_preview":"عرض المعاينة",
"show_MMl":" MML عرض"
}, },
"columns": { "columns": {
"id": "الرقم التعريفي", "id": "الرقم التعريفي",

View File

@ -1,6 +1,7 @@
interface TextLatexPart { interface TextLatexPart {
text: string; text: string;
isLatex: boolean; isLatex: boolean;
key:number
} }
export const parseTextAndLatex = (input: string): TextLatexPart[] => { export const parseTextAndLatex = (input: string): TextLatexPart[] => {
@ -8,13 +9,13 @@ interface TextLatexPart {
const parts = input.split(/(\$\$[^$]+\$\$)/g); const parts = input.split(/(\$\$[^$]+\$\$)/g);
parts.forEach(part => { parts.forEach((part,index) => {
if (part.startsWith('$$') && part.endsWith('$$')) { if (part.startsWith('$$') && part.endsWith('$$')) {
result.push({ text: part.slice(2, -2), isLatex: true }); result.push({ text: part.slice(2, -2), isLatex: true , key:index });
} else if (part.trim()) { } else if (part.trim()) {
result.push({ text: part, isLatex: false }); result.push({ text: part, isLatex: false,key:index });
} }
}); });

View File

@ -1,4 +1,5 @@
import { create } from "zustand"; import { create } from "zustand";
import { LocalStorageEnum } from "../enums/LocalStorageEnum";
interface ModelState { interface ModelState {
objectToEdit: any; objectToEdit: any;
@ -27,6 +28,9 @@ interface ModelState {
ShowHint: any; ShowHint: any;
setShowHint: (data: any) => void; setShowHint: (data: any) => void;
ShowLatexOption: any;
setShowLatexOption: (data: any) => void;
} }
export const useObjectToEdit = create<ModelState>((set) => ({ export const useObjectToEdit = create<ModelState>((set) => ({
@ -52,6 +56,8 @@ export const useObjectToEdit = create<ModelState>((set) => ({
setDeletedQuestions: (data) => set(() => ({ DeletedQuestions: data })), setDeletedQuestions: (data) => set(() => ({ DeletedQuestions: data })),
SavedQuestionData: [], SavedQuestionData: [],
setSavedQuestionData: (data) => set(() => ({ SavedQuestionData: data })), setSavedQuestionData: (data) => set(() => ({ SavedQuestionData: data })),
ShowHint: false, ShowHint: localStorage?.getItem(LocalStorageEnum.HINT_INPUT) === "true",
setShowHint: (data) => set(() => ({ ShowHint: data })), setShowHint: (data) => set(() => ({ ShowHint: data })),
ShowLatexOption: localStorage?.getItem(LocalStorageEnum.LATEX_OPTION_INPUT) === "true" ,
setShowLatexOption: (data) => set(() => ({ ShowLatexOption: data })),
})); }));