Merge branch 'dev' of into dev
This commit is contained in:
commit
3a877b5053
|
|
@ -27,6 +27,7 @@ const ImageBoxField = ({ name }: any) => {
|
||||||
|
|
||||||
const handleFileChange = (event: any) => {
|
const handleFileChange = (event: any) => {
|
||||||
const file = event.target.files[0];
|
const file = event.target.files[0];
|
||||||
|
|
||||||
if (file) {
|
if (file) {
|
||||||
const maxSize = 2 * 1024 * 1024;
|
const maxSize = 2 * 1024 * 1024;
|
||||||
|
|
||||||
|
|
@ -42,6 +43,8 @@ const ImageBoxField = ({ name }: any) => {
|
||||||
|
|
||||||
if (file) {
|
if (file) {
|
||||||
generateImagePreview(file, setImagePreview);
|
generateImagePreview(file, setImagePreview);
|
||||||
|
console.log(file,"file");
|
||||||
|
|
||||||
formik.setFieldValue(name, file);
|
formik.setFieldValue(name, file);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -55,7 +58,7 @@ const ImageBoxField = ({ name }: any) => {
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
setImagePreview("");
|
setImagePreview("");
|
||||||
formik.setFieldValue(name, "");
|
formik.setFieldValue(name, null);
|
||||||
|
|
||||||
if (fileInputRef.current) {
|
if (fileInputRef.current) {
|
||||||
fileInputRef.current.value = "";
|
fileInputRef.current.value = "";
|
||||||
|
|
@ -79,9 +82,9 @@ const ImageBoxField = ({ name }: any) => {
|
||||||
</div>
|
</div>
|
||||||
<div className="ImageBox" onClick={handleButtonClick}>
|
<div className="ImageBox" onClick={handleButtonClick}>
|
||||||
{imagePreview ? (
|
{imagePreview ? (
|
||||||
<img src={imagePreview} onClick={handleButtonClick} alt="Preview" className="imagePreview" />
|
<img src={imagePreview} alt="Preview" className="imagePreview" />
|
||||||
) : (
|
) : (
|
||||||
<ImageIcon onClick={handleButtonClick} className="ImageBoxIcon" />
|
<ImageIcon className="ImageBoxIcon" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
|
|
|
||||||
|
|
@ -9,20 +9,32 @@ const SelectTag: React.FC = () => {
|
||||||
const [searchValue, setSearchValue] = useState<string>("");
|
const [searchValue, setSearchValue] = useState<string>("");
|
||||||
|
|
||||||
const [fieldValue, setFieldValue] = useState<string>("");
|
const [fieldValue, setFieldValue] = useState<string>("");
|
||||||
|
const [NewAdditionalData, setNewAdditionalData] = useState({})
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
const handleChange = (value: string[]) => {
|
const handleChange = (value: any,option:any) => {
|
||||||
|
console.log(option);
|
||||||
console.log(value);
|
console.log(value);
|
||||||
|
const newSelectedOption = option?.pop()
|
||||||
|
console.log(newSelectedOption);
|
||||||
|
|
||||||
|
const newObject = {
|
||||||
|
id:newSelectedOption?.id,
|
||||||
|
name:newSelectedOption?.name
|
||||||
|
}
|
||||||
|
setNewAdditionalData(newObject)
|
||||||
formik.setFieldValue("tags", value);
|
formik.setFieldValue("tags", value);
|
||||||
setSearchValue("");
|
setSearchValue("");
|
||||||
setFieldValue("");
|
setFieldValue("");
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSearch = useDebounce((value: string) => {
|
const handleSearch = useDebounce((value: string) => {
|
||||||
|
console.log(value,"value");
|
||||||
|
|
||||||
setSearchValue(value);
|
setSearchValue(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleFieldChange = (value: string) => {
|
const handleFieldChange = (value: string) => {
|
||||||
|
|
||||||
setFieldValue(value);
|
setFieldValue(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -36,6 +48,12 @@ const SelectTag: React.FC = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
const initialData = formik?.values?.tags?.filter((item:any)=>{
|
||||||
|
return item?.id
|
||||||
|
|
||||||
|
}) ?? []
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const options = data?.data ?? [];
|
const options = data?.data ?? [];
|
||||||
const additionalData =
|
const additionalData =
|
||||||
|
|
@ -46,7 +64,16 @@ const SelectTag: React.FC = () => {
|
||||||
const value =
|
const value =
|
||||||
formik?.values?.tags?.map((item: any) => item?.id ?? item) ?? [];
|
formik?.values?.tags?.map((item: any) => item?.id ?? item) ?? [];
|
||||||
|
|
||||||
const AllOptions = [...options, ...additionalData];
|
const AllOptions = [...options, ...additionalData,NewAdditionalData, ...(initialData)];
|
||||||
|
|
||||||
|
const uniqueOptions = Array.from(
|
||||||
|
new Map(
|
||||||
|
AllOptions
|
||||||
|
.filter(item => Object.keys(item).length > 0) // Filter out empty objects
|
||||||
|
.map(item => [item.id, item]) // Create [id, item] pairs to ensure uniqueness
|
||||||
|
).values()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="SelectTag">
|
<div className="SelectTag">
|
||||||
|
|
@ -58,7 +85,7 @@ const SelectTag: React.FC = () => {
|
||||||
placeholder=""
|
placeholder=""
|
||||||
fieldNames={{ label: "name", value: "id" }}
|
fieldNames={{ label: "name", value: "id" }}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
options={AllOptions}
|
options={uniqueOptions}
|
||||||
filterOption={false}
|
filterOption={false}
|
||||||
loading={isLoading}
|
loading={isLoading}
|
||||||
notFoundContent={isLoading ? <Spin /> : t("practical.not_found")}
|
notFoundContent={isLoading ? <Spin /> : t("practical.not_found")}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 80px;
|
min-height: 80px;
|
||||||
// padding-inline: 20px;
|
|
||||||
> * {
|
> * {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
min-width: 150px;
|
min-width: 150px;
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,59 @@
|
||||||
import { useFormikContext } from "formik";
|
import { useFormikContext } from "formik";
|
||||||
import React from "react";
|
import React, { useState } 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";
|
import { Checkbox, CheckboxProps, Popconfirm, Popover } from "antd";
|
||||||
import { 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";
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const { values, setFieldValue, setValues } = useFormikContext<any>();
|
const { values, setValues } = useFormikContext<any>();
|
||||||
const { isBseQuestion, setIsBseQuestion } = useObjectToEdit();
|
const { isBseQuestion, setIsBseQuestion,ShowHint,setShowHint } = useObjectToEdit();
|
||||||
const { setSavedQuestionData } = useObjectToEdit();
|
// const [Setting, setSetting] = useState(false)
|
||||||
|
const isEdited = ()=>{
|
||||||
|
|
||||||
|
if(isBseQuestion || values?.isBase === 1){
|
||||||
|
|
||||||
|
const content = !values?.content ;
|
||||||
|
const content_image = !values?.content_image ;
|
||||||
|
|
||||||
|
const Questions = values?.Questions?.length <= 1 && values?.Questions?.[0]?.answers?.length === 0 ;
|
||||||
|
const defaultQuestionHint = Object.keys(values?.Questions?.[0] ?? {})?.length <= 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(content && content_image && Questions && defaultQuestionHint) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
const content = !values?.content ;
|
||||||
|
const content_image = !values?.content_image ;
|
||||||
|
const hint = !values?.hint ;
|
||||||
|
const answers = !(values?.answers?.length > 0) ;
|
||||||
|
const tags = !(values?.tags?.length > 0) ;
|
||||||
|
if(content && content_image && hint && answers && tags) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
const handleChange = () => {
|
const handleChange = () => {
|
||||||
setSavedQuestionData(null);
|
|
||||||
localStorage.removeItem(QUESTION_OBJECT_KEY);
|
|
||||||
if (isBseQuestion) {
|
if (isBseQuestion) {
|
||||||
setIsBseQuestion(false);
|
setIsBseQuestion(false);
|
||||||
setValues(null);
|
setValues(null);
|
||||||
setFieldValue("isBase", 0);
|
|
||||||
} else {
|
} else {
|
||||||
setIsBseQuestion(true);
|
setIsBseQuestion(true);
|
||||||
setValues(null);
|
setValues(null);
|
||||||
setFieldValue("isBase", 1);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const confirm: PopconfirmProps['onConfirm'] = (e) => {
|
const confirm: PopconfirmProps['onConfirm'] = (e) => {
|
||||||
console.log(e);
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
handleChange()
|
handleChange() ;
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
@ -50,6 +72,25 @@ const Header = () => {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
const handleOpenChange = (newOpen: boolean) => {
|
||||||
|
// setSetting(newOpen);
|
||||||
|
};
|
||||||
|
const onChange: CheckboxProps['onChange'] = (e) => {
|
||||||
|
setShowHint(e.target.checked);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const contentSetting = (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<Checkbox checked={ShowHint} onChange={onChange}>
|
||||||
|
{ t("header.show_hint")}
|
||||||
|
</Checkbox>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="exercise_add_header mb-4">
|
<header className="exercise_add_header mb-4">
|
||||||
<article>
|
<article>
|
||||||
|
|
@ -62,7 +103,17 @@ const Header = () => {
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
<div>
|
<div>
|
||||||
<Popconfirm
|
|
||||||
|
<div className="question_header_setting">
|
||||||
|
<Popover onOpenChange={handleOpenChange} trigger="click" content={contentSetting}>
|
||||||
|
<SettingFilled/>
|
||||||
|
|
||||||
|
</Popover>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{
|
||||||
|
isEdited() ?
|
||||||
|
<Popconfirm
|
||||||
title={t("header.this_will_un_do_all_your_changes")}
|
title={t("header.this_will_un_do_all_your_changes")}
|
||||||
okText={t("practical.yes")}
|
okText={t("practical.yes")}
|
||||||
cancelText={t("practical.no")}
|
cancelText={t("practical.no")}
|
||||||
|
|
@ -77,6 +128,23 @@ const Header = () => {
|
||||||
: t("header.exercise")}
|
: t("header.exercise")}
|
||||||
|
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
|
|
||||||
|
|
||||||
|
:
|
||||||
|
|
||||||
|
<>
|
||||||
|
|
||||||
|
|
||||||
|
<GoArrowSwitch onClick={()=>confirm()} className="m-2" />
|
||||||
|
{isBseQuestion || values?.isBase === 1
|
||||||
|
? t("header.malty_exercise")
|
||||||
|
: t("header.exercise")}
|
||||||
|
</>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ const FormikFormModel: React.FC<FormikFormProps> = ({
|
||||||
>
|
>
|
||||||
{(formik) => {
|
{(formik) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen === "") {
|
if (isOpen === "" || isOpen === "isSuccess") {
|
||||||
formik.setErrors({});
|
formik.setErrors({});
|
||||||
formik.resetForm();
|
formik.resetForm();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import React, { lazy, Suspense } from "react";
|
import React, { lazy, Suspense, useEffect } from "react";
|
||||||
import { useAddKeyToData, Table, useTranslation, usePagination } from ".";
|
import { useAddKeyToData, Table, useTranslation, usePagination } from ".";
|
||||||
import { DataTableProps } from "../../../types/Table";
|
import { DataTableProps } from "../../../types/Table";
|
||||||
|
import { useDataTableState } from "../../../zustand/TabState";
|
||||||
const NotFoundLottie = React.lazy(
|
const NotFoundLottie = React.lazy(
|
||||||
() => import("../../../Components/Lottie/NotFound/NotFoundLottie"),
|
() => import("../../../Components/Lottie/NotFound/NotFoundLottie"),
|
||||||
);
|
);
|
||||||
|
|
@ -14,21 +15,26 @@ const DataTable: React.FC<DataTableProps> = ({
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const data: any[] = response?.data?.data || [];
|
const data: any[] = response?.data?.data || [];
|
||||||
const dataSource = useAddKeyToData(data);
|
|
||||||
const columns = useColumns();
|
const columns = useColumns();
|
||||||
const { pagination, handlePageChange } = usePagination(response?.data);
|
const { pagination, handlePageChange } = usePagination(response?.data);
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const getRowClassName = (record: any, index: number): string => {
|
const getRowClassName = (_record: any, index: number): string => {
|
||||||
return index % 2 === 0 ? "even-row" : "odd-row";
|
return index % 2 === 0 ? "even-row" : "odd-row";
|
||||||
};
|
};
|
||||||
const isRefetching = response?.isRefetching;
|
const isRefetching = response?.isRefetching;
|
||||||
const isLoading = response?.isLoading;
|
const isLoading = response?.isLoading;
|
||||||
|
const dataLength = data?.length ;
|
||||||
|
const {setDataTableLength} = useDataTableState()
|
||||||
|
useEffect(() => {
|
||||||
|
setDataTableLength(dataLength)
|
||||||
|
}, [dataLength])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table
|
<Table
|
||||||
style={{ minHeight: "300px" }}
|
style={{ minHeight: "300px" }}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
dataSource={dataSource}
|
dataSource={data}
|
||||||
|
rowKey={"id"}
|
||||||
rowClassName={(record, index) => getRowClassName(record, index)}
|
rowClassName={(record, index) => getRowClassName(record, index)}
|
||||||
className="DataTable"
|
className="DataTable"
|
||||||
loading={{
|
loading={{
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { useLocation, useNavigate } from "react-router-dom";
|
|
||||||
import { PaginationAntd, PaginationMeta } from "../../types/Table";
|
import { PaginationAntd, PaginationMeta } from "../../types/Table";
|
||||||
import { useFilterStateState } from "../../zustand/Filter";
|
import { useFilterStateState } from "../../zustand/Filter";
|
||||||
|
|
||||||
|
|
@ -8,8 +7,6 @@ interface Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
const usePagination = (data: Data) => {
|
const usePagination = (data: Data) => {
|
||||||
const navigate = useNavigate();
|
|
||||||
const location = useLocation();
|
|
||||||
const { Filter ,setFilter } = useFilterStateState();
|
const { Filter ,setFilter } = useFilterStateState();
|
||||||
|
|
||||||
const [pagination, setPagination] = useState<PaginationAntd>({
|
const [pagination, setPagination] = useState<PaginationAntd>({
|
||||||
|
|
@ -29,7 +26,6 @@ const usePagination = (data: Data) => {
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
const handlePageChange = (page: number) => {
|
const handlePageChange = (page: number) => {
|
||||||
// navigate(`?page=${page}`);
|
|
||||||
setFilter({
|
setFilter({
|
||||||
...Filter,
|
...Filter,
|
||||||
page:page
|
page:page
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ const App: React.FC = () => {
|
||||||
sort_by
|
sort_by
|
||||||
});
|
});
|
||||||
|
|
||||||
return <DataTable response={response} useColumns={useColumns} />;
|
return <DataTable response={response} useColumns={useColumns} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,10 @@
|
||||||
import { TableColumnsType } from "antd";
|
import { TableColumnsType } from "antd";
|
||||||
import { FaPlus } from "react-icons/fa";
|
|
||||||
import useModalHandler from "../../../utils/useModalHandler";
|
import useModalHandler from "../../../utils/useModalHandler";
|
||||||
import { ModalEnum } from "../../../enums/Model";
|
import { ModalEnum } from "../../../enums/Model";
|
||||||
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { ABILITIES_ENUM } from "../../../enums/abilities";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
canAddGrade,
|
|
||||||
canDeleteGrade,
|
canDeleteGrade,
|
||||||
canEditGrade,
|
canEditGrade,
|
||||||
canShowGrade,
|
canShowGrade,
|
||||||
|
|
@ -15,7 +12,6 @@ import {
|
||||||
import ActionButtons from "../../../Components/Table/ActionButtons";
|
import ActionButtons from "../../../Components/Table/ActionButtons";
|
||||||
import ColumnsImage from "../../../Components/Columns/ColumnsImage";
|
import ColumnsImage from "../../../Components/Columns/ColumnsImage";
|
||||||
import { Grade } from "../../../types/Grade";
|
import { Grade } from "../../../types/Grade";
|
||||||
import { useFilterState } from "../../../Components/Utils/Filter/FilterState";
|
|
||||||
import { useFilterStateState } from "../../../zustand/Filter";
|
import { useFilterStateState } from "../../../zustand/Filter";
|
||||||
|
|
||||||
export const useColumns = () => {
|
export const useColumns = () => {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ const SelectTag: React.FC = () => {
|
||||||
const [fieldValue, setFieldValue] = useState<string>("");
|
const [fieldValue, setFieldValue] = useState<string>("");
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
const handleChange = (value: string[]) => {
|
const handleChange = (value: string[]) => {
|
||||||
console.log(value);
|
console.log(value,"value");
|
||||||
|
|
||||||
formik.setFieldValue("tags", value);
|
formik.setFieldValue("tags", value);
|
||||||
setSearchValue("");
|
setSearchValue("");
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ const AddPage: React.FC = () => {
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
if(haveImageOrContent){
|
if(haveImageOrContent){
|
||||||
toast.error("validation.one_of_image_and_content_should_be_enter")
|
toast.error(t("validation.one_of_image_and_content_should_be_enter"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,7 +127,8 @@ const AddPage: React.FC = () => {
|
||||||
const haveAnswers = answers?.length > 0;
|
const haveAnswers = answers?.length > 0;
|
||||||
const haveMoreThanOneAnswer = haveAnswers && answers?.length > 1;
|
const haveMoreThanOneAnswer = haveAnswers && answers?.length > 1;
|
||||||
const haveOneAnswerRight = haveMoreThanOneAnswer && answers?.some((item: any) => item?.isCorrect === 1 || item.isCorrect === true);
|
const haveOneAnswerRight = haveMoreThanOneAnswer && 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 && answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
|
||||||
|
console.log(haveImageOrContent,"haveImageOrContent");
|
||||||
|
|
||||||
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"));
|
||||||
|
|
@ -145,7 +146,7 @@ const AddPage: React.FC = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(haveImageOrContent){
|
if(haveImageOrContent){
|
||||||
toast.error("validation.one_of_image_and_content_should_be_enter")
|
toast.error(t("validation.one_of_image_and_content_should_be_enter"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,6 @@ const EditPage: React.FC = () => {
|
||||||
const handleSubmit = (values: any) => {
|
const handleSubmit = (values: any) => {
|
||||||
const DataToSend = structuredClone(values);
|
const DataToSend = structuredClone(values);
|
||||||
setTagsSearch(null);
|
setTagsSearch(null);
|
||||||
console.log(DataToSend);
|
|
||||||
|
|
||||||
if (isBseQuestion) {
|
if (isBseQuestion) {
|
||||||
const UpdateBseQuestion = {
|
const UpdateBseQuestion = {
|
||||||
|
|
@ -89,6 +88,8 @@ const EditPage: React.FC = () => {
|
||||||
if (item?.id) {
|
if (item?.id) {
|
||||||
const itemToSend = structuredClone(item);
|
const itemToSend = structuredClone(item);
|
||||||
const keysToRemove = ["content_image"];
|
const keysToRemove = ["content_image"];
|
||||||
|
console.log(itemToSend,"itemToSend");
|
||||||
|
|
||||||
const updatedObject = removeStringKeys(itemToSend, keysToRemove);
|
const updatedObject = removeStringKeys(itemToSend, keysToRemove);
|
||||||
console.log(updatedObject, "updatedObject");
|
console.log(updatedObject, "updatedObject");
|
||||||
|
|
||||||
|
|
@ -96,16 +97,6 @@ const EditPage: React.FC = () => {
|
||||||
const oldAnswers = [] as any;
|
const oldAnswers = [] as any;
|
||||||
const newAnswers = [] as any;
|
const newAnswers = [] as any;
|
||||||
|
|
||||||
if (updatedObject?.answers?.length > 0) {
|
|
||||||
const isValidAnswers = updatedObject?.answers?.some(
|
|
||||||
(answer: any) => answer?.isCorrect === 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
// if(!isValidAnswers){
|
|
||||||
// toast.error(t("validation.at_least_one_answer_should_be_correct"));
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
updatedObject?.answers?.forEach((item: any) => {
|
updatedObject?.answers?.forEach((item: any) => {
|
||||||
if (item?.id) {
|
if (item?.id) {
|
||||||
oldAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0 });
|
oldAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0 });
|
||||||
|
|
@ -118,7 +109,6 @@ const EditPage: React.FC = () => {
|
||||||
new: newAnswers,
|
new: newAnswers,
|
||||||
};
|
};
|
||||||
console.log(answers);
|
console.log(answers);
|
||||||
|
|
||||||
mutate({
|
mutate({
|
||||||
...updatedObject,
|
...updatedObject,
|
||||||
answers,
|
answers,
|
||||||
|
|
@ -127,7 +117,10 @@ const EditPage: React.FC = () => {
|
||||||
} else {
|
} else {
|
||||||
console.log(values?.id);
|
console.log(values?.id);
|
||||||
|
|
||||||
const tags = processTags(DataToSend);
|
const tags = processTags(item);
|
||||||
|
console.log(item,"DataToSend");
|
||||||
|
|
||||||
|
console.log(tags,"tags");
|
||||||
mutateAdd({
|
mutateAdd({
|
||||||
...item,
|
...item,
|
||||||
subject_id: subject_id,
|
subject_id: subject_id,
|
||||||
|
|
@ -149,19 +142,17 @@ const EditPage: React.FC = () => {
|
||||||
|
|
||||||
const oldAnswers = [] as any;
|
const oldAnswers = [] as any;
|
||||||
const newAnswers = [] as any;
|
const newAnswers = [] as any;
|
||||||
if (updatedObject?.answers?.length > 0) {
|
|
||||||
// const isValidAnswers = updatedObject?.answers?.some((answer:any) => answer?.isCorrect === 1 || answer?.isCorrect === true)
|
|
||||||
// const isValidAnswers2 = updatedObject?.answers?.filter((answer: any) => answer?.isCorrect === 1 || answer?.isCorrect === true ).length > 1;
|
|
||||||
// console.log(isValidAnswers2);
|
|
||||||
// console.log(isValidAnswers,"isValidAnswers");
|
|
||||||
// if(!isValidAnswers || isValidAnswers2){
|
|
||||||
// toast.error(t("validation.at_least_one_answer_should_be_correct"));
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
updatedObject?.answers?.forEach((item: any) => {
|
updatedObject?.answers?.forEach((item: any) => {
|
||||||
if (item?.id) {
|
if (item?.id) {
|
||||||
oldAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0 });
|
console.log(item,"item");
|
||||||
|
const deletedImage = item?.content_image === null
|
||||||
|
if(deletedImage){
|
||||||
|
oldAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0, content_image:"" });
|
||||||
|
|
||||||
|
}else{
|
||||||
|
oldAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0 });
|
||||||
|
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
newAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0 });
|
newAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0 });
|
||||||
}
|
}
|
||||||
|
|
@ -181,7 +172,6 @@ const EditPage: React.FC = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
navigate(-1);
|
navigate(-1);
|
||||||
|
|
@ -191,6 +181,7 @@ const EditPage: React.FC = () => {
|
||||||
const handleValidateSingleQuestion = (values: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) )
|
||||||
|
|
||||||
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")) ;
|
||||||
|
|
@ -200,6 +191,10 @@ const EditPage: React.FC = () => {
|
||||||
toast.error(t("validation.it_should_have_more_than_one_correct_answers")) ;
|
toast.error(t("validation.it_should_have_more_than_one_correct_answers")) ;
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
if(haveImageOrContent){
|
||||||
|
toast.error(t("validation.one_of_image_and_content_should_be_enter"))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -210,6 +205,7 @@ const handleValidateBaseQuestion = (values: any) => {
|
||||||
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) )
|
||||||
|
|
||||||
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"));
|
||||||
|
|
@ -226,6 +222,12 @@ const handleValidateBaseQuestion = (values: any) => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(haveImageOrContent){
|
||||||
|
toast.error(t("validation.one_of_image_and_content_should_be_enter"))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,13 @@ import TextField from "./TextField";
|
||||||
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 { useObjectToEdit } from "../../../../../zustand/ObjectToEditState";
|
||||||
|
|
||||||
const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => {
|
const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
|
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
const { ShowHint } = useObjectToEdit();
|
||||||
|
|
||||||
const handleDeleteChoice = () => {
|
const handleDeleteChoice = () => {
|
||||||
console.log(index);
|
console.log(index);
|
||||||
|
|
@ -26,6 +28,16 @@ const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
formik.setFieldValue("answers", updatedAnswers);
|
formik.setFieldValue("answers", updatedAnswers);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const values = formik?.values?.answers?.[index] ;
|
||||||
|
const handelCanDeleteAnswers = ()=>{
|
||||||
|
const content = values?.content ;
|
||||||
|
const content_image = values?.content_image ;
|
||||||
|
if(!content && !content_image ){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="ChoiceFields">
|
<div className="ChoiceFields">
|
||||||
|
|
@ -52,32 +64,45 @@ const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
name={index}
|
name={index}
|
||||||
type="Checkbox"
|
type="Checkbox"
|
||||||
/>
|
/>
|
||||||
|
{handelCanDeleteAnswers() ?
|
||||||
|
<p className="delete_question_options" onClick={()=>{handleDeleteChoice()}}>
|
||||||
|
{t("header.delete_choice")}
|
||||||
|
<GoTrash
|
||||||
|
className="trash_icon"
|
||||||
|
|
||||||
|
size={17}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
:
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
title={t("header.this_will_un_do_all_your_changes")}
|
title={t("header.this_will_un_do_all_your_changes")}
|
||||||
okText={t("practical.yes")}
|
okText={t("practical.yes")}
|
||||||
cancelText={t("practical.no")}
|
cancelText={t("practical.no")}
|
||||||
onConfirm={()=>{handleDeleteChoice()}}
|
onConfirm={()=>{handleDeleteChoice()}}
|
||||||
defaultOpen={false}
|
defaultOpen={false}
|
||||||
|
|
||||||
>
|
>
|
||||||
<p className="delete_question_options">
|
<p className="delete_question_options">
|
||||||
{t("header.delete_choice")}
|
{t("header.delete_choice")}
|
||||||
<GoTrash
|
<GoTrash
|
||||||
className="trash_icon"
|
className="trash_icon"
|
||||||
|
|
||||||
size={17}
|
size={17}
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="exercise_form_width">
|
<div className="exercise_form_width">
|
||||||
|
{ShowHint &&
|
||||||
<ValidationField
|
<ValidationField
|
||||||
className=" "
|
className="hint"
|
||||||
placeholder="_"
|
placeholder="_"
|
||||||
name={`answers.${index}.hint`}
|
name={`answers.${index}.hint`}
|
||||||
label="hint"
|
label="hint"
|
||||||
|
|
@ -86,6 +111,8 @@ const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
showCount={false}
|
showCount={false}
|
||||||
autoSize={{ minRows: 2, maxRows: 10 }}
|
autoSize={{ minRows: 2, maxRows: 10 }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,8 @@ const Choices = () => {
|
||||||
{formik?.values?.answers?.map((item: Choice, index: number) => {
|
{formik?.values?.answers?.map((item: Choice, index: number) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
key={index}
|
||||||
|
className="Choices"
|
||||||
>
|
>
|
||||||
<ChoiceFields index={index} data={item} />
|
<ChoiceFields index={index} data={item} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { toast } from "react-toastify";
|
||||||
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 { useObjectToEdit } from "../../../../../../zustand/ObjectToEditState";
|
||||||
|
|
||||||
const ChoiceFields = ({
|
const ChoiceFields = ({
|
||||||
index,
|
index,
|
||||||
|
|
@ -23,7 +24,7 @@ const ChoiceFields = ({
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
|
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
const { ShowHint } = useObjectToEdit();
|
||||||
const handleDeleteChoice = () => {
|
const handleDeleteChoice = () => {
|
||||||
const arrayLength = formik.values.Questions?.[parent_index].answers?.length;
|
const arrayLength = formik.values.Questions?.[parent_index].answers?.length;
|
||||||
|
|
||||||
|
|
@ -42,6 +43,19 @@ const ChoiceFields = ({
|
||||||
formik.setFieldValue(`Questions[${parent_index}].answers`, updatedAnswers);
|
formik.setFieldValue(`Questions[${parent_index}].answers`, updatedAnswers);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const values = formik.values.Questions?.[parent_index]?.answers?.[index] ;
|
||||||
|
console.log(values,"values");
|
||||||
|
|
||||||
|
const handelCanDeleteAnswers = ()=>{
|
||||||
|
const content = values?.content ;
|
||||||
|
const content_image = values?.content_image ;
|
||||||
|
if(!content && !content_image ){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="ChoiceFields">
|
<div className="ChoiceFields">
|
||||||
|
|
@ -71,7 +85,19 @@ const ChoiceFields = ({
|
||||||
parent_index={parent_index}
|
parent_index={parent_index}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Popconfirm
|
|
||||||
|
{handelCanDeleteAnswers() ?
|
||||||
|
<p className="delete_question_options" onClick={()=>{handleDeleteChoice()}} >
|
||||||
|
{t("header.delete_choice")}
|
||||||
|
<GoTrash
|
||||||
|
className="trash_icon"
|
||||||
|
|
||||||
|
size={17}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
:
|
||||||
|
|
||||||
|
<Popconfirm
|
||||||
title={t("header.this_will_un_do_all_your_changes")}
|
title={t("header.this_will_un_do_all_your_changes")}
|
||||||
okText={t("practical.yes")}
|
okText={t("practical.yes")}
|
||||||
cancelText={t("practical.no")}
|
cancelText={t("practical.no")}
|
||||||
|
|
@ -89,12 +115,17 @@ const ChoiceFields = ({
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="exercise_form_width">
|
<div className="exercise_form_width">
|
||||||
|
{ShowHint &&
|
||||||
<ValidationField
|
<ValidationField
|
||||||
className=" "
|
className="hint"
|
||||||
placeholder="_"
|
placeholder="_"
|
||||||
name={`Questions.${parent_index}.answers.${index}.hint`}
|
name={`Questions.${parent_index}.answers.${index}.hint`}
|
||||||
label="hint"
|
label="hint"
|
||||||
|
|
@ -103,6 +134,8 @@ const ChoiceFields = ({
|
||||||
showCount={false}
|
showCount={false}
|
||||||
autoSize={{ minRows: 2, maxRows: 10 }}
|
autoSize={{ minRows: 2, maxRows: 10 }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,8 @@ const Choices = ({ parent_index }: { parent_index: number }) => {
|
||||||
).map((item: Choice, index: number) => {
|
).map((item: Choice, index: number) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
className="Choices ChoicesMalty"
|
||||||
|
key={index}
|
||||||
>
|
>
|
||||||
<ChoiceFields
|
<ChoiceFields
|
||||||
key={index}
|
key={index}
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,12 @@ import { toast } from "react-toastify";
|
||||||
|
|
||||||
const Form = () => {
|
const Form = () => {
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
const { setSuccess, Success, setSavedQuestionData } = useObjectToEdit();
|
const { setSuccess, Success, setSavedQuestionData ,ShowHint} = useObjectToEdit();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSavedQuestionData(formik.values);
|
setSavedQuestionData(formik.values);
|
||||||
}, [formik?.values]);
|
}, [formik?.values]);
|
||||||
|
|
||||||
// console.log(formik?.errors);
|
|
||||||
|
|
||||||
const handleAddChoice = (
|
const handleAddChoice = (
|
||||||
parent_index: number,
|
parent_index: number,
|
||||||
fromKeyCombination: boolean = false,
|
fromKeyCombination: boolean = false,
|
||||||
|
|
@ -94,6 +92,11 @@ const Form = () => {
|
||||||
}
|
}
|
||||||
}, [Success]);
|
}, [Success]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row className="w-100 exercise_form_container">
|
<Row className="w-100 exercise_form_container">
|
||||||
<div className="exercise_form">
|
<div className="exercise_form">
|
||||||
|
|
@ -113,7 +116,7 @@ const Form = () => {
|
||||||
(item: Choice, parent_index: number) => {
|
(item: Choice, parent_index: number) => {
|
||||||
return (
|
return (
|
||||||
<div key={parent_index}>
|
<div key={parent_index}>
|
||||||
<div className="exercise_form">
|
<div className="exercise_form QuestionFIeld">
|
||||||
<QuestionFIeld
|
<QuestionFIeld
|
||||||
key={parent_index}
|
key={parent_index}
|
||||||
index={parent_index}
|
index={parent_index}
|
||||||
|
|
@ -135,6 +138,7 @@ const Form = () => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="exercise_form_width">
|
<div className="exercise_form_width">
|
||||||
|
{ShowHint &&
|
||||||
<ValidationField
|
<ValidationField
|
||||||
className=" "
|
className=" "
|
||||||
placeholder="_"
|
placeholder="_"
|
||||||
|
|
@ -145,6 +149,8 @@ const Form = () => {
|
||||||
autoSize={{ minRows: 2, maxRows: 10 }}
|
autoSize={{ minRows: 2, maxRows: 10 }}
|
||||||
showCount={false}
|
showCount={false}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
}
|
||||||
<MaltySelectTag parent_index={parent_index} />
|
<MaltySelectTag parent_index={parent_index} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,21 @@ const QuestionFIeld = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
formik.setFieldValue(`Questions`, updatedAnswers);
|
formik.setFieldValue(`Questions`, updatedAnswers);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const values = formik.values.Questions?.[index] ;
|
||||||
|
|
||||||
|
const handelCanDeleteAnswers = ()=>{
|
||||||
|
const content = values?.content ;
|
||||||
|
const content_image = values?.content_image ;
|
||||||
|
if(!content && !content_image ){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="exercise_forms">
|
<div className="exercise_forms">
|
||||||
|
|
@ -48,7 +63,22 @@ const QuestionFIeld = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
|
|
||||||
<ImageBoxField name={`Questions.${index}.content_image`} />
|
<ImageBoxField name={`Questions.${index}.content_image`} />
|
||||||
|
|
||||||
<div className="answer_status" >
|
{handelCanDeleteAnswers() ?
|
||||||
|
<div className="answer_status" >
|
||||||
|
<p className="delete_question_options" onClick={()=>{handleDeleteQuestion()}}>
|
||||||
|
{t("header.delete_question")}
|
||||||
|
<GoTrash
|
||||||
|
className="trash_icon"
|
||||||
|
|
||||||
|
size={17}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
:
|
||||||
|
|
||||||
|
<div className="answer_status" >
|
||||||
|
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
title={t("header.this_will_un_do_all_your_changes")}
|
title={t("header.this_will_un_do_all_your_changes")}
|
||||||
okText={t("practical.yes")}
|
okText={t("practical.yes")}
|
||||||
|
|
@ -68,6 +98,9 @@ const QuestionFIeld = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,16 @@ const MaltySelectTag = ({ parent_index }: { parent_index: number }) => {
|
||||||
const [fieldValue, setFieldValue] = useState<string>("");
|
const [fieldValue, setFieldValue] = useState<string>("");
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
const values = formik?.values?.Questions?.[parent_index]?.tags;
|
const values = formik?.values?.Questions?.[parent_index]?.tags;
|
||||||
const handleChange = (value: string[]) => {
|
const [NewAdditionalData, setNewAdditionalData] = useState({})
|
||||||
|
|
||||||
|
const handleChange = (value: string[],option:any) => {
|
||||||
|
const newSelectedOption = option?.pop()
|
||||||
|
const newObject = {
|
||||||
|
id:newSelectedOption?.id,
|
||||||
|
name:newSelectedOption?.name
|
||||||
|
}
|
||||||
|
setNewAdditionalData(newObject)
|
||||||
|
|
||||||
formik.setFieldValue(`Questions.[${parent_index}].tags`, value);
|
formik.setFieldValue(`Questions.[${parent_index}].tags`, value);
|
||||||
setSearchValue("");
|
setSearchValue("");
|
||||||
setFieldValue("");
|
setFieldValue("");
|
||||||
|
|
@ -46,7 +55,22 @@ const MaltySelectTag = ({ parent_index }: { parent_index: number }) => {
|
||||||
(item: any) => item?.id ?? item,
|
(item: any) => item?.id ?? item,
|
||||||
) ?? [];
|
) ?? [];
|
||||||
|
|
||||||
const AllOptions = [...options, ...additionalData];
|
|
||||||
|
const initialData = formik?.values?.Questions[parent_index]?.tags?.filter((item:any)=>{
|
||||||
|
return item?.id
|
||||||
|
|
||||||
|
}) ?? []
|
||||||
|
|
||||||
|
|
||||||
|
const AllOptions = [...options, ...additionalData,NewAdditionalData , ...(initialData)];
|
||||||
|
|
||||||
|
const uniqueOptions = Array.from(
|
||||||
|
new Map(
|
||||||
|
AllOptions
|
||||||
|
.filter(item => Object.keys(item).length > 0) // Filter out empty objects
|
||||||
|
.map(item => [item.id, item]) // Create [id, item] pairs to ensure uniqueness
|
||||||
|
).values()
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="SelectTag">
|
<div className="SelectTag">
|
||||||
|
|
@ -58,7 +82,7 @@ const MaltySelectTag = ({ parent_index }: { parent_index: number }) => {
|
||||||
placeholder=""
|
placeholder=""
|
||||||
fieldNames={{ label: "name", value: "id" }}
|
fieldNames={{ label: "name", value: "id" }}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
options={AllOptions}
|
options={uniqueOptions}
|
||||||
filterOption={false}
|
filterOption={false}
|
||||||
loading={isLoading}
|
loading={isLoading}
|
||||||
notFoundContent={isLoading ? <Spin /> : t("practical.not_found")}
|
notFoundContent={isLoading ? <Spin /> : t("practical.not_found")}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ import { toast } from "react-toastify";
|
||||||
const Form = () => {
|
const Form = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
const { setSuccess, Success } = useObjectToEdit();
|
const { setSuccess, Success,ShowHint } = useObjectToEdit();
|
||||||
|
|
||||||
const handleAddChoice = (fromKeyCombination: boolean = false) => {
|
const handleAddChoice = (fromKeyCombination: boolean = false) => {
|
||||||
formik.setFieldValue("answers", [
|
formik.setFieldValue("answers", [
|
||||||
|
|
@ -68,7 +68,9 @@ const Form = () => {
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
||||||
<div className="exercise_form_width">
|
<div className="exercise_form_width">
|
||||||
|
{ShowHint &&
|
||||||
<ValidationField
|
<ValidationField
|
||||||
className=" "
|
className=" "
|
||||||
placeholder="_"
|
placeholder="_"
|
||||||
|
|
@ -80,6 +82,8 @@ const Form = () => {
|
||||||
autoSize={{ minRows: 2, maxRows: 10 }}
|
autoSize={{ minRows: 2, maxRows: 10 }}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
}
|
||||||
<SelectTag />
|
<SelectTag />
|
||||||
</div>
|
</div>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,6 @@ const TableHeader = () => {
|
||||||
{name:LessonName, path:`lesson/${lesson_id }`}
|
{name:LessonName, path:`lesson/${lesson_id }`}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="TableWithHeader">
|
<div className="TableWithHeader">
|
||||||
<Suspense fallback={<Spin />}>
|
<Suspense fallback={<Spin />}>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import { Question } from "../../../types/Item";
|
import { Question } from "../../../types/Item";
|
||||||
import { toast } from "react-toastify";
|
|
||||||
|
|
||||||
export const getInitialValues = (objectToEdit: Question): any => {
|
export const getInitialValues = (objectToEdit: Question): any => {
|
||||||
const tags = objectToEdit?.tags?.map((item: any, index: number) => {
|
const tags = objectToEdit?.tags?.map((item: any, index: number) => {
|
||||||
|
|
@ -60,7 +59,6 @@ export const getInitialValuesBase = (objectToEdit: Question): any => {
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
console.log(newAnswers,"newAnswers");
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
|
|
@ -123,6 +121,7 @@ export const getValidationSchemaBase = () => {
|
||||||
|
|
||||||
export function processTags(DataToSend: any) {
|
export function processTags(DataToSend: any) {
|
||||||
console.log(DataToSend?.tags);
|
console.log(DataToSend?.tags);
|
||||||
|
console.log(DataToSend);
|
||||||
|
|
||||||
const oldTags = DataToSend?.tags
|
const oldTags = DataToSend?.tags
|
||||||
?.map((item: any, index: number) => {
|
?.map((item: any, index: number) => {
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,16 @@ import { handelImageState } from "../../../../utils/DataToSendImageState";
|
||||||
import LayoutModel from "../../../../Layout/Dashboard/LayoutModel";
|
import LayoutModel from "../../../../Layout/Dashboard/LayoutModel";
|
||||||
import { QueryStatusEnum } from "../../../../enums/QueryStatus";
|
import { QueryStatusEnum } from "../../../../enums/QueryStatus";
|
||||||
import ModelForm from "./ModelForm";
|
import ModelForm from "./ModelForm";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import { ParamsEnum } from "../../../../enums/params";
|
||||||
|
|
||||||
const ModalForm: React.FC = () => {
|
const ModalForm: React.FC = () => {
|
||||||
const { objectToEdit } = useObjectToEdit((state) => state);
|
const { objectToEdit } = useObjectToEdit((state) => state);
|
||||||
|
|
||||||
const { mutate, status } = useUpdateSubject();
|
const { mutate, status } = useUpdateSubject();
|
||||||
|
const {subject_id} = useParams<ParamsEnum>()
|
||||||
const handleSubmit = (values: any) => {
|
const handleSubmit = (values: any) => {
|
||||||
const Data_to_send = { ...values };
|
const Data_to_send = { ...values,subject_id };
|
||||||
const handelImage = handelImageState(Data_to_send, "icon");
|
const handelImage = handelImageState(Data_to_send, "icon");
|
||||||
mutate(handelImage);
|
mutate(handelImage);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
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 useFilter from "../../Components/FilterField/components/useFilter";
|
||||||
|
import { Select } from "antd";
|
||||||
|
|
||||||
const Dummy = () => {
|
const Dummy = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
@ -8,12 +9,15 @@ const Dummy = () => {
|
||||||
return (
|
return (
|
||||||
<div className="DummyHomePage">
|
<div className="DummyHomePage">
|
||||||
|
|
||||||
<FilterButton/>
|
{/* <FilterButton/>
|
||||||
<FilterBody>
|
<FilterBody>
|
||||||
karim
|
karim
|
||||||
</FilterBody>
|
</FilterBody>
|
||||||
|
<Select
|
||||||
|
style={{width:"200px"}}
|
||||||
|
showSearch
|
||||||
|
/> */}
|
||||||
|
|
||||||
karim2
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
.filter_header {
|
.filter_header {
|
||||||
padding: 20px 20px;
|
padding: 20px 20px;
|
||||||
border-radius: 10px 10px 0 0;
|
border-radius: 10px 10px 0 0;
|
||||||
box-shadow: 2px 2px 7px 2px rgba(0, 0, 0, 0.1);
|
box-shadow: 0px 0px 32px 2px #080F3414;
|
||||||
|
|
||||||
>div {
|
>div {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -105,15 +105,3 @@
|
||||||
.model_sub_children {
|
.model_sub_children {
|
||||||
padding-bottom: 30px;
|
padding-bottom: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-select-selection-search {
|
|
||||||
// color: var(--value) !important;
|
|
||||||
// display: none !important;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
:where(.css-dev-only-do-not-override-oad6qy).ant-select-single.ant-select-lg .ant-select-selector .ant-select-selection-search {
|
|
||||||
input {}
|
|
||||||
}
|
|
||||||
|
|
||||||
:where(.css-dev-only-do-not-override-oad6qy).ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-search-input {}
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
@import "./Layout.scss";
|
@import "./Layout.scss";
|
||||||
@import "./SideBar.scss";
|
@import "./SideBar.scss";
|
||||||
@import "./DataTable.scss";
|
@import "./DataTable.scss";
|
||||||
|
|
||||||
@import "./DataState.scss";
|
@import "./DataState.scss";
|
||||||
@import "./PageHeader.scss";
|
@import "./PageHeader.scss";
|
||||||
@import "./FilterLayout.scss";
|
@import "./FilterLayout.scss";
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,7 @@
|
||||||
|
|
||||||
.exercise_add_header {
|
.exercise_add_header {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
gap: 30px;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 14px 20px;
|
padding: 14px 20px;
|
||||||
|
|
@ -142,6 +143,7 @@
|
||||||
box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, 0.1);
|
box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, 0.1);
|
||||||
div{
|
div{
|
||||||
margin-left: 25px;
|
margin-left: 25px;
|
||||||
|
display: flex;
|
||||||
}
|
}
|
||||||
img {
|
img {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
@ -263,3 +265,48 @@
|
||||||
font-size: 19px;
|
font-size: 19px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.Choices{
|
||||||
|
padding-inline: 20px;
|
||||||
|
.textarea_exercise,.hint{
|
||||||
|
width: calc(50vw - 10px) !important;
|
||||||
|
}
|
||||||
|
.ValidationField{
|
||||||
|
|
||||||
|
.text{
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.QuestionFIeld{
|
||||||
|
padding-inline: 10px;
|
||||||
|
.textarea_exercise{
|
||||||
|
width: calc(50vw - 10px) !important;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.ValidationField{
|
||||||
|
.text{
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.Choices.ChoicesMalty{
|
||||||
|
.textarea_exercise,.hint{
|
||||||
|
width: calc(50vw - 20px) !important;
|
||||||
|
}
|
||||||
|
.ValidationField{
|
||||||
|
|
||||||
|
.text{
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.question_header_setting{
|
||||||
|
margin-inline: 40px;
|
||||||
|
}
|
||||||
|
|
@ -53,7 +53,7 @@ function useAxios() {
|
||||||
console.log(error?.response);
|
console.log(error?.response);
|
||||||
|
|
||||||
const status = error?.request?.status;
|
const status = error?.request?.status;
|
||||||
const errorMsg = error?.response?.data?.message;
|
const errorMsg = error?.response?.data?.error;
|
||||||
const errorField = error?.response?.data;
|
const errorField = error?.response?.data;
|
||||||
const method = error.config.method;
|
const method = error.config.method;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ import { useMutation, UseMutationResult } from "react-query";
|
||||||
import useAxios from "./useAxios";
|
import useAxios from "./useAxios";
|
||||||
import { HEADER_KEY } from "../config";
|
import { HEADER_KEY } from "../config";
|
||||||
import { AxiosResponse } from "../../types/Axios";
|
import { AxiosResponse } from "../../types/Axios";
|
||||||
|
import { useDataTableState } from "../../zustand/TabState";
|
||||||
|
import { useFilterStateState } from "../../zustand/Filter";
|
||||||
|
|
||||||
type DataToSend = {
|
type DataToSend = {
|
||||||
id?: number | string | any;
|
id?: number | string | any;
|
||||||
|
|
@ -14,8 +16,12 @@ function useDeleteMutation(
|
||||||
toast: boolean = true,
|
toast: boolean = true,
|
||||||
): UseMutationResult<AxiosResponse, unknown, DataToSend, unknown> {
|
): UseMutationResult<AxiosResponse, unknown, DataToSend, unknown> {
|
||||||
const axios = useAxios();
|
const axios = useAxios();
|
||||||
|
const {DataTableLength} = useDataTableState()
|
||||||
|
const { setFilter ,Filter } = useFilterStateState();
|
||||||
|
const page = Filter?.page ;
|
||||||
return useMutation<AxiosResponse, unknown, DataToSend, unknown>(
|
return useMutation<AxiosResponse, unknown, DataToSend, unknown>(
|
||||||
async (dataToSend) => {
|
async (dataToSend) => {
|
||||||
|
|
||||||
const { data } = await axios.delete(url + `/` + dataToSend?.id, {
|
const { data } = await axios.delete(url + `/` + dataToSend?.id, {
|
||||||
headers: {
|
headers: {
|
||||||
[HEADER_KEY]: key,
|
[HEADER_KEY]: key,
|
||||||
|
|
@ -25,7 +31,21 @@ function useDeleteMutation(
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
);
|
{
|
||||||
|
onSuccess : (data) =>{
|
||||||
|
if(DataTableLength === 1 && page > 1){
|
||||||
|
setFilter(
|
||||||
|
{
|
||||||
|
...Filter,
|
||||||
|
page: page - 1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useDeleteMutation;
|
export default useDeleteMutation;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
import { useQuery } from "react-query";
|
import { useQuery } from "react-query";
|
||||||
import useAxios from "./useAxios";
|
import useAxios from "./useAxios";
|
||||||
import { useLocation } from "react-router-dom";
|
|
||||||
import { PaginationParams } from "../utils/PaginationParams";
|
|
||||||
import { filterParams } from "../utils/filterParams";
|
import { filterParams } from "../utils/filterParams";
|
||||||
import { useFilterStateState } from "../../zustand/Filter";
|
import { useFilterStateState } from "../../zustand/Filter";
|
||||||
function useGetQuery(
|
function useGetQuery(
|
||||||
|
|
@ -13,11 +11,9 @@ function useGetQuery(
|
||||||
const axios = useAxios();
|
const axios = useAxios();
|
||||||
const { show, pagination, ...remainingParams } = params;
|
const { show, pagination, ...remainingParams } = params;
|
||||||
|
|
||||||
const location = useLocation();
|
const { Filter } = useFilterStateState();
|
||||||
const { Filter ,setFilter } = useFilterStateState();
|
|
||||||
const page = Filter?.page ;
|
const page = Filter?.page ;
|
||||||
const per_page = Filter?.per_page ;
|
const per_page = Filter?.per_page ;
|
||||||
// const { per_page } = PaginationParams(location);
|
|
||||||
|
|
||||||
const paramToSend = pagination
|
const paramToSend = pagination
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,8 @@
|
||||||
"at_least_one_answer_should_be_correct": "يجب أن تكون إجابة واحدة صحيحة",
|
"at_least_one_answer_should_be_correct": "يجب أن تكون إجابة واحدة صحيحة",
|
||||||
"it_should_have_more_than_one_answers": "يجب أن يحتوي على أكثر من إجابة",
|
"it_should_have_more_than_one_answers": "يجب أن يحتوي على أكثر من إجابة",
|
||||||
"it_should_have_more_than_one_correct_answers": "يجب أن يحتوي على إجابة صحيحة",
|
"it_should_have_more_than_one_correct_answers": "يجب أن يحتوي على إجابة صحيحة",
|
||||||
"File_size_exceeds_2_MB_limit.":"حجم الملف يتجاوز الحد الأقصى البالغ 2 ميجابايت"
|
"File_size_exceeds_2_MB_limit.":"حجم الملف يتجاوز الحد الأقصى البالغ 2 ميجابايت",
|
||||||
|
"one_of_image_and_content_should_be_enter":"يجب إدخال صورة أو محتوى واحد على الأقل"
|
||||||
},
|
},
|
||||||
"header": {
|
"header": {
|
||||||
"register_students": "تسجيل الطلاب",
|
"register_students": "تسجيل الطلاب",
|
||||||
|
|
@ -138,7 +139,9 @@
|
||||||
"change": "تغيير",
|
"change": "تغيير",
|
||||||
"role_list": "قائمة الأدوار",
|
"role_list": "قائمة الأدوار",
|
||||||
"managers":"مدراء",
|
"managers":"مدراء",
|
||||||
"sales":"المبيعات"
|
"sales":"المبيعات",
|
||||||
|
"hide_hint":"اخفاء الشرح",
|
||||||
|
"show_hint":"عرض الشرح"
|
||||||
},
|
},
|
||||||
"columns": {
|
"columns": {
|
||||||
"id": "الرقم التعريفي",
|
"id": "الرقم التعريفي",
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ export function removeStringKeys(obj: any, keysToRemove: string[]): any {
|
||||||
// Check if the value is a string or "null" and the key is in keysToRemove
|
// Check if the value is a string or "null" and the key is in keysToRemove
|
||||||
if (
|
if (
|
||||||
keysToRemove.includes(key) &&
|
keysToRemove.includes(key) &&
|
||||||
(typeof value === "string" || value === "null")
|
(typeof value === "string")
|
||||||
) {
|
) {
|
||||||
delete obj[key];
|
delete obj[key];
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,13 @@ interface ModelState {
|
||||||
|
|
||||||
SavedQuestionData: any;
|
SavedQuestionData: any;
|
||||||
setSavedQuestionData: (data: any) => void;
|
setSavedQuestionData: (data: any) => void;
|
||||||
|
|
||||||
|
ShowHint: any;
|
||||||
|
setShowHint: (data: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useObjectToEdit = create<ModelState>((set) => ({
|
export const useObjectToEdit = create<ModelState>((set) => ({
|
||||||
c: null,
|
objectToEdit: null,
|
||||||
setObjectToEdit: (data) => set(() => ({ objectToEdit: data })),
|
setObjectToEdit: (data) => set(() => ({ objectToEdit: data })),
|
||||||
OldObjectToEdit: null,
|
OldObjectToEdit: null,
|
||||||
setOldObjectToEdit: (data) => set(() => ({ OldObjectToEdit: data })),
|
setOldObjectToEdit: (data) => set(() => ({ OldObjectToEdit: data })),
|
||||||
|
|
@ -49,4 +52,6 @@ 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: true,
|
||||||
|
setShowHint: (data) => set(() => ({ ShowHint: data })),
|
||||||
}));
|
}));
|
||||||
|
|
|
||||||
12
src/zustand/TabState.ts
Normal file
12
src/zustand/TabState.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { create } from "zustand";
|
||||||
|
|
||||||
|
interface DataTableState {
|
||||||
|
|
||||||
|
DataTableLength: number;
|
||||||
|
setDataTableLength: (Key: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useDataTableState = create<DataTableState>((set) => ({
|
||||||
|
DataTableLength: 0,
|
||||||
|
setDataTableLength: (Key) => set((state) => ({ DataTableLength: Key })),
|
||||||
|
}));
|
||||||
Loading…
Reference in New Issue
Block a user