-
{t("header.notifications")}
+
{t("header.notifications")}
diff --git a/src/Pages/Admin/Profile/Form/AttachmentForm.tsx b/src/Pages/Admin/Profile/Form/AttachmentForm.tsx
new file mode 100644
index 0000000..da3397c
--- /dev/null
+++ b/src/Pages/Admin/Profile/Form/AttachmentForm.tsx
@@ -0,0 +1,25 @@
+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 (
+
+ );
+};
+
+export default AttachmentForm;
diff --git a/src/Pages/Admin/Profile/Form/HeaderForm.tsx b/src/Pages/Admin/Profile/Form/HeaderForm.tsx
new file mode 100644
index 0000000..eb9a94e
--- /dev/null
+++ b/src/Pages/Admin/Profile/Form/HeaderForm.tsx
@@ -0,0 +1,24 @@
+import { Button } from 'antd';
+import React from 'react'
+import { useTranslation } from 'react-i18next'
+
+const HeaderForm = ({name,Icon,ButtonIcon, isHaveButtonIcon= true,buttonName = "edit"}:{name:string,Icon:any,ButtonIcon?:any,isHaveButtonIcon?:boolean,buttonName?:string}) => {
+ const {t} = useTranslation();
+ return (
+ <>
+
+
+
{t(`header.${name}`)}
+
+
+
+
+ >
+ )
+}
+
+export default HeaderForm
\ No newline at end of file
diff --git a/src/Pages/Admin/Profile/Form/ImageBoxField/ImageBoxField.scss b/src/Pages/Admin/Profile/Form/ImageBoxField/ImageBoxField.scss
new file mode 100644
index 0000000..66e2f2f
--- /dev/null
+++ b/src/Pages/Admin/Profile/Form/ImageBoxField/ImageBoxField.scss
@@ -0,0 +1,38 @@
+.ImageBoxField {
+ .ImageBox {
+ width: 120px;
+ height: 120px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border: max(1.5px, 0.1vw) dashed #a9c3f1;
+ margin-block: 10px;
+ border-radius: 5px;
+ z-index: 9999999 !important;
+ .ImageBoxIcon {
+ cursor: pointer;
+ }
+ .imagePreview {
+ max-width: 99%;
+ height: auto;
+ max-height: 99%;
+ object-fit: contain;
+ border-radius: 5px;
+ }
+ }
+ .ImageHeader {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ gap: 10px;
+ }
+
+ .ImageCancelIcon {
+ width: 16px !important;
+ height: 16px !important;
+ }
+ .ImageBoxIcon {
+ width: 20px !important;
+ height: 20px !important;
+ }
+}
diff --git a/src/Pages/Admin/Profile/Form/ImageBoxField/ImageBoxField.tsx b/src/Pages/Admin/Profile/Form/ImageBoxField/ImageBoxField.tsx
new file mode 100644
index 0000000..d163048
--- /dev/null
+++ b/src/Pages/Admin/Profile/Form/ImageBoxField/ImageBoxField.tsx
@@ -0,0 +1,87 @@
+import { useFormikContext } from "formik";
+import { useState, useRef, useEffect } from "react";
+import "./ImageBoxField.scss";
+import ImageIcon from "./ImageIcon";
+import ImageCancelIcon from "./ImageCancelIcon";
+import { generateImagePreview } from "./generateImagePreview";
+import { getNestedValue } from "../../../../../utils/getNestedValue";
+import { useTranslation } from "react-i18next";
+
+// Helper function to generate image preview from a File
+
+const ImageBoxField = ({ name }: any) => {
+ const formik = useFormikContext
();
+ const value = getNestedValue(formik.values, name);
+ const [imagePreview, setImagePreview] = useState(null);
+ const fileInputRef = useRef(null);
+
+ useEffect(() => {
+ if (value instanceof File) {
+ generateImagePreview(value, setImagePreview);
+ } else if (typeof value === "string") {
+ setImagePreview(value);
+ } else {
+ setImagePreview(null);
+ }
+ }, [value]);
+
+ const handleFileChange = (event: any) => {
+ const file = event.target.files[0];
+ if (file) {
+ generateImagePreview(file, setImagePreview);
+ formik.setFieldValue(name, file);
+ }
+ };
+
+ const handleButtonClick = () => {
+ const fileInput = fileInputRef.current;
+ if (fileInput) {
+ fileInput.click();
+ }
+ };
+
+ const handleCancel = () => {
+ setImagePreview("");
+ formik.setFieldValue(name, "");
+
+ if (fileInputRef.current) {
+ fileInputRef.current.value = "";
+ }
+ };
+ const [t] = useTranslation();
+ return (
+
+
+
+ {imagePreview ? (
+ <>
+
+
+ >
+ ) : (
+
hidden
+ )}
+
+
+ {imagePreview ? (
+

+ ) : (
+
+ )}
+
+
+
+ );
+};
+
+export default ImageBoxField;
diff --git a/src/Pages/Admin/Profile/Form/ImageBoxField/ImageCancelIcon.tsx b/src/Pages/Admin/Profile/Form/ImageBoxField/ImageCancelIcon.tsx
new file mode 100644
index 0000000..d42ba53
--- /dev/null
+++ b/src/Pages/Admin/Profile/Form/ImageBoxField/ImageCancelIcon.tsx
@@ -0,0 +1,18 @@
+import React from "react";
+
+interface ImageCancelIconProps extends React.HTMLAttributes {}
+
+const ImageCancelIcon: React.FC = (props) => {
+ return (
+
+ );
+};
+
+export default ImageCancelIcon;
diff --git a/src/Pages/Admin/Profile/Form/ImageBoxField/ImageIcon.tsx b/src/Pages/Admin/Profile/Form/ImageBoxField/ImageIcon.tsx
new file mode 100644
index 0000000..4ca597a
--- /dev/null
+++ b/src/Pages/Admin/Profile/Form/ImageBoxField/ImageIcon.tsx
@@ -0,0 +1,18 @@
+import React from "react";
+
+interface ImageIconProps extends React.HTMLAttributes {}
+
+const ImageIcon: React.FC = (props) => {
+ return (
+
+ );
+};
+
+export default ImageIcon;
diff --git a/src/Pages/Admin/Profile/Form/ImageBoxField/generateImagePreview.ts b/src/Pages/Admin/Profile/Form/ImageBoxField/generateImagePreview.ts
new file mode 100644
index 0000000..3f754d3
--- /dev/null
+++ b/src/Pages/Admin/Profile/Form/ImageBoxField/generateImagePreview.ts
@@ -0,0 +1,10 @@
+export const generateImagePreview = (
+ file: File,
+ setImagePreview: (result: string) => void,
+) => {
+ const reader = new FileReader();
+ reader.onloadend = () => {
+ setImagePreview(reader.result as string);
+ };
+ reader.readAsDataURL(file);
+};
diff --git a/src/Pages/Admin/Profile/Form/PasswordDetailsForm.tsx b/src/Pages/Admin/Profile/Form/PasswordDetailsForm.tsx
new file mode 100644
index 0000000..88efe37
--- /dev/null
+++ b/src/Pages/Admin/Profile/Form/PasswordDetailsForm.tsx
@@ -0,0 +1,26 @@
+import { useTranslation } from "react-i18next";
+import { FaStore } from "react-icons/fa";
+import ValidationField from "../../../../Components/ValidationField/ValidationField";
+import { CiEdit } from "react-icons/ci";
+import HeaderForm from "./HeaderForm";
+
+const PasswordDetailsForm = () => {
+ const [t] = useTranslation();
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+export default PasswordDetailsForm;
diff --git a/src/Pages/Admin/Profile/Form/PersonalDetailsForm.tsx b/src/Pages/Admin/Profile/Form/PersonalDetailsForm.tsx
new file mode 100644
index 0000000..96d9ed5
--- /dev/null
+++ b/src/Pages/Admin/Profile/Form/PersonalDetailsForm.tsx
@@ -0,0 +1,56 @@
+import { useTranslation } from "react-i18next";
+import { FaStore } from "react-icons/fa";
+import ValidationField from "../../../../Components/ValidationField/ValidationField";
+import { statusType } from "../../../../config/statusType";
+import { Button } from "antd";
+import { CiEdit } from "react-icons/ci";
+import HeaderForm from "./HeaderForm";
+
+const PersonalDetailsForm = () => {
+ const [t] = useTranslation();
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default PersonalDetailsForm;
diff --git a/src/Pages/Admin/Profile/Form/TitleDetailsForm.tsx b/src/Pages/Admin/Profile/Form/TitleDetailsForm.tsx
new file mode 100644
index 0000000..1e62655
--- /dev/null
+++ b/src/Pages/Admin/Profile/Form/TitleDetailsForm.tsx
@@ -0,0 +1,33 @@
+import { useTranslation } from "react-i18next";
+import { FaStore } from "react-icons/fa";
+import ValidationField from "../../../../Components/ValidationField/ValidationField";
+import { nationalities } from "../../../../types/App";
+import { CiEdit } from "react-icons/ci";
+import HeaderForm from "./HeaderForm";
+
+const TitleDetailsForm = () => {
+ const [t] = useTranslation();
+
+ return (
+
+
+
+
+
+
+
+ );
+};
+
+export default TitleDetailsForm;
diff --git a/src/Pages/Admin/Profile/Form/formUtils.ts b/src/Pages/Admin/Profile/Form/formUtils.ts
new file mode 100644
index 0000000..b14915a
--- /dev/null
+++ b/src/Pages/Admin/Profile/Form/formUtils.ts
@@ -0,0 +1,13 @@
+import * as Yup from "yup";
+
+export const getInitialValues = (objectToEdit: Partial) => {
+ return {
+ id: objectToEdit?.id ?? null,
+ name: objectToEdit?.name ?? null,
+ };
+};
+
+export const getValidationSchema = () => {
+ // validate input
+ return Yup.object().shape({});
+};
diff --git a/src/Pages/Admin/Profile/Page.tsx b/src/Pages/Admin/Profile/Page.tsx
new file mode 100644
index 0000000..def9cc2
--- /dev/null
+++ b/src/Pages/Admin/Profile/Page.tsx
@@ -0,0 +1,58 @@
+import { useTranslation } from "react-i18next";
+import useSetPageTitle from "../../../Hooks/useSetPageTitle";
+import PageHeader from "../../../Layout/Dashboard/PageHeader";
+import { Suspense } from "react";
+import { Spin } from "antd";
+import { ModalEnum } from "../../../enums/Model";
+import { canAddReSeller } from "../../../utils/hasAbilityFn";
+import { Formik, Form } from "formik";
+import { getInitialValues, getValidationSchema } from "./Form/formUtils";
+import PersonalDetailsForm from "./Form/PersonalDetailsForm";
+import TitleDetailsForm from "./Form/TitleDetailsForm";
+import AttachmentForm from "./Form/AttachmentForm";
+import PasswordDetailsForm from "./Form/PasswordDetailsForm";
+
+const Page = () => {
+ const [t] = useTranslation();
+ useSetPageTitle(t(`page_header.add_reseller`));
+ const handelSubmit = (values: any) => {
+ console.log(values, "values");
+ };
+ useSetPageTitle([
+ {name:`${t(`page_header.home`)}`, path:"/"},
+ {name:`${t(`page_header.profile`)}`, path:"tag"}
+ ]);
+ return (
+
+ );
+};
+
+export default Page;
diff --git a/src/Pages/Admin/Reseller/Add/Page.tsx b/src/Pages/Admin/Reseller/Add/Page.tsx
index 19d6daa..8a16bc0 100644
--- a/src/Pages/Admin/Reseller/Add/Page.tsx
+++ b/src/Pages/Admin/Reseller/Add/Page.tsx
@@ -25,13 +25,13 @@ const TableHeader = () => {
ModelAbility={ModalEnum?.RE_SELLER_ADD}
canAdd={false}
/>
-