diff --git a/src/Components/Loaders/FullscreenLoaders.jsx b/src/Components/Loaders/FullscreenLoaders.jsx
index 151917d..4f2348a 100644
--- a/src/Components/Loaders/FullscreenLoaders.jsx
+++ b/src/Components/Loaders/FullscreenLoaders.jsx
@@ -1,16 +1,16 @@
import { Box, Spinner, Text } from "@chakra-ui/react";
import React from "react";
-import './FullscreenLoaders.css'
+import "./FullscreenLoaders.css";
-const FullscreenLoaders = ({height}) => {
+const FullscreenLoaders = ({ height }) => {
return (
{/*
@@ -23,8 +23,16 @@ const FullscreenLoaders = ({height}) => {
*/}
- {/* Loading... */}
-
+ {/* Loading... */}
+ {/* */}
+
+
);
};
diff --git a/src/Components/Loaders/Loader01.jsx b/src/Components/Loaders/Loader01.jsx
index 24b8f96..67e3c02 100644
--- a/src/Components/Loaders/Loader01.jsx
+++ b/src/Components/Loaders/Loader01.jsx
@@ -4,6 +4,16 @@ import { Spinner } from "@chakra-ui/react";
const Loader01 = () => {
return (
+ //
//
diff --git a/src/Constants/Constants.js b/src/Constants/Constants.js
index aaf5bd7..da74880 100644
--- a/src/Constants/Constants.js
+++ b/src/Constants/Constants.js
@@ -1,6 +1,7 @@
import dns from "node:dns"
import * as XLSX from 'xlsx';
+import CryptoJS from "crypto-js";
export const generateSerialNumber = (index, currentPage, pageSize) => {
@@ -218,4 +219,18 @@ export function formatDateToYYYYMMDD(dateString) {
// Combine the formatted parts
return `${year}-${month}-${day}`;
-}
\ No newline at end of file
+}
+
+
+// Encrypt a string
+export const encryptString = (text) => {
+ const ciphertext = CryptoJS.AES.encrypt(text, import.meta.env.VITE_ROLE_ENCRYPTION_KEY).toString();
+ return ciphertext;
+};
+
+// Decrypt a string
+export const decryptString = (ciphertext) => {
+ const bytes = CryptoJS.AES.decrypt(ciphertext, import.meta.env.VITE_ROLE_ENCRYPTION_KEY);
+ const originalText = bytes.toString(CryptoJS.enc.Utf8);
+ return originalText;
+};
\ No newline at end of file
diff --git a/src/Layout/DefaultLayout.jsx b/src/Layout/DefaultLayout.jsx
index 69d8659..8d0f028 100644
--- a/src/Layout/DefaultLayout.jsx
+++ b/src/Layout/DefaultLayout.jsx
@@ -15,7 +15,12 @@ import {
TbTransactionDollar,
} from "react-icons/tb";
import { TbArrowBadgeRightFilled } from "react-icons/tb";
-import { ArrowBackIcon, ArrowLeftIcon, ArrowRightIcon, AtSignIcon } from "@chakra-ui/icons";
+import {
+ ArrowBackIcon,
+ ArrowLeftIcon,
+ ArrowRightIcon,
+ AtSignIcon,
+} from "@chakra-ui/icons";
import {
Link,
NavLink,
@@ -83,6 +88,7 @@ import ApproveRequest from "../Pages/FawateerChecker/ApproveRequest/ApproveReque
import ApproveHistoryMaker from "../Pages/FawateerChecker/ApproveHistory/ApproveHistoryMaker";
import ApproveHistory from "../Pages/FawateerChecker/ApproveHistory/ApproveHistoryChecker";
import { useProfileQuery } from "../Services/io.service";
+import SubAdmin from "../Pages/SubAdmin/SubAdmin";
const DashboardLayout = ({ isOnline }) => {
const userRole = localStorage.getItem("role");
@@ -165,24 +171,24 @@ const DashboardLayout = ({ isOnline }) => {
Sponsor
);
- case path.startsWith("/email"):
- return (
-
- Email Notifiation
-
- );
+ case path.startsWith("/email"):
+ return (
+
+ Email Notifiation
+
+ );
case path.startsWith("/investment-type"):
return (
Investment Type
);
- case path.startsWith("/profile"):
- return (
-
- Profile
-
- );
+ case path.startsWith("/profile"):
+ return (
+
+ Profile
+
+ );
case path.startsWith("/exchange-rate"):
return (
@@ -241,7 +247,7 @@ const DashboardLayout = ({ isOnline }) => {
Deposite Request
);
-
+
case path.startsWith("/fawateer"):
return (
@@ -249,13 +255,13 @@ const DashboardLayout = ({ isOnline }) => {
Fawateer Deposit
);
- case path.startsWith("/fawateer-history"):
- return (
-
-
- Fawateer Deposit
-
- );
+ case path.startsWith("/fawateer-history"):
+ return (
+
+
+ Fawateer Deposit
+
+ );
case path.startsWith("/withdraw-request"):
return (
@@ -398,6 +404,19 @@ const DashboardLayout = ({ isOnline }) => {
return
;
}
+ const filteredNav = nav.map((item) => {
+ if (item.submenu) {
+ return {
+ ...item,
+ submenu: item.submenu.filter(
+ (submenuItem) =>
+ !(!data?.data?.superAdmin && submenuItem.title === "Sub Admin")
+ ),
+ };
+ }
+ return item;
+ });
+
return (
{
index={openIndex}
onChange={handleAccordionChange}
>
- {nav.map(({ title, type, Icon, submenu, path }, index) => {
+ {filteredNav.map(({ title, type, Icon, submenu, path }, index) => {
if (type === "accordion") {
return (
@@ -788,6 +807,7 @@ const AppContent = ({ data }) => {
)
}
/>
+
} />
);
diff --git a/src/Pages/ChangePassword.jsx b/src/Pages/ChangePassword.jsx
index 84624c2..fa6a898 100644
--- a/src/Pages/ChangePassword.jsx
+++ b/src/Pages/ChangePassword.jsx
@@ -5,6 +5,8 @@ import {
FormErrorMessage,
FormLabel,
Input,
+ InputGroup,
+ InputRightElement,
Modal,
ModalBody,
ModalCloseButton,
@@ -15,23 +17,33 @@ import {
useToast,
} from "@chakra-ui/react";
import * as yup from "yup";
-import React, { useState, useEffect, useContext } from "react";
-import { useForm, Controller } from "react-hook-form";
+import React, { useState, useContext } from "react";
+import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
-import { v4 as uuidv4 } from "uuid";
-import { useParams } from "react-router-dom";
import CustomAlertDialog from "../Components/CustomAlertDialog";
import ToastBox from "../Components/ToastBox";
-import GlobalStateContext from "../Contexts/GlobalStateContext";
-import CurrencyInput from "../Components/CurrencyInput";
+import { useUpdatePasswordMutation } from "../Services/change.password.service";
+import { all } from "axios";
-const ioNav = yup.object().shape({
- transactionDate: yup.string().required("Date is required"),
- transactionAmount: yup.string().required("New NAV is required"),
- comments: yup
+// Validation schema
+const passwordSchema = yup.object().shape({
+ oldPassword: yup.string().required("Current Password is required"),
+ newPassword: yup
.string()
- .notRequired()
- .max(200, "Approve Comment cannot be more than 200 characters"),
+ .required("New Password is required")
+ .min(8, "Password must be at least 8 characters long")
+ .max(16, "Password must be at most 50 characters long")
+ .matches(/[A-Z]/, "Password must contain at least one uppercase letter")
+ .matches(/[a-z]/, "Password must contain at least one lowercase letter")
+ .matches(/[0-9]/, "Password must contain at least one number")
+ .matches(
+ /[@$!%*?]/,
+ "Password must contain at least one special character"
+ ),
+ confirmNewPassword: yup
+ .string()
+ .required("Confirm Password is required")
+ .oneOf([yup.ref("newPassword")], "Passwords must match"),
});
const ChangePassword = ({
@@ -40,124 +52,145 @@ const ChangePassword = ({
firstField,
actionId,
setActionId,
- data,
}) => {
- const params = useParams();
- const id = params?.id;
- const [file, setFile] = useState("");
- const [fileName, setFileName] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [alert, setAlert] = useState(false);
+ const [showCurrentPassword, setShowCurrentPassword] = useState(false);
+ const [showNewPassword, setShowNewPassword] = useState(false);
+ const [showConfirmPassword, setShowConfirmPassword] = useState(false);
const toast = useToast();
- const [showPassword, setShowPassword] = useState(false);
- const [subject, setSubject] = useState("");
- const togglePasswordVisibility = () => setShowPassword(!showPassword);
- // ======================[ Cotext Api ]
- const { IODetails } = useContext(GlobalStateContext);
- const found = data?.find((item) => item?.id === actionId);
-
- // const [addNavDetails] = useAddNavDetailsMutation()
- // const {
- // data
- // } = useGetArtifactsQuery(id)
+ const [updatePassword] = useUpdatePasswordMutation();
+ // Form handling
const {
- control,
+ register,
handleSubmit,
- watch,
reset,
formState: { errors },
} = useForm({
- resolver: yupResolver(ioNav),
+ resolver: yupResolver(passwordSchema),
+ mode: "all",
});
-// const onSubmit = async (data) => {
-// setIsLoading(true);
-
-// try {
-// const res = await addNavDetails({ data, id });
-// if (res?.data?.statusCode === 201) {
-// setIsLoading(false);
-// toast({
-// render: () => ,
-// });
-// handleClose();
-// } else if (res?.error?.status === 400) {
-// toast({
-// render: () => (
-//
-// ),
-// });
-// handleClose();
-// }
-// } catch (error) {
-// console.log(error);
-// }
-// };
-
- const handleSave = () => {
- handleSubmit(onSubmit)();
+ // Form submit handler
+ const onSubmit = async (data) => {
+ setIsLoading(true);
+ try {
+ const res = await updatePassword(data); // Assuming API request works as expected
+ if (res?.data?.statusCode === 200) {
+ toast({
+ render: () => ,
+ });
+ handleClose();
+ } else if (res?.error) {
+ toast({
+ render: () => (
+
+ ),
+ });
+ }
+ } catch (error) {
+ console.error(error);
+ } finally {
+ setIsLoading(false);
+ }
};
+ // Handle modal close
const handleClose = () => {
- setIsLoading(false);
setAlert(false);
onClose();
+ reset();
};
-
return (
<>
-
+
- Change Password
+ Change Password
-
- Current Password
- setSubject(e.target.value)}
+ {/* Current Password */}
+
+
+ Current Password
+
+
+
-
- {errors.ChangePassword?.message}
+ />
+
+
+
+
+
+ {errors.oldPassword?.message}
-
- New Password
- setSubject(e.target.value)}
+
+ {/* New Password */}
+
+
+ New Password
+
+
+
-
+ />
+
+
+
+
+
{errors.newPassword?.message}
-
- Re-Type New Password
- setSubject(e.target.value)}
+
+ {/* Confirm Password */}
+
+
+ Confirm New Password
+
+
+
-
- {errors.conformPassword?.message}
+ />
+
+
+
+
+
+ {errors.confirmNewPassword?.message}
@@ -165,22 +198,20 @@ const ChangePassword = ({
-
@@ -191,8 +222,8 @@ const ChangePassword = ({
setAlert(false)}
- alertHandler={handleSave}
- message={"Are you sure you want to change password?"}
+ alertHandler={handleSubmit(onSubmit)}
+ message={"Are you sure you want to change the password?"}
isLoading={isLoading}
/>
>
diff --git a/src/Pages/ForgetPassword.jsx b/src/Pages/ForgetPassword.jsx
index 8b78aba..23ed47b 100644
--- a/src/Pages/ForgetPassword.jsx
+++ b/src/Pages/ForgetPassword.jsx
@@ -1,178 +1,134 @@
import {
- Button,
- DrawerFooter,
- FormControl,
- FormErrorMessage,
- FormLabel,
- Input,
- Modal,
- ModalBody,
- ModalCloseButton,
- ModalContent,
- ModalHeader,
- ModalOverlay,
- Stack,
- useToast,
- } from "@chakra-ui/react";
- import * as yup from "yup";
- import React, { useState, useEffect, useContext } from "react";
- import { useForm, Controller } from "react-hook-form";
- import { yupResolver } from "@hookform/resolvers/yup";
- import { v4 as uuidv4 } from "uuid";
- import { useParams } from "react-router-dom";
- import CustomAlertDialog from "../Components/CustomAlertDialog";
- import ToastBox from "../Components/ToastBox";
- import GlobalStateContext from "../Contexts/GlobalStateContext";
- import CurrencyInput from "../Components/CurrencyInput";
-
- const ioNav = yup.object().shape({
- transactionDate: yup.string().required("Date is required"),
- transactionAmount: yup.string().required("New NAV is required"),
- comments: yup
- .string()
- .notRequired()
- .max(200, "Approve Comment cannot be more than 200 characters"),
+ Button,
+ DrawerFooter,
+ FormControl,
+ FormErrorMessage,
+ FormLabel,
+ Input,
+ Modal,
+ ModalBody,
+ ModalCloseButton,
+ ModalContent,
+ ModalHeader,
+ ModalOverlay,
+ Stack,
+ useToast,
+} from "@chakra-ui/react";
+import * as yup from "yup";
+import React, { useState} from "react";
+import { useForm, Controller } from "react-hook-form";
+import { yupResolver } from "@hookform/resolvers/yup";
+import { useForgetPasswordMutation } from "../Services/forget.password.service";
+import ToastBox from "../Components/ToastBox";
+
+const validationSchema = yup.object().shape({
+ emailAddress: yup
+ .string()
+ .email("Invalid email format")
+ .required("Email, Phone, or Username is required"),
+});
+
+const ForgetPassword = ({ isOpen, onClose, firstField }) => {
+ const toast = useToast();
+ const [isLoading, setIsLoading] = useState(false);
+
+ const [forgetPassword] = useForgetPasswordMutation();
+
+ const {
+ control,
+ handleSubmit,
+ formState: { errors },
+ } = useForm({
+ resolver: yupResolver(validationSchema),
});
-
- const ForgetPassword = ({
- isOpen,
- onClose,
- firstField,
- actionId,
- setActionId,
- data,
- }) => {
- const params = useParams();
- const id = params?.id;
- const [file, setFile] = useState("");
- const [fileName, setFileName] = useState("");
- const [isLoading, setIsLoading] = useState(false);
- const [alert, setAlert] = useState(false);
- const toast = useToast();
-
- const [showPassword, setShowPassword] = useState(false);
- const [subject, setSubject] = useState("");
- // ======================[ Cotext Api ]
- const { IODetails } = useContext(GlobalStateContext);
- const found = data?.find((item) => item?.id === actionId);
-
- // const [addNavDetails] = useAddNavDetailsMutation()
- // const {
- // data
- // } = useGetArtifactsQuery(id)
-
- const {
- control,
- handleSubmit,
- watch,
- reset,
- formState: { errors },
- } = useForm({
- resolver: yupResolver(ioNav),
- });
-
- // const onSubmit = async (data) => {
- // setIsLoading(true);
-
- // try {
- // const res = await addNavDetails({ data, id });
- // if (res?.data?.statusCode === 201) {
- // setIsLoading(false);
- // toast({
- // render: () => ,
- // });
- // handleClose();
- // } else if (res?.error?.status === 400) {
- // toast({
- // render: () => (
- //
- // ),
- // });
- // handleClose();
- // }
- // } catch (error) {
- // console.log(error);
- // }
- // };
-
- const handleSave = () => {
- handleSubmit(onSubmit)();
- };
-
- const handleClose = () => {
- setIsLoading(false);
- setAlert(false);
- onClose();
- };
+
+ const onSubmit = async (formData) => {
-
- return (
- <>
-
-
-
- Forget Password
-
-
-
-
- Email, Phone, or UserName
- setSubject(e.target.value)}
- focusBorderColor="forestGreen.300"
- rounded={4}
- // type={showPassword ? "text" : "password"}
- type="text"
- />
-
- {errors.ChangePassword?.message}
-
-
-
-
-
-
- {/* */}
-
-
-
-
-
-
- setAlert(false)}
- alertHandler={handleSave}
- message={"Are you sure you want to change password?"}
- isLoading={isLoading}
- />
- >
- );
+ setIsLoading(true);
+ try {
+ const res = await forgetPassword(formData);
+ if (res?.data?.statusCode === 200) {
+ toast({
+ render: () => ,
+ });
+ handleClose();
+ } else if (res?.error?.status === 401) {
+ toast({
+ render: () => (
+
+ ),
+ });
+ handleClose();
+ }
+ } catch (error) {
+ console.error(error);
+ } finally {
+ setIsLoading(false);
+ }
};
-
- export default ForgetPassword;
-
\ No newline at end of file
+
+ const handleClose = () => {
+ setIsLoading(false);
+ onClose();
+ };
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+export default ForgetPassword;
diff --git a/src/Pages/IO_Management/CreateIO/IOCashDetails/IOCashDetails.jsx b/src/Pages/IO_Management/CreateIO/IOCashDetails/IOCashDetails.jsx
index a66e6af..255c726 100644
--- a/src/Pages/IO_Management/CreateIO/IOCashDetails/IOCashDetails.jsx
+++ b/src/Pages/IO_Management/CreateIO/IOCashDetails/IOCashDetails.jsx
@@ -20,6 +20,7 @@ import AddCaseDetails from "./AddCaseDetails";
import { useUpdateIOCaseMutation } from "../../../../Services/io.service";
import ToastBox from "../../../../Components/ToastBox";
import { useParams } from "react-router-dom";
+import { encryptString } from "../../../../Constants/Constants";
const IOCashDetails = () => {
const params = useParams();
@@ -105,7 +106,7 @@ const IOCashDetails = () => {
{IODetails?.isInvestedAmount
- ? localStorage?.getItem("role") === "Maker" && (
+ ? localStorage?.getItem("role") === encryptString(import.meta.env.VITE_VITE_MAKER) && (
}
diff --git a/src/Pages/IO_Management/CreateIO/IOCashDetails/Pending.jsx b/src/Pages/IO_Management/CreateIO/IOCashDetails/Pending.jsx
index b025968..06bc1d9 100644
--- a/src/Pages/IO_Management/CreateIO/IOCashDetails/Pending.jsx
+++ b/src/Pages/IO_Management/CreateIO/IOCashDetails/Pending.jsx
@@ -38,6 +38,7 @@ import { useUpdateIOCaseMutation } from "../../../../Services/io.service";
import RequestApproveModal from "./RequestApproveModal";
import RequestRejectModal from "./RequestRejectModal";
import AddCaseDetails from "./AddCaseDetails";
+import { encryptString } from "../../../../Constants/Constants";
const formatDate = (date) => new Date(date).toLocaleDateString();
@@ -104,7 +105,7 @@ const Pending = () => {
"Comments",
"Update By",
"Update On",
- ...(localStorage?.getItem('role')!=="Maker" ? ["Actions"] : []),
+ ...(localStorage?.getItem('role')!==encryptString(import.meta.env.VITE_VITE_MAKER) ? ["Actions"] : []),
];
@@ -166,7 +167,7 @@ const Pending = () => {
),
Actions: (
- {localStorage?.getItem("role") !== "Maker" ?
+ {localStorage?.getItem("role") !== encryptString(import.meta.env.VITE_VITE_MAKER) ?
{index===0&&
{
const params = useParams();
@@ -152,7 +153,7 @@ const IONAVDetails = () => {
{IODetails?.isInvestedAmount
- ? localStorage?.getItem("role") === "Maker" && (
+ ? localStorage?.getItem("role") === encryptString(import.meta.env.VITE_VITE_MAKER) && (
}
diff --git a/src/Pages/IO_Management/CreateIO/IONAVDetails/Pending.jsx b/src/Pages/IO_Management/CreateIO/IONAVDetails/Pending.jsx
index 928532a..a249bce 100644
--- a/src/Pages/IO_Management/CreateIO/IONAVDetails/Pending.jsx
+++ b/src/Pages/IO_Management/CreateIO/IONAVDetails/Pending.jsx
@@ -22,6 +22,7 @@ import ToastBox from "../../../../Components/ToastBox";
import AddNavDetails from "./AddNavDetails";
import RequestApproveModal from "./RequestApproveModal";
import RequestRejectModal from "./RequestRejectModal";
+import { encryptString } from "../../../../Constants/Constants";
const formatDate = (date) => new Date(date).toLocaleDateString();
@@ -90,7 +91,7 @@ const Pending = () => {
"Investment Closed",
"Comments",
"Updated By",
- ...(localStorage?.getItem("role") !== "Maker" ? ["Status"] : []),
+ ...(localStorage?.getItem("role") !== encryptString(import.meta.env.VITE_VITE_MAKER) ? ["Status"] : []),
];
const extractedArray = filteredData?.map((item, index) => ({
diff --git a/src/Pages/IO_Management/CreateIO/IOTransaction/Pending.jsx b/src/Pages/IO_Management/CreateIO/IOTransaction/Pending.jsx
index a8db39d..d7d181a 100644
--- a/src/Pages/IO_Management/CreateIO/IOTransaction/Pending.jsx
+++ b/src/Pages/IO_Management/CreateIO/IOTransaction/Pending.jsx
@@ -27,6 +27,7 @@ import ViewAmountInvested from "./ViewAmountInvested";
import ViewDistributionInvestor from "./ViewDistributionInvestor";
import ViewExit from "./ViewExit";
import ViewCancel from "./ViewCancel";
+import { encryptString } from "../../../../Constants/Constants";
const formatDate = (date) => new Date(date).toLocaleDateString();
@@ -195,7 +196,7 @@ const Pending = () => {
}
}}
>
- {localStorage?.getItem("role") === "Maker" ? : null} {localStorage?.getItem("role") === "Maker" ? "View" : "Approve / Reject"}
+ {localStorage?.getItem("role") === encryptString(import.meta.env.VITE_VITE_MAKER) ? : null} {localStorage?.getItem("role") === encryptString(import.meta.env.VITE_VITE_MAKER) ? "View" : "Approve / Reject"}
),
diff --git a/src/Pages/IO_Management/CreateIO/IOTransaction/ViewAmountInvested.jsx b/src/Pages/IO_Management/CreateIO/IOTransaction/ViewAmountInvested.jsx
index 9af6d74..6c8cdbc 100644
--- a/src/Pages/IO_Management/CreateIO/IOTransaction/ViewAmountInvested.jsx
+++ b/src/Pages/IO_Management/CreateIO/IOTransaction/ViewAmountInvested.jsx
@@ -27,6 +27,7 @@ import CurrencyInput from "../../../../Components/CurrencyInput";
import RequestRejectModal from "./RequestRejectModal";
import ApproveInvestedModal from "./ApproveInvestedModal";
import { formatDate } from "../../../Master/Sponser/Sponsers";
+import { encryptString } from "../../../../Constants/Constants";
// Validation schema
const validationSchema = yup.object().shape({
@@ -236,7 +237,7 @@ const ViewAmountInvested = ({ isOpen, onClose, id: investorId }) => {
/>
- {localStorage?.getItem("role") !== "Maker" &&
+ {localStorage?.getItem("role") !== encryptString(import.meta.env.VITE_VITE_MAKER) &&
- {localStorage?.getItem("role") !== "Maker" &&
+ {localStorage?.getItem("role") !== encryptString(import.meta.env.VITE_VITE_MAKER) &&