Compare commits

..

3 Commits

Author SHA1 Message Date
karimaldeen
6213253337 Merge branch 'main' of https://git.point-dev.net/Karimaldeen/nerd_project_dashboard 2024-08-18 12:06:15 +03:00
karimaldeen
fa8e8a7099 end question 2024-08-18 12:04:44 +03:00
karimaldeen
e020fb69c1 drag 2024-08-17 15:37:08 +03:00
36 changed files with 211 additions and 153 deletions

View File

@ -0,0 +1,51 @@
import React, { useState } from 'react';
const DragAndDropList: React.FC = () => {
const [items, setItems] = useState<string[]>(['Item 1', 'Item 2', 'Item 3', 'Item 4']);
const [draggedItemIndex, setDraggedItemIndex] = useState<number | null>(null);
const handleDragStart = (index: number) => {
setDraggedItemIndex(index);
};
const handleDragOver = (index: number) => {
if (index !== draggedItemIndex && draggedItemIndex !== null) {
const newItems = [...items];
const draggedItem = newItems[draggedItemIndex];
newItems.splice(draggedItemIndex, 1);
newItems.splice(index, 0, draggedItem);
setItems(newItems);
setDraggedItemIndex(index);
}
};
const handleDrop = () => {
setDraggedItemIndex(null);
};
return (
<div>
{items.map((item, index) => (
<div
key={index}
draggable
onDragStart={() => handleDragStart(index)}
onDragOver={() => handleDragOver(index)}
onDrop={handleDrop}
style={{
padding: '8px',
margin: '4px',
border: '1px solid #ccc',
backgroundColor: '#f9f9f9',
cursor: 'move',
userSelect: 'none'
}}
>
{item}
</div>
))}
</div>
);
};
export default DragAndDropList;

View File

