add filter

This commit is contained in:
karimaldeen 2024-09-15 12:53:32 +03:00
parent 21cbcc91bb
commit e8e50d0526
16 changed files with 196 additions and 130 deletions

View File

@ -1,7 +1,5 @@
import React, { useState, useEffect, useRef } from "react";
import { useTranslation } from "react-i18next";
import { IoSearch } from "react-icons/io5";
import { useLocation, useNavigate } from "react-router-dom";
import { useFilterStateState } from "../../zustand/Filter";
import { useDebounce } from "../../utils/useDebounce";
@ -15,15 +13,16 @@ const SearchField: React.FC<Props> = ({ placeholder, searchBy }) => {
const [searchQuery, setSearchQuery] = useState<string>("");
const inputRef = useRef<HTMLInputElement>(null);
const { setFilter } = useFilterStateState();
const { setFilter,Filter } = useFilterStateState();
const handleInputChange = (value: string) => {
setSearchQuery(value);
};
console.log(searchBy,"searchBy");
const handleInputChangeWithDebounce = useDebounce((value: string) => {
setFilter({
name: value,
[searchBy]: value,
});
});

View File

@ -7,7 +7,7 @@
margin-bottom: 10px;
position: relative;
min-height: 80px;
padding-inline: 20px;
// padding-inline: 20px;
> * {
width: 100% !important;
min-width: 150px;

View File

@ -14,9 +14,13 @@ import useFilter from "../../Components/Utils/Filter/useFilter";
const FilterLayout = ({
filterTitle,
sub_children,
search_by = "name",
width = "500px"
}: {
filterTitle: string;
sub_children: any;
search_by?:string
width?:string
}) => {
const { t } = useTranslation();
const translateArray = translateOptions(search_array, t);
@ -37,6 +41,7 @@ const FilterLayout = ({
ModelClassName="filter_model_direction"
isOpen={isOpen}
setIsOpen={setIsOpen}
width={width}
>
<div className="model_sub_children">{sub_children}</div>
<FilterSubmit />
@ -66,7 +71,7 @@ const FilterLayout = ({
</span>
<div className="header_search">
<SearchField searchBy="" placeholder={t("practical.search_here")} />
<SearchField searchBy={search_by} placeholder={t("practical.search_here")} />
</div>
</div>
</div>

View File

@ -27,12 +27,6 @@ const PageHeader = ({
const { t } = useTranslation();
const PrevPath = getPrevPathRoute(location.pathname);
const handelNavigate = () => {
if (PrevPath === 0) {
return;
}
navigate(deletePathSegments(location.pathname, PrevPath));
};
const handleNavigateToPage = (location: string) => {
navigate(location);
};
@ -41,7 +35,7 @@ const PageHeader = ({
return (
<div className="page_header">
<header className="d-flex justify-content-between">
<span className="page_header_links" onClick={handelNavigate}>
<span className="page_header_links" >
<h1 className="page_title">{t(`PageTitle.${pageTitle}`)}</h1>
<span className="page_links">
<PageTitleComponent/>

View File

@ -1,33 +0,0 @@
import React from "react";
import { getInitialValues, getValidationSchema } from "./formUtil";
import { ModalEnum } from "../../../../enums/Model";
import LayoutModel from "../../../../Layout/Dashboard/LayoutModel";
import { QueryStatusEnum } from "../../../../enums/QueryStatus";
import ModelForm from "./ModelForm";
import { useAddGrade } from "../../../../api/grade";
const AddModel: React.FC = () => {
const { mutate, status } = useAddGrade();
const handleSubmit = (values: any) => {
mutate({
...values,
});
};
return (
<>
<LayoutModel
status={status as QueryStatusEnum}
ModelEnum={ModalEnum.GRADE_ADD}
modelTitle="grade"
handleSubmit={handleSubmit}
getInitialValues={getInitialValues({})}
getValidationSchema={getValidationSchema}
>
<ModelForm />
</LayoutModel>
</>
);
};
export default AddModel;

View File

@ -1,38 +0,0 @@
import React from "react";
import { getInitialValues, getValidationSchema } from "./formUtil";
import { ModalEnum } from "../../../../enums/Model";
import LayoutModel from "../../../../Layout/Dashboard/LayoutModel";
import ModelForm from "./ModelForm";
import { QueryStatusEnum } from "../../../../enums/QueryStatus";
import { useObjectToEdit } from "../../../../zustand/ObjectToEditState";
import { useUpdateQuestion } from "../../../../api/Question";
import { handelImageState } from "../../../../utils/DataToSendImageState";
const EditModel: React.FC = () => {
const { mutate, status } = useUpdateQuestion();
const { objectToEdit } = useObjectToEdit((state) => state);
const handleSubmit = (values: any) => {
const Data_to_send = { ...values };
const handelImage = handelImageState(Data_to_send, "icon");
mutate(handelImage);
};
return (
<>
<LayoutModel
status={status as QueryStatusEnum}
ModelEnum={ModalEnum.QUESTION_BANK_EDIT}
modelTitle="QuestionBank"
handleSubmit={handleSubmit}
getInitialValues={getInitialValues(objectToEdit)}
getValidationSchema={getValidationSchema}
isAddModal={false}
>
<ModelForm />
</LayoutModel>
</>
);
};
export default EditModel;

View File

@ -2,15 +2,141 @@ import React from "react";
import ValidationField from "../../../../Components/ValidationField/ValidationField";
import { Col, Row } from "reactstrap";
import { useFormikContext } from "formik";
import { useGetAllGrade } from "../../../../api/grade";
import { useValidationValidationParamState } from "../../../../Components/ValidationField/state/ValidationValidationParamState";
import { useGetAllUnit } from "../../../../api/unit";
import { useGetAllSubject } from "../../../../api/subject";
import { useGetAllLesson } from "../../../../api/lesson";
const FilterForm = () => {
const formik = useFormikContext();
const { ValidationParamState } = useValidationValidationParamState();
const {
GradeName, GradeCurrentPage,
SubjectName, SubjectCurrentPage,
UnitName, UnitCurrentPage,
LessonName, LessonCurrentPage
} = ValidationParamState;
const { data: Grade, isLoading: isLoadingGrade } = useGetAllGrade({
name: GradeName,
page: GradeCurrentPage
});
const GradeOption = Grade?.data ?? []
const canChangeGradePage = !!Grade?.links?.next;
const GradePage = Grade?.meta?.currentPage;
/// subject_id
const { data: Subject, isLoading: isLoadingSubject } = useGetAllSubject({
name: SubjectName,
page: SubjectCurrentPage
});
const SubjectOption = Subject?.data ?? []
const canChangeSubjectPage = !!Subject?.links?.next;
const SubjectPage = Subject?.meta?.currentPage;
/// unit_id
const { data: Unit, isLoading: isLoadingUnit } = useGetAllUnit({
name: UnitName,
page: UnitCurrentPage
});
const UnitOption = Unit?.data ?? []
const canChangeUnitPage = !!Unit?.links?.next;
const UnitPage = Unit?.meta?.currentPage;
/// lessonsIds
const { data: Lesson, isLoading: isLoadingLesson } = useGetAllLesson({
name: LessonName,
page: LessonCurrentPage
});
const LessonOption = Lesson?.data ?? []
const canChangeLessonPage = !!Lesson?.links?.next;
const LessonPage = Lesson?.meta?.currentPage;
return (
<div>
<Row>
<Col>
<ValidationField placeholder="name" label="name" name="name" />
{/*
grade_id
*/}
<ValidationField
searchBy="GradeName"
name="grade_id"
label="grade"
type="Search"
option={GradeOption}
isLoading={isLoadingGrade}
canChangePage={canChangeGradePage}
PageName={"GradeCurrentPage"}
page={GradePage}
/>
{/*
subject_id
*/}
<ValidationField
searchBy="SubjectName"
name="subject_id"
label="subject"
type="Search"
option={SubjectOption}
isLoading={isLoadingSubject}
canChangePage={canChangeSubjectPage}
PageName={"SubjectCurrentPage"}
page={SubjectPage}
/>
</Col>
<Col>
{/*
unit_id
*/}
<ValidationField
searchBy="UnitName"
name="unit_id"
label="unit"
type="Search"
option={UnitOption}
isLoading={isLoadingUnit}
canChangePage={canChangeUnitPage}
PageName={"UnitCurrentPage"}
page={UnitPage}
/>
{/*
lessonsIds
*/}
<ValidationField
searchBy="LessonName"
name="lessonsIds"
label="lesson"
type="Search"
option={LessonOption}
isMulti
isLoading={isLoadingLesson}
canChangePage={canChangeLessonPage}
PageName={"LessonCurrentPage"}
page={LessonPage}
/>
</Col>
</Row>
</div>

View File

@ -1,19 +0,0 @@
import * as Yup from "yup";
import { Grade, GradeInitialValues } from "../../../../types/Grade";
export const getInitialValues = (
objectToEdit: Partial<Grade>,
): GradeInitialValues => {
return {
id: objectToEdit?.id,
name: objectToEdit?.name ?? "",
icon: objectToEdit?.icon ?? "",
};
};
export const getValidationSchema = () => {
// validate input
return Yup.object().shape({
name: Yup.string().required("validation.required"),
});
};

View File

@ -10,8 +10,6 @@ import FilterForm from "./Model/FilterForm";
import { canAddQuestionBank } from "../../../utils/hasAbilityFn";
const Table = lazy(() => import("./Table"));
const AddModalForm = lazy(() => import("./Model/AddModel"));
const EditModalForm = lazy(() => import("./Model/EditModel"));
const DeleteModalForm = lazy(
() => import("../../../Layout/Dashboard/DeleteModels"),
);
@ -33,10 +31,8 @@ const TableHeader = () => {
ModelAbility={ModalEnum?.QUESTION_BANK_ADD}
canAdd={canAddQuestionBank}
/>
<FilterLayout sub_children={<FilterForm />} filterTitle="table.QuestionBank" />
<FilterLayout width="700px" search_by="content" sub_children={<FilterForm />} filterTitle="table.QuestionBank" />
<Table />
<AddModalForm />
<EditModalForm />
<DeleteModalForm
deleteMutation={deleteMutation}
ModelEnum={ModalEnum?.QUESTION_BANK_DELETE}

View File

@ -3,13 +3,20 @@ import React from "react";
import DataTable from "../../../Layout/Dashboard/Table/DataTable";
import { useGetAllQuestion } from "../../../api/Question";
import { useFilterState } from "../../../Components/Utils/Filter/FilterState";
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
import { useFilterStateState } from "../../../zustand/Filter";
const App: React.FC = () => {
const { filterState } = useFilterState();
const { setFilter,Filter } = useFilterStateState();
console.log(filterState,"filterState");
const response = useGetAllQuestion({
pagination: true,
...filterState,
content:Filter?.content
});
return <DataTable response={response} useColumns={useColumns} />;

View File

@ -1,6 +1,5 @@
import { TableColumnsType } from "antd";
import { Question } from "../../../types/Item";
import { FaPlus } from "react-icons/fa";
import { ModalEnum } from "../../../enums/Model";
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
import { useTranslation } from "react-i18next";
@ -8,7 +7,6 @@ import { ABILITIES_ENUM } from "../../../enums/abilities";
import { useNavigate } from "react-router-dom";
import { useModalState } from "../../../zustand/Modal";
import {
canAddQuestion,
canDeleteQuestion,
canEditQuestion,
} from "../../../utils/hasAbilityFn";
@ -19,19 +17,18 @@ export const useColumns = () => {
const navigate = useNavigate();
const { setIsOpen } = useModalState((state) => state);
const handelAdd = () => {
setObjectToEdit({});
navigate(`${ABILITIES_ENUM?.QUESTION}/add`);
};
const handelDelete = (data: any) => {
setObjectToEdit(data);
setIsOpen(ModalEnum?.QUESTION_DELETE);
};
const handleEdit = (record: any) => {
setObjectToEdit(record);
navigate(`${ABILITIES_ENUM?.QUESTION}/${record?.id}`);
console.log(record,"record");
const lesson = record?.lessons?.[0] ;
const unit = lesson?.unit;
const subject = unit?.subject;
const grade = subject?.grade;
navigate(`/${ABILITIES_ENUM?.GRADE}/${grade?.id}/${ABILITIES_ENUM?.SUBJECT}/${subject?.id}/${ABILITIES_ENUM?.UNIT}/${unit?.id}/${ABILITIES_ENUM?.LESSON}/${lesson?.id}/${ABILITIES_ENUM?.QUESTION}/${record?.id}`);
};
const [t] = useTranslation();
@ -51,6 +48,24 @@ export const useColumns = () => {
render: (text, record) => record?.content,
ellipsis: true,
},
{
title: `${t("columns.course")}`,
dataIndex: "lessons",
key: "lessons",
align: "center",
render: (text, record) => {
const lesson = record?.lessons?.[0] ;
const unit = lesson?.unit;
const subject = unit?.subject;
const grade = subject?.grade;
return (
<> {grade?.name} </>
)
},
ellipsis: true,
},
{
title: `${t("columns.hint")}`,
dataIndex: "hint",

View File

@ -61,6 +61,9 @@
border-radius: var(--border-radius);
transition: 1s ease-in-out;
animation: fadeInRight 1s ease-in-out;
max-height: 90vh;
overflow-y: scroll;
@include Scrollbar;
> header {
display: flex;

View File

@ -85,3 +85,8 @@
font-size: 8px !important;
}
}
.model_sub_children{
padding-bottom: 30px;
}

View File

@ -209,12 +209,12 @@
}
.SelectTag {
padding-inline: 20px;
// padding-inline: 20px;
}
.exercise_add {
.add_new_button {
padding-inline: 20px !important;
// padding-inline: 20px !important;
}
}
@ -229,12 +229,12 @@
display: flex;
align-items: center;
justify-content: center;
>{
flex: 1;
min-height: auto;
min-width: 30px;
// >{
// flex: 1;
// min-height: auto;
// min-width: 30px;
}
// }
.ant-btn{
min-height: 30px !important;
max-height: 30px !important;

View File

@ -192,7 +192,8 @@
"base_question": " تمرين متعدد ",
"normal_question": " تمرين عادي",
"hint":"شرح ",
"tags":"كلمات مفتاحية"
"tags":"كلمات مفتاحية",
"course":" الصفوف"
},
"practical": {
"to_confirm_deletion_please_re_enter": "لتأكيد الحذف، يرجى إعادة الإدخال",
@ -428,7 +429,11 @@
"Seller Percentage": "نسبة البائع",
"city": "المحافظة",
"personal_image": "صورة شخصية",
"id_image": "صورة الهوية"
"id_image": "صورة الهوية",
"grade":"الصفوف",
"subject":"المادة",
"unit":"الوحدة",
"lesson":"الدرس"
},
"select": {
"enums": {

View File

@ -315,7 +315,8 @@ export interface Question {
question_options_count?: any;
answers: QuestionOption[];
hint?: string;
tags: tags[]; // Assuming tags are strings, adjust as per actual data type
tags: tags[];
lessons:any
}
export type report = {