add question VariableSizeList

This commit is contained in:
karimaldeen 2024-09-21 14:15:12 +03:00
parent 869e857f2c
commit cda04660bf
5 changed files with 75 additions and 272 deletions

View File

@ -0,0 +1,67 @@
import React, { useCallback } from "react";
import { Choice } from "../../../../../../types/Item";
import QuestionFIeld from "../QuestionFIeld/QuestionFIeld";
import Choices from "../ChoiceField/Choices";
import { FaCirclePlus } from "react-icons/fa6";
import ValidationField from "../../../../../../Components/ValidationField/ValidationField";
import MaltySelectTag from "../Tags/MaltySelectTag";
import { toast } from "react-toastify";
export const Question: React.FC<any> = React.memo(({ index, style, data }) => {
const { values, setFieldValue, ShowHint, t } = data;
const handleAddChoice = useCallback((
parent_index: number,
fromKeyCombination: boolean = false,
) => {
setFieldValue(`Questions.[${parent_index}].answers`, [
...(values?.Questions?.[parent_index]?.answers as Choice[]),
{
answer: null,
content_image: null,
content: null,
isCorrect: 0,
},
]);
if (fromKeyCombination) {
toast.success(t("header.new_choice_have_been_added"));
}
}, [setFieldValue, values, t]);
return (
<div style={style}>
<div className="exercise_form QuestionFIeld">
<QuestionFIeld setFieldValue={setFieldValue} values={values} key={index} index={index} />
</div>
<Choices setFieldValue={setFieldValue} values={values} parent_index={index} />
{values?.Questions?.[index]?.answers?.length < 5 && (
<p className="add_new_button">
<FaCirclePlus
onClick={() => handleAddChoice(index)}
size={23}
/>{" "}
{t("header.add_new_choice")}
</p>
)}
<div className="exercise_form_width">
{ShowHint && (
<ValidationField
className=" "
placeholder="_"
name={`Questions.${index}.hint`}
label="hint_question"
type="TextArea"
style={{ width: "100%", height: 60, resize: "none" }}
autoSize={{ minRows: 2, maxRows: 10 }}
showCount={false}
/>
)}
<MaltySelectTag parent_index={index} />
</div>
</div>
);
});

View File

@ -1,115 +0,0 @@
import React, { useCallback, useMemo } from 'react';
import { FixedSizeList as List, areEqual } from 'react-window';
import { Choice } from '../../../../../../types/Item';
import QuestionFIeld from '../QuestionFIeld/QuestionFIeld';
import Choices from '../ChoiceField/Choices';
import { FaCirclePlus } from 'react-icons/fa6';
import ValidationField from '../../../../../../Components/ValidationField/ValidationField';
import MaltySelectTag from '../Tags/MaltySelectTag';
import { useTranslation } from 'react-i18next';
import { useObjectToEdit } from '../../../../../../zustand/ObjectToEditState';
import { toast } from 'react-toastify';
interface QuestionsProps {
setFieldValue: (field: string, value: any) => void;
values: {
Questions: Choice[];
};
}
const Row: React.FC<any> = React.memo(({ index, data }) => {
const { values, setFieldValue } = data;
const { ShowHint } = useObjectToEdit();
const [t] = useTranslation();
const handleAddChoice = useCallback((
parent_index: number,
fromKeyCombination: boolean = false,
) => {
setFieldValue(`Questions.[${parent_index}].answers`, [
...(values?.Questions?.[parent_index]?.answers as Choice[]),
{
answer: null,
content_image: null,
content: null,
isCorrect: 0,
},
]);
if (fromKeyCombination) {
toast.success(t("header.new_choice_have_been_added"));
}
}, [setFieldValue, values, t]);
return (
<div key={index}>
<div className="exercise_form QuestionFIeld">
<QuestionFIeld setFieldValue={setFieldValue} values={values} key={index} index={index} />
</div>
<Choices setFieldValue={setFieldValue} values={values} parent_index={index} />
{values?.Questions?.[index]?.answers?.length < 5 && (
<p className="add_new_button">
<FaCirclePlus
onClick={() => handleAddChoice(index)}
size={23}
/>{" "}
{t("header.add_new_choice")}
</p>
)}
<div className="exercise_form_width">
{ShowHint && (
<ValidationField
className=" "
placeholder="_"
name={`Questions.${index}.hint`}
label="hint_question"
type="TextArea"
style={{ width: "100%", height: 60, resize: "none" }}
autoSize={{ minRows: 2, maxRows: 10 }}
showCount={false}
/>
)}
<MaltySelectTag parent_index={index} />
</div>
</div>
);
}, areEqual);
const Questions: React.FC<QuestionsProps> = React.memo(({ setFieldValue, values }) => {
const questions = values.Questions || [];
const itemData = useMemo(() => ({ values, setFieldValue }), [values, setFieldValue]);
const itemSize = 1100;
const listHeight = useMemo(() => {
return Math.min(1300, questions.length * itemSize); // Adjust 400 to your desired max height
}, [questions.length]);
return (
<>
<List
height={listHeight}
itemCount={questions.length}
itemSize={itemSize}
width="100%"
itemData={itemData}
direction='rtl'
>
{Row}
</List>
{/* {(values?.Questions || [])?.map(
(item: Choice, parent_index: number) => {
return (
<Row key={parent_index} index={parent_index} data={{values, setFieldValue}} />
);
}
)} */}
</>
);
}, (prevProps, nextProps) => prevProps.values.Questions === nextProps.values.Questions);
export default Questions;