@ -10,11 +10,11 @@ const App: React.FC = () => {
const { subject_id } = useParams<ParamsEnum>(); const { subject_id } = useParams<ParamsEnum>();
const response = useGetAllUnit({ subject_id: subject_id, pagination: true }); const response = useGetAllUnit({ subject_id: subject_id, pagination: true });
const { setOldObjectToEdit } = useObjectToEdit(); const { setOldObjectToEdit } = useObjectToEdit();
console.log(response?.data?.data, "response?.data"); // console.log(response?.data?.data, "response?.data");
const data = response?.data?.data; const data = response?.data?.data;
const lastElement = const lastElement =
response?.data?.data && response?.data?.data[data?.length - 1]; response?.data?.data && response?.data?.data[data?.length - 1];
console.log(lastElement); // console.log(lastElement);
useEffect(() => { useEffect(() => {
if (lastElement) { if (lastElement) {

View File

@ -11,11 +11,11 @@ const App: React.FC = () => {
const response = useGetAllLesson({ unit_id: unit_id, pagination: true }); const response = useGetAllLesson({ unit_id: unit_id, pagination: true });
const { setOldObjectToEdit } = useObjectToEdit(); const { setOldObjectToEdit } = useObjectToEdit();
console.log(response?.data?.data, "response?.data"); // console.log(response?.data?.data, "response?.data");
const data = response?.data?.data; const data = response?.data?.data;
const lastElement = const lastElement =
response?.data?.data && response?.data?.data[data?.length - 1]; response?.data?.data && response?.data?.data[data?.length - 1];
console.log(lastElement); // console.log(lastElement);
useEffect(() => { useEffect(() => {
if (lastElement) { if (lastElement) {

View File

@ -104,7 +104,6 @@ const AddPage: React.FC = () => {
const DataToSend = structuredClone(values); const DataToSend = structuredClone(values);
console.log(DataToSend); console.log(DataToSend);
return ;
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) {
@ -126,6 +125,13 @@ const AddPage: React.FC = () => {
Questions?.map((item: Question) => { Questions?.map((item: Question) => {
const tags = processTags(item); const tags = processTags(item);
console.log(item); console.log(item);
const answers = item?.answers?.map((item:any,index:number)=>{
return {
order:index,
...item
}
})
console.log(answers);
mutate({ mutate({
...item, ...item,
@ -133,18 +139,28 @@ const AddPage: React.FC = () => {
subject_id: subject_id, subject_id: subject_id,
tags, tags,
lessons_ids: [lesson_id], lessons_ids: [lesson_id],
answers
}); });
}); });
console.log(newBseQuestionId, "newBseQuestionId"); console.log(newBseQuestionId, "newBseQuestionId");
}); });
} else { } else {
const tags = processTags(DataToSend); const tags = processTags(DataToSend);
console.log(values,"values");
const answers = values?.answers?.map((item:any,index:number)=>{
return {
order:index,
...item
}
})
mutate({ mutate({
...values, ...values,
subject_id: subject_id, subject_id: subject_id,
tags, tags,
lessons_ids: [lesson_id], lessons_ids: [lesson_id],
canAnswersBeShuffled, canAnswersBeShuffled,
answers
}); });
} }
}; };
@ -168,8 +184,8 @@ const AddPage: React.FC = () => {
} }
}, [isSuccess, isSuccessAsync]); }, [isSuccess, isSuccessAsync]);
let cleanedQuestionOptions = cleanObject(SavedQuestionData); let cleanedAnswers = cleanObject(SavedQuestionData);
let noChange = hasItems(cleanedQuestionOptions); let noChange = hasItems(cleanedAnswers);
useSaveOnDisconnect(noChange, QUESTION_OBJECT_KEY, SavedQuestionData); useSaveOnDisconnect(noChange, QUESTION_OBJECT_KEY, SavedQuestionData);

View File

@ -152,25 +152,25 @@ const EditPage: React.FC = () => {
console.log(updatedObject, "updatedObject"); console.log(updatedObject, "updatedObject");
const tags = processTags(updatedObject); const tags = processTags(updatedObject);
const oldQuestionOptions = [] as any; const oldanswers = [] as any;
const newQuestionOptions = [] as any; const newanswers = [] as any;
updatedObject?.QuestionOptions?.forEach((item: any) => { updatedObject?.answers?.forEach((item: any) => {
if (item?.id) { if (item?.id) {
oldQuestionOptions.push(item); oldanswers.push(item);
} else { } else {
newQuestionOptions.push(item); newanswers.push(item);
} }
}); });
const QuestionOptions = { const answers = {
old: oldQuestionOptions, old: oldanswers,
new: newQuestionOptions, new: newanswers,
}; };
console.log(QuestionOptions); console.log(answers);
mutate({ mutate({
...updatedObject, ...updatedObject,
QuestionOptions, answers,
tags, tags,
}); });
} else { } else {
@ -197,26 +197,26 @@ const EditPage: React.FC = () => {
} }
console.log(updatedObject); console.log(updatedObject);
const oldQuestionOptions = [] as any; const oldanswers = [] as any;
const newQuestionOptions = [] as any; const newanswers = [] as any;
updatedObject?.QuestionOptions?.forEach((item: any) => { updatedObject?.answers?.forEach((item: any) => {
if (item?.id) { if (item?.id) {
console.log(item); console.log(item);
oldQuestionOptions.push(item); oldanswers.push(item);
} else { } else {
newQuestionOptions.push(item); newanswers.push(item);
} }
}); });
const QuestionOptions = { const answers = {
old: oldQuestionOptions, old: oldanswers,
new: newQuestionOptions, new: newanswers,
}; };
console.log(QuestionOptions, "QuestionOptions"); console.log(answers, "answers");
mutate({ ...updatedObject, QuestionOptions, tags }); mutate({ ...updatedObject, answers, tags });
} }
}; };

View File

