Compare commits

..

No commits in common. "3407250e9261123958aac2a809637d6886f35d30" and "7506c9850d5910ec06b24d3654513aa1e527f589" have entirely different histories.

15 changed files with 49 additions and 293 deletions

File diff suppressed because one or more lines are too long

View File

@ -3,26 +3,22 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { GoArrowSwitch } from 'react-icons/go';
import { useObjectToEdit } from '../../zustand/ObjectToEditState';
import { QUESTION_OBJECT_KEY } from '../../config/AppKey';
const Header = () => {
const [t] = useTranslation();
const { values, setFieldValue,setValues } = useFormikContext<any>();
const {isBseQuestion,set_isBseQuestion} = useObjectToEdit()
const {set_SavedQuestionData} = useObjectToEdit()
const handleChange = () => {
set_SavedQuestionData(null)
localStorage.removeItem(QUESTION_OBJECT_KEY)
if (isBseQuestion) {
set_isBseQuestion(false)
setValues(null)
setFieldValue("isBase",0)
} else {
set_isBseQuestion(true)
setValues(null)
setFieldValue("isBase",1)
}
};
@ -33,7 +29,7 @@ const Header = () => {
</div>
<div>
<GoArrowSwitch onClick={handleChange} className="m-2" />
{isBseQuestion || values?.isBase === 1 ? t("header.malty_exercise") :t("header.exercise") }
{isBseQuestion ? t("header.malty_exercise") :t("header.exercise") }
</div>
</header>
);

View File

@ -1,32 +1,20 @@
import { useEffect } from 'react';
import { setLocalStorageQuestions } from '../utils/setLocalStorageQuestions';
import { setLocalStorageBaseQuestions } from '../utils/setLocalStorageBaseQuestions';
const useSaveOnDisconnect = (noChange: boolean, QUESTION_OBJECT_KEY: string, SavedQuestionData: any) => {
useEffect(() => {
const handleBeforeUnload = (event: BeforeUnloadEvent) => {
console.log("disconnect");
if (noChange) {
if(SavedQuestionData?.isBase ===1){
setLocalStorageQuestions(QUESTION_OBJECT_KEY, SavedQuestionData);
}else{
setLocalStorageQuestions(QUESTION_OBJECT_KEY, SavedQuestionData);
}
const jsonData = JSON.stringify(SavedQuestionData);
localStorage.setItem(QUESTION_OBJECT_KEY, jsonData);
}
};
const handleOffline = () => {
console.log("disconnect");
if (noChange) {
if(SavedQuestionData?.isBase ===1){
setLocalStorageQuestions(QUESTION_OBJECT_KEY, SavedQuestionData);
}else{
setLocalStorageQuestions(QUESTION_OBJECT_KEY, SavedQuestionData);
}
const jsonData = JSON.stringify(SavedQuestionData);
localStorage.setItem(QUESTION_OBJECT_KEY, jsonData);
}
};

View File

@ -1,8 +1,9 @@
import React, { Suspense, lazy, useEffect } from "react";
import React, { useEffect } from "react";
import { Modal, Spin } from "antd";
import FormikForm from "../../Layout/Dashboard/FormikFormModel";
import ModelBody from "./Model/Add";
import { getInitialValues, getValidationSchema ,getInitialValuesBase, getValidationSchemaBase, processTags} from "./Model/formUtil";
import { useAddQuestion, useAddQuestionAsync } from "../../api/Question";
import { useAddQuestion } from "../../api/Question";
import { useTranslation } from "react-i18next";
import { useNavigate, useParams } from "react-router-dom";
import { ParamsEnum } from "../../enums/params";
@ -13,33 +14,33 @@ import { Question } from "../../types/Item";
import BaseForm from './Model/Malty/Add'
import Form from './Model/Add'
import { toast } from "react-toastify";
const AcceptModal = lazy(() => import('./Model/AcceptModal'));
import AcceptModal from "./Model/AcceptModal";
import { useModalState } from "../../zustand/Modal";
import { ModalEnum } from "../../enums/Model";
import { cleanObject } from "../../utils/cleanObject";
import { hasItems } from "../../utils/hasItems";
import { QUESTION_OBJECT_KEY } from "../../config/AppKey";
import useSaveOnDisconnect from "../../Hooks/useSaveOnDisconnect";
import { getLocalStorageQuestions } from "../../utils/setLocalStorageQuestions";
import { getLocalStorage } from "../../utils/LocalStorage";
const AddPage: React.FC = () => {
const {isSuccess:isSuccessAsync,mutateAsync} = useAddQuestionAsync()
const { mutate,isSuccess, isLoading} = useAddQuestion();
const {isBseQuestion,set_Tags_search,set_object_to_edit,set_Success,SavedQuestionData} = useObjectToEdit()
const { mutate, isSuccess, isLoading ,mutateAsync} = useAddQuestion();
const {object_to_edit,set_Tags_search,set_object_to_edit,set_Success,SavedQuestionData} = useObjectToEdit()
const {subject_id,lesson_id} = useParams<ParamsEnum>()
const {isBseQuestion,set_isBseQuestion} = useObjectToEdit()
const { setIsOpen } = useModalState((state) => state);
const handleSubmit = (values: any, { resetForm }: { resetForm: () => void }) => {
const DataToSend = structuredClone(values);
console.log(DataToSend, "DataToSend");
set_Tags_search(null);
console.log(isBseQuestion);
if (isBseQuestion || DataToSend?.isBase === 1) {
if (isBseQuestion) {
const newBseQuestion = {
"subject_id": subject_id,
"content": DataToSend?.content,
@ -50,14 +51,12 @@ const AddPage: React.FC = () => {
mutateAsync(newBseQuestion).then((data:any) => {
mutateAsync(newBseQuestion).then((data) => {
const newBseQuestionId = (data as any)?.data?.id;
const Questions = DataToSend?.Questions;
console.log(1);
Questions?.map((item: Question) => {
const tags = processTags(item);
console.log(item);
mutate({
...item,
@ -74,32 +73,27 @@ const AddPage: React.FC = () => {
} else {
const tags = processTags(DataToSend);
mutate({ ...values, subject_id: subject_id, tags , "lessons_ids":[lesson_id] })
}
};
const navigate = useNavigate()
useEffect(() => {
if (isSuccessAsync && ( SavedQuestionData?.Questions?.length > 0 ? isSuccess: true )) {
if(isSuccess){
toast.success(t("validation.the_possess_done_successful"))
set_object_to_edit(null)
set_Success(true)
localStorage.removeItem(QUESTION_OBJECT_KEY)
}
}, [isSuccess,isSuccessAsync])
}, [isSuccess])
let cleanedQuestionOptions = cleanObject(SavedQuestionData);
let noChange =hasItems(cleanedQuestionOptions)
useSaveOnDisconnect(noChange, QUESTION_OBJECT_KEY, SavedQuestionData);
const SavedData = getLocalStorageQuestions(QUESTION_OBJECT_KEY)
const SavedData = {} as any
console.log(SavedData);
const handleCancel = () => {
if(!noChange){
@ -114,17 +108,16 @@ const AddPage: React.FC = () => {
const [t] = useTranslation();
console.log(SavedData?.isBase === 1);
if(isBseQuestion || SavedData?.isBase === 1){
if(isBseQuestion){
return (
<div className="exercise_add">
<FormikForm
handleSubmit={handleSubmit}
initialValues={getInitialValuesBase(SavedData)}
initialValues={getInitialValuesBase(object_to_edit)}
validationSchema={getValidationSchemaBase}
>
@ -145,10 +138,7 @@ const AddPage: React.FC = () => {
</div>
</main>
</FormikForm>
<Suspense fallback={<Spin/>}>
<AcceptModal/>
</Suspense>
</div>
);
}
@ -157,7 +147,7 @@ const AddPage: React.FC = () => {
<FormikForm
handleSubmit={handleSubmit}
initialValues={getInitialValues(SavedData)}
initialValues={getInitialValues(object_to_edit)}
validationSchema={getValidationSchema}
>
@ -180,9 +170,7 @@ const AddPage: React.FC = () => {
</div>
</main>
</FormikForm>
<Suspense fallback={<Spin/>}>
<AcceptModal/>
</Suspense>
</div>
);
};

View File

@ -17,7 +17,7 @@ const Form = () => {
const formik = useFormikContext<any>();
const { isOpen } = useModalState((state) => state);
// const {data} = useGetAllQuestion();
const{set_Success,Success,set_SavedQuestionData} = useObjectToEdit()
const{set_Success,Success} = useObjectToEdit()
useEffect(() => {
if (Success) {
@ -29,10 +29,6 @@ const Form = () => {
}
}, [Success]);
useEffect(() => {
set_SavedQuestionData(formik.values)
}, [formik?.values])
// console.log(formik?.errors);
console.log(formik?.values?.Questions,"formik?.values?.Questions");

View File

@ -1,7 +1,5 @@
import * as Yup from "yup";
import { Question } from "../../../types/Item";
import { getLocalStorage } from "../../../utils/LocalStorage";
import { QUESTION_OBJECT_KEY } from "../../../config/AppKey";
export const getInitialValues = (objectToEdit: Question): any => {
@ -9,14 +7,12 @@ export const getInitialValues = (objectToEdit: Question): any => {
return { ...item, key: index }
});
return {
id: objectToEdit?.id ?? null,
content: objectToEdit?.content ?? "",
image: objectToEdit?.image ?? "",
subject_id: objectToEdit?.subject_id ?? '',
isBase: 0,
isBase: objectToEdit?.isBase,
parent_id: objectToEdit?.parent_id ?? '',
QuestionOptions: objectToEdit?.QuestionOptions ?? [],
tags: tags ?? [],
@ -67,7 +63,7 @@ export const getInitialValuesBase = (objectToEdit: Question): any => {
content: objectToEdit?.content ?? "",
image: objectToEdit?.image ?? "",
subject_id: objectToEdit?.subject_id ?? '',
isBase: 1,
isBase: objectToEdit?.isBase,
parent_id: objectToEdit?.parent_id ?? '',
Questions: questions,
};

View File

@ -6,8 +6,8 @@ import { useParams } from "react-router-dom";
import { ParamsEnum } from "../../enums/params";
const App: React.FC = () => {
const {lesson_id} = useParams<ParamsEnum>()
const response = useGetAllQuestion({ lesson_id:lesson_id, pagination: true });
const {subject_id} = useParams<ParamsEnum>()
const response = useGetAllQuestion({ subject_id:subject_id, pagination: true });
return <DataTable response={response} useColumns={useColumns} />;
};

View File

@ -11,13 +11,10 @@ const API = {
};
const KEY = "question";
const KEY2 = "questionBases";
export const useGetAllQuestion = (params?: any) =>
useGetQuery(KEY, API.GET, params);
export const useAddQuestion = () => useAddMutation(KEY, API.ADD,false);
export const useAddQuestionAsync = () => useAddMutation(KEY2, API.ADD);
export const useUpdateQuestion = (params?: any) =>
useUpdateMutation(KEY, API.GET,false);
export const useDeleteQuestion = (params?: any) =>

View File

@ -7,24 +7,19 @@ import { AxiosResponse } from "../../types/Axios";
function useAddMutation(
key: string,
url: string,
toast: boolean = true
toast:boolean = true
): UseMutationResult<AxiosResponse, unknown, any, unknown> {
const axios = useAxios();
console.log(toast,key);
return useMutation<AxiosResponse, unknown, any, unknown>(
async (dataToSend) => {
const filterDataToSend = filterData(dataToSend);
const { data } = await axios.post(url, filterDataToSend, {
headers: {
"Content-Type": "multipart/form-data",
["X-Custom-Message"] : toast ,
[HEADER_KEY]: key,
["X-Custom-Message"] : toast
},
});
return data;

View File

@ -43,7 +43,6 @@ function useAxios() {
const key = response.config.headers[HEADER_KEY];
const isToasted = response.config.headers["X-Custom-Message"];
console.log(isToasted);
const ResponseMessage =
responseMsg || t("validation.the_possess_done_successful");

View File

@ -16,29 +16,3 @@ export const setLocalStorage = (key: string, data: any) => {
console.error("Error stringify data for localStorage", error);
}
};
export const setLocalStorageWithFile = async (key: string, data: any) => {
try {
if (data.image instanceof File) {
const base64String = await convertFileToBase64(data.image);
data.image = base64String;
}
const jsonData = JSON.stringify(data);
localStorage.setItem(key, jsonData);
} catch (error) {
console.error("Error stringifying data for localStorage", error);
}
};
export const convertFileToBase64 = (file: File): Promise<string> => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => {
resolve(reader.result as string);
};
reader.onerror = reject;
reader.readAsDataURL(file);
});
};

View File

@ -1,15 +0,0 @@
export const base64StringToFile = (base64String:string) => {
// Convert base64 to blob
const byteCharacters = atob(base64String.split(',')[1]);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
const blob = new Blob([byteArray], { type: 'image/jpeg' });
// Create a File object from Blob (optional: provide a filename)
const file = new File([blob], 'image.jpg', { type: 'image/jpeg' });
return file;
};

View File

@ -1,71 +0,0 @@
import { convertFileToBase64 } from "./LocalStorage";
import { base64StringToFile } from "./base64StringToFile";
export const setLocalStorageBaseQuestions = async (key: string, data: any) => {
try {
// Convert the main image if it is a File
if (data.image instanceof File) {
data.image = await convertFileToBase64(data.image);
}
if (Array.isArray(data.Questions)) {
for (const option of data.Questions) {
if (option.image instanceof File) {
option.image = await convertFileToBase64(option.image);
}
}
}
if (Array.isArray(data.Questions.QuestionOptions)) {
for (const option of data.Questions.QuestionOptions) {
if (option.answer_image instanceof File) {
option.answer_image = await convertFileToBase64(option.answer_image);
}
}
}
const jsonData = JSON.stringify(data);
localStorage.setItem(key, jsonData);
} catch (error) {
console.error("Error stringifying data for localStorage", error);
}
};
export const getLocalStorageBaseQuestions = (key: string): any | null => {
try {
const jsonData = localStorage.getItem(key);
if (!jsonData) return null;
const data = JSON.parse(jsonData);
// Convert the main image from base64 to File if necessary
if (typeof data.image === 'string' && data.image.length > 0) {
data.image = base64StringToFile(data.image);
}
// Convert each image in Questions from base64 to File if necessary
if (Array.isArray(data.Questions)) {
for (const option of data.Questions) {
if (typeof option.image === 'string' ) {
option.image = base64StringToFile(option.image);
}
}
}
if (Array.isArray(data.Questions.QuestionOptions)) {
for (const option of data.Questions.QuestionOptions) {
if (typeof option.answer_image === 'string' ) {
option.answer_image = base64StringToFile(option.answer_image);
}
}
}
return data;
} catch (error) {
console.error("Error parsing data from localStorage", error);
return null;
}
};

View File

@ -1,87 +0,0 @@
import { convertFileToBase64 } from "./LocalStorage";
import { base64StringToFile } from "./base64StringToFile";
export const setLocalStorageQuestions = async (key: string, data: any) => {
try {
// Convert the main image if it is a File
if (data.image instanceof File) {
data.image = await convertFileToBase64(data.image);
}
// Check for QuestionOptions array and convert answer_image if it's a File
if (Array.isArray(data.QuestionOptions)) {
for (const option of data.QuestionOptions) {
if (option.answer_image instanceof File) {
option.answer_image = await convertFileToBase64(option.answer_image);
}
}
}
// Check for Questions array and convert image if it's a File
if (Array.isArray(data.Questions)) {
for (const question of data.Questions) {
if (question.image instanceof File) {
question.image = await convertFileToBase64(question.image);
}
// Check for nested QuestionOptions and convert answer_image if it's a File
if (Array.isArray(question.QuestionOptions)) {
for (const option of question.QuestionOptions) {
if (option.answer_image instanceof File) {
option.answer_image = await convertFileToBase64(option.answer_image);
}
}
}
}
}
const jsonData = JSON.stringify(data);
localStorage.setItem(key, jsonData);
} catch (error) {
console.error("Error stringifying data for localStorage", error);
}
};
export const getLocalStorageQuestions = (key: string): any | null => {
try {
const jsonData = localStorage.getItem(key);
if (!jsonData) return null;
const data = JSON.parse(jsonData);
// Convert back the main image if it's a base64 string
if (typeof data.image === 'string' && data.image.length > 0) {
data.image = base64StringToFile(data.image);
}
// Check for QuestionOptions array and convert answer_image if it's a base64 string
if (Array.isArray(data.QuestionOptions)) {
for (const option of data.QuestionOptions) {
if (typeof option.answer_image === 'string' && option.answer_image.length > 0) {
option.answer_image = base64StringToFile(option.answer_image);
}
}
}
// Check for Questions array and convert image if it's a base64 string
if (Array.isArray(data.Questions)) {
for (const question of data.Questions) {
if (typeof question.image === 'string' && question.image.length > 0) {
question.image = base64StringToFile(question.image);
}
// Check for nested QuestionOptions and convert answer_image if it's a base64 string
if (Array.isArray(question.QuestionOptions)) {
for (const option of question.QuestionOptions) {
if (typeof option.answer_image === 'string' && option.answer_image.length > 0) {
option.answer_image = base64StringToFile(option.answer_image);
}
}
}
}
}
return data;
} catch (error) {
console.error("Error parsing data from localStorage", error);
return null;
}
};