Compare commits
2 Commits
7506c9850d
...
3407250e92
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3407250e92 | ||
|
|
7bf6fef55a |
File diff suppressed because one or more lines are too long
|
|
@ -3,22 +3,26 @@ import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { GoArrowSwitch } from 'react-icons/go';
|
import { GoArrowSwitch } from 'react-icons/go';
|
||||||
import { useObjectToEdit } from '../../zustand/ObjectToEditState';
|
import { useObjectToEdit } from '../../zustand/ObjectToEditState';
|
||||||
|
import { QUESTION_OBJECT_KEY } from '../../config/AppKey';
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const { values, setFieldValue,setValues } = useFormikContext<any>();
|
const { values, setFieldValue,setValues } = useFormikContext<any>();
|
||||||
const {isBseQuestion,set_isBseQuestion} = useObjectToEdit()
|
const {isBseQuestion,set_isBseQuestion} = useObjectToEdit()
|
||||||
|
const {set_SavedQuestionData} = useObjectToEdit()
|
||||||
const handleChange = () => {
|
const handleChange = () => {
|
||||||
|
set_SavedQuestionData(null)
|
||||||
|
localStorage.removeItem(QUESTION_OBJECT_KEY)
|
||||||
if (isBseQuestion) {
|
if (isBseQuestion) {
|
||||||
set_isBseQuestion(false)
|
set_isBseQuestion(false)
|
||||||
setValues(null)
|
setValues(null)
|
||||||
|
setFieldValue("isBase",0)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
set_isBseQuestion(true)
|
set_isBseQuestion(true)
|
||||||
setValues(null)
|
setValues(null)
|
||||||
|
setFieldValue("isBase",1)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -29,7 +33,7 @@ const Header = () => {
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<GoArrowSwitch onClick={handleChange} className="m-2" />
|
<GoArrowSwitch onClick={handleChange} className="m-2" />
|
||||||
{isBseQuestion ? t("header.malty_exercise") :t("header.exercise") }
|
{isBseQuestion || values?.isBase === 1 ? t("header.malty_exercise") :t("header.exercise") }
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,32 @@
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
import { setLocalStorageQuestions } from '../utils/setLocalStorageQuestions';
|
||||||
|
import { setLocalStorageBaseQuestions } from '../utils/setLocalStorageBaseQuestions';
|
||||||
|
|
||||||
const useSaveOnDisconnect = (noChange: boolean, QUESTION_OBJECT_KEY: string, SavedQuestionData: any) => {
|
const useSaveOnDisconnect = (noChange: boolean, QUESTION_OBJECT_KEY: string, SavedQuestionData: any) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleBeforeUnload = (event: BeforeUnloadEvent) => {
|
const handleBeforeUnload = (event: BeforeUnloadEvent) => {
|
||||||
console.log("disconnect");
|
console.log("disconnect");
|
||||||
if (noChange) {
|
if (noChange) {
|
||||||
const jsonData = JSON.stringify(SavedQuestionData);
|
if(SavedQuestionData?.isBase ===1){
|
||||||
localStorage.setItem(QUESTION_OBJECT_KEY, jsonData);
|
setLocalStorageQuestions(QUESTION_OBJECT_KEY, SavedQuestionData);
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
setLocalStorageQuestions(QUESTION_OBJECT_KEY, SavedQuestionData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOffline = () => {
|
const handleOffline = () => {
|
||||||
console.log("disconnect");
|
console.log("disconnect");
|
||||||
if (noChange) {
|
if (noChange) {
|
||||||
const jsonData = JSON.stringify(SavedQuestionData);
|
if(SavedQuestionData?.isBase ===1){
|
||||||
localStorage.setItem(QUESTION_OBJECT_KEY, jsonData);
|
setLocalStorageQuestions(QUESTION_OBJECT_KEY, SavedQuestionData);
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
setLocalStorageQuestions(QUESTION_OBJECT_KEY, SavedQuestionData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import React, { useEffect } from "react";
|
import React, { Suspense, lazy, useEffect } from "react";
|
||||||
import { Modal, Spin } from "antd";
|
import { Modal, Spin } from "antd";
|
||||||
import FormikForm from "../../Layout/Dashboard/FormikFormModel";
|
import FormikForm from "../../Layout/Dashboard/FormikFormModel";
|
||||||
import ModelBody from "./Model/Add";
|
|
||||||
import { getInitialValues, getValidationSchema ,getInitialValuesBase, getValidationSchemaBase, processTags} from "./Model/formUtil";
|
import { getInitialValues, getValidationSchema ,getInitialValuesBase, getValidationSchemaBase, processTags} from "./Model/formUtil";
|
||||||
import { useAddQuestion } from "../../api/Question";
|
import { useAddQuestion, useAddQuestionAsync } from "../../api/Question";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { ParamsEnum } from "../../enums/params";
|
import { ParamsEnum } from "../../enums/params";
|
||||||
|
|
@ -14,33 +13,33 @@ import { Question } from "../../types/Item";
|
||||||
import BaseForm from './Model/Malty/Add'
|
import BaseForm from './Model/Malty/Add'
|
||||||
import Form from './Model/Add'
|
import Form from './Model/Add'
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import AcceptModal from "./Model/AcceptModal";
|
const AcceptModal = lazy(() => import('./Model/AcceptModal'));
|
||||||
|
|
||||||
import { useModalState } from "../../zustand/Modal";
|
import { useModalState } from "../../zustand/Modal";
|
||||||
import { ModalEnum } from "../../enums/Model";
|
import { ModalEnum } from "../../enums/Model";
|
||||||
import { cleanObject } from "../../utils/cleanObject";
|
import { cleanObject } from "../../utils/cleanObject";
|
||||||
import { hasItems } from "../../utils/hasItems";
|
import { hasItems } from "../../utils/hasItems";
|
||||||
import { QUESTION_OBJECT_KEY } from "../../config/AppKey";
|
import { QUESTION_OBJECT_KEY } from "../../config/AppKey";
|
||||||
import useSaveOnDisconnect from "../../Hooks/useSaveOnDisconnect";
|
import useSaveOnDisconnect from "../../Hooks/useSaveOnDisconnect";
|
||||||
import { getLocalStorage } from "../../utils/LocalStorage";
|
import { getLocalStorageQuestions } from "../../utils/setLocalStorageQuestions";
|
||||||
|
|
||||||
const AddPage: React.FC = () => {
|
const AddPage: React.FC = () => {
|
||||||
|
|
||||||
|
const {isSuccess:isSuccessAsync,mutateAsync} = useAddQuestionAsync()
|
||||||
const { mutate, isSuccess, isLoading ,mutateAsync} = useAddQuestion();
|
const { mutate,isSuccess, isLoading} = useAddQuestion();
|
||||||
const {object_to_edit,set_Tags_search,set_object_to_edit,set_Success,SavedQuestionData} = useObjectToEdit()
|
const {isBseQuestion,set_Tags_search,set_object_to_edit,set_Success,SavedQuestionData} = useObjectToEdit()
|
||||||
|
|
||||||
const {subject_id,lesson_id} = useParams<ParamsEnum>()
|
const {subject_id,lesson_id} = useParams<ParamsEnum>()
|
||||||
const {isBseQuestion,set_isBseQuestion} = useObjectToEdit()
|
|
||||||
const { setIsOpen } = useModalState((state) => state);
|
const { setIsOpen } = useModalState((state) => state);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleSubmit = (values: any, { resetForm }: { resetForm: () => void }) => {
|
const handleSubmit = (values: any, { resetForm }: { resetForm: () => void }) => {
|
||||||
const DataToSend = structuredClone(values);
|
const DataToSend = structuredClone(values);
|
||||||
console.log(DataToSend, "DataToSend");
|
|
||||||
set_Tags_search(null);
|
set_Tags_search(null);
|
||||||
|
console.log(isBseQuestion);
|
||||||
|
|
||||||
if (isBseQuestion) {
|
if (isBseQuestion || DataToSend?.isBase === 1) {
|
||||||
const newBseQuestion = {
|
const newBseQuestion = {
|
||||||
"subject_id": subject_id,
|
"subject_id": subject_id,
|
||||||
"content": DataToSend?.content,
|
"content": DataToSend?.content,
|
||||||
|
|
@ -51,12 +50,14 @@ const AddPage: React.FC = () => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mutateAsync(newBseQuestion).then((data) => {
|
mutateAsync(newBseQuestion).then((data:any) => {
|
||||||
const newBseQuestionId = (data as any)?.data?.id;
|
const newBseQuestionId = (data as any)?.data?.id;
|
||||||
const Questions = DataToSend?.Questions;
|
const Questions = DataToSend?.Questions;
|
||||||
|
console.log(1);
|
||||||
|
|
||||||
Questions?.map((item: Question) => {
|
Questions?.map((item: Question) => {
|
||||||
const tags = processTags(item);
|
const tags = processTags(item);
|
||||||
|
console.log(item);
|
||||||
|
|
||||||
mutate({
|
mutate({
|
||||||
...item,
|
...item,
|
||||||
|
|
@ -73,27 +74,32 @@ const AddPage: React.FC = () => {
|
||||||
} else {
|
} else {
|
||||||
const tags = processTags(DataToSend);
|
const tags = processTags(DataToSend);
|
||||||
mutate({ ...values, subject_id: subject_id, tags , "lessons_ids":[lesson_id] })
|
mutate({ ...values, subject_id: subject_id, tags , "lessons_ids":[lesson_id] })
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if(isSuccess){
|
|
||||||
toast.success(t("validation.the_possess_done_successful"))
|
if (isSuccessAsync && ( SavedQuestionData?.Questions?.length > 0 ? isSuccess: true )) {
|
||||||
set_object_to_edit(null)
|
set_object_to_edit(null)
|
||||||
set_Success(true)
|
set_Success(true)
|
||||||
localStorage.removeItem(QUESTION_OBJECT_KEY)
|
localStorage.removeItem(QUESTION_OBJECT_KEY)
|
||||||
|
|
||||||
}
|
}
|
||||||
}, [isSuccess])
|
}, [isSuccess,isSuccessAsync])
|
||||||
|
|
||||||
let cleanedQuestionOptions = cleanObject(SavedQuestionData);
|
let cleanedQuestionOptions = cleanObject(SavedQuestionData);
|
||||||
let noChange =hasItems(cleanedQuestionOptions)
|
let noChange =hasItems(cleanedQuestionOptions)
|
||||||
|
|
||||||
|
|
||||||
useSaveOnDisconnect(noChange, QUESTION_OBJECT_KEY, SavedQuestionData);
|
useSaveOnDisconnect(noChange, QUESTION_OBJECT_KEY, SavedQuestionData);
|
||||||
|
|
||||||
|
|
||||||
const SavedData = {} as any
|
const SavedData = getLocalStorageQuestions(QUESTION_OBJECT_KEY)
|
||||||
|
|
||||||
console.log(SavedData);
|
console.log(SavedData);
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
if(!noChange){
|
if(!noChange){
|
||||||
|
|
@ -108,16 +114,17 @@ const AddPage: React.FC = () => {
|
||||||
|
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
console.log(SavedData?.isBase === 1);
|
||||||
|
|
||||||
|
if(isBseQuestion || SavedData?.isBase === 1){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(isBseQuestion){
|
|
||||||
return (
|
return (
|
||||||
<div className="exercise_add">
|
<div className="exercise_add">
|
||||||
|
|
||||||
<FormikForm
|
<FormikForm
|
||||||
handleSubmit={handleSubmit}
|
handleSubmit={handleSubmit}
|
||||||
initialValues={getInitialValuesBase(object_to_edit)}
|
initialValues={getInitialValuesBase(SavedData)}
|
||||||
validationSchema={getValidationSchemaBase}
|
validationSchema={getValidationSchemaBase}
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|
@ -138,7 +145,10 @@ const AddPage: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</FormikForm>
|
</FormikForm>
|
||||||
<AcceptModal/>
|
<Suspense fallback={<Spin/>}>
|
||||||
|
<AcceptModal/>
|
||||||
|
</Suspense>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -147,7 +157,7 @@ const AddPage: React.FC = () => {
|
||||||
|
|
||||||
<FormikForm
|
<FormikForm
|
||||||
handleSubmit={handleSubmit}
|
handleSubmit={handleSubmit}
|
||||||
initialValues={getInitialValues(object_to_edit)}
|
initialValues={getInitialValues(SavedData)}
|
||||||
validationSchema={getValidationSchema}
|
validationSchema={getValidationSchema}
|
||||||
|
|
||||||
>
|
>
|
||||||
|
|
@ -170,7 +180,9 @@ const AddPage: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</FormikForm>
|
</FormikForm>
|
||||||
<AcceptModal/>
|
<Suspense fallback={<Spin/>}>
|
||||||
|
<AcceptModal/>
|
||||||
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ const Form = () => {
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
const { isOpen } = useModalState((state) => state);
|
const { isOpen } = useModalState((state) => state);
|
||||||
// const {data} = useGetAllQuestion();
|
// const {data} = useGetAllQuestion();
|
||||||
const{set_Success,Success} = useObjectToEdit()
|
const{set_Success,Success,set_SavedQuestionData} = useObjectToEdit()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Success) {
|
if (Success) {
|
||||||
|
|
@ -29,6 +29,10 @@ const Form = () => {
|
||||||
}
|
}
|
||||||
}, [Success]);
|
}, [Success]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
set_SavedQuestionData(formik.values)
|
||||||
|
}, [formik?.values])
|
||||||
|
|
||||||
// console.log(formik?.errors);
|
// console.log(formik?.errors);
|
||||||
console.log(formik?.values?.Questions,"formik?.values?.Questions");
|
console.log(formik?.values?.Questions,"formik?.values?.Questions");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import { Question } from "../../../types/Item";
|
import { Question } from "../../../types/Item";
|
||||||
|
import { getLocalStorage } from "../../../utils/LocalStorage";
|
||||||
|
import { QUESTION_OBJECT_KEY } from "../../../config/AppKey";
|
||||||
|
|
||||||
|
|
||||||
export const getInitialValues = (objectToEdit: Question): any => {
|
export const getInitialValues = (objectToEdit: Question): any => {
|
||||||
|
|
@ -7,12 +9,14 @@ export const getInitialValues = (objectToEdit: Question): any => {
|
||||||
return { ...item, key: index }
|
return { ...item, key: index }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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 ?? '',
|
||||||
isBase: objectToEdit?.isBase,
|
isBase: 0,
|
||||||
parent_id: objectToEdit?.parent_id ?? '',
|
parent_id: objectToEdit?.parent_id ?? '',
|
||||||
QuestionOptions: objectToEdit?.QuestionOptions ?? [],
|
QuestionOptions: objectToEdit?.QuestionOptions ?? [],
|
||||||
tags: tags ?? [],
|
tags: tags ?? [],
|
||||||
|
|
@ -63,7 +67,7 @@ export const getInitialValuesBase = (objectToEdit: Question): any => {
|
||||||
content: objectToEdit?.content ?? "",
|
content: objectToEdit?.content ?? "",
|
||||||
image: objectToEdit?.image ?? "",
|
image: objectToEdit?.image ?? "",
|
||||||
subject_id: objectToEdit?.subject_id ?? '',
|
subject_id: objectToEdit?.subject_id ?? '',
|
||||||
isBase: objectToEdit?.isBase,
|
isBase: 1,
|
||||||
parent_id: objectToEdit?.parent_id ?? '',
|
parent_id: objectToEdit?.parent_id ?? '',
|
||||||
Questions: questions,
|
Questions: questions,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ import { useParams } from "react-router-dom";
|
||||||
import { ParamsEnum } from "../../enums/params";
|
import { ParamsEnum } from "../../enums/params";
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
const {subject_id} = useParams<ParamsEnum>()
|
const {lesson_id} = useParams<ParamsEnum>()
|
||||||
const response = useGetAllQuestion({ subject_id:subject_id, pagination: true });
|
const response = useGetAllQuestion({ lesson_id:lesson_id, pagination: true });
|
||||||
|
|
||||||
return <DataTable response={response} useColumns={useColumns} />;
|
return <DataTable response={response} useColumns={useColumns} />;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,13 @@ const API = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const KEY = "question";
|
const KEY = "question";
|
||||||
|
const KEY2 = "questionBases";
|
||||||
|
|
||||||
export const useGetAllQuestion = (params?: any) =>
|
export const useGetAllQuestion = (params?: any) =>
|
||||||
useGetQuery(KEY, API.GET, params);
|
useGetQuery(KEY, API.GET, params);
|
||||||
export const useAddQuestion = () => useAddMutation(KEY, API.ADD,false);
|
export const useAddQuestion = () => useAddMutation(KEY, API.ADD,false);
|
||||||
|
export const useAddQuestionAsync = () => useAddMutation(KEY2, API.ADD);
|
||||||
|
|
||||||
export const useUpdateQuestion = (params?: any) =>
|
export const useUpdateQuestion = (params?: any) =>
|
||||||
useUpdateMutation(KEY, API.GET,false);
|
useUpdateMutation(KEY, API.GET,false);
|
||||||
export const useDeleteQuestion = (params?: any) =>
|
export const useDeleteQuestion = (params?: any) =>
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,24 @@ import { AxiosResponse } from "../../types/Axios";
|
||||||
function useAddMutation(
|
function useAddMutation(
|
||||||
key: string,
|
key: string,
|
||||||
url: string,
|
url: string,
|
||||||
toast:boolean = true
|
toast: boolean = true
|
||||||
|
|
||||||
): UseMutationResult<AxiosResponse, unknown, any, unknown> {
|
): UseMutationResult<AxiosResponse, unknown, any, unknown> {
|
||||||
const axios = useAxios();
|
const axios = useAxios();
|
||||||
|
console.log(toast,key);
|
||||||
|
|
||||||
|
|
||||||
return useMutation<AxiosResponse, unknown, any, unknown>(
|
return useMutation<AxiosResponse, unknown, any, unknown>(
|
||||||
|
|
||||||
async (dataToSend) => {
|
async (dataToSend) => {
|
||||||
const filterDataToSend = filterData(dataToSend);
|
const filterDataToSend = filterData(dataToSend);
|
||||||
|
|
||||||
const { data } = await axios.post(url, filterDataToSend, {
|
const { data } = await axios.post(url, filterDataToSend, {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "multipart/form-data",
|
"Content-Type": "multipart/form-data",
|
||||||
|
["X-Custom-Message"] : toast ,
|
||||||
[HEADER_KEY]: key,
|
[HEADER_KEY]: key,
|
||||||
["X-Custom-Message"] : toast
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return data;
|
return data;
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ function useAxios() {
|
||||||
|
|
||||||
const key = response.config.headers[HEADER_KEY];
|
const key = response.config.headers[HEADER_KEY];
|
||||||
const isToasted = response.config.headers["X-Custom-Message"];
|
const isToasted = response.config.headers["X-Custom-Message"];
|
||||||
|
console.log(isToasted);
|
||||||
|
|
||||||
const ResponseMessage =
|
const ResponseMessage =
|
||||||
responseMsg || t("validation.the_possess_done_successful");
|
responseMsg || t("validation.the_possess_done_successful");
|
||||||
|
|
|
||||||
|
|
@ -16,3 +16,29 @@ export const setLocalStorage = (key: string, data: any) => {
|
||||||
console.error("Error stringify data for localStorage", error);
|
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);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
|
||||||
15
src/utils/base64StringToFile.ts
Normal file
15
src/utils/base64StringToFile.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
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;
|
||||||
|
};
|
||||||
71
src/utils/setLocalStorageBaseQuestions.ts
Normal file
71
src/utils/setLocalStorageBaseQuestions.ts
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
87
src/utils/setLocalStorageQuestions.ts
Normal file
87
src/utils/setLocalStorageQuestions.ts
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user