This commit is contained in:
karimaldeen 2024-09-24 15:25:26 +03:00
commit d71e5c4fce
35 changed files with 722 additions and 111 deletions

View File

@ -21,6 +21,8 @@ interface LayoutModalProps {
ModelClassName?: string;
width?: string;
isLoading?: boolean;
buttonTitle?:string;
initialButtonName?:boolean
}
const LayoutModel = ({
@ -35,6 +37,8 @@ const LayoutModel = ({
ModelClassName,
width = "800px",
isLoading = false,
buttonTitle,
initialButtonName = true,
}: LayoutModalProps) => {
const { isOpen, setIsOpen } = useModalState((state) => state);
const { setObjectToEdit } = useObjectToEdit();
@ -67,7 +71,7 @@ const LayoutModel = ({
onCancel={handleCancel}
>
<Formik
<Formik
enableReinitialize={true}
initialValues={getInitialValues}
validationSchema={getValidationSchema}
@ -84,9 +88,9 @@ const LayoutModel = ({
return <Form className="w-100">
<header>
<header>
<span>
{t(`practical.${isAddModal ? "add" : "edit"}`)}{" "}
{t(`practical.${isAddModal ? "add" : "edit"}`)}{" "}
{t(`models.${modelTitle}`)}{" "}
</span>
<MdCancel onClick={handleCancel} />
@ -105,7 +109,10 @@ const LayoutModel = ({
disabled={status === QueryStatusEnum.LOADING || !formik.dirty}
type="submit"
>
{t(`practical.${isAddModal ? "add" : "edit"}`)}
{
initialButtonName ? t(`practical.${isAddModal ? "add" : "edit"}`)
: t(`practical.${buttonTitle}`)
}
{status === QueryStatusEnum.LOADING && (
<span className="Spinier_Div">
<Spin />

View File

@ -41,12 +41,12 @@ const Page = () => {
<TitleDetailsForm />
<PasswordDetailsForm/>
<AttachmentForm />
<div className="resellerButton">
{/* <div className="resellerButton">
<button type="button">{t("practical.cancel")}</button>
<button type="submit">
{t("practical.add")} {t("models.reseller")}
</button>
</div>
</div> */}
</Form>
</Formik>
</div>

View File

@ -1,22 +1,40 @@
import { useTranslation } from "react-i18next";
import useSetPageTitle from "../../../../Hooks/useSetPageTitle";
import PageHeader from "../../../../Layout/Dashboard/PageHeader";
import { Suspense } from "react";
import { Suspense, useEffect } from "react";
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 { getInitialValues, getValidationSchema } from "../Form/formUtils";
import TitleDetailsForm from "../Form/TitleDetailsForm";
import AttachmentForm from "../Form/AttachmentForm";
import { useAddReseller } from "../../../../api/reseller";
import { useNavigate } from "react-router-dom";
import { QueryStatusEnum } from "../../../../enums/QueryStatus";
const TableHeader = () => {
const [t] = useTranslation();
const Navigate = useNavigate();
const {mutate, isSuccess,status} = useAddReseller();
useSetPageTitle(t(`page_header.add_reseller`));
const handelSubmit = (values: any) => {
console.log(values, "values");
const handleSubmit = (values: any) => {
const DataToSend = {
...values,
location: {
lat: values.lat,
lng: values.lng,
},
};
mutate(DataToSend);
};
useEffect(() => {
if(isSuccess === true){
console.log(1);
Navigate('/reseller')
}
}, [isSuccess])
return (
<div className="TableWithHeader">
<Suspense fallback={<Spin />}>
@ -29,19 +47,26 @@ const TableHeader = () => {
<Formik
initialValues={getInitialValues({})}
validationSchema={getValidationSchema}
onSubmit={handelSubmit}
onSubmit={handleSubmit}
>
<Form className="Form_details_container">
<PersonalDetailsForm />
<TitleDetailsForm />
<AttachmentForm />
<div className="resellerButton">
<button type="button">{t("practical.cancel")}</button>
<button type="submit">
{t("practical.add")} {t("models.reseller")}
</button>
</div>
</Form>
{({ resetForm }) => (
<Form className="Form_details_container">
<PersonalDetailsForm />
<TitleDetailsForm />
<AttachmentForm />
<div className="resellerButton">
<button type="button" onClick={() => Navigate('/reseller')}>{t("practical.cancel")}</button>
<button type="submit">
{t("practical.add")} {t("models.reseller")}
{status === QueryStatusEnum.LOADING && (
<span className="Spinier_Div">
<Spin />
</span>
)}
</button>
</div>
</Form>
)}
</Formik>
</div>
</Suspense>

View File

@ -1,7 +1,84 @@
import React from "react";
import { useTranslation } from "react-i18next";
import useSetPageTitle from "../../../../Hooks/useSetPageTitle";
import PageHeader from "../../../../Layout/Dashboard/PageHeader";
import { Suspense, useEffect } from "react";
import { Spin } from "antd";
import { ModalEnum } from "../../../../enums/Model";
import PersonalDetailsForm from "../Form/PersonalDetailsForm";
import { Formik, Form } from "formik";
import { getInitialValues, getInitialValuesEdit, getValidationSchema } from "../Form/formUtils";
import TitleDetailsForm from "../Form/TitleDetailsForm";
import AttachmentForm from "../Form/AttachmentForm";
import useModalHandler from "../../../../utils/useModalHandler";
import { useObjectToEdit } from "../../../../zustand/ObjectToEditState";
import { useUpdateReseller } from "../../../../api/reseller";
import { useNavigate } from "react-router-dom";
import { QueryStatusEnum } from "../../../../enums/QueryStatus";
const Page = () => {
return <div>Page</div>;
const TableHeader = ({canEdit,ModelAbility}:{canEdit?: any;ModelAbility?: any;}) => {
const [t] = useTranslation();
const { objectToEdit , setObjectToEdit } = useObjectToEdit();
const {mutate, isSuccess,status} = useUpdateReseller();
const Navigate = useNavigate()
console.log(objectToEdit);
useSetPageTitle(t(`page_header.add_reseller`));
const handleSubmit = (values: any) => {
const DataToSend = {
...values,
location: {
lat: values.lat,
lng: values.lng,
},
};
mutate(DataToSend);
};
useEffect(() => {
if(isSuccess === true){
console.log(1);
Navigate('/reseller')
}
}, [isSuccess])
return (
<div className="TableWithHeader">
<Suspense fallback={<Spin />}>
<PageHeader
pageTitle="edit_reseller"
ModelAbility={ModalEnum?.RE_SELLER_EDIT}
canAdd={false}
/>
<div>
<Formik
initialValues={getInitialValuesEdit(objectToEdit)}
validationSchema={getValidationSchema}
onSubmit={handleSubmit}
>
{({ resetForm }) => (
<Form className="Form_details_container">
<PersonalDetailsForm isEdit={true} />
<TitleDetailsForm />
<AttachmentForm />
<div className="resellerButton">
<button type="button" onClick={()=>Navigate('/reseller')}>{t("practical.cancel")}</button>
<button type="submit">
{t("practical.edit")} {t("models.reseller")}
{status === QueryStatusEnum.LOADING && (
<span className="Spinier_Div">
<Spin />
</span>
)}
</button>
</div>
</Form>
)}
</Formik>
</div>
</Suspense>
</div>
);
};
export default Page;
export default TableHeader;

View File

@ -6,7 +6,7 @@ import { convert_data_to_select } from "../../../../Layout/app/Const";
import { userTypeOptions } from "../../../../config/userTypeOptions";
import { statusType } from "../../../../config/statusType";
const PersonalDetailsForm = () => {
const PersonalDetailsForm = ({isEdit}:{isEdit?:boolean}) => {
const [t] = useTranslation();
return (
<div className="PersonalDetailsForm">
@ -16,6 +16,55 @@ const PersonalDetailsForm = () => {
</header>
<main className="main_form_body">
<ValidationField
name={"first_name"}
placeholder={"_"}
label={"first_name"}
/>
<ValidationField
name={"last_name"}
placeholder={"_"}
label={"last_name"}
/>
<ValidationField
name={"contact_number1"}
placeholder={"_"}
label={"contact_number1"}
/>
<ValidationField
name={"contact_number2"}
placeholder={"_"}
label={"contact_number2"}
/>
<ValidationField
name={"username"}
placeholder={"_"}
label={"username"}
type="text"
/>
{isEdit? "" :
<ValidationField
name={"password"}
placeholder={"_"}
label={"password"}
/>
}
<ValidationField
name={"card_number"}
placeholder={"_"}
label={"ID Number"}
/>
<ValidationField
name={"location_lat"}
placeholder={"_"}
label={"lat"}
/>
<ValidationField
name={"location_lng"}
placeholder={"_"}
label={"lng"}
/>
{/* <ValidationField
name={"id_number"}
placeholder={"_"}
label={"ID Number"}
@ -67,7 +116,7 @@ const PersonalDetailsForm = () => {
placeholder={"_"}
label={"Seller Percentage"}
type="text"
/>
/> */}
</main>
</div>
);

View File

@ -15,13 +15,13 @@ const TitleDetailsForm = () => {
</header>
<main className="main_form_body">
<ValidationField
name={"city_id"}
name={"area_id"}
placeholder={"_"}
label={"city"}
type="Select"
option={nationalities}
// type="Select"
// option={nationalities}
/>
<ValidationField name={"address"} placeholder={"_"} label={"address"} />
{/* <ValidationField name={"address"} placeholder={"_"} label={"address"} /> */}
</main>
</div>
);

View File

@ -1,13 +1,89 @@
import * as Yup from "yup";
import { objectToKeyValueArray } from "../../../../utils/objectToKeyValueArray";
export const getInitialValues = (objectToEdit: Partial<any>) => {
interface Location {
lat: number;
lng: number;
}
interface User {
username: string;
phone_number?: number;
type?:string
}
interface PersonalDetailsForm {
id: number;
first_name: string | null;
last_name: string | null;
location: Location[];
contact_number1: string | null;
contact_number2: string | null;
card_number: string | null;
username: string | null;
password: string | null;
area_id: number | null;
}
interface PersonalDetailsEditForm {
id: number;
first_name: string | null;
last_name: string | null;
location: Location[];
contact_number1: string | null;
contact_number2: string | null;
card_number: string | null;
user: User;
area_id: number | null;
}
export const getInitialValues = (objectToEdit: Partial<PersonalDetailsForm>) => {
const location = objectToEdit?.location?.[0] || { lat: 0, lng: 0 };
return {
id: objectToEdit?.id ?? null,
name: objectToEdit?.name ?? null,
id: objectToEdit?.id ?? 0,
first_name: objectToEdit?.first_name ?? null,
last_name: objectToEdit?.last_name ?? null,
location_lat: location.lat,
location_lng: location.lng,
contact_number1: objectToEdit?.contact_number1 ?? null,
contact_number2: objectToEdit?.contact_number2 ?? null,
card_number: objectToEdit?.card_number ?? null,
username: objectToEdit?.username ?? null,
password: objectToEdit?.password ?? null,
area_id: objectToEdit?.area_id ?? null,
};
};
export const getValidationSchema = () => {
// validate input
return Yup.object().shape({});
return Yup.object().shape({
id: Yup.number().required(),
first_name: Yup.string().required('first_name is required'),
last_name: Yup.string().required('last_name is required'),
location_lat: Yup.string().required('lat is required'),
location_lng: Yup.string().required('lng is required'),
contact_number1: Yup.string().required('contact_number1 is required'),
contact_number2: Yup.string().required('contact_number2 is required'),
username: Yup.string().required('username is required'),
area_id: Yup.number().required('area_id is required'),
});
};
export const getInitialValuesEdit = (objectToEdit: Partial<PersonalDetailsEditForm>) => {
const location = objectToEdit?.location || { lat: 0, lng: 0 };
console.log(objectToEdit);
return {
id: objectToEdit?.id ?? 0,
first_name: objectToEdit?.first_name ?? null,
last_name: objectToEdit?.last_name ?? null,
location_lat: location.lat,
location_lng: location.lng,
contact_number1: objectToEdit?.contact_number1 ?? null,
contact_number2: objectToEdit?.contact_number2 ?? null,
card_number: objectToEdit?.card_number ?? null,
username: objectToEdit?.user?.username ?? null,
area_id: objectToEdit?.area_id ?? null,
};
};

View File

@ -10,6 +10,8 @@ import { useDeleteTag } from "../../../api/tags";
import PageHeader from "../../../Layout/Dashboard/PageHeader";
import FilterLayout from "../../../Layout/Dashboard/FilterLayout";
import FilterForm from "./Form/FilterForm";
import EditReSeller from "./Edit/Page";
import { useDeleteReseller } from "../../../api/reseller";
const Table = lazy(() => import("./Table"));
const DeleteModalForm = lazy(
() => import("../../../Layout/Dashboard/DeleteModels"),
@ -24,7 +26,7 @@ const TableHeader = () => {
{name:`${t(`page_header.home`)}`, path:"/"},
{name:`${t(`page_header.reseller`)}`, path:"reseller"}
]);
const deleteMutation = useDeleteTag();
const deleteMutation = useDeleteReseller();
return (
<div className="TableWithHeader">
<Suspense fallback={<Spin />}>
@ -40,6 +42,7 @@ const TableHeader = () => {
filterTitle="table.reseller"
/>
<Table />
{/* <EditReSeller/> */}
<DeleteModalForm
deleteMutation={deleteMutation}
ModelEnum={ModalEnum?.RE_SELLER_DELETE}

View File

@ -4,13 +4,14 @@ import useModalHandler from "../../../utils/useModalHandler";
import { ModalEnum } from "../../../enums/Model";
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import { useNavigate, useParams } from "react-router-dom";
import {
canDeleteReSeller,
canEditReSeller,
canShowReSeller,
} from "../../../utils/hasAbilityFn";
import ActionButtons from "../../../Components/Table/ActionButtons";
import { ABILITIES_ENUM } from "../../../enums/abilities";
export const useColumns = () => {
const { handel_open_model } = useModalHandler();
@ -27,9 +28,9 @@ export const useColumns = () => {
handel_open_model(ModalEnum?.RE_SELLER_DELETE);
};
const handleEdit = (record: ReSeller) => {
const handleEdit = (record: ReSeller) => {
setObjectToEdit(record);
handel_open_model(ModalEnum?.RE_SELLER_EDIT);
navigate(`/${ABILITIES_ENUM?.RE_SELLER}/${record?.id}/edit`)
};
const [t] = useTranslation();

View File

@ -12,7 +12,7 @@ const NotificationCard = ({
const {t} = useTranslation();
return (
<div className='notification_card'>
<div className='notification_card_setting'>
<div>
<h5>{t(`${name}`)}</h5>
<p>{t(`${description}`)}</p>

View File

@ -2,6 +2,7 @@ import { Form, useFormikContext } from "formik";
import { useTranslation } from "react-i18next";
import ValidationField from "../../Components/ValidationField/ValidationField";
import { Input } from "antd";
type FormFieldType = {
isLoading: boolean;
@ -18,7 +19,7 @@ const FormField = ({ isLoading }: FormFieldType) => {
<ValidationField name="username" label="username" />
<ValidationField name="password" label="password" />
<ValidationField name="password" label="password" as={Input.Password} />
<button disabled={ !isValid || isLoading} type="submit" className="auth_submit_button">
{t("practical.login")}

View File

@ -5,7 +5,7 @@ const CollectionInfoCard = ({label,value}:{label:string,value:string}) => {
const {t} = useTranslation();
return (
<div className='collection_info_card'>
<h5>{t(label)}</h5>
<h5>{t(`card.${label}`)}</h5>
<p>{t(value)}</p>
</div>
)

View File

@ -0,0 +1,33 @@
import React from 'react'
import CollectionInfoCard from './CollectionInfoCard'
import { useTranslation } from 'react-i18next'
const CollectionsCards = ({data}:{data?:any}) => {
const {t} = useTranslation();
return (
<>
<CollectionInfoCard
label={t('total_sells')}
value={"210"}
/>
<CollectionInfoCard
label={t('reseller_profit')}
value={"210"}
/>
<CollectionInfoCard
label={t('company_profit')}
value={"210"}
/>
<CollectionInfoCard
label={t('collected')}
value={"210"}
/>
<CollectionInfoCard
label={t('residual')}
value={"210"}
/>
</>
)
}
export default CollectionsCards

View File

@ -5,8 +5,7 @@ import useSetPageTitle from "../../../Hooks/useSetPageTitle";
import PageHeader from "../../../Layout/Dashboard/PageHeader";
import FilterLayout from "../../../Layout/Dashboard/FilterLayout";
import FilterForm from "./Model/FilterForm";
import CollectionInfoCard from "./Model/CollectionInfoCard";
import { CollectionData } from "../../../faker/item";
import CollectionsCards from "./Model/CollectionsCards";
const Table = lazy(() => import("./Table"));
const TableHeader = () => {
@ -23,9 +22,7 @@ const TableHeader = () => {
pageTitle="collections"
/>
<div className="collection_infos">
{CollectionData?.map((collection:any)=>(
<CollectionInfoCard label={collection.label} value={collection.value}/>
))}
<CollectionsCards/>
</div>
<FilterLayout
sub_children={<FilterForm />}

View File

@ -3,13 +3,13 @@ import DataTable from "../../../Layout/Dashboard/Table/DataTable";
import { useColumns } from "./useTableColumns";
import useSearchQuery from "../../../api/utils/useSearchQuery";
import { useFilterState } from "../../../Components/Utils/Filter/FilterState";
import { useGetAllSales } from "../../../api/sales";
import { useGetAllCollections } from "../../../api/collections";
const App: React.FC = () => {
const [searchQuery] = useSearchQuery("name");
const { filterState } = useFilterState();
const response = useGetAllSales({
const response = useGetAllCollections({
name: searchQuery,
pagination: true,
...filterState,

View File

@ -3,15 +3,9 @@ import Table from "./Table";
import { FaPlus } from "react-icons/fa";
import AddModalForm from "./Model/AddModel";
import EditModalForm from "./Model/EditModel";
// import DeleteModalForm from "../../";
export {
Table,
useColumns,
AddModalForm,
EditModalForm,
// DeleteModalForm,
FaPlus,
};

View File

@ -41,12 +41,12 @@ const Page = () => {
<TitleDetailsForm />
<PasswordDetailsForm/>
<AttachmentForm />
<div className="resellerButton">
{/* <div className="resellerButton">
<button type="button">{t("practical.cancel")}</button>
<button type="submit">
{t("practical.add")} {t("models.reseller")}
</button>
</div>
</div> */}
</Form>
</Formik>
</div>

View File

@ -1,31 +1,53 @@
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 { useAddStudentPackage } from "../../../../api/studentPackage";
import ValidationModelForm from "./ValidationModelForm";
import SalesModelForm from "./SalesModelForm";
import SubmitModelForm from "./SubmitModelForm";
import { useAddSales } from "../../../../api/sales";
import LayoutModel from "./LayoutModel";
const AddModel: React.FC = () => {
const { mutate, status } = useAddSales();
const handleSubmit = (values: any) => {
mutate({
...values,
});
// mutate({
// ...values,
// });
};
enum modal {
Number= 0,
Package= 1,
Sure= 2
}
const Forms = {
[modal.Number]: <ValidationModelForm /> ,
[modal.Package] : <SalesModelForm /> ,
[modal.Sure]: <SubmitModelForm />
}
// const modelTitle = Forms.[modal.Number] ? "sale" : Forms.Package ? "adcs" : "Ascas";
return (
<>
<LayoutModel
status={status as QueryStatusEnum}
ModelEnum={ModalEnum.Sales_ADD}
modelTitle="sale"
modelTitle={"modelTitle"}
handleSubmit={handleSubmit}
getInitialValues={getInitialValues({})}
getValidationSchema={getValidationSchema}
initialButtonName={false}
buttonTitle="search"
>
<ModelForm />
{/* {Forms["Number"]} */}
<>
<SalesModelForm/>
</>
</LayoutModel>
</>
);

View File

@ -0,0 +1,103 @@
import React, { useEffect } from "react";
import { Divider, Modal, Spin } from "antd";
import { useModalState } from "../../../../zustand/Modal";
import { useObjectToEdit } from "../../../../zustand/ObjectToEditState";
import { useTranslation } from "react-i18next";
import { QueryStatusEnum } from "../../../../enums/QueryStatus";
import SpinContainer from "../../../../Components/Layout/SpinContainer";
import { MdCancel } from "react-icons/md";
import { Form, Formik } from "formik";
interface LayoutModalProps {
isAddModal?: boolean;
modelTitle: string;
handleSubmit: (values: any) => void;
getInitialValues: any;
getValidationSchema: any;
children: React.ReactNode;
status: QueryStatusEnum;
ModelEnum: any;
ModelClassName?: string;
width?: string;
isLoading?: boolean;
buttonTitle?:string;
initialButtonName?:boolean
}
const LayoutModel = ({
isAddModal = true,
children,
handleSubmit = () => {},
getInitialValues,
getValidationSchema,
status,
modelTitle,
ModelEnum,
ModelClassName,
width = "800px",
isLoading = false,
buttonTitle,
initialButtonName = true,
}: LayoutModalProps) => {
const { isOpen, setIsOpen } = useModalState((state) => state);
const { setObjectToEdit } = useObjectToEdit();
useEffect(() => {
if (isAddModal && status === QueryStatusEnum.SUCCESS) {
setIsOpen("isSuccess");
setObjectToEdit({});
return;
}
if (status === QueryStatusEnum.SUCCESS) {
setIsOpen("");
setObjectToEdit({});
}
}, [setIsOpen, status]);
const handleCancel = () => {
setIsOpen("");
setObjectToEdit({});
};
const [t] = useTranslation();
return (
<>
<Modal
className={"ModalForm " + ModelClassName}
centered
width={width}
footer={null}
open={isOpen === ModelEnum}
onCancel={handleCancel}
>
<Formik
enableReinitialize={true}
initialValues={getInitialValues}
validationSchema={getValidationSchema}
onSubmit={handleSubmit}
>
{(formik) => {
useEffect(() => {
if (isOpen === "" || isOpen === "isSuccess") {
formik.setErrors({});
formik.resetForm();
}
}, [isOpen]);
return <Form className="w-100 reseller_modal_form">
<Divider />
<main className="main_modal">
{isLoading ? <SpinContainer /> : children}
</main>
</Form>;
}}
</Formik>
</Modal>
</>
);
};
export default LayoutModel;

View File

@ -1,26 +0,0 @@
import { Col, Row } from "reactstrap";
import ValidationField from "../../../../Components/ValidationField/ValidationField";
import useFormatDataToSelect from "../../../../utils/useFormatDataToSelect";
const Form = ({ isEdit }: { isEdit?: boolean }) => {
const typeOptions = [
{ id: "student", name: "student" },
{ id: "reseller", name: "reseller" },
{ id: "admin", name: "admin" },
];
const typeArray = useFormatDataToSelect(typeOptions);
return (
<Row className="w-100">
<Col>
<ValidationField
placeholder="phone_number"
label="phone_number"
name="phone_number"
/>
</Col>
</Row>
);
};
export default Form;

View File

@ -0,0 +1,62 @@
import { Col, Row } from "reactstrap";
import ValidationField from "../../../../Components/ValidationField/ValidationField";
import useFormatDataToSelect from "../../../../utils/useFormatDataToSelect";
import { useFormikContext } from "formik";
import { useModalState } from "../../../../zustand/Modal";
import { useObjectToEdit } from "../../../../zustand/ObjectToEditState";
import { useTranslation } from "react-i18next";
import { QueryStatusEnum } from "../../../../enums/QueryStatus";
import { Divider, Spin } from "antd";
import { MdCancel } from "react-icons/md";
const Form = ({status}:{status?:any}) => {
const {values,setFieldValue} = useFormikContext<any>()
console.log(values?.currentModalIndex);
const { isOpen, setIsOpen } = useModalState((state) => state);
const { setObjectToEdit } = useObjectToEdit();
const {t} = useTranslation();
const formik = useFormikContext();
const handleNext = ()=>{
setFieldValue( "currentModalIndex" , values?.currentModalIndex + 1 )
}
const handleCancel = () => {
setIsOpen("");
setObjectToEdit({});
};
return (
values?.currentModalIndex == 0 &&
<div className="w-100">
<header className="modal_title">
<span>
{t(`models.add_sales`)}{" "}
</span>
<MdCancel onClick={handleCancel} />
</header>
<Divider />
sac
{values?.currentModalIndex}
<div className="buttons">
<div className="back_button pointer" onClick={handleCancel}>
{t("practical.cancel")}
</div>
<button
className="add_button"
disabled={status === QueryStatusEnum.LOADING || !formik.dirty}
onClick={handleNext}
>
{t(`practical.search`)}
{status === QueryStatusEnum.LOADING && (
<span className="Spinier_Div">
<Spin />
</span>
)}
</button>
</div>
</div>
);
};
export default Form;

View File

@ -0,0 +1,62 @@
import { Col, Row } from "reactstrap";
import ValidationField from "../../../../Components/ValidationField/ValidationField";
import useFormatDataToSelect from "../../../../utils/useFormatDataToSelect";
import { useFormikContext } from "formik";
import { useModalState } from "../../../../zustand/Modal";
import { useObjectToEdit } from "../../../../zustand/ObjectToEditState";
import { useTranslation } from "react-i18next";
import { QueryStatusEnum } from "../../../../enums/QueryStatus";
import { Divider, Spin } from "antd";
import { MdCancel } from "react-icons/md";
const Form = ({status}:{status?:any}) => {
const {values,setFieldValue} = useFormikContext<any>()
console.log(values?.currentModalIndex);
const { isOpen, setIsOpen } = useModalState((state) => state);
const { setObjectToEdit } = useObjectToEdit();
const {t} = useTranslation();
const formik = useFormikContext();
const handleNext = ()=>{
setFieldValue( "currentModalIndex" , values?.currentModalIndex + 1 )
}
const handleCancel = () => {
setIsOpen("");
setObjectToEdit({});
};
return (
values?.currentModalIndex == 1 &&
<div className="w-100">
<header className="modal_title">
<span>
{t(`models.are_you_sure_about_sale`)}{" "}
</span>
<MdCancel onClick={handleCancel} />
</header>
<Divider />
{values?.currentModalIndex}
<div className="buttons">
<div className="back_button pointer" onClick={handleCancel}>
{t("practical.cancel")}
</div>
<button
className="add_button"
disabled={status === QueryStatusEnum.LOADING || !formik.dirty}
onClick={handleNext}
>
{t(`practical.search`)}
{status === QueryStatusEnum.LOADING && (
<span className="Spinier_Div">
<Spin />
</span>
)}
</button>
</div>
</div>
);
};
export default Form;

View File

@ -0,0 +1,72 @@
import { Col, Row } from "reactstrap";
import ValidationField from "../../../../Components/ValidationField/ValidationField";
import useFormatDataToSelect from "../../../../utils/useFormatDataToSelect";
import { useFormikContext } from "formik";
import { useModalState } from "../../../../zustand/Modal";
import { useObjectToEdit } from "../../../../zustand/ObjectToEditState";
import { useTranslation } from "react-i18next";
import { QueryStatusEnum } from "../../../../enums/QueryStatus";
import { Divider, Spin } from "antd";
import { MdCancel } from "react-icons/md";
const Form = ({status}:{status?:any}) => {
const {values,setFieldValue} = useFormikContext<any>()
console.log(values?.currentModalIndex);
const { isOpen, setIsOpen } = useModalState((state) => state);
const { setObjectToEdit } = useObjectToEdit();
const {t} = useTranslation();
const formik = useFormikContext();
const handleNext = ()=>{
setFieldValue( "currentModalIndex" , values?.currentModalIndex + 1 )
}
const handleCancel = () => {
setIsOpen("");
setObjectToEdit({});
};
return (
values?.currentModalIndex == 1 &&
<div className="w-100">
<header className="modal_title">
<span>
{t(`models.`)}{" "}
</span>
<MdCancel onClick={handleCancel} />
</header>
<Divider />
<Row className="w-100">
<Col>
<ValidationField
placeholder="phone_number"
label="phone_number"
name="phone_number"
/>
<Divider className="margin_auto"/>
</Col>
{values?.currentModalIndex}
<div className="buttons">
<div className="back_button pointer" onClick={handleCancel}>
{t("practical.cancel")}
</div>
<button
className="add_button"
disabled={status === QueryStatusEnum.LOADING || !formik.dirty}
onClick={handleNext}
>
{t(`practical.search`)}
{status === QueryStatusEnum.LOADING && (
<span className="Spinier_Div">
<Spin />
</span>
)}
</button>
</div>
</Row>
</div>
);
};
export default Form;

View File

@ -4,10 +4,16 @@ export const getInitialValues = (objectToEdit: any): any => {
return {
id: objectToEdit?.id ?? null,
phone_number: objectToEdit?.phone_number ?? null,
currentModalIndex: 0
};
};
export const getValidationSchema = () => {
return Yup.object().shape({
phone_number: Yup.number().required("validation.required"),
phone_number: Yup.string()
.required("Phone number is required")
.length(10, "Phone number must be exactly 10 numbers")
.matches(/^\d{10}$/, "Phone number must be a valid 10-number number"),
currentModalIndex: Yup.number().max(2)
});
};
};

View File

@ -4,7 +4,6 @@ import { lazy, Suspense } from "react";
import { Spin } from "antd";
import { canAddSales } from "../../../utils/hasAbilityFn";
import useSetPageTitle from "../../../Hooks/useSetPageTitle";
import { useDeleteTag } from "../../../api/tags";
import PageHeader from "../../../Layout/Dashboard/PageHeader";
import FilterLayout from "../../../Layout/Dashboard/FilterLayout";
import FilterForm from "./Model/FilterForm";

View File

@ -1,6 +1,8 @@
import { TCrudRoute, TMenuItem } from "./types/App";
import { FaCashRegister, FaCity, FaHome, FaMoneyBill, FaPaperclip, FaSellcast, FaTag, FaUser, FaUserShield } from "react-icons/fa";
import { GoDotFill } from "react-icons/go";
import { MdOutlineSell } from "react-icons/md";
import { CgProfile } from "react-icons/cg";
import { GrGroup } from "react-icons/gr";
import React from "react";
@ -196,7 +198,7 @@ export const menuItems: TMenuItem[] = [
{
header: "page_header.sales",
element: <Sales />,
icon: <FaSellcast />,
icon: <MdOutlineSell />,
text: "sidebar.sales",
path: `/${ABILITIES_ENUM?.Sales}`,
abilities: ABILITIES_ENUM?.Sales,
@ -207,7 +209,7 @@ export const menuItems: TMenuItem[] = [
{
header: "page_header.collections",
element: <Collections />,
icon: <FaSellcast />,
icon: <FaMoneyBill />,
text: "sidebar.collections",
path: `/${ABILITIES_ENUM?.Collections}`,
abilities: ABILITIES_ENUM?.Collections,
@ -218,7 +220,7 @@ export const menuItems: TMenuItem[] = [
{
header: "page_header.profile",
element: <ProfileReSeller />,
icon: <FaSellcast />,
icon: <CgProfile />,
text: "sidebar.profile",
path: `/${ABILITIES_ENUM?.PROFILE}`,
abilities: ABILITIES_ENUM?.Profile_RE_SELLER,
@ -280,7 +282,6 @@ export const CrudRoute: TCrudRoute[] = [
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
prevPath: 2,
},
{
header: "page_header.add_reseller",
element: <AddReSeller />,

View File

@ -102,6 +102,12 @@
color: #fff !important;
}
.margin_auto{
@include Flex;
min-width: 100% !important;
margin-inline: auto !important;
}
.disabled{
pointer-events: none;
opacity: 0.6;

View File

@ -15,3 +15,4 @@
@import './profile.scss';
@import './collections.scss';
@import './setting.scss';
@import './sales.scss';

View File

@ -73,4 +73,13 @@
.main_form_body{
border-radius: 10px;
}
}
}

View File

@ -0,0 +1,6 @@
.reseller_modal_form{
width: 100%;
.modal_title{
height: 5vh;
}
}

View File

@ -52,7 +52,7 @@
.setting_tab_header,
.notification_card,
.notification_card_setting,
.security_card {
display: flex;
justify-content: space-between;
@ -87,7 +87,7 @@
margin-bottom: 30px;
}
.notification_card{
.notification_card_setting{
&:nth-last-child(1) {
border: none;
}

View File

@ -6,5 +6,5 @@ const API = {
const KEY = "collections";
export const useGetAllSales = (params?: any, options?: any) =>
export const useGetAllCollections = (params?: any, options?: any) =>
useGetQuery(KEY, API.GET, params, options);

View File

@ -2,10 +2,11 @@ import useAddMutation from "./helper/useAddMutation";
import useGetQuery from "./helper/useGetQuery";
const API = {
GET: "/sales",
ADD: "/sales",
DELETE: "/sales",
UPDATE: "/sales",
GET: "/resellers/studentPackage",
ADD: "/resellers/studentPackage",
GET_BY_PHONE: "/resellers/studentPackage/student",
GET_SUMMERY: "/resellers/studentPackage/summery",
};
const KEY = "sales";

View File

@ -308,7 +308,8 @@
"Devices associated with the account":"الأجهزة المرتبطة بالحساب",
"account_activities":"أنشطة الحساب",
"This will close your account. Your account will be interactive when you log in again":"سيؤدي هذا إلى إغلاق حسابك. سيكون حسابك تفاعليا عند تسجيل الدخول مرة أخرى",
"Your account will be permanently deleted":"سيتم حذف حسابك نهائيا"
"Your account will be permanently deleted":"سيتم حذف حسابك نهائيا",
"search":"بحث"
},
"Table": {
"header": "",
@ -397,7 +398,9 @@
"package": "حزمة",
"packageItem": "عنصر الحزمة",
"Area":"المنطقة",
"City":"مدينة"
"City":"مدينة",
"add_sales":"إضافة عملية بيع",
"are_you_sure_about_sale":"هل أنت متأكد من عملية البيع ؟"
},
"education_class_actions": {
"Student_Records": "سجلات الطلاب",
@ -526,7 +529,11 @@
"role":"الدور",
"submit_password":"تأكيد كلمة المرور",
"join_date":"تاريخ الانضمام",
"verify":"التحقق"
"verify":"التحقق",
"contact_number1":"رقم الهاتف",
"contact_number2":"رقم الهاتف الإضافي",
"lat":"الطول",
"lng":"العرض"
},
"select": {
"enums": {
@ -911,7 +918,8 @@
"edit_manager":"تعديل مدير",
"City":"مدينة",
"Area":"المنطقة",
"setting":"الإعدادات"
"setting":"الإعدادات",
"edit_reseller":"تعديل البائع"
},
"page_header": {
"home": "لوحة القيادة",
@ -981,6 +989,13 @@
"upload_your_photo_and_personal_data_here":"قم بتحميل صورتك وبياناتك الشخصية هنا",
"get_notified_of_whats_happening_now_you_can_turn_it_off_at_any_time":"احصل على إشعار بما يحدث الآن ، يمكنك إيقاف تشغيله في أي وقت"
},
"card" : {
"residual":"المتبقي",
"collected":"تم تحصيله",
"company_profit":"المستحقات",
"reseller_profit":"نسبة الأرباح (10%)",
"total_sells":"إجمالي المبيعات"
},
"alphabet": {
"A": "A",
"B": "B",

View File

@ -0,0 +1,9 @@
export function objectToKeyValueArray(obj: { [key: string]: any } | null | undefined): Array<{ key: string; value: any }> {
if (!obj) {
return [{ key: '', value: '' }]
}
return Object.entries(obj).map(([key, value]) => ({
key,
value
}));
}