@ -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,7 +35,7 @@ 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}`)}

View File

@ -18,13 +18,13 @@ 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 (

View File

@ -11,8 +11,8 @@ const Choices = () => {
// Check if the item was dropped outside the list // Check if the item was dropped outside the list
if (!result.destination) return; if (!result.destination) return;
// Create a new array from the current QuestionOptions // Create a new array from the current answers
const items = Array.from(formik?.values?.QuestionOptions); const items = Array.from(formik?.values?.answers);
// Remove the item from the original position // Remove the item from the original position
const [reorderedItem] = items.splice(result.source.index, 1); const [reorderedItem] = items.splice(result.source.index, 1);
@ -29,7 +29,7 @@ const Choices = () => {
// Update the formik state with the new order // Update the formik state with the new order
console.log(updatedItems, "updatedItems"); console.log(updatedItems, "updatedItems");
formik.setFieldValue("QuestionOptions", updatedItems); formik.setFieldValue("answers", updatedItems);
}; };
return ( return (
@ -37,7 +37,7 @@ const Choices = () => {
<Droppable droppableId="choices"> <Droppable droppableId="choices">
{(provided) => ( {(provided) => (
<div {...provided.droppableProps} ref={provided.innerRef}> <div {...provided.droppableProps} ref={provided.innerRef}>
{formik?.values?.QuestionOptions?.map( {formik?.values?.answers?.map(
(item: Choice, index: number) => { (item: Choice, index: number) => {
// Use a unique identifier for draggableId // Use a unique identifier for draggableId
const draggableId = item.name const draggableId = item.name

View File

@ -12,10 +12,10 @@ const File = ({
className, className,
props, props,
}: any) => { }: any) => {
const newName = `QuestionOptions[${name}].answer_image`; const newName = `answers[${name}].answer_image`;
const { formik, t, isError, errorMsg } = useFormField(newName, props); const { formik, t, isError, errorMsg } = useFormField(newName, props);
let imageUrl = formik?.values?.QuestionOptions[name]?.answer_image ?? null; let imageUrl = formik?.values?.answers[name]?.answer_image ?? null;
// console.log(imageUrl); // console.log(imageUrl);
const fileList: UploadFile[] = useMemo(() => { const fileList: UploadFile[] = useMemo(() => {
@ -46,7 +46,7 @@ const File = ({
formik.setFieldValue(newName, null); formik.setFieldValue(newName, null);
} else { } else {
formik.setFieldValue( formik.setFieldValue(
`QuestionOptions[${name}].answer_image`, `answers[${name}].answer_image`,
value?.file?.originFileObj, value?.file?.originFileObj,
); );
} }

View File

@ -18,7 +18,7 @@ const HintField = ({
id, id,
className, className,
}: any) => { }: any) => {
const newName = `QuestionOptions[${name}].hint`; const newName = `answers[${name}].hint`;
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>,

View File

@ -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>,

View File

@ -33,9 +33,9 @@ const Form = () => {
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,
@ -54,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: [],
}, },
]); ]);
@ -106,7 +106,7 @@ const Form = () => {
<Choices parent_index={parent_index} /> <Choices parent_index={parent_index} />
{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

View File

@ -19,12 +19,12 @@ const CheckboxField = ({
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}

View File

@ -26,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);
@ -37,12 +37,12 @@ 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 (

View File

@ -14,10 +14,10 @@ const Choices = ({ parent_index }: { parent_index: number }) => {
if (!result.destination) return; if (!result.destination) return;
console.log(formik?.values?.Questions?.[parent_index]?.QuestionOptions); console.log(formik?.values?.Questions?.[parent_index]?.answers);
// Create a new array from the current QuestionOptions // Create a new array from the current answers
const items = Array.from(formik?.values?.Questions?.[parent_index]?.QuestionOptions); const items = Array.from(formik?.values?.Questions?.[parent_index]?.answers);
console.log(items); console.log(items);
// Remove the item from the original position // Remove the item from the original position
const [reorderedItem] = items.splice(result.source.index, 1); const [reorderedItem] = items.splice(result.source.index, 1);
@ -36,7 +36,7 @@ const Choices = ({ parent_index }: { parent_index: number }) => {
// Update the formik state with the new order // Update the formik state with the new order
console.log(updatedItems, "updatedItems"); console.log(updatedItems, "updatedItems");
formik.setFieldValue(`Questions.${parent_index}.QuestionOptions`, updatedItems); formik.setFieldValue(`Questions.${parent_index}.answers`, updatedItems);
}; };
return ( return (
@ -47,7 +47,7 @@ const Choices = ({ parent_index }: { parent_index: number }) => {
<div {...provided.droppableProps} ref={provided.innerRef}> <div {...provided.droppableProps} ref={provided.innerRef}>
{( {(
(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) => {
const draggableId = item.name const draggableId = item.name
? item.name.toString() ? item.name.toString()

View File

@ -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,
); );
} }

View File

@ -16,7 +16,7 @@ const HintField = ({
id, id,
className, className,
}: any) => { }: any) => {
const newName = `Questions[${parent_index}].QuestionOptions[${name}].hint`; const newName = `Questions[${parent_index}].answers[${name}].hint`;
const { formik, isError, errorMsg, t } = useFormField(newName, props); const { formik, isError, errorMsg, t } = useFormField(newName, props);
const TextFilehandleChange = ( const TextFilehandleChange = (

View File

@ -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>,

View File

@ -30,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,
@ -53,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: [],
}, },
]); ]);
@ -103,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
@ -114,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

View File

@ -26,10 +26,10 @@ 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 (

View File

@ -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;

View File

@ -28,10 +28,10 @@ const Form = () => {
}, [formik?.values]); }, [formik?.values]);
const handleAddChoice = () => { const handleAddChoice = () => {
formik.setFieldValue("QuestionOptions", [ formik.setFieldValue("answers", [
...((formik?.values as any)?.QuestionOptions as Choice[]), ...((formik?.values as any)?.answers as Choice[]),
{ {
answer: null, content: null,
answer_image: null, answer_image: null,
isCorrect: 0, isCorrect: 0,
}, },
@ -69,7 +69,7 @@ const Form = () => {
/> />
</div> </div>
<Choices /> <Choices />
{formik?.values?.QuestionOptions?.length < 5 && ( {formik?.values?.answers?.length < 5 && (
<p className="add_new_button"> <p className="add_new_button">
<FaCirclePlus onClick={handleAddChoice} size={23} />{" "} <FaCirclePlus onClick={handleAddChoice} size={23} />{" "}
{t("header.add_new_choice")} {t("header.add_new_choice")}

View File

@ -7,16 +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 ?? 0, 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 ?? [],
}; };
}; };
@ -26,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(),
}), }),
@ -48,7 +50,8 @@ export const getInitialValuesBase = (objectToEdit: Question): any => {
return { return {
...item, ...item,
canAnswersBeShuffled: item?.canAnswersBeShuffled ?? 0, canAnswersBeShuffled: objectToEdit?.canAnswersBeShuffled ? 1 : 0,
hint: item?.hint ?? "",
tags, tags,
}; };
}); });
@ -62,8 +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 ?? 0, canAnswersBeShuffled: objectToEdit?.canAnswersBeShuffled ? 1 : 0,
hint: objectToEdit?.hint ?? "",
Questions: questions, Questions: questions,
}; };
}; };
@ -77,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(),
}), }),

View File

@ -60,12 +60,14 @@ export const useColumns = () => {
record?.isBase ? t("practical.yes") : t("practical.no"), record?.isBase ? t("practical.yes") : t("practical.no"),
}, },
{ {
title: `${t("columns.question_options_count")}`, title: t("columns.canAnswersBeShuffled"),
dataIndex: "name", dataIndex: "canAnswersBeShuffled",
key: "name", key: "canAnswersBeShuffled",
align: "center", align: "center",
render: (text, record) => record?.question_options_count, render: (text, record) =>
record?.canAnswersBeShuffled ? t("practical.yes") : t("practical.no"),
}, },
{ {
title: canAddQuestion ? ( title: canAddQuestion ? (
<button onClick={() => handelAdd()} className="add_button"> <button onClick={() => handelAdd()} className="add_button">

View File

@ -33,6 +33,7 @@ export const menuItems: TMenuItem[] = [
abilities: ABILITIES_ENUM?.PASS, abilities: ABILITIES_ENUM?.PASS,
abilities_value: ABILITIES_VALUES_ENUM.INDEX, abilities_value: ABILITIES_VALUES_ENUM.INDEX,
prevPath: 0, prevPath: 0,
}, },
{ {
header: "page_header.grade", header: "page_header.grade",

View File

@ -1,9 +1,9 @@
export const BaseURL = "http://192.168.1.111:8000/api/"; export const BaseURL = "http://127.0.0.1:8000/api/";
// export const BaseURL = "http://127.0.0.1:8000/api/"; // export const BaseURL = "http://127.0.0.1:8000/api/";
// export const BaseURL = "http://192.168.1.120:8000/api/"; // export const BaseURL = "http://192.168.1.120:8000/api/";
// export const ImageBaseURL = "http://192.168.1.9:8000/"; // export const ImageBaseURL = "http://192.168.1.9:8000/";
export const ImageBaseURL = "http://192.168.1.111:8000/api/"; export const ImageBaseURL = "http://127.0.0.1:8000/api/";
export const HEADER_KEY = "X-Custom-Query-Key"; export const HEADER_KEY = "X-Custom-Query-Key";

5
src/enums/UserType.ts Normal file
View File

@ -0,0 +1,5 @@
export enum UserTypeEnum {
ADMIN = "ADMIN",
RE_SELLER = "RE_SELLER",
}

View File

@ -6,7 +6,7 @@ function QueryProvider({ children }: any) {
defaultOptions: { defaultOptions: {
queries: { queries: {
refetchOnWindowFocus: false, refetchOnWindowFocus: false,
// staleTime:Infinity staleTime:60
}, },
}, },
}); });

View File

@ -155,6 +155,7 @@
"min_mark_to_pass": "علامة النجاح", "min_mark_to_pass": "علامة النجاح",
"isBase": "سؤال رئيسي", "isBase": "سؤال رئيسي",
"question_options_count": "عدد الخيارات", "question_options_count": "عدد الخيارات",
"canAnswersBeShuffled":"يمكن خلط الإجابات",
"price":"السعر", "price":"السعر",
"grade_id":"رقم تعريف الدرجة" "grade_id":"رقم تعريف الدرجة"
}, },

View File

@ -1,6 +1,7 @@
import { ReactElement, LazyExoticComponent, ReactNode } from "react"; import { ReactElement, LazyExoticComponent, ReactNode } from "react";
import { Mark_State, Payment_type, term_type } from "./Item"; import { Mark_State, Payment_type, term_type } from "./Item";
import { ABILITIES_ENUM, ABILITIES_VALUES_ENUM } from "../enums/abilities"; import { ABILITIES_ENUM, ABILITIES_VALUES_ENUM } from "../enums/abilities";
import { UserTypeEnum } from "../enums/UserType";
export type ChildrenType = { export type ChildrenType = {
children: ReactNode; children: ReactNode;
@ -14,6 +15,7 @@ type TMenuItemBase = {
withOutLayout?: boolean; withOutLayout?: boolean;
abilities: ABILITIES_ENUM; abilities: ABILITIES_ENUM;
abilities_value: ABILITIES_VALUES_ENUM; abilities_value: ABILITIES_VALUES_ENUM;
type?:UserTypeEnum
prevPath: number; prevPath: number;
}; };
@ -37,6 +39,7 @@ export type TCrudRoute = {
element: ReactElement | LazyExoticComponent<any>; element: ReactElement | LazyExoticComponent<any>;
abilities: ABILITIES_ENUM; abilities: ABILITIES_ENUM;
abilities_value: ABILITIES_VALUES_ENUM; abilities_value: ABILITIES_VALUES_ENUM;
type?:ABILITIES_ENUM
prevPath: number; prevPath: number;
}; };

View File

@ -312,7 +312,8 @@ export interface Question {
image: string | null; image: string | null;
Questions?: any[]; Questions?: any[];
question_options_count?: any; question_options_count?: any;
QuestionOptions: QuestionOption[]; answers: QuestionOption[];
hint?:string;
tags: tags[]; // Assuming tags are strings, adjust as per actual data type tags: tags[]; // Assuming tags are strings, adjust as per actual data type
} }

5
src/types/UserType.ts Normal file
View File

@ -0,0 +1,5 @@
import { Nullable } from "./App";
// Define the Teacher interface
export type UserType = "admin" | "reSeller"

View File

@ -28,11 +28,14 @@ class AbilityManager {
} }
return new Set(JSON.parse(abilitiesString)); return new Set(JSON.parse(abilitiesString));
} }
public hasAbility( public hasAbility(
category: ABILITIES_ENUM, category: ABILITIES_ENUM,
value: ABILITIES_VALUES_ENUM, value: ABILITIES_VALUES_ENUM,
): boolean { ): boolean {
// Allow all abilities if the category is PASS // Allow all abilities if the category is PASS
return true; return true;
if (category === ABILITIES_ENUM.PASS) { if (category === ABILITIES_ENUM.PASS) {
return true; return true;
@ -44,7 +47,7 @@ class AbilityManager {
} }
// Construct the ability string // Construct the ability string
const abilityString = `${category}::${value}`; const abilityString = `${category}`;
// Check if the constructed ability string exists in the abilities set // Check if the constructed ability string exists in the abilities set
return this.abilities.has(abilityString); return this.abilities.has(abilityString);

View File

@ -15,8 +15,8 @@ export const setLocalStorageBaseQuestions = async (key: string, data: any) => {
} }
} }
} }
if (Array.isArray(data.Questions.QuestionOptions)) { if (Array.isArray(data.Questions.answers)) {
for (const option of data.Questions.QuestionOptions) { for (const option of data.Questions.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);
} }
@ -50,8 +50,8 @@ export const getLocalStorageBaseQuestions = (key: string): any | null => {
} }
} }
} }
if (Array.isArray(data.Questions.QuestionOptions)) { if (Array.isArray(data.Questions.answers)) {
for (const option of data.Questions.QuestionOptions) { for (const option of data.Questions.answers) {
if (typeof option.answer_image === "string") { if (typeof option.answer_image === "string") {
option.answer_image = base64StringToFile(option.answer_image); option.answer_image = base64StringToFile(option.answer_image);
} }

View File

@ -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);
} }
@ -23,9 +23,9 @@ export const setLocalStorageQuestions = async (key: string, data: any) => {
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
@ -73,9 +73,9 @@ export const getLocalStorageQuestions = (key: string): any | null => {
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