This commit is contained in:
karimaldeen 2024-09-12 16:54:48 +03:00
parent bd59108fdc
commit 9f433d3f9b
107 changed files with 828 additions and 772 deletions

View File

@ -11,7 +11,6 @@ import { RoleByType } from "./utils/RoleByType";
const Page404 = lazy(() => import("./Layout/Ui/NotFoundPage"));
const Auth = lazy(() => import("./Pages/Auth/Page"));
const App = () => {
return (
<Routes>
<Route
@ -37,8 +36,8 @@ const App = () => {
{CrudRoute.map((route) => {
const useAbility = hasAbility(route.abilities, route.abilities_value);
if(!RoleByType(route)){
return false ;
if (!RoleByType(route)) {
return false;
}
if (!useAbility) {
return false;

View File

@ -43,12 +43,10 @@ const SelectTag: React.FC = () => {
? [{ id: searchValue, name: searchValue }]
: [];
const value =
formik?.values?.tags?.map((item: any) => item?.id ?? item) ?? [];
const value = formik?.values?.tags?.map((item: any) => item?.id ?? item) ?? [];
const AllOptions = [...options, ...additionalData]
const AllOptions = [...options, ...additionalData];
return (
<div className="SelectTag">

View File

@ -15,22 +15,17 @@ const SearchField: React.FC<Props> = ({ placeholder, searchBy }) => {
const [searchQuery, setSearchQuery] = useState<string>("");
const inputRef = useRef<HTMLInputElement>(null);
const {setFilter} = useFilterStateState()
const { setFilter } = useFilterStateState();
const handleInputChange = (value: string) => {
setSearchQuery(value);
};
const handleInputChangeWithDebounce = useDebounce(
(value: string) => {
const handleInputChangeWithDebounce = useDebounce((value: string) => {
setFilter({
name:value
})
}
)
name: value,
});
});
const handleToggleDropdown = () => {
setIsOpen(!isOpen);
@ -60,7 +55,10 @@ const SearchField: React.FC<Props> = ({ placeholder, searchBy }) => {
className="search__input"
placeholder={t(placeholder)}
value={searchQuery}
onChange={(e) => {handleInputChange(e.target.value) ; handleInputChangeWithDebounce(e.target.value)}}
onChange={(e) => {
handleInputChange(e.target.value);
handleInputChangeWithDebounce(e.target.value);
}}
/>
</div>
</div>

View File

@ -6,11 +6,11 @@ import { useFilterStateState } from "../../zustand/Filter";
const OrderBySelect = () => {
const { t } = useTranslation();
const {setFilter} = useFilterStateState()
const { setFilter } = useFilterStateState();
const handleChange = (value: string) => {
setFilter({
sort_by:value
})
sort_by: value,
});
};
return (
@ -29,8 +29,14 @@ const OrderBySelect = () => {
options={[
{ value: "ascending", label: t("select.array.order.ascending") },
{ value: "descending", label: t("select.array.order.descending") },
{ value: "recently_viewed", label: t("select.array.order.recently_viewed") },
{ value: "recently_arrived", label: t("select.array.order.recently_arrived") },
{
value: "recently_viewed",
label: t("select.array.order.recently_viewed"),
},
{
value: "recently_arrived",
label: t("select.array.order.recently_arrived"),
},
]}
/>
</div>

View File

@ -4,7 +4,6 @@ import { Divider, Select } from "antd";
import usePagination from "../../Layout/Dashboard/usePagination";
import { useNavigate } from "react-router-dom";
const PaginationColumn = () => {
const { t } = useTranslation();
const navigate = useNavigate();
@ -13,7 +12,6 @@ const PaginationColumn = () => {
navigate(`?per_page=${value}`);
};
return (
<div className="pagination_column">
<Select

View File

@ -1,30 +1,20 @@
import React from 'react'
import React from "react";
interface IFilterBody {
children:React.ReactNode
children: React.ReactNode;
}
const useFilter = () => {
const FilterButton = ()=>{
return (
<div>
FilterButton
</div>
)
}
const FilterBody = ({children}:IFilterBody)=>{
return (
<div>
FilterBody
</div>
)
}
const FilterButton = () => {
return <div>FilterButton</div>;
};
const FilterBody = ({ children }: IFilterBody) => {
return <div>FilterBody</div>;
};
return {
FilterButton , FilterBody
}
}
FilterButton,
FilterBody,
};
};
export default useFilter
export default useFilter;

View File

@ -1,5 +1,3 @@
export enum FilterEnum {
FILTER="FILTER"
FILTER = "FILTER",
}

View File

@ -21,14 +21,6 @@ export const useFilterState = create<FilterState>((set, get) => ({
},
}));
// import { create } from "zustand";
// interface FilterState {

View File

@ -1,6 +1,12 @@
import React, { ReactNode, useEffect, useState } from "react";
import { FaFilter } from "react-icons/fa";
import { Form, Formik, FormikConfig, FormikHelpers, useFormikContext } from "formik";
import {
Form,
Formik,
FormikConfig,
FormikHelpers,
useFormikContext,
} from "formik";
import { Button, ButtonProps, Divider, Modal } from "antd";
import { useTranslation } from "react-i18next";
import { useModalState } from "./Modal";
@ -38,7 +44,7 @@ const useFilter = () => {
const { filterState, setFilterState, clearFilterState } = useFilterState();
const [t] = useTranslation();
const [formValues, setFormValues] = useState({});
const formik = useFormikContext()
const formik = useFormikContext();
// Define the type for the callback
type SubmitCallback = () => void;
// console.log(formik?.values);
@ -63,12 +69,9 @@ const useFilter = () => {
);
};
useEffect(() => {
setFormValues({})
setFilterState({})
}, [])
setFormValues({});
setFilterState({});
}, []);
const FilterBody = ({
onSubmit,
@ -93,10 +96,9 @@ const useFilter = () => {
setIsOpen("");
};
const handleCancel = (isCancel = false) => {
if(isCancel){
if (isCancel) {
setIsOpen("");
return ;
return;
}
setIsOpen("");
@ -119,7 +121,7 @@ const useFilter = () => {
footer={null}
open={isOpen}
onOk={handleOpen}
onCancel={()=>{}}
onCancel={() => {}}
mask={false}
style={{ position: "absolute", top: "31.4%", left: "16.7%" }}
>
@ -127,16 +129,20 @@ const useFilter = () => {
enableReinitialize={true}
onSubmit={handleSubmit}
initialValues={formValues}
onReset={()=>{handleCancel(false)}}
onReset={() => {
handleCancel(false);
}}
{...formikProps}
>
{(formik) => {
return (
<Form>
<div>
<header> {t("models.filter")} <FaXmark onClick={()=>handleCancel(true)} /> </header>
<header>
{" "}
{t("models.filter")}{" "}
<FaXmark onClick={() => handleCancel(true)} />{" "}
</header>
<Divider />
<main className="main_modal">
{isLoading ? <SpinContainer /> : children}
@ -144,25 +150,31 @@ const useFilter = () => {
</main>
</div>
</Form>
)
);
}}
</Formik>
</Modal>
</>
);
};
interface SubmitButtonProps extends Omit<ButtonProps, "loading"> {
}
interface SubmitButtonProps extends Omit<ButtonProps, "loading"> {}
const FilterSubmit = ({ ...buttonProps }: SubmitButtonProps) => {
return (
<div className="filter-submit-buttons buttons">
<Button className="back_button filter_modal_add_button" type="default" htmlType="reset">
<Button
className="back_button filter_modal_add_button"
type="default"
htmlType="reset"
>
{t("practical.reset")}
</Button>
<Button className="add_button pointer filter_modal_add_button" type="primary" {...buttonProps} htmlType="submit">
<Button
className="add_button pointer filter_modal_add_button"
type="primary"
{...buttonProps}
htmlType="submit"
>
{t(`practical.submit`)}
</Button>
</div>
@ -186,5 +198,4 @@ const useFilter = () => {
};
};
export default useFilter;

View File

@ -16,7 +16,7 @@ const Default = ({
label_icon,
...props
}: any) => {
const { errorMsg, isError, t,formik } = useFormField(name, props);
const { errorMsg, isError, t, formik } = useFormField(name, props);
return (
<div className="ValidationField w-100">

View File

@ -26,19 +26,23 @@ const Header = () => {
}
};
const content = (
const content = (
<div>
<p> (CTRL + SHIFT + {CombinationKeyEnum.CHOICE}) {t("header.add_choice")} </p>
<p> (CTRL + SHIFT + {CombinationKeyEnum.QUESTION}) {t("header.add_question")} </p>
<p>
{" "}
(CTRL + SHIFT + {CombinationKeyEnum.CHOICE}) {t("header.add_choice")}{" "}
</p>
<p>
{" "}
(CTRL + SHIFT + {CombinationKeyEnum.QUESTION}){" "}
{t("header.add_question")}{" "}
</p>
</div>
);
);
return (
<header className="exercise_add_header mb-4">
<article>
<Popover content={content} title={t("practical.Abbreviations")}>
<img src="/Icon/QuestionIcon.svg" alt="" />
</Popover>

View File

@ -1,4 +1,4 @@
import { useEffect } from 'react';
import { useEffect } from "react";
type KeyCombination = {
ctrlKey?: boolean;
@ -6,12 +6,17 @@ type KeyCombination = {
code: string; // Use string here for flexibility
};
const useKeyCombination = (keyCombination: KeyCombination, callback: () => void) => {
const useKeyCombination = (
keyCombination: KeyCombination,
callback: () => void,
) => {
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
const matches =
(keyCombination.ctrlKey === undefined || event.ctrlKey === keyCombination.ctrlKey) &&
(keyCombination.shiftKey === undefined || event.shiftKey === keyCombination.shiftKey) &&
(keyCombination.ctrlKey === undefined ||
event.ctrlKey === keyCombination.ctrlKey) &&
(keyCombination.shiftKey === undefined ||
event.shiftKey === keyCombination.shiftKey) &&
event.code === keyCombination.code;
if (matches) {
@ -21,10 +26,10 @@ const useKeyCombination = (keyCombination: KeyCombination, callback: () => void)
}
};
window.addEventListener('keydown', handleKeyDown);
window.addEventListener("keydown", handleKeyDown);
return () => {
window.removeEventListener('keydown', handleKeyDown);
window.removeEventListener("keydown", handleKeyDown);
};
}, [keyCombination, callback]);
};

View File

@ -10,14 +10,14 @@ interface ModalFormProps {
deleteMutation: any;
ModelEnum: any;
isNavigate?: boolean;
idVerify?:boolean
idVerify?: boolean;
}
const DeleteModels: React.FC<ModalFormProps> = ({
deleteMutation,
ModelEnum,
isNavigate = false,
idVerify = true
idVerify = true,
}) => {
const { isOpen, setIsOpen } = useModalState((state) => state);
const [inputValue, setInputValue] = useState("");
@ -27,9 +27,8 @@ const DeleteModels: React.FC<ModalFormProps> = ({
console.log(objectToEdit?.key);
console.log(inputValue);
const iaDisabled =
idVerify ?
Number(objectToEdit?.id) !== Number(inputValue) || isLoading
const iaDisabled = idVerify
? Number(objectToEdit?.id) !== Number(inputValue) || isLoading
: objectToEdit?.key !== inputValue || isLoading;
const navigate = useNavigate();
@ -44,13 +43,13 @@ const DeleteModels: React.FC<ModalFormProps> = ({
}, [isSuccess, setIsOpen]);
const handleSubmit = () => {
idVerify?
mutate({
idVerify
? mutate({
id: Number(objectToEdit?.id),
})
: mutate({
id:objectToEdit?.key,
})
id: objectToEdit?.key,
});
};
const handleCancel = () => {

View File

@ -25,10 +25,9 @@ const FilterLayout = ({
// type: type,
// page: currentPage,
const { FilterBody , FilterSubmit} = useFilter();
const { FilterBody, FilterSubmit } = useFilter();
return (
<div className="filter_header">
<div className="filter_header_top">
<h4>{t(filterTitle)}</h4>
@ -40,7 +39,7 @@ const FilterLayout = ({
setIsOpen={setIsOpen}
>
<div className="model_sub_children">{sub_children}</div>
<FilterSubmit/>
<FilterSubmit />
</FilterBody>
<div className="filter_button" onClick={() => setIsOpen(true)}>
<span>
@ -55,7 +54,6 @@ const FilterLayout = ({
<OrderBySelect />
</span>
</div>
</div>
<Divider />
@ -70,7 +68,6 @@ const FilterLayout = ({
<div className="header_search">
<SearchField searchBy="" placeholder={t("practical.search_here")} />
</div>
</div>
</div>
);

View File

@ -29,7 +29,6 @@ const FormikFormModel: React.FC<FormikFormProps> = ({
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleSubmit}
>
{(formik) => {
useEffect(() => {

View File

@ -39,7 +39,7 @@ const PageHeader = ({
navigate(location);
};
console.log();
const {PageTitle} = usePageTitleState()
const { PageTitle } = usePageTitleState();
return (
<div className="page_header">
<header className="d-flex justify-content-between">

View File

@ -32,7 +32,7 @@ const DataTable: React.FC<DataTableProps> = ({
rowClassName={(record, index) => getRowClassName(record, index)}
className="DataTable"
loading={{
spinning: isLoading || isRefetching ,
spinning: isLoading || isRefetching,
indicator: (
<Suspense fallback={<></>}>
<LoadingLottie />

View File

@ -50,9 +50,8 @@ const SideBar = ({
if (!useAbility) {
return <React.Fragment key={index}></React.Fragment>;
}
if(!RoleByType(item)){
return <React.Fragment key={index}></React.Fragment> ;
if (!RoleByType(item)) {
return <React.Fragment key={index}></React.Fragment>;
}
return (
<MenuItem

View File

@ -30,10 +30,7 @@ const TableHeader = () => {
ModelAbility={ModalEnum?.GRADE_ADD}
canAdd={canAddGrade}
/>
<FilterLayout
sub_children={<FilterForm />}
filterTitle="table.grade"
/>
<FilterLayout sub_children={<FilterForm />} filterTitle="table.grade" />
<Table />
<AddModalForm />
<EditModalForm />

View File

@ -1,11 +1,16 @@
import { Col, Row } from "reactstrap";
import ValidationField from "../../../../Components/ValidationField/ValidationField";
const Form = ({isEdit}:{isEdit?:boolean}) => {
const Form = ({ isEdit }: { isEdit?: boolean }) => {
return (
<Row className="w-100">
<Col>
<ValidationField placeholder="key" label="key" name="key" disabled={isEdit? true : false} />
<ValidationField
placeholder="key"
label="key"
name="key"
disabled={isEdit ? true : false}
/>
<ValidationField placeholder="value" label="value" name="value" />
</Col>
</Row>

View File

@ -18,9 +18,7 @@ const DeleteModalForm = lazy(
const TableHeader = () => {
const [t] = useTranslation();
useSetPageTitle(
t(`page_header.param`),
);
useSetPageTitle(t(`page_header.param`));
const deleteMutation = useDeleteParam();
return (
<div className="TableWithHeader">

View File

@ -15,21 +15,27 @@ const App: React.FC = () => {
pagination: true,
...filterState,
});
const [t] = useTranslation()
const transformedData = response?.data?.data && typeof response.data.data === 'object'
const [t] = useTranslation();
const transformedData =
response?.data?.data && typeof response.data.data === "object"
? Object.entries(response.data.data).map(([key, value]) => ({
key: key,
value: value
value: value,
}))
: [];
return <DataTable response={response} useColumns={useColumns} dataSource={transformedData}
return (
<DataTable
response={response}
useColumns={useColumns}
dataSource={transformedData}
pagination={{
nextIcon: <>{t("practical.next")}</>,
prevIcon: <> {t("practical.prev")} </>,
className: "pagination_antd",
}}
/>;
/>
);
};
export default App;

View File

@ -4,7 +4,12 @@ import { ModalEnum } from "../../../enums/Model";
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
import { useModalState } from "../../../zustand/Modal";
import { useTranslation } from "react-i18next";
import { canDeleteParam, canDeleteUser, canEditParam, canEditUser } from "../../../utils/hasAbilityFn";
import {
canDeleteParam,
canDeleteUser,
canEditParam,
canEditUser,
} from "../../../utils/hasAbilityFn";
import ActionButtons from "../../../Components/Table/ActionButtons";
export const useColumns = () => {
@ -56,5 +61,3 @@ export const useColumns = () => {
return columns;
};

View File

@ -6,20 +6,17 @@ import { Spin } from "antd";
import { ModalEnum } from "../../../../enums/Model";
import { canAddReSeller } from "../../../../utils/hasAbilityFn";
import PersonalDetailsForm from "../Form/PersonalDetailsForm";
import { Formik ,Form} from "formik";
import { Formik, Form } from "formik";
import { getInitialValues, getValidationSchema } from "../Form/formUtils";
import TitleDetailsForm from "../Form/TitleDetailsForm";
import AttachmentForm from "../Form/AttachmentForm";
const TableHeader = () => {
const [t] = useTranslation();
useSetPageTitle(t(`page_header.add_reseller`));
const handelSubmit = (values:any)=>{
console.log(values,"values");
}
const handelSubmit = (values: any) => {
console.log(values, "values");
};
return (
<div className="TableWithHeader">
<Suspense fallback={<Spin />}>
@ -28,20 +25,21 @@ const TableHeader = () => {
ModelAbility={ModalEnum?.RE_SELLER_ADD}
canAdd={false}
/>
<div className="bg2" >
<Formik initialValues={getInitialValues({})} validationSchema={getValidationSchema} onSubmit={handelSubmit} >
<div className="bg2">
<Formik
initialValues={getInitialValues({})}
validationSchema={getValidationSchema}
onSubmit={handelSubmit}
>
<Form>
<PersonalDetailsForm/>
<TitleDetailsForm/>
<AttachmentForm/>
<PersonalDetailsForm />
<TitleDetailsForm />
<AttachmentForm />
<div className="resellerButton">
<button type="button">
{t("practical.cancel")}
</button>
<button type="button">{t("practical.cancel")}</button>
<button type="submit">
{t("practical.add")} {t("models.reseller")}
</button>
</div>
</Form>
</Formik>

View File

@ -1,9 +1,7 @@
import React from 'react'
import React from "react";
const Page = () => {
return (
<div>Page</div>
)
}
return <div>Page</div>;
};
export default Page
export default Page;

View File

@ -1,24 +1,23 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { FaImage } from 'react-icons/fa'
import ImageBoxField from './ImageBoxField/ImageBoxField';
import React from "react";
import { useTranslation } from "react-i18next";
import { FaImage } from "react-icons/fa";
import ImageBoxField from "./ImageBoxField/ImageBoxField";
const AttachmentForm = () => {
const [t] = useTranslation();
return (
<div className='AttachmentForm'>
<header className='header_form'>
<div className="AttachmentForm">
<header className="header_form">
<FaImage />
<h4>{t("header.attachment")}</h4>
</header>
<main className='main_form_body'>
<main className="main_form_body">
<ImageBoxField name="personal_image" />
<ImageBoxField name="id_image" />
</main>
</div>
)
}
);
};
export default AttachmentForm
export default AttachmentForm;

View File

@ -7,7 +7,11 @@ const FilterForm = () => {
<div>
<Row>
<Col>
<ValidationField placeholder="first_name" label="first_name" name="first_name" />
<ValidationField
placeholder="first_name"
label="first_name"
name="first_name"
/>
{/* <ValidationField placeholder="last_name" label="last_name" name="last_name" /> */}
</Col>
{/* <Col>

View File

@ -48,7 +48,7 @@ const ImageBoxField = ({ name }: any) => {
fileInputRef.current.value = "";
}
};
const [t] = useTranslation()
const [t] = useTranslation();
return (
<div className="ImageBoxField">
<header>{t(`input.${name}`)}</header>

View File

@ -1,35 +1,76 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { FaStore } from 'react-icons/fa'
import ValidationField from '../../../../Components/ValidationField/ValidationField';
import { convert_data_to_select } from '../../../../Layout/app/Const';
import { userTypeOptions } from '../../../../config/userTypeOptions';
import { statusType } from '../../../../config/statusType';
import React from "react";
import { useTranslation } from "react-i18next";
import { FaStore } from "react-icons/fa";
import ValidationField from "../../../../Components/ValidationField/ValidationField";
import { convert_data_to_select } from "../../../../Layout/app/Const";
import { userTypeOptions } from "../../../../config/userTypeOptions";
import { statusType } from "../../../../config/statusType";
const PersonalDetailsForm = () => {
const [t] = useTranslation();
return (
<div className='PersonalDetailsForm'>
<header className='header_form'>
<div className="PersonalDetailsForm">
<header className="header_form">
<FaStore />
<h4>{t("header.personal_information")}</h4>
</header>
<main className='main_form_body'>
<ValidationField name={"id_number"} placeholder={"_"} label={"ID Number"} />
<ValidationField name={"addition_date"} placeholder={"_"} type='Date' label={"Addition Date"} />
<ValidationField name={"status"} placeholder={"_"} label={"Status"} type='Select' option={statusType} />
<main className="main_form_body">
<ValidationField
name={"id_number"}
placeholder={"_"}
label={"ID Number"}
/>
<ValidationField
name={"addition_date"}
placeholder={"_"}
type="Date"
label={"Addition Date"}
/>
<ValidationField
name={"status"}
placeholder={"_"}
label={"Status"}
type="Select"
option={statusType}
/>
<ValidationField name={"full_name"} placeholder={"_"} label={"Full Name"} />
<ValidationField name={"phone_number"} placeholder={"_"} label={"Phone Number"} type='text' />
<ValidationField name={"mobile_number"} placeholder={"_"} label={"Mobile Number"} />
<ValidationField name={"username"} placeholder={"_"} label={"Username"} />
<ValidationField name={"password"} placeholder={"_"} label={"Password"} type='text' />
<ValidationField name={"seller_percentage"} placeholder={"_"} label={"Seller Percentage"} type='text' />
<ValidationField
name={"full_name"}
placeholder={"_"}
label={"Full Name"}
/>
<ValidationField
name={"phone_number"}
placeholder={"_"}
label={"Phone Number"}
type="text"
/>
<ValidationField
name={"mobile_number"}
placeholder={"_"}
label={"Mobile Number"}
/>
<ValidationField
name={"username"}
placeholder={"_"}
label={"Username"}
/>
<ValidationField
name={"password"}
placeholder={"_"}
label={"Password"}
type="text"
/>
<ValidationField
name={"seller_percentage"}
placeholder={"_"}
label={"Seller Percentage"}
type="text"
/>
</main>
</div>
)
}
);
};
export default PersonalDetailsForm
export default PersonalDetailsForm;

View File

@ -1,25 +1,30 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { FaRegAddressBook } from 'react-icons/fa'
import ValidationField from '../../../../Components/ValidationField/ValidationField';
import { nationalities } from '../../../../types/App';
import React from "react";
import { useTranslation } from "react-i18next";
import { FaRegAddressBook } from "react-icons/fa";
import ValidationField from "../../../../Components/ValidationField/ValidationField";
import { nationalities } from "../../../../types/App";
const TitleDetailsForm = () => {
const [t] = useTranslation();
return (
<div className='TitleDetailsForm'>
<header className='header_form'>
<div className="TitleDetailsForm">
<header className="header_form">
<FaRegAddressBook />
<h4>{t("header.address")}</h4>
</header>
<main className='main_form_body'>
<ValidationField name={"city_id"} placeholder={"_"} label={"city"} type='Select' option={nationalities} />
<main className="main_form_body">
<ValidationField
name={"city_id"}
placeholder={"_"}
label={"city"}
type="Select"
option={nationalities}
/>
<ValidationField name={"address"} placeholder={"_"} label={"address"} />
</main>
</div>
)
}
);
};
export default TitleDetailsForm
export default TitleDetailsForm;

View File

@ -1,17 +1,13 @@
import * as Yup from "yup";
export const getInitialValues = (
objectToEdit: Partial<any>,
) => {
export const getInitialValues = (objectToEdit: Partial<any>) => {
return {
id: objectToEdit?.id ?? null ,
id: objectToEdit?.id ?? null,
name: objectToEdit?.name ?? null,
};
};
export const getValidationSchema = () => {
// validate input
return Yup.object().shape({
});
return Yup.object().shape({});
};

View File

@ -45,7 +45,6 @@ const TableHeader = () => {
deleteMutation={deleteMutation}
ModelEnum={ModalEnum?.RE_SELLER_DELETE}
/>
</Suspense>
</div>
);

View File

@ -11,7 +11,7 @@ const App: React.FC = () => {
const response = useGetAllReseller({
name: searchQuery,
pagination: true,
...filterState
...filterState,
});
return <DataTable response={response} useColumns={useColumns} />;

View File

@ -21,7 +21,6 @@ export const useColumns = () => {
const { setObjectToEdit } = useObjectToEdit((state) => state);
const navigate = useNavigate();
const handelDelete = (data: ReSeller) => {
setObjectToEdit(data);
handel_open_model(ModalEnum?.RE_SELLER_DELETE);
@ -63,7 +62,7 @@ export const useColumns = () => {
render: (_text, record) => record?.user?.username,
},
{
title:"",
title: "",
key: "actions",
align: "center",
@ -72,11 +71,9 @@ export const useColumns = () => {
<ActionButtons
canDelete={canDeleteReSeller}
canEdit={canEditReSeller}
index={index}
onDelete={() => handelDelete(record)}
onEdit={() => handleEdit(record)}
/>
);
},

View File

@ -7,8 +7,16 @@ const FilterForm = () => {
<div>
<Row>
<Col>
<ValidationField placeholder="first_name" label="first_name" name="first_name" />
<ValidationField placeholder="last_name" label="last_name" name="last_name" />
<ValidationField
placeholder="first_name"
label="first_name"
name="first_name"
/>
<ValidationField
placeholder="last_name"
label="last_name"
name="last_name"
/>
</Col>
</Row>
</div>

View File

@ -19,7 +19,6 @@ const Form = () => {
placeholder="term"
label="term"
option={termsArray}
/>
</Col>
</Row>

View File

@ -42,7 +42,7 @@ const TableHeader = () => {
" / " +
` ${t("header.subject_of_class")} (${gradeName})` +
" / " +
SubjectName
SubjectName,
);
return (

View File

@ -8,11 +8,25 @@ const FilterForm = () => {
<div>
<Row>
<Col>
<ValidationField placeholder="username" label="username" name="username" />
<ValidationField placeholder="phone_number" label="phone_number" name="phone_number" />
<ValidationField
placeholder="username"
label="username"
name="username"
/>
<ValidationField
placeholder="phone_number"
label="phone_number"
name="phone_number"
/>
</Col>
<Col>
<ValidationField type="Select" option={userTypeOptions} placeholder="type" label="type" name="type" />
<ValidationField
type="Select"
option={userTypeOptions}
placeholder="type"
label="type"
name="type"
/>
</Col>
</Row>
</div>

View File

@ -3,25 +3,59 @@ import ValidationField from "../../../../Components/ValidationField/ValidationFi
import useFormatDataToSelect from "../../../../utils/useFormatDataToSelect";
import { userTypeOptions } from "../../../../config/userTypeOptions";
const Form = ({isEdit}:{isEdit?:boolean}) => {
const Form = ({ isEdit }: { isEdit?: boolean }) => {
return (
<Row className="w-100">
{isEdit ? "" :
{isEdit ? (
""
) : (
<Col>
<>
<ValidationField placeholder="username" label="username" name="username" />
<ValidationField placeholder="password" label="password" name="password" />
<ValidationField placeholder="phone_number" label="phone_number" name="phone_number" />
<ValidationField
placeholder="username"
label="username"
name="username"
/>
<ValidationField
placeholder="password"
label="password"
name="password"
/>
<ValidationField
placeholder="phone_number"
label="phone_number"
name="phone_number"
/>
</>
</Col>}
</Col>
)}
<Col>
{isEdit ? "":
<ValidationField type="Select" option={userTypeOptions} placeholder="type" label="type" name="type" />}
<ValidationField type="Select" option={userTypeOptions} placeholder="roles" label="roles" name="role_id" />
<ValidationField type="Select" option={userTypeOptions} placeholder="abilities" label="abilities" name="abilities" isMulti={true} />
{isEdit ? (
""
) : (
<ValidationField
type="Select"
option={userTypeOptions}
placeholder="type"
label="type"
name="type"
/>
)}
<ValidationField
type="Select"
option={userTypeOptions}
placeholder="roles"
label="roles"
name="role_id"
/>
<ValidationField
type="Select"
option={userTypeOptions}
placeholder="abilities"
label="abilities"
name="abilities"
isMulti={true}
/>
</Col>
</Row>
);

View File

@ -6,7 +6,6 @@ export const getInitialValues = (objectToEdit: any): any => {
password: objectToEdit?.password ?? null,
phone_number: objectToEdit?.phone_number ?? null,
type: objectToEdit?.type ?? null,
};
};

View File

@ -18,9 +18,7 @@ const DeleteModalForm = lazy(
const TableHeader = () => {
const [t] = useTranslation();
useSetPageTitle(
t(`page_header.user`),
);
useSetPageTitle(t(`page_header.user`));
const deleteMutation = useDeleteUser();
return (
<div className="TableWithHeader">

View File

@ -37,7 +37,6 @@ const TableHeader = () => {
show: grade_id,
});
const gradeName = grade?.data?.name ?? "";
const SubjectName = Subject?.data?.name ?? "";
const unitName = unit?.data?.name ?? "";
@ -49,10 +48,9 @@ const TableHeader = () => {
" / " +
SubjectName +
" / " +
unitName
unitName,
);
return (
<div className="TableWithHeader">
<Suspense fallback={<Spin />}>

View File

@ -22,28 +22,20 @@ import { toast } from "react-toastify";
const AcceptModal = lazy(() => import("./Model/AcceptModal"));
const AddPage: React.FC = () => {
const { mutateAsync } = useAddQuestionAsync();
const { mutate, isLoading ,isSuccess} = useAddQuestion();
const {
isBseQuestion,
setTagsSearch,
objectToEdit,
setSuccess
} = useObjectToEdit();
const { mutate, isLoading, isSuccess } = useAddQuestion();
const { isBseQuestion, setTagsSearch, objectToEdit, setSuccess } =
useObjectToEdit();
const [t] = useTranslation();
const { subject_id, lesson_id } =
useParams<ParamsEnum>();
const { subject_id, lesson_id } = useParams<ParamsEnum>();
console.log(objectToEdit,"objectToEdit");
console.log(objectToEdit, "objectToEdit");
const handleSubmit = (
values: any,
{ resetForm }: { resetForm: () => void },
) => {
const DataToSend = structuredClone(values);
setTagsSearch(null);
console.log(1);
@ -76,11 +68,15 @@ console.log(objectToEdit,"objectToEdit");
};
});
console.log(answers);
if(answers?.length > 0){
const isValidAnswers = answers?.some((answer:any) => answer?.isCorrect === 1)
if (answers?.length > 0) {
const isValidAnswers = answers?.some(
(answer: any) => answer?.isCorrect === 1,
);
if(!isValidAnswers){
toast.error(t("validation.at_least_one_answer_should_be_correct"));
if (!isValidAnswers) {
toast.error(
t("validation.at_least_one_answer_should_be_correct"),
);
return;
}
}
@ -100,19 +96,19 @@ console.log(objectToEdit,"objectToEdit");
const tags = processTags(DataToSend);
const answers = values?.answers?.map((item: any, index: number) => {
return {
order: index,
...item,
};
});
if(answers?.length > 0){
const isValidAnswers = answers?.some((answer:any) => answer?.isCorrect === 1)
if (answers?.length > 0) {
const isValidAnswers = answers?.some(
(answer: any) => answer?.isCorrect === 1,
);
console.log(!isValidAnswers);
if(!isValidAnswers){
if (!isValidAnswers) {
toast.error(t("validation.at_least_one_answer_should_be_correct"));
return;
}
@ -135,26 +131,16 @@ console.log(objectToEdit,"objectToEdit");
const navigate = useNavigate();
const handleCancel = () => {
navigate(-1);
};
useEffect(() => {
console.log("all api success");
if(isSuccess){
setSuccess(true )
if (isSuccess) {
setSuccess(true);
}
}, [isSuccess])
}, [isSuccess]);
if (isBseQuestion) {
return (

View File

@ -25,13 +25,8 @@ import BaseForm from "./Model/Malty/Form";
import { Question } from "../../../types/Item";
import { toast } from "react-toastify";
const EditPage: React.FC = () => {
const {
subject_id,
lesson_id,
question_id,
} = useParams<ParamsEnum>();
const { subject_id, lesson_id, question_id } = useParams<ParamsEnum>();
const { isBseQuestion, setIsBseQuestion, setTagsSearch, DeletedQuestions } =
useObjectToEdit();
@ -58,8 +53,6 @@ const EditPage: React.FC = () => {
const [t] = useTranslation();
const handleSubmit = (values: any) => {
const DataToSend = structuredClone(values);
setTagsSearch(null);
@ -101,9 +94,10 @@ const EditPage: React.FC = () => {
const oldAnswers = [] as any;
const newAnswers = [] as any;
if(updatedObject?.answers?.length > 0){
const isValidAnswers = updatedObject?.answers?.some((answer:any) => answer?.isCorrect === 1)
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"));
@ -112,9 +106,9 @@ const EditPage: React.FC = () => {
}
updatedObject?.answers?.forEach((item: any) => {
if (item?.id) {
oldAnswers.push({...item,isCorrect:item?.isCorrect ? 1 : 0});
oldAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0 });
} else {
newAnswers.push({...item,isCorrect:item?.isCorrect ? 1 : 0});
newAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0 });
}
});
const answers = {
@ -142,7 +136,6 @@ const EditPage: React.FC = () => {
}
});
} else {
const keysToRemove = ["content_image"];
console.log(DataToSend);
const updatedObject = removeStringKeys(DataToSend, keysToRemove);
@ -154,13 +147,11 @@ const EditPage: React.FC = () => {
const oldAnswers = [] as any;
const newAnswers = [] as any;
if(updatedObject?.answers?.length > 0){
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;
@ -168,9 +159,9 @@ const EditPage: React.FC = () => {
}
updatedObject?.answers?.forEach((item: any) => {
if (item?.id) {
oldAnswers.push({...item,isCorrect:item?.isCorrect ? 1 : 0});
oldAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0 });
} else {
newAnswers.push({...item,isCorrect:item?.isCorrect ? 1 : 0});
newAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0 });
}
});
@ -178,15 +169,12 @@ const EditPage: React.FC = () => {
old: oldAnswers,
new: newAnswers,
};
console.log(tags,"tags");
if(tags?.new?.length < 1 && tags?.old?.length < 1){
mutate({ ...updatedObject, answers, tags:"" });
}else{
console.log(tags, "tags");
if (tags?.new?.length < 1 && tags?.old?.length < 1) {
mutate({ ...updatedObject, answers, tags: "" });
} else {
mutate({ ...updatedObject, answers, tags });
}
}
};

View File

@ -5,14 +5,18 @@ import useFormatDataToSelect from "../../../utils/useFormatDataToSelect";
const FilterForm = () => {
const yesNoArray = [
{id: "لا", name:"لا"},
{id: "نعم", name:"نعم"},
]
{ id: "لا", name: "لا" },
{ id: "نعم", name: "نعم" },
];
return (
<div>
<Row>
<Col>
<ValidationField placeholder="content" label="content" name="content" />
<ValidationField
placeholder="content"
label="content"
name="content"
/>
{/* <ValidationField type="Select" option={yesNoArray} placeholder="isBase" label="isBase" name="isBase" /> */}
</Col>
{/* <Col>

View File

@ -35,7 +35,10 @@ const CheckboxField = ({
<Checkbox
onChange={onChange || CheckboxhandleChange}
disabled={isDisabled}
checked={formik.values?.answers?.[name]?.isCorrect === 1 || formik.values?.answers?.[name]?.isCorrect === true}
checked={
formik.values?.answers?.[name]?.isCorrect === 1 ||
formik.values?.answers?.[name]?.isCorrect === true
}
className={className}
>
{t(`input.${label ? label : name}`)}

View File

@ -28,7 +28,6 @@ const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => {
return (
<>
<div className="ChoiceFields">
<TextField
className="textarea_exercise"
placeholder={"choice"}

View File

@ -59,7 +59,7 @@ const Choices = () => {
{...provided.dragHandleProps}
>
<div className="HolderQuestion">
<HolderOutlined/>
<HolderOutlined />
</div>
<ChoiceFields index={index} data={item} />
</div>

View File

@ -42,7 +42,8 @@ const CheckboxField = ({
disabled={isDisabled}
checked={
formik.values?.Questions?.[parent_index]?.answers?.[name]
?.isCorrect === 1 || formik.values?.Questions?.[parent_index]?.answers?.[name]
?.isCorrect === 1 ||
formik.values?.Questions?.[parent_index]?.answers?.[name]
?.isCorrect === true
}
className={className}

View File

@ -44,7 +44,6 @@ const ChoiceFields = ({
formik.setFieldValue(`Questions[${parent_index}].answers`, updatedAnswers);
};
return (
<>
<div className="ChoiceFields">

View File

@ -69,7 +69,7 @@ const Choices = ({ parent_index }: { parent_index: number }) => {
{...provided.dragHandleProps}
>
<div className="HolderQuestion">
<HolderOutlined/>
<HolderOutlined />
</div>
<ChoiceFields
key={index}

View File

@ -18,18 +18,21 @@ const Form = () => {
const formik = useFormikContext<any>();
const { setSuccess, Success, setSavedQuestionData } = useObjectToEdit();
useEffect(() => {
setSavedQuestionData(formik.values);
}, [formik?.values]);
// console.log(formik?.errors);
const handleAddChoice = (parent_index: number,fromKeyCombination:boolean = false) => {
const handleAddChoice = (
parent_index: number,
fromKeyCombination: boolean = false,
) => {
console.log(parent_index);
formik.setFieldValue(`Questions.[${parent_index}].answers`, [
...((formik?.values as any)?.Questions?.[parent_index]?.answers as Choice[]),
...((formik?.values as any)?.Questions?.[parent_index]
?.answers as Choice[]),
{
answer: null,
@ -38,12 +41,12 @@ const Form = () => {
},
]);
if(fromKeyCombination){
toast.success(t("header.new_choice_have_been_added"))
if (fromKeyCombination) {
toast.success(t("header.new_choice_have_been_added"));
}
};
const handleAddQuestion = (fromKeyCombination:boolean = false) => {
const handleAddQuestion = (fromKeyCombination: boolean = false) => {
formik.setFieldValue("Questions", [
...((formik?.values as any)?.Questions as Choice[]),
@ -62,27 +65,28 @@ const Form = () => {
const max_mark = formik?.values?.max_mark + 1;
formik.setFieldValue("max_mark", max_mark);
if(fromKeyCombination){
toast.success(t("header.new_question_have_been_added"))
if (fromKeyCombination) {
toast.success(t("header.new_question_have_been_added"));
}
};
const [t] = useTranslation();
const lastQuestions = formik?.values?.Questions?.length - 1;
useKeyCombination(
{ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.CHOICE },
() => {
handleAddChoice(lastQuestions, true);
},
);
const lastQuestions = formik?.values?.Questions?.length -1 ;
useKeyCombination({ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.CHOICE }, () => {
handleAddChoice(lastQuestions,true)
});
useKeyCombination({ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.QUESTION }, () => {
handleAddQuestion(true)
});
useKeyCombination(
{ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.QUESTION },
() => {
handleAddQuestion(true);
},
);
return (
<Row className="w-100 exercise_form_container">
<div className="exercise_form">
<ValidationField
@ -139,7 +143,7 @@ const Form = () => {
)}
<p className="add_new_button">
<FaCirclePlus onClick={()=>handleAddQuestion()} size={23} />{" "}
<FaCirclePlus onClick={() => handleAddQuestion()} size={23} />{" "}
{t("header.add_new_question")}
</p>
</Row>

View File

@ -41,14 +41,16 @@ const MaltySelectTag = ({ parent_index }: { parent_index: number }) => {
? [{ id: searchValue, name: searchValue }]
: [];
console.log(options);
const value = formik?.values?.Questions[parent_index]?.tags?.map((item: any) => item?.id ?? item) ?? [];
const value =
formik?.values?.Questions[parent_index]?.tags?.map(
(item: any) => item?.id ?? item,
) ?? [];
console.log(formik?.values?.Questions[parent_index]);
console.log(value);
const AllOptions = [...options, ...additionalData]
const AllOptions = [...options, ...additionalData];
return (
<div className="SelectTag">
@ -59,7 +61,6 @@ const value = formik?.values?.Questions[parent_index]?.tags?.map((item: any) =>
style={{ width: "100%", height: "40px" }}
placeholder=""
fieldNames={{ label: "name", value: "id" }}
onChange={handleChange}
options={AllOptions}
filterOption={false}

View File

@ -18,11 +18,7 @@ const Form = () => {
const formik = useFormikContext<any>();
const { setSuccess, Success } = useObjectToEdit();
const handleAddChoice = (fromKeyCombination:boolean = false ) => {
const handleAddChoice = (fromKeyCombination: boolean = false) => {
formik.setFieldValue("answers", [
...((formik?.values as any)?.answers as Choice[]),
{
@ -32,28 +28,26 @@ const Form = () => {
},
]);
if(fromKeyCombination){
toast.success(t("header.new_choice_have_been_added"))
if (fromKeyCombination) {
toast.success(t("header.new_choice_have_been_added"));
}
};
useKeyCombination({ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.CHOICE }, () => {
handleAddChoice(true)
});
useKeyCombination(
{ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.CHOICE },
() => {
handleAddChoice(true);
},
);
useEffect(() => {
if(Success){
formik?.setValues({})
formik.setErrors({})
setSuccess(false)
if (Success) {
formik?.setValues({});
formik.setErrors({});
setSuccess(false);
console.log(formik.errors);
}
}, [Success])
}, [Success]);
return (
<Row className="w-100 exercise_form_container">
@ -70,7 +64,7 @@ const Form = () => {
<Choices />
{formik?.values?.answers?.length < 5 && (
<p className="add_new_button">
<FaCirclePlus onClick={()=>handleAddChoice()} size={23} />{" "}
<FaCirclePlus onClick={() => handleAddChoice()} size={23} />{" "}
{t("header.add_new_choice")}
</p>
)}

View File

@ -2,7 +2,6 @@ import * as Yup from "yup";
import { Question } from "../../../../types/Item";
import { toast } from "react-toastify";
export const getInitialValues = (objectToEdit: Question): any => {
const tags = objectToEdit?.tags?.map((item: any, index: number) => {
return { ...item };
@ -27,15 +26,13 @@ export const getValidationSchema = () => {
return Yup.object().shape({
content_image: Yup.string().nullable(),
content: Yup.string().required("validation.required"),
answers: Yup.array()
.of(
answers: Yup.array().of(
Yup.object().shape({
content: Yup.string().required("validation.required"),
content_image: Yup.string().nullable(),
isCorrect: Yup.boolean(),
}),
)
),
});
};
@ -45,13 +42,13 @@ export const getInitialValuesBase = (objectToEdit: Question): any => {
id: tag?.id,
name: tag?.name,
}));
console.log(item,"item");
console.log(item, "item");
return {
...item,
canAnswersBeShuffled: objectToEdit?.canAnswersBeShuffled ? 1 : 0,
hint: objectToEdit?.hint ?? "",
isBase:0,
isBase: 0,
tags,
};
});
@ -89,13 +86,16 @@ export const getValidationSchemaBase = () => {
}),
)
.test(
'at-least-one-correct',
'At least one answer must be correct',
(answers:any) => {
console.log(answers,"answers");
"at-least-one-correct",
"At least one answer must be correct",
(answers: any) => {
console.log(answers, "answers");
return answers.some((answer:any) => answer.isCorrect === true || answer.isCorrect === 1);
}
return answers.some(
(answer: any) =>
answer.isCorrect === true || answer.isCorrect === 1,
);
},
),
}),
),
@ -108,7 +108,7 @@ export function processTags(DataToSend: any) {
const oldTags = DataToSend?.tags
?.map((item: any, index: number) => {
if (typeof item === "number" || typeof item?.id === "number") {
return item?.id ?? item ;
return item?.id ?? item;
}
})
.filter((item: any) => item !== undefined);
@ -117,7 +117,10 @@ export function processTags(DataToSend: any) {
?.map((item: any, index: number) => {
console.log(item);
if (typeof item === "string" && item !== "" || typeof item?.id === "string" && item?.id !== "" ) {
if (
(typeof item === "string" && item !== "") ||
(typeof item?.id === "string" && item?.id !== "")
) {
console.log(item);
return { name: item?.id ?? item };

View File

@ -24,8 +24,7 @@ const TableHeader = () => {
const deleteMutation = useDeleteQuestion();
const { unit_id, grade_id, subject_id, lesson_id } =
useParams<ParamsEnum>();
const { unit_id, grade_id, subject_id, lesson_id } = useParams<ParamsEnum>();
const { data: unit } = useGetAllUnit({ show: unit_id });
const { data: Subject } = useGetAllSubject({
@ -53,7 +52,7 @@ const TableHeader = () => {
" / " +
unitName +
" / " +
LessonName
LessonName,
);
return (
@ -68,7 +67,8 @@ const TableHeader = () => {
/>
<FilterLayout
sub_children={<FilterForm />}
filterTitle={` ${unitName} (${LessonName}) `} />
filterTitle={` ${unitName} (${LessonName}) `}
/>
<Table />
</Suspense>
<DeleteModels

View File

@ -35,7 +35,7 @@ const TableWithHeader = () => {
useSetPageTitle(
t(`page_header.grade`) +
" / " +
` ${t("header.subject_of_class")} (${gradeName})`
` ${t("header.subject_of_class")} (${gradeName})`,
);
return (

View File

@ -7,14 +7,11 @@ import useFilter from "../../Components/FilterField/components/useFilter";
const Dummy = () => {
const [t] = useTranslation();
useSetPageTitle(`${t(ABILITIES_ENUM?.MAIN_PAGE)} / ${t("dashboard")}`);
const {FilterButton,FilterBody} = useFilter()
return(
const { FilterButton, FilterBody } = useFilter();
return (
<div className="DummyHomePage">
<FilterButton/>
<FilterBody>
karim
</FilterBody>
<FilterButton />
<FilterBody>karim</FilterBody>
</div>
);
};

View File

@ -7,7 +7,11 @@ const FilterForm = () => {
<div>
<Row>
<Col>
<ValidationField placeholder="activation_date" label="activation_date" name="activation_date" />
<ValidationField
placeholder="activation_date"
label="activation_date"
name="activation_date"
/>
{/* <ValidationField placeholder="name" label="name" name="name" /> */}
</Col>
</Row>

View File

@ -2,24 +2,41 @@ import { Col, Row } from "reactstrap";
import ValidationField from "../../../../Components/ValidationField/ValidationField";
import useFormatDataToSelect from "../../../../utils/useFormatDataToSelect";
const Form = ({isEdit}:{isEdit?:boolean}) => {
const Form = ({ isEdit }: { isEdit?: boolean }) => {
const typeOptions = [
{ id: "student", name: "student" },
{ id: "reseller", name: "reseller" },
{ id: "admin", name: "admin" },
]
const typeArray = useFormatDataToSelect(typeOptions)
];
const typeArray = useFormatDataToSelect(typeOptions);
return (
<Row className="w-100">
<Col>
<ValidationField type="Date" placeholder="activation_date" label="activation_date" name="activation_date" />
<ValidationField type="Date" placeholder="expiration_date" label="expiration_date" name="expiration_date" />
<ValidationField placeholder="student_id" label="student_id" name="student_id" />
<ValidationField
type="Date"
placeholder="activation_date"
label="activation_date"
name="activation_date"
/>
<ValidationField
type="Date"
placeholder="expiration_date"
label="expiration_date"
name="expiration_date"
/>
<ValidationField
placeholder="student_id"
label="student_id"
name="student_id"
/>
</Col>
<Col>
<ValidationField placeholder="package_id" label="package_id" name="package_id" />
<ValidationField
placeholder="package_id"
label="package_id"
name="package_id"
/>
</Col>
</Row>
);

View File

@ -12,7 +12,6 @@ export const getInitialValues = (objectToEdit: any): any => {
: null,
student_id: objectToEdit?.student_id ?? null,
package_id: objectToEdit?.package_id ?? null,
};
};
export const getValidationSchema = () => {

View File

@ -18,9 +18,7 @@ const DeleteModalForm = lazy(
const TableHeader = () => {
const [t] = useTranslation();
useSetPageTitle(
t(`page_header.student_package`),
);
useSetPageTitle(t(`page_header.student_package`));
// const deleteMutation = useDeleteUser();
return (
<div className="TableWithHeader">

View File

@ -46,24 +46,24 @@ export const useColumns = () => {
key: "first_name",
align: "center",
render: (row) => {
return(row?.student?.first_name)
}
return row?.student?.first_name;
},
},
{
title: t("columns.last_name"),
key: "last_name",
align: "center",
render: (row) => {
return(row?.student?.last_name)
}
return row?.student?.last_name;
},
},
{
title: t("columns.sex"),
key: "sex",
align: "center",
render: (row) => {
return(row?.student?.sex)
}
return row?.student?.sex;
},
},
// {
// title: t("columns.procedure"),

View File

@ -23,14 +23,17 @@ const Report = React.lazy(() => import("./Pages/Admin/Report/Page"));
const Student = React.lazy(() => import("./Pages/Admin/Student/Page"));
const ReSeller = React.lazy(() => import("./Pages/Admin/Reseller/Page"));
const AddReSeller = React.lazy(() => import("./Pages/Admin/Reseller/Add/Page"));
const EditReSeller = React.lazy(() => import("./Pages/Admin/Reseller/Edit/Page"));
const EditReSeller = React.lazy(
() => import("./Pages/Admin/Reseller/Edit/Page"),
);
const User = React.lazy(() => import("./Pages/Admin/User/Page"));
const Param = React.lazy(() => import("./Pages/Admin/Param/Page"));
/// RESELLER ///
const Student_Package = React.lazy(() => import("./Pages/ReSeller/StudentPackage/Page"));
const Student_Package = React.lazy(
() => import("./Pages/ReSeller/StudentPackage/Page"),
);
import { hasAbility } from "./utils/hasAbility";
import { ABILITIES_ENUM, ABILITIES_VALUES_ENUM } from "./enums/abilities";
@ -48,7 +51,7 @@ export const menuItems: TMenuItem[] = [
abilities: ABILITIES_ENUM?.PASS,
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
prevPath: 0,
type:UserTypeEnum?.PASS
type: UserTypeEnum?.PASS,
},
{
header: "page_header.grade",
@ -89,7 +92,6 @@ export const menuItems: TMenuItem[] = [
abilities: ABILITIES_ENUM?.STUDENT,
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
prevPath: 0,
},
{
header: "page_header.reSeller",
@ -122,7 +124,6 @@ export const menuItems: TMenuItem[] = [
prevPath: 0,
},
/// RESELLER /////
{
@ -134,12 +135,9 @@ export const menuItems: TMenuItem[] = [
abilities: ABILITIES_ENUM?.Student_Package,
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
prevPath: 0,
type:UserTypeEnum.RE_SELLER
type: UserTypeEnum.RE_SELLER,
},
// {
// header: "page_header.tags",
// element: <Tags />,

View File

@ -298,25 +298,21 @@ button:disabled {
visibility: hidden;
}
.bg2{
.bg2 {
background: var(--bg2);
}
.header_form{
.header_form {
display: flex;
align-items: center;
gap: 20px;
padding: 20px;
h4{
h4 {
font-size: 20px;
}
svg{
svg {
background: var(--bg);
padding: 10px;
width: 40px;
height: 40px;
}
}

View File

@ -18,12 +18,10 @@
align-items: center;
justify-content: center;
color: var(--white);
}
}
.AuthForm {
height: 440px;
width: 600px;
min-width: 300px;

View File

@ -61,5 +61,3 @@
font-size: 16px;
}
}

View File

@ -74,13 +74,14 @@
}
}
.filter_modal_add_button, .filter_modal_cancel_button{
.filter_modal_add_button,
.filter_modal_cancel_button {
padding: 20px 10px !important;
}
@media screen and (max-width:800px) {
.filter_modal_add_button, .filter_modal_cancel_button{
@media screen and (max-width: 800px) {
.filter_modal_add_button,
.filter_modal_cancel_button {
font-size: 8px !important;
}
}

View File

@ -133,7 +133,7 @@
margin: 0 !important;
box-shadow: 0px 0px 4px 2px rgba(0, 0, 0, 0.1);
img{
img {
cursor: pointer;
}
}
@ -197,21 +197,17 @@
width: 100%;
}
.SelectTag {
padding-inline: 20px;
}
.exercise_add{
.add_new_button{
.exercise_add {
.add_new_button {
padding-inline: 20px !important;
}
}
.HolderQuestion{
.HolderQuestion {
transform: translateY(55px);
z-index: -1;
}

View File

@ -9,4 +9,4 @@
@import "./subject.scss";
@import "./Marks.scss";
@import "./exercise.scss";
@import './reSeller.scss';
@import "./reSeller.scss";

View File

@ -1,37 +1,32 @@
.main_form_body{
.main_form_body {
display: flex;
flex-wrap: wrap;
background: var(--bg);
padding: 40px 10px;
>*{
> * {
// max-width: 30%;
flex-basis: 33%;
}
}
}
.AttachmentForm{
.main_form_body{
.AttachmentForm {
.main_form_body {
padding: 30px 50px;
gap: 40px;
>*{
> * {
// max-width: 30%;
flex-basis: 10%;
}
}
}
}
.resellerButton{
.resellerButton {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 20px;
padding: 20px;
button{
button {
all: unset;
cursor: pointer;
padding: 8px 26px;
@ -39,12 +34,10 @@
border-radius: 5px;
background: var(--primary);
color: var(--white);
&:first-child{
background: #F2F4F8;
color: #515B73;
box-shadow: 0px 0px 4px rgb(0, 0, 0,.08);
&:first-child {
background: #f2f4f8;
color: #515b73;
box-shadow: 0px 0px 4px rgb(0, 0, 0, 0.08);
}
}
}
}

View File

@ -5,7 +5,7 @@ import { AxiosResponse } from "../../types/Axios";
type DataToSend = {
id?: number | string | any;
key?: string | any
key?: string | any;
};
function useDeleteMutation(

View File

@ -13,7 +13,7 @@ function useGetQuery(
options: any = {},
) {
const axios = useAxios();
const {Filter} = useFilterStateState()
const { Filter } = useFilterStateState();
const sort_by = Filter?.sort_by ?? null;
const name = Filter?.name ?? null;
const { show, pagination, ...remainingParams } = params;
@ -23,8 +23,8 @@ function useGetQuery(
const { page, per_page } = PaginationParams(location);
const paramToSend = pagination
? { page: page, per_page: per_page, name,...remainingParams , sort_by }
: { name,...remainingParams ,sort_by};
? { page: page, per_page: per_page, name, ...remainingParams, sort_by }
: { name, ...remainingParams, sort_by };
const filteredParams = filterParams(paramToSend);

View File

@ -19,7 +19,6 @@ const useUpdateMutation = (
request = dataToSend;
id = dataToSend.get("id");
console.log(dataToSend);
} else {
request = { ...dataToSend, _method: "PUT" };
id = dataToSend?.id || dataToSend?.key;

View File

@ -2,4 +2,4 @@ export const statusType = [
{ id: "upcoming", name: "select.upcoming" },
{ id: "waiting", name: "select.waiting" },
{ id: "done", name: "select.done" },
]
];

View File

@ -2,4 +2,4 @@ export const userTypeOptions = [
{ id: "student", name: "student" },
{ id: "reseller", name: "reseller" },
{ id: "admin", name: "admin" },
]
];

View File

@ -1,6 +1,4 @@
export enum CombinationKeyEnum {
QUESTION = "KeyK",
CHOICE = "KeyJ"
CHOICE = "KeyJ",
}

View File

@ -186,6 +186,4 @@ export enum ModalEnum {
Student_Package_EDIT = "Student_Package.edit",
Student_Package_ADD = "Student_Package.add",
Student_Package_DELETE = "Student_Package.delete",
}

View File

@ -1,6 +1,5 @@
export enum UserTypeEnum {
ADMIN = "admin",
RE_SELLER = "reseller",
PASS="pass"
}
PASS = "pass",
}

View File

@ -46,7 +46,7 @@ export enum ABILITIES_ENUM {
Report = "report",
User = "user",
RE_SELLER = "reseller",
Student_Package = "student_package"
Student_Package = "student_package",
////
}

View File

@ -46,7 +46,7 @@
"grade_to_pass_must_be_less_than_max_grade": "يجب أن تكون درجة النجاح أقل من الحد الأقصى للدرجة",
"max_mark_must_be_greater_than_min_mark_to_pass": "يجب ان تكون اكبر من علامة النجاح",
"Sorry, the question must have at least one option": "عذرًا، يجب أن يحتوي السؤال على خيار واحد على الأقل",
"at_least_one_answer_should_be_correct":"يجب أن تكون إجابة واحدة صحيحة"
"at_least_one_answer_should_be_correct": "يجب أن تكون إجابة واحدة صحيحة"
},
"header": {
"register_students": "تسجيل الطلاب",
@ -116,14 +116,14 @@
"add_question": "اضافة سؤال",
"new_choice_have_been_added": "تم إضافة خيار جديد",
"new_question_have_been_added": "تم إضافة سؤال جديد",
"sort_by":"ترتيب حسب",
"filter":"تصفية",
"per_page":"صف لكل صفحة",
"entries":"ادخالات",
"personal_information":"المعلومات الشخصية",
"address":"العنوان",
"attachment":"المرفق",
"subject_of_class":"مواد الصف"
"sort_by": "ترتيب حسب",
"filter": "تصفية",
"per_page": "صف لكل صفحة",
"entries": "ادخالات",
"personal_information": "المعلومات الشخصية",
"address": "العنوان",
"attachment": "المرفق",
"subject_of_class": "مواد الصف"
},
"columns": {
"id": "الرقم التعريفي",
@ -408,9 +408,9 @@
"Phone Number": "رقم الهاتف",
"Mobile Number": "رقم الموبايل",
"Seller Percentage": "نسبة البائع",
"city":"المحافظة",
"personal_image":"صورة شخصية",
"id_image":"صورة الهوية"
"city": "المحافظة",
"personal_image": "صورة شخصية",
"id_image": "صورة الهوية"
},
"select": {
"enums": {
@ -704,9 +704,9 @@
"recently_arrived": "وصلت مؤخرا"
}
},
"upcoming":"فعال",
"waiting":"قيد الانتظار",
"done":"انتهى"
"upcoming": "فعال",
"waiting": "قيد الانتظار",
"done": "انتهى"
},
"sidebar": {
@ -767,10 +767,10 @@
"user": "مستخدم",
"param": "معامل",
"student_package": "حزمة الطالب",
"add_reseller":"إضافة بائع",
"grade":"الصفوف" ,
"report":"تقرير",
"tags":"كلمات مفتاحية"
"add_reseller": "إضافة بائع",
"grade": "الصفوف",
"report": "تقرير",
"tags": "كلمات مفتاحية"
},
"page_header": {
"dashboard": "لوحة القيادة / الصفحة الرئيسية",
@ -812,8 +812,8 @@
"table": {
"student": "قائمة الطلاب",
"reseller": "البائعين",
"grade":"قائمة الصفوف",
"subjects":"مواد الصف"
"grade": "قائمة الصفوف",
"subjects": "مواد الصف"
},
"alphabet": {
"A": "A",
@ -843,5 +843,5 @@
"Y": "Y",
"Z": "Z"
},
"upcoming":""
"upcoming": ""
}

View File

@ -1,3 +1 @@
{
}
{}

View File

@ -16,7 +16,7 @@ type TMenuItemBase = {
withOutLayout?: boolean;
abilities: ABILITIES_ENUM;
abilities_value: ABILITIES_VALUES_ENUM;
type?:UserTypeEnum
type?: UserTypeEnum;
prevPath: number;
};
@ -40,7 +40,7 @@ export type TCrudRoute = {
element: ReactElement | LazyExoticComponent<any>;
abilities: ABILITIES_ENUM;
abilities_value: ABILITIES_VALUES_ENUM;
type?:UserTypeEnum
type?: UserTypeEnum;
prevPath: number;
};

View File

@ -342,7 +342,6 @@ export type param = {
value: string;
};
export type Student_Package = {
id: number;
student: student;
@ -351,7 +350,7 @@ export type Student_Package = {
};
type student = {
first_name:string;
last_name:string;
sex:string
}
first_name: string;
last_name: string;
sex: string;
};

View File

@ -2,12 +2,11 @@ import { Nullable } from "./App";
// Define the Teacher interface
interface ReSellerUser {
id: number;
username: string;
phone_number: string | null;
type: 'reseller' | 'other'; // Specify other types if needed
type: "reseller" | "other"; // Specify other types if needed
}
interface ReSellerLocation {
@ -21,7 +20,6 @@ interface ContactInfo {
card_number: string | null;
}
export interface ReSeller {
id: number;
user: ReSellerUser;
@ -29,8 +27,8 @@ export interface ReSeller {
last_name: string;
location: ReSellerLocation;
contact_info: ContactInfo;
contact_number1 : string | number
contact_number2 : string | number
contact_number1: string | number;
contact_number2: string | number;
}
export interface InitialValues {
@ -42,9 +40,9 @@ export interface InitialValues {
lat: string | Number;
lng: string | Number;
contact_info: ContactInfo;
contact_number1 : string | number
contact_number2 : string | number
username : string
contact_number1: string | number;
contact_number2: string | number;
username: string;
}
export type ReSellerInitialValues = Partial<Nullable<InitialValues>>;

View File

@ -2,25 +2,27 @@ import { USER_KEY } from "../config/AppKey";
import { UserTypeEnum } from "../enums/UserType";
import { getLocalStorage } from "./LocalStorage";
export const RoleByType = (item: { type?: string }):boolean=>{
export const RoleByType = (item: { type?: string }): boolean => {
const type = item?.type ?? UserTypeEnum.ADMIN;
const LocalType = getLocalStorage(USER_KEY)?.type ?? undefined ;
const isAdmin = LocalType === UserTypeEnum.ADMIN ;
const LocalType = getLocalStorage(USER_KEY)?.type ?? undefined;
const isAdmin = LocalType === UserTypeEnum.ADMIN;
const isReSeller = LocalType === UserTypeEnum.RE_SELLER;
const isReSellerRoute = type === UserTypeEnum.RE_SELLER;
if(!LocalType){
return false
if (!LocalType) {
return false;
}
if(type === UserTypeEnum.PASS) { return true } ;
if(isAdmin && isReSellerRoute ){
return false ;
if (type === UserTypeEnum.PASS) {
return true;
}
if(isReSeller && !isReSellerRoute ){
return false ;
}
if (isAdmin && isReSellerRoute) {
return false;
}
if (isReSeller && !isReSellerRoute) {
return false;
}
return true;
}
};

View File

@ -1,10 +1,10 @@
export const formatDate = (dateString:any) => {
export const formatDate = (dateString: any) => {
if (!dateString) return null; // Handle empty date string
const date = new Date(dateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are zero-based
const day = String(date.getDate()).padStart(2, '0');
const month = String(date.getMonth() + 1).padStart(2, "0"); // Months are zero-based
const day = String(date.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`; // Return formatted date
};
};

View File

@ -620,7 +620,6 @@ export const canDeleteUser = hasAbility(
ABILITIES_VALUES_ENUM.DELETE,
);
/// ReSeller
export const canAddReSeller = hasAbility(
@ -641,7 +640,6 @@ export const canShowReSeller = hasAbility(
ABILITIES_VALUES_ENUM.SHOW,
);
/// Param
export const canAddParam = hasAbility(
@ -662,7 +660,6 @@ export const canShowParam = hasAbility(
ABILITIES_VALUES_ENUM.SHOW,
);
/// User
export const canAddStudent_Package = hasAbility(

View File

@ -1,6 +1,6 @@
export function removeStringKeys(obj: any, keysToRemove: string[]): any {
// Check if the input is an object or array
if (obj && typeof obj === 'object') {
if (obj && typeof obj === "object") {
// Handle arrays
if (Array.isArray(obj)) {
obj.forEach((item, index) => {
@ -12,7 +12,10 @@ export function removeStringKeys(obj: any, keysToRemove: string[]): any {
if (obj.hasOwnProperty(key)) {
const value = obj[key];
// Check if the value is a string or "null" and the key is in keysToRemove
if (keysToRemove.includes(key) && (typeof value === 'string' || value === 'null')) {
if (
keysToRemove.includes(key) &&
(typeof value === "string" || value === "null")
) {
delete obj[key];
} else {
// Recursively process nested objects or arrays

View File

@ -2,7 +2,6 @@ const useFormatDataToSelect = (Data: any) => {
const format = (data: any) => {
if (!Array.isArray(data)) return []; // Check if data is an array
return data?.map((item: any) => ({
value: item?.id,
label: item?.name ?? item?.title,
}));