View File

@ -1,85 +0,0 @@
import React from 'react'
import QuestionFIeld from '../QuestionFIeld/QuestionFIeld';
import { Choice } from '../../../../../../types/Item';
import Choices from '../ChoiceField/Choices';
import { FaCirclePlus } from 'react-icons/fa6';
import ValidationField from '../../../../../../Components/ValidationField/ValidationField';
import MaltySelectTag from '../Tags/MaltySelectTag';
import { useObjectToEdit } from '../../../../../../zustand/ObjectToEditState';
import { toast } from 'react-toastify';
import { useTranslation } from 'react-i18next';
// Memoized Questions Component
const Questions = React.memo(({setFieldValue,values}:any) => {
const { ShowHint } = useObjectToEdit();
const [t] = useTranslation();
const handleAddChoice = (
parent_index: number,
fromKeyCombination: boolean = false,
) => {
setFieldValue(`Questions.[${parent_index}].answers`, [
...((values as any)?.Questions?.[parent_index]
?.answers as Choice[]),
{
answer: null,
content_image: null,
content: null,
isCorrect: 0,
},
]);
if (fromKeyCombination) {
toast.success(t("header.new_choice_have_been_added"));
}
};
return (
<>
{(values?.Questions || [])?.map(
(item: Choice, parent_index: number) => {
return (
<div key={parent_index}>
<div className="exercise_form QuestionFIeld">
<QuestionFIeld setFieldValue={setFieldValue} values={values} key={parent_index} index={parent_index} />
</div>
<Choices setFieldValue={setFieldValue} values={values} parent_index={parent_index} />
{values?.Questions?.[parent_index]?.answers?.length < 5 && (
<p className="add_new_button">
<FaCirclePlus
onClick={() => handleAddChoice(parent_index)}
size={23}
/>{" "}
{t("header.add_new_choice")}
</p>
)}
<div className="exercise_form_width">
{ShowHint && (
<ValidationField
className=" "
placeholder="_"
name={`Questions.${parent_index}.hint`}
label="hint_question"
type="TextArea"
style={{ width: "100%", height: 60, resize: "none" }}
autoSize={{ minRows: 2, maxRows: 10 }}
showCount={false}
/>
)}
<MaltySelectTag parent_index={parent_index} />
</div>
</div>
);
}
)}
</>
);
}, (prevProps, nextProps) => {
return prevProps.values.Questions === nextProps.values.Questions;
});
export default Questions;

View File

@ -1,14 +1,8 @@
import React, { useCallback, useMemo, useRef, useEffect } from 'react'; import React, { useCallback, useMemo, useRef, useEffect } from 'react';
import { VariableSizeList as List } from 'react-window'; import { VariableSizeList as List } from 'react-window';
import { Choice } from '../../../../../../types/Item';
import QuestionFIeld from '../QuestionFIeld/QuestionFIeld';
import Choices from '../ChoiceField/Choices';
import { FaCirclePlus } from 'react-icons/fa6';
import ValidationField from '../../../../../../Components/ValidationField/ValidationField';
import MaltySelectTag from '../Tags/MaltySelectTag';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useObjectToEdit } from '../../../../../../zustand/ObjectToEditState'; import { useObjectToEdit } from '../../../../../../zustand/ObjectToEditState';
import { toast } from 'react-toastify'; import { Question } from './Question';
interface QuestionsProps { interface QuestionsProps {
setFieldValue: (field: string, value: any) => void; setFieldValue: (field: string, value: any) => void;
@ -17,67 +11,8 @@ interface QuestionsProps {
}; };
} }
const Row: React.FC<any> = React.memo(({ index, style, data }) => {
const { values, setFieldValue, ShowHint, t } = data;
const handleAddChoice = useCallback((
parent_index: number,
fromKeyCombination: boolean = false,
) => {
setFieldValue(`Questions.[${parent_index}].answers`, [
...(values?.Questions?.[parent_index]?.answers as Choice[]),
{
answer: null,
content_image: null,
content: null,
isCorrect: 0,
},
]);
if (fromKeyCombination) {
toast.success(t("header.new_choice_have_been_added"));
}
}, [setFieldValue, values, t]);
return (
<div style={style}>
<div className="exercise_form QuestionFIeld">
<QuestionFIeld setFieldValue={setFieldValue} values={values} key={index} index={index} />
</div>
<Choices setFieldValue={setFieldValue} values={values} parent_index={index} />
{values?.Questions?.[index]?.answers?.length < 5 && (
<p className="add_new_button">
<FaCirclePlus
onClick={() => handleAddChoice(index)}
size={23}
/>{" "}
{t("header.add_new_choice")}
</p>
)}
<div className="exercise_form_width">
{ShowHint && (
<ValidationField
className=" "
placeholder="_"
name={`Questions.${index}.hint`}
label="hint_question"
type="TextArea"
style={{ width: "100%", height: 60, resize: "none" }}
autoSize={{ minRows: 2, maxRows: 10 }}
showCount={false}
/>
)}
<MaltySelectTag parent_index={index} />
</div>
</div>
);
});
const Questions: React.FC<QuestionsProps> = React.memo(({ setFieldValue, values }) => { const Questions: React.FC<QuestionsProps> = React.memo(({ setFieldValue, values }) => {
const questions = values.Questions || []; const questions = values?.Questions || [];
const { ShowHint } = useObjectToEdit(); const { ShowHint } = useObjectToEdit();
const [t] = useTranslation(); const [t] = useTranslation();
const listRef = useRef<List>(null); const listRef = useRef<List>(null);
@ -111,16 +46,16 @@ const Questions: React.FC<QuestionsProps> = React.memo(({ setFieldValue, values
<List <List
ref={listRef} ref={listRef}
height={window.innerHeight - 20} // Adjust based on your layout height={window.innerHeight - 20} // Adjust based on your layout
itemCount={questions.length} itemCount={questions?.length}
itemSize={getItemSize} itemSize={getItemSize}
width="100%" width="100%"
itemData={itemData} itemData={itemData}
direction='rtl' direction='rtl'
className='ListQuestions' className=' '
> >
{Row} {Question}
</List> </List>
); );
}, (prevProps, nextProps) => prevProps.values.Questions === nextProps.values.Questions); }, (prevProps, nextProps) => prevProps?.values?.Questions === nextProps?.values?.Questions);
export default Questions; export default Questions;

View File

@ -357,5 +357,6 @@
.ListQuestions{ .ListQuestions{
@include Scrollbar() @include Scrollbar();
margin-bottom: 30px;
} }