diff --git a/src/Components/DataTable/NormalTable.jsx b/src/Components/DataTable/NormalTable.jsx
index af3155f..a08a134 100644
--- a/src/Components/DataTable/NormalTable.jsx
+++ b/src/Components/DataTable/NormalTable.jsx
@@ -58,7 +58,6 @@ const NormalTable = ({
};
-
const handleCheckboxChange = (value) => {
if (radio) {
// If radio is true, select only one option
diff --git a/src/Components/Popups/ConfirmReversalPopups.jsx b/src/Components/Popups/ConfirmReversalPopups.jsx
new file mode 100644
index 0000000..b6e7183
--- /dev/null
+++ b/src/Components/Popups/ConfirmReversalPopups.jsx
@@ -0,0 +1,202 @@
+import {
+ Box,
+ Button,
+ Checkbox,
+ FormControl,
+ FormLabel,
+ Input,
+ Modal,
+ ModalBody,
+ ModalCloseButton,
+ ModalContent,
+ ModalFooter,
+ ModalHeader,
+ ModalOverlay,
+ Text,
+ Textarea,
+ useBoolean,
+} from "@chakra-ui/react";
+import React, { useEffect, useState } from "react";
+import PropTypes from "prop-types";
+
+import * as yup from "yup";
+import { yupResolver } from "@hookform/resolvers/yup";
+import { useForm } from "react-hook-form";
+import ReactQuill from "react-quill";
+
+export const conformModalSchema = yup.object().shape({
+ comment: yup
+ .string()
+ .min(2, "Minimum length should be 2 characters.")
+ .max(150, "Maximum length should be 150 characters.")
+ // .matches(/^[^\d]+$/, "Sponsor Name cannot contain numbers")
+ .required("Comment is required"),
+ subject: yup.string().notRequired(),
+ emailTemplate: yup.string().notRequired(),
+});
+
+const ConfirmReversalPopups = ({
+ isOpen,
+ onClose,
+ handleConfirm,
+ isLoading,
+}) => {
+ const {
+ watch,
+ register,
+ reset,
+ handleSubmit,
+ setValue,
+ formState: { errors },
+ } = useForm({
+ resolver: yupResolver(conformModalSchema),
+ mode: "all",
+ });
+
+ const [richTextValue, setRichTextValue] = useState("");
+
+ useEffect(() => {
+ setValue("emailTemplate", richTextValue);
+ }, [richTextValue]);
+
+ // Reset the form when the modal closes
+ useEffect(() => {
+ if (!isOpen) {
+ reset(); // Clear the form state
+ }
+ }, [isOpen, reset]);
+
+ const [emailApproval, setEmailApproval] = useBoolean(false);
+
+ const modules = {
+ toolbar: [
+ // [{ header: "1" }, { header: "2" },
+ // // { font: [] }
+ // ],
+ // [{ size: [] }],
+ ["bold", "italic", "underline", "strike", "blockquote"],
+ [{ list: "ordered" }, { list: "bullet" }],
+ ["clean"],
+ ],
+ };
+
+ return (
+
+
+
+ Approve
+
+ {
+ handleConfirm(data);
+ reset();
+ onClose();
+ })}
+ >
+
+
+ Comment
+
+ {errors.comment ? (
+
+ {errors.comment.message}
+
+ ) : (
+
+ Maximum length should be 150 characters. You have entered{" "}
+ {watch()?.comment?.length || 0} characters.
+
+ )}
+
+
+
+ Send an email to the user upon approval
+
+
+ {emailApproval && (
+
+
+
+ Subject
+
+
+
+
+
+ Message
+
+
+
+
+ )}
+
+
+
+
+
+
+
+
+ );
+};
+
+ConfirmReversalPopups.propTypes = {
+ isOpen: PropTypes.bool.isRequired,
+ onClose: PropTypes.func.isRequired,
+ handelApproved: PropTypes.func.isRequired,
+ isLoading: PropTypes.func.isRequired,
+ richTextValue: PropTypes.any.isRequired,
+ setRichTextValue: PropTypes.any.isRequired,
+};
+
+export default ConfirmReversalPopups;
diff --git a/src/Components/Popups/InitiateReversalPopups.jsx b/src/Components/Popups/InitiateReversalPopups.jsx
new file mode 100644
index 0000000..0a78a02
--- /dev/null
+++ b/src/Components/Popups/InitiateReversalPopups.jsx
@@ -0,0 +1,133 @@
+import {
+ Box,
+ Button,
+ FormControl,
+ FormLabel,
+ Modal,
+ ModalBody,
+ ModalCloseButton,
+ ModalContent,
+ ModalFooter,
+ ModalHeader,
+ ModalOverlay,
+ Text,
+ Textarea,
+} from "@chakra-ui/react";
+import React, { useEffect } from "react";
+import PropTypes from "prop-types";
+
+import * as yup from "yup";
+import { yupResolver } from "@hookform/resolvers/yup";
+import { useForm } from "react-hook-form";
+
+export const conformModalSchema = yup.object().shape({
+ comment: yup
+ .string()
+ .min(2, "Minimum length should be 2 characters.")
+ .max(150, "Maximum length should be 150 characters.")
+ // .matches(/^[^\d]+$/, "Sponsor Name cannot contain numbers")
+ .required("Comment is required"),
+});
+
+const InitiateReversalPopup = ({
+ isOpen,
+ onClose,
+ handelApproved,
+ isLoading,
+}) => {
+ const {
+ watch,
+ register,
+ reset,
+ handleSubmit,
+ formState: { errors },
+ } = useForm({
+ resolver: yupResolver(conformModalSchema),
+ mode: "all",
+ });
+
+ // Reset the form when the modal closes
+ useEffect(() => {
+ if (!isOpen) {
+ reset(); // Clear the form state
+ }
+ }, [isOpen, reset]);
+
+ return (
+
+
+
+ Reversal Reason
+
+ {
+ handelApproved(data);
+ reset();
+ onClose();
+ })}
+ >
+
+
+ Comment
+
+
+ {errors.comment ? (
+
+ {errors.comment.message}
+
+ ) : (
+
+ Maximum length should be 150 characters. You have entered{" "}
+ {watch()?.comment?.length || 0} characters.
+
+ )}
+
+
+
+
+
+
+
+
+
+ );
+};
+
+InitiateReversalPopup.propTypes = {
+ isOpen: PropTypes.bool.isRequired,
+ isLoading: PropTypes.bool.isRequired,
+ onClose: PropTypes.func.isRequired,
+ handelApproved: PropTypes.func.isRequired,
+};
+
+export default InitiateReversalPopup;
diff --git a/src/Components/Popups/RejectReversalPopups.jsx b/src/Components/Popups/RejectReversalPopups.jsx
new file mode 100644
index 0000000..23fc9dc
--- /dev/null
+++ b/src/Components/Popups/RejectReversalPopups.jsx
@@ -0,0 +1,132 @@
+import {
+ Box,
+ Button,
+ FormControl,
+ FormLabel,
+ Modal,
+ ModalBody,
+ ModalCloseButton,
+ ModalContent,
+ ModalFooter,
+ ModalHeader,
+ ModalOverlay,
+ Text,
+ Textarea,
+} from "@chakra-ui/react";
+import React, { useEffect } from "react";
+import PropTypes from "prop-types";
+
+import * as yup from "yup";
+import { yupResolver } from "@hookform/resolvers/yup";
+import { useForm } from "react-hook-form";
+
+export const conformModalSchema = yup.object().shape({
+ comment: yup
+ .string()
+ .min(2, "Minimum length should be 2 characters.")
+ .max(150, "Maximum length should be 150 characters.")
+ // .matches(/^[^\d]+$/, "Sponsor Name cannot contain numbers")
+ .required("Comment is required"),
+});
+
+const RejectReversalPopups = ({
+ isOpen,
+ onClose,
+ handelApproved,
+ isLoading,
+}) => {
+ const {
+ watch,
+ register,
+ reset,
+ handleSubmit,
+ formState: { errors },
+ } = useForm({
+ resolver: yupResolver(conformModalSchema),
+ mode: "all",
+ });
+
+ // Reset the form when the modal closes
+ useEffect(() => {
+ if (!isOpen) {
+ reset(); // Clear the form state
+ }
+ }, [isOpen, reset]);
+
+ return (
+
+
+
+ Reject
+
+ {
+ handelApproved(data);
+ reset();
+ onClose();
+ })}
+ >
+
+
+ Comment
+
+ {errors.comment ? (
+
+ {errors.comment.message}
+
+ ) : (
+
+ Maximum length should be 150 characters. You have entered{" "}
+ {watch()?.comment?.length || 0} characters.
+
+ )}
+
+
+
+
+
+
+
+
+
+ );
+};
+
+RejectReversalPopups.propTypes = {
+ isOpen: PropTypes.bool.isRequired,
+ onClose: PropTypes.func.isRequired,
+ handelApproved: PropTypes.func.isRequired,
+ isLoading: PropTypes.func.isRequired,
+};
+
+export default RejectReversalPopups;
diff --git a/src/Contexts/GlobalStateProvider.jsx b/src/Contexts/GlobalStateProvider.jsx
index b172727..4ecd2b8 100644
--- a/src/Contexts/GlobalStateProvider.jsx
+++ b/src/Contexts/GlobalStateProvider.jsx
@@ -6,7 +6,7 @@ import { v4 as uuidv4 } from "uuid";
import { TbClock2 } from "react-icons/tb";
import { CiWallet } from "react-icons/ci";
import { HiOutlineReceiptPercent } from "react-icons/hi2";
-import { IoMdQrScanner } from "react-icons/io";
+import { IoMdQrScanner } from "react-icons/io";
import { GrDocumentPdf } from "react-icons/gr";
import { AiOutlineFileGif } from "react-icons/ai";
@@ -1674,6 +1674,79 @@ const GlobalStateProvider = ({ children }) => {
},
]);
+ const [opportunities, setOpportunities] = useState([
+ {
+ id: 1,
+ Investors: "Blackstone",
+ amountRemaining: "10 %",
+ totalDealsize: "$ 520",
+ noViews: "50",
+ },
+ {
+ id: 2,
+ Investors: "Blackstone",
+ amountRemaining: "10 %",
+ totalDealsize: "$ 520",
+ noViews: "50",
+ },
+ {
+ id: 3,
+ Investors: "Blackstone",
+ amountRemaining: "10 %",
+ totalDealsize: "$ 520",
+ noViews: "50",
+ },
+ {
+ id: 4,
+ Investors: "Blackstone",
+ amountRemaining: "10 %",
+ totalDealsize: "$ 520",
+ noViews: "50",
+ },
+ {
+ id: 5,
+ Investors: "Blackstone",
+ amountRemaining: "10 %",
+ totalDealsize: "$ 520",
+ noViews: "50",
+ },
+ {
+ id: 6,
+ Investors: "Blackstone",
+ amountRemaining: "10 %",
+ totalDealsize: "$ 520",
+ noViews: "50",
+ },
+ {
+ id: 7,
+ Investors: "Blackstone",
+ amountRemaining: "10 %",
+ totalDealsize: "$ 520",
+ noViews: "50",
+ },
+ {
+ id: 8,
+ Investors: "Blackstone",
+ amountRemaining: "10 %",
+ totalDealsize: "$ 520",
+ noViews: "50",
+ },
+ {
+ id: 9,
+ Investors: "Blackstone",
+ amountRemaining: "10 %",
+ totalDealsize: "$ 520",
+ noViews: "50",
+ },
+ {
+ id: 10,
+ Investors: "Blackstone",
+ amountRemaining: "10 %",
+ totalDealsize: "$ 520",
+ noViews: "50",
+ },
+ ]);
+
const [InvestorWallet, setInvestorWallet] = useState(null);
// ==============[ prod state ]===============================
@@ -1767,6 +1840,8 @@ const GlobalStateProvider = ({ children }) => {
setIONAVDetail,
iOTransaction,
setIOTransaction,
+ opportunities,
+ setOpportunities,
}}
>
{children}
diff --git a/src/Images/dash_icon_1.svg b/src/Images/dash_icon_1.svg
new file mode 100644
index 0000000..d6ddeb7
--- /dev/null
+++ b/src/Images/dash_icon_1.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/Images/dash_icon_2.svg b/src/Images/dash_icon_2.svg
new file mode 100644
index 0000000..02736d2
--- /dev/null
+++ b/src/Images/dash_icon_2.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/Images/dash_icon_3.svg b/src/Images/dash_icon_3.svg
new file mode 100644
index 0000000..1592b46
--- /dev/null
+++ b/src/Images/dash_icon_3.svg
@@ -0,0 +1,7 @@
+
diff --git a/src/Images/dash_icon_3n.png b/src/Images/dash_icon_3n.png
new file mode 100644
index 0000000..07686be
Binary files /dev/null and b/src/Images/dash_icon_3n.png differ
diff --git a/src/Images/dash_icon_4.svg b/src/Images/dash_icon_4.svg
new file mode 100644
index 0000000..9a1efb8
--- /dev/null
+++ b/src/Images/dash_icon_4.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/Images/dash_icon_5.svg b/src/Images/dash_icon_5.svg
new file mode 100644
index 0000000..d548db0
--- /dev/null
+++ b/src/Images/dash_icon_5.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/Images/dash_icon_6.svg b/src/Images/dash_icon_6.svg
new file mode 100644
index 0000000..81207ec
--- /dev/null
+++ b/src/Images/dash_icon_6.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/Images/dash_icon_6n.png b/src/Images/dash_icon_6n.png
new file mode 100644
index 0000000..4c6af97
Binary files /dev/null and b/src/Images/dash_icon_6n.png differ
diff --git a/src/Images/dash_icon_7.svg b/src/Images/dash_icon_7.svg
new file mode 100644
index 0000000..6c9d94b
--- /dev/null
+++ b/src/Images/dash_icon_7.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/Layout/DefaultLayout.jsx b/src/Layout/DefaultLayout.jsx
index f615b1e..f799b27 100644
--- a/src/Layout/DefaultLayout.jsx
+++ b/src/Layout/DefaultLayout.jsx
@@ -1,6 +1,5 @@
import React, { useContext, useEffect, useState } from "react";
import { CgProfile } from "react-icons/cg";
-import { useDispatch } from "react-redux";
import logoMiniDark from "../assets/favicon.png";
import logoMini from "../assets/logo-min.png";
import logoDark from "../assets/logo.png";
@@ -24,23 +23,26 @@ import {
Button,
Image,
Text,
- Tooltip
+ Tooltip,
} from "@chakra-ui/react";
import Cookies from "js-cookie"; // Import the Cookies library
import { GrManual } from "react-icons/gr";
import { HiOutlineChartSquareBar } from "react-icons/hi";
+import { HiOutlineBanknotes } from "react-icons/hi2";
import { LuContact } from "react-icons/lu";
import { MdNotificationsNone, MdOutlineAddChart } from "react-icons/md";
import {
+ RiAccountBoxLine,
RiBankLine,
RiExchangeBoxLine,
RiFileUserLine,
RiMoneyDollarBoxLine,
} from "react-icons/ri";
import {
+ TbLayoutDashboard,
TbListDetails,
TbReportMoney,
- TbTransactionDollar
+ TbTransactionDollar,
} from "react-icons/tb";
import { VscSymbolClass } from "react-icons/vsc";
import {
@@ -52,6 +54,7 @@ import {
useNavigate,
} from "react-router-dom";
import HeaderMain from "../Components/HeaderMain";
+import { isMaker } from "../Constants/Constants";
import GlobalStateContext from "../Contexts/GlobalStateContext";
import CreateRequest from "../Pages/Fawateer/CreateRequest";
import ApproveHistory from "../Pages/FawateerChecker/ApproveHistory/ApproveHistoryChecker";
@@ -139,6 +142,21 @@ const DashboardLayout = ({ isOnline }) => {
switch (true) {
case "/":
return "👋🏻 Hi, Admin";
+
+ // case path.startsWith("/"):
+ // return (z
+ //
+ // Dashboard
+ //
+ // );
+
+ case path.startsWith("/investment-opportunities"):
+ return (
+
+
+ dashboard / Open Opportunities
+
+ );
case path.startsWith("/sponser"):
return (
@@ -218,7 +236,7 @@ const DashboardLayout = ({ isOnline }) => {
return (
- Deposite Request
+ Deposit Request
);
@@ -241,21 +259,21 @@ const DashboardLayout = ({ isOnline }) => {
return (
- Withdrawal pending request
+ Withdrawal Pending Request
);
case path.startsWith("/withdraw-history"):
return (
- Withdrawal request
+ Withdrawal Request
);
case path.startsWith("/investor-request"):
return (
- Investor pending request
+ Investor Pending Request
);
case path.startsWith("/investor-history"):
@@ -269,16 +287,39 @@ const DashboardLayout = ({ isOnline }) => {
return (
- Deletion pending request
+ Deletion Pending Request
);
case path.startsWith("/deletion-history"):
return (
- Deletion request
+ Deletion Request
);
+
+ case path.startsWith("/bank-deposit-request"):
+ return (
+
+
+ Reversal Transaction / Deposit Request
+
+ );
+ case path.startsWith("/reversal-fawateer-deposit"):
+ return (
+
+
+ Reversal Transaction / Fawateer Deposit
+
+ );
+ case path.startsWith("/account-deletion-request"):
+ return (
+
+
+ Reversal Transaction / Account Deletion Request
+
+ );
+
case path.startsWith("/bank-investor"):
return (
@@ -297,7 +338,7 @@ const DashboardLayout = ({ isOnline }) => {
return (
- Push Notification
+ Push Notification
);
case path.startsWith("/contact"):
@@ -325,7 +366,7 @@ const DashboardLayout = ({ isOnline }) => {
return (
- Deletion pending request
+ Deletion Pending Request
);
case path.startsWith("/deletion-history"):
@@ -339,7 +380,7 @@ const DashboardLayout = ({ isOnline }) => {
return (
- Deletion pending request
+ Deletion Pending Request
);
case path.startsWith("/deletion-history"):
@@ -349,7 +390,7 @@ const DashboardLayout = ({ isOnline }) => {
Deletion request
);
- case path.startsWith("/subadmin"):
+ case path.startsWith("/subadmin"):
return (
@@ -385,7 +426,17 @@ const DashboardLayout = ({ isOnline }) => {
return ;
}
- const filteredNav = nav.map((item) => {
+ const _filteredNav = isMaker()
+ ? nav.filter(
+ (item) =>
+ item.title !== "REVERSAL TRANSACTION" &&
+ item.path !== "/bank-deposit-request" &&
+ item.path !== "/reversal-fawateer-deposit" &&
+ item.path !== "/account-deletion-request"
+ )
+ : nav;
+
+ const filteredNav = _filteredNav.map((item) => {
if (item.submenu) {
return {
...item,
@@ -395,6 +446,9 @@ const DashboardLayout = ({ isOnline }) => {
),
};
}
+ // if (item.title === "REVERSAL TRANSACTION" && item.type === "title") {
+ // }
+
return item;
});
@@ -515,10 +569,169 @@ const DashboardLayout = ({ isOnline }) => {
index={openIndex}
onChange={handleAccordionChange}
>
- {filteredNav.map(({ title, type, Icon, submenu, path }, index) => {
- if (type === "accordion") {
- return (
-
+ {filteredNav.map(
+ ({ title, type, Icon, submenu, path }, index) => {
+ if (type === "accordion") {
+ return (
+
+
+
+
+ {/* {Icon && title === "Admin" ? : } */}
+ {Icon && (
+
+ )}
+
+
+ {title}
+
+
+
+
+
+
+ {submenu?.map(
+ (
+ {
+ title: subMenuTitle,
+ path: link,
+ icon: SubIcon,
+ },
+ i
+ ) => (
+
+
+
+
+
+
+ {SubIcon && (
+
+ )}
+
+ {subMenuTitle === "Aprover Request"
+ ? data?.data?.role === "Maker"
+ ? "Create Request"
+ : "Aprover Request"
+ : subMenuTitle}
+
+
+
+
+ )
+ )}
+
+
+ );
+ } else if (type === "title") {
+ return (
+
+ {title}
+
+ );
+ } else if (type === "single") {
+ return (
{
placement="top-start"
color={"blue.800"}
>
-
- }
+
- {/* {Icon && title === "Admin" ? : } */}
- {Icon && (
-
- )}
-
-
- {title}
-
-
-
-
+ {title}
+
+
-
- {submenu?.map(
- (
- { title: subMenuTitle, path: link, icon: SubIcon },
- i
- ) => (
-
-
-
-
-
-
- {SubIcon && (
-
- )}
-
- {subMenuTitle === "Aprover Request"
- ? data?.data?.role === "Maker"
- ? "Create Request"
- : "Aprover Request"
- : subMenuTitle}
-
-
-
-
- )
- )}
-
-
- );
- } else if (type === "title") {
- return (
-
- {title}
-
- );
- } else if (type === "single") {
- return (
-
-
- {Icon && }
-
- {title}
-
-
-
- );
- } else {
- return null;
+ );
+ } else {
+ return null;
+ }
}
- })}
+ )}
diff --git a/src/Pages/AccountDeletion/DeletionHistory.jsx b/src/Pages/AccountDeletion/DeletionHistory.jsx
index 1108499..de621a3 100644
--- a/src/Pages/AccountDeletion/DeletionHistory.jsx
+++ b/src/Pages/AccountDeletion/DeletionHistory.jsx
@@ -7,6 +7,8 @@ import {
Input,
Text,
Tooltip,
+ useBoolean,
+ useDisclosure,
useToast,
} from "@chakra-ui/react";
import React, { useContext, useEffect, useState } from "react";
@@ -19,25 +21,37 @@ import { formatDate } from "../../Components/Functions/UTCConvertor";
import { CheckIcon, CloseIcon } from "@chakra-ui/icons";
import { useGetDeleteHistoryQuery } from "../../Services/delete.request.service";
import { TABLE_PAGINATION } from "../../Constants/Paginations";
+import InitiateReversalPopup from "../../Components/Popups/InitiateReversalPopups";
+import ToastBox from "../../Components/ToastBox";
+import { useCreateAccountDeletionReversalRequestMutation } from "../../Services/reversal.account.deletion.service";
+import { isMaker } from "../../Constants/Constants";
// import { formatDate } from "../../Components/Functions/UTCConvertor";
const DeletionHistory = () => {
const toast = useToast();
- const { slideFromRight, setDeleteHistory } =
- useContext(GlobalStateContext);
+ const { slideFromRight, setDeleteHistory } = useContext(GlobalStateContext);
const [deleteAlert, setDeleteAlert] = useState(false);
const [actionId, setActionId] = useState(false);
const [mouseEntered, setMouseEntered] = useState(false);
const [mouseEnteredId, setMouseEnteredId] = useState("");
-
-
- // =========================== [Use State] =============================
+ // =========================== [Use State] =============================
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
const [searchTerm, setSearchTerm] = useState("");
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
+ const [reversalId, setReversalId] = useState();
+ const {
+ isOpen: isOpenInRev,
+ onOpen: onOpenInRev,
+ onClose: onCloseInRev,
+ } = useDisclosure();
+ const [isReversalLoading, setIsReversalLoading] = useBoolean();
+
+ const [createAccountDeletionReversalRequest] =
+ useCreateAccountDeletionReversalRequestMutation();
+
// Debounce the search term to avoid making a request on every keystroke
useEffect(() => {
const handler = setTimeout(() => {
@@ -48,33 +62,33 @@ const DeletionHistory = () => {
};
}, [searchTerm]);
-
const {
data: deleteHistory,
isLoading,
- refetch
- } = useGetDeleteHistoryQuery({
- page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
- size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
- search: debouncedSearchTerm,
- },
- {
- skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
- })
+ refetch,
+ } = useGetDeleteHistoryQuery(
+ {
+ page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
+ size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
+ search: debouncedSearchTerm,
+ },
+ {
+ skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
+ }
+ );
const formatDate = (date) => {
- return new Date(date).toLocaleDateString('en-GB', {
- day: '2-digit',
- month: '2-digit',
- year: 'numeric',
+ return new Date(date).toLocaleDateString("en-GB", {
+ day: "2-digit",
+ month: "2-digit",
+ year: "numeric",
});
};
- // Use useEffect to refetch data when the component mounts
- useEffect(() => {
- refetch();
-}, [refetch]);
-
+ // Use useEffect to refetch data when the component mounts
+ useEffect(() => {
+ refetch();
+ }, [refetch]);
// ====================================================[Table Setup]================================================================
const tableHeadRow = [
@@ -85,7 +99,8 @@ const DeletionHistory = () => {
"Last Name",
"Country",
"Phone Number",
- "Status"
+ "Status",
+ isMaker() && "Reversal Action",
];
const extractedArray = deleteHistory?.data?.rows?.map((item, index) => ({
@@ -96,7 +111,7 @@ const DeletionHistory = () => {
as={"span"}
color={"gray.800"}
className="d-flex align-items-center web-text-small"
- fontWeight={'500'}
+ fontWeight={"500"}
>
{index + 1}.
@@ -107,7 +122,7 @@ const DeletionHistory = () => {
as={"span"}
color={"gray.600"}
className="d-flex align-items-center web-text-small"
- fontWeight={'500'}
+ fontWeight={"500"}
>
{formatDate(item.Requested_on)}
@@ -118,7 +133,7 @@ const DeletionHistory = () => {
as={"span"}
color={"gray.600"}
className="d-flex align-items-center web-text-small"
- fontWeight={'500'}
+ fontWeight={"500"}
>
{item.clientId}
@@ -129,7 +144,7 @@ const DeletionHistory = () => {
as={"span"}
color={"gray.800"}
className="d-flex align-items-center web-text-small"
- fontWeight={'500'}
+ fontWeight={"500"}
>
{item.firstName}
{/* {formatDate(item.charge)} */}
@@ -141,51 +156,77 @@ const DeletionHistory = () => {
as={"span"}
color={"gray.800"}
className="d-flex align-items-center web-text-small"
- fontWeight={'500'}
+ fontWeight={"500"}
>
{item.lastName}
),
- "Country": (
-
{item.country}
),
"Phone Number": (
-
{item.phoneNumber}
),
- "Status": (
-
{item.deletionStatus}
),
+ "Reversal Action": (
+
+ {item.deletionStatus === "Approved" ? (
+
+ {!item.isReversal ? (
+
+ ) : (
+ "Under process"
+ )}
+
+ ) : (
+ ""
+ )}
+
+ ),
}));
const handleDelete = () => {
- const deleteHistory = sponser.filter(
- (sponsor) => sponsor.id !== actionId
- );
+ const deleteHistory = sponser.filter((sponsor) => sponsor.id !== actionId);
setTimeout(() => {
setSponser(deleteHistory);
@@ -195,6 +236,45 @@ const DeletionHistory = () => {
setIsLoading(true);
};
+ const handleApproved = async (data) => {
+ setIsReversalLoading.on(); // Start loading
+ try {
+ const { error, data: responseData } =
+ await createAccountDeletionReversalRequest({
+ id: reversalId,
+ data,
+ });
+
+ if (error) {
+ throw error; // Explicitly handle the error
+ }
+
+ // Success: Perform necessary actions
+ refetch();
+ toast({
+ render: () => (
+
+ ),
+ });
+ onCloseInRev();
+ } catch (error) {
+ // Handle errors
+ toast({
+ render: () => (
+
+ ),
+ });
+ console.error("Error:", error);
+ } finally {
+ setIsReversalLoading.off(); // Ensure loading is toggled off
+ }
+ };
+
return (
@@ -244,6 +324,12 @@ const DeletionHistory = () => {
alertHandler={handleDelete}
isLoading={isLoading}
/>
+
);
};
diff --git a/src/Pages/AccountDeletion/DeletionRequest.jsx b/src/Pages/AccountDeletion/DeletionRequest.jsx
index c4f0f2e..f90c867 100644
--- a/src/Pages/AccountDeletion/DeletionRequest.jsx
+++ b/src/Pages/AccountDeletion/DeletionRequest.jsx
@@ -91,17 +91,17 @@ const DeletionRequest = () => {
// ====================================================[Table Setup]================================================================
const tableHeadRow = [
"Sr No.",
- "Requested on",
+ "Requested On",
"Client ID",
- "First name",
- "Last name",
+ "First Name",
+ "Last Name",
"Country",
- "Phone number",
+ "Phone Number",
"Status",
"Action"
];
- const extractedArray = filteredData?.map((item, index) => ({
+ const extractedArray = data?.data?.rows?.map((item, index) => ({
id: item?.id,
"Sr No.": (
{
{index + 1}.
),
- "Requested on": (
+ "Requested On": (
{
{item?.clientId}
),
- "First name": (
+ "First Name": (
{
{/* {formatDate(item.charge)} */}
),
- "Last name": (
+ "Last Name": (
{
),
- "Phone number": (
+ "Phone Number": (
{
- const toast = useToast()
+const DeletionRequestApprove = ({
+ isOpen,
+ onClose,
+ firstField,
+ id,
+ data: requestData,
+}) => {
+ const toast = useToast();
const [file, setFile] = useState();
- const [isBtnLoading , setIsBtnLoading] = useState(false)
- const [isBtnLoadingReject , setIsBtnLoadingReject] = useState(false)
- const [isReject , setIsReject] = useState(false)
+ const [isBtnLoading, setIsBtnLoading] = useState(false);
+ const [isBtnLoadingReject, setIsBtnLoadingReject] = useState(false);
+ const [isReject, setIsReject] = useState(false);
- const fileredData = requestData?.find((item)=> item?.id === id)
- const [ updateApproveRequest ] = useApproveDepositRequestMutation()
- const { data, isLoading } = useGetDeleteRequestByIdQuery(id, {
+ const fileredData = requestData?.find((item) => item?.id === id);
+ const [updateApproveRequest] = useApproveDepositRequestMutation();
+ const { data, isLoading } = useGetDeleteRequestByIdQuery(id, {
skip: !id,
});
-
const {
register,
reset,
+ watch,
handleSubmit,
formState: { errors },
} = useForm({
resolver: yupResolver(conformModalSchema),
+ mode: "all",
});
+ const { refetch } = useGetDeleteRequestQuery();
+
useEffect(() => {
reset({
- comment:fileredData?.comment
- })
-
-
- }, [requestData, id])
-
- const onSubmit = async(data) => {
- setIsBtnLoading(isReject?false:true)
- setIsBtnLoadingReject(isReject)
+ comment: fileredData?.comment,
+ });
+ }, [requestData, id]);
+
+ const onSubmit = async (data) => {
+ setIsBtnLoading(isReject ? false : true);
+ setIsBtnLoadingReject(isReject);
const approveReq = {
- adminComment:data?.adminComment,
- deletionStatus: isReject?"Reject": "Approved"
+ adminComment: data?.adminComment,
+ deletionStatus: isReject ? "Reject" : "Approved",
+ };
+
+ try {
+ const res = await updateApproveRequest({ id, data: approveReq });
+
+ if (res?.error) {
+ toast({
+ render: () => (
+
+ ),
+ });
+ heandleOnClose();
+ } else if (res?.data?.statusCode === 200) {
+ toast({
+ render: () => ,
+ });
+ refetch();
+ heandleOnClose();
+ }
+ } catch (error) {
+ console.log(error);
}
-
- try {
- const res = await updateApproveRequest({ id ,data:approveReq })
-
-
- if (res?.error) {
- toast({
- render: () => (
-
- ),
- });
- heandleOnClose()
- }else if(res?.data?.statusCode === 200) {
- toast({
- render: () => (
-
- ),
- });
- heandleOnClose()
- }
-
- } catch (error) {
-
- }
-
};
- const onReject = () => {
-
- }
-
-
+ const onReject = () => {};
useEffect(() => {
if (data) {
@@ -112,16 +124,20 @@ const DeletionRequestApprove = ({ isOpen, onClose, firstField, id, data:requestD
}
}, [data, reset]);
- const heandleOnClose = () =>{
- reset()
- onClose()
- setIsBtnLoading(false)
- setIsReject(false)
- setIsBtnLoadingReject(false)
- }
+ const heandleOnClose = () => {
+ reset();
+ onClose();
+ setIsBtnLoading(false);
+ setIsReject(false);
+ setIsBtnLoadingReject(false);
+ };
return (
-
+
@@ -133,7 +149,10 @@ const DeletionRequestApprove = ({ isOpen, onClose, firstField, id, data:requestD
- Investor Comment {fileredData?.currencyCode}
+
+ Investor Comment{" "}
+ {fileredData?.currencyCode}
+
{/*
Admin Comment
@@ -163,14 +183,22 @@ const DeletionRequestApprove = ({ isOpen, onClose, firstField, id, data:requestD
fontSize="sm"
type="textarea"
size="sm"
- placeholder={"Enter your comments...."}
+ placeholder={"Enter your comment...."}
resize={"none"}
+ mb={2}
/>
{errors.adminComment && (
{errors.adminComment.message}
)}
+
+
+ {" "}
+ Maximum length should be 200 characters. You have entered
+
+ {watch("adminComment")?.length || 0} characters.
+
@@ -180,9 +208,10 @@ const DeletionRequestApprove = ({ isOpen, onClose, firstField, id, data:requestD
type="submit"
size={"sm"}
rounded={"sm"}
- variant={'ghost'}
- onClick={()=> setIsReject(true)}
+ variant={"ghost"}
+ onClick={() => setIsReject(true)}
isLoading={isBtnLoadingReject}
+ fontWeight={500}
>
Reject
diff --git a/src/Pages/Admin/Investor/UnbanInvestor/ReasonBanModal.jsx b/src/Pages/Admin/Investor/UnbanInvestor/ReasonBanModal.jsx
index 3e7d9d2..6acb4a1 100644
--- a/src/Pages/Admin/Investor/UnbanInvestor/ReasonBanModal.jsx
+++ b/src/Pages/Admin/Investor/UnbanInvestor/ReasonBanModal.jsx
@@ -34,7 +34,7 @@ import { useUpdateBanMutation, useUpdateUnbanMutation } from "../../../../Servic
const toast = useToast()
const {
- register,
+ register,
reset,
handleSubmit,
formState: { errors },
diff --git a/src/Pages/Admin/Notification.jsx b/src/Pages/Admin/Notification.jsx
index 874a28a..1579aa1 100644
--- a/src/Pages/Admin/Notification.jsx
+++ b/src/Pages/Admin/Notification.jsx
@@ -26,7 +26,10 @@ import ToastBox from "../../Components/ToastBox";
import NormalTable from "../../Components/DataTable/NormalTable";
import GlobalStateContext from "../../Contexts/GlobalStateContext";
import { useGetInvestorsQuery } from "../../Services/investor.details.service";
-import { INVESTOR_TABLE_PAGINATION, TABLE_PAGINATION } from "../../Constants/Paginations";
+import {
+ INVESTOR_TABLE_PAGINATION,
+ TABLE_PAGINATION,
+} from "../../Constants/Paginations";
import { formatDate, generateSerialNumber } from "../../Constants/Constants";
import { ViewIcon } from "@chakra-ui/icons";
import { useGetUnbanInvestorQuery } from "../../Services/ban.investor.service";
@@ -49,7 +52,7 @@ export const notification = yup.object().shape({
export const notificationNew = yup.object().shape({
title: yup.string().required("Notification Header is required"),
- message: yup.string().required("Message is required"),
+ message: yup.string().notRequired(),
});
const Notification = () => {
@@ -59,7 +62,9 @@ const Notification = () => {
const [isLoading, setIsLoading] = useState(false);
const [selectedRadio, setSelectedRadio] = useState([]);
const [pageSize, setPageSize] = useState(INVESTOR_TABLE_PAGINATION?.size);
- const [currentPage, setCurrentPage] = useState(INVESTOR_TABLE_PAGINATION?.page);
+ const [currentPage, setCurrentPage] = useState(
+ INVESTOR_TABLE_PAGINATION?.page
+ );
const [searchTerm, setSearchTerm] = useState("");
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
const [country, setCountry] = useState("");
@@ -108,16 +113,18 @@ const Notification = () => {
}, 300);
return () => clearTimeout(handler);
}, [searchTerm]);
-
- const { data: investorDetails, isLoading: investorDetailsLoading, refetch } =
- useGetUnbanInvestorQuery(
+ const {
+ data: investorDetails,
+ isLoading: investorDetailsLoading,
+ refetch,
+ } = useGetUnbanInvestorQuery(
{
page: 1, // Omit pagination for search
size: 10000, // Omit pagination for search
// page: debouncedSearchTerm ? undefined : currentPage, // Disable pagination for search
// size: debouncedSearchTerm ? undefined : 10000 || pageSize || 500, // Disable pagination for search
- search: debouncedSearchTerm, // Pass search term
+ search: debouncedSearchTerm, // Pass search term
country_xid: country,
KYCStatus: kyc,
},
@@ -131,10 +138,6 @@ const Notification = () => {
// console.log("Debounced Search Term:", debouncedSearchTerm);
// console.log("Investor Details:", investorDetails);
// }, [searchTerm, debouncedSearchTerm, investorDetails]);
-
-
-
- console.log(investorDetails);
const [sendNotification] = useSendNotificationMutation();
@@ -190,7 +193,6 @@ const Notification = () => {
setIsLoading(true);
try {
const res = await sendNotification(dataToPass);
- console.log(res);
if (res?.error) {
toast({
@@ -313,7 +315,6 @@ const Notification = () => {
),
}));
-
return (
diff --git a/src/Pages/BankDepositRequest/BankDepositRequest.jsx b/src/Pages/BankDepositRequest/BankDepositRequest.jsx
new file mode 100644
index 0000000..8c9d4ae
--- /dev/null
+++ b/src/Pages/BankDepositRequest/BankDepositRequest.jsx
@@ -0,0 +1,463 @@
+import {
+ Badge,
+ Box,
+ Button,
+ HStack,
+ Input,
+ Switch,
+ Text,
+ Tooltip,
+ useToast,
+ useDisclosure,
+ Link,
+ useBoolean,
+} from "@chakra-ui/react";
+import React, { useContext, useEffect, useState } from "react";
+import { useNavigate } from "react-router-dom";
+
+import { CheckIcon, CloseIcon, ExternalLinkIcon } from "@chakra-ui/icons";
+import { debounce } from "../Admin/Contact";
+import { OPACITY_ON_LOAD } from "../../Layout/animations";
+import GlobalStateContext from "../../Contexts/GlobalStateContext";
+import CustomAlertDialog from "../../Components/CustomAlertDialog";
+import ToastBox from "../../Components/ToastBox";
+import NormalTable from "../../Components/DataTable/NormalTable";
+import { TABLE_PAGINATION } from "../../Constants/Paginations";
+import { generateSerialNumber } from "../../Constants/Constants";
+import { useGetDepositHistoryQuery } from "../../Services/deposit.request.service";
+import Pagination from "../../Components/Pagination";
+import ConfirmModal from "./ConfirmModal";
+import RejectModal from "./RejectModal";
+import {
+ useApproveBankDepositRequestMutation,
+ useGetBankDepositMasterQuery,
+ useRejectbankDepositRequestMutation,
+} from "../../Services/bankdeposit.request.service";
+import RejectReversalPopups from "../../Components/Popups/RejectReversalPopups";
+import ConfirmReversalPopups from "../../Components/Popups/ConfirmReversalPopups";
+
+const formatDate = (date) => {
+ return new Date(date).toLocaleDateString("en-GB", {
+ day: "2-digit",
+ month: "2-digit",
+ year: "numeric",
+ });
+}; // Simple date formatter
+
+const BankDepositRequest = () => {
+ const navigate = useNavigate();
+ const toast = useToast();
+ const { depositHistory, setDepositHistory, slideFromRight } =
+ useContext(GlobalStateContext);
+ const [isLoading, setIsLoading] = useState(true);
+ const [deleteAlert, setDeleteAlert] = useState(false);
+ const [actionId, setActionId] = useState(false);
+ const [mouseEntered, setMouseEntered] = useState(false);
+ const [mouseEnteredId, setMouseEnteredId] = useState("");
+ const {
+ isOpen: isConfirmOpen,
+ onOpen: onConfirmOpen,
+ onClose: onConfirmClose,
+ } = useDisclosure();
+ const {
+ isOpen: isRejectOpen,
+ onOpen: onRejectOpen,
+ onClose: onRejectClose,
+ } = useDisclosure();
+
+ // =========================== [Use State] =============================
+ const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
+ const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
+ const [searchTerm, setSearchTerm] = useState("");
+ const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
+
+ const [rejectbankDepositRequest] = useRejectbankDepositRequestMutation();
+
+ const [approveBankDepositRequest] = useApproveBankDepositRequestMutation();
+
+ const [isReversalLoading, setIsReversalLoading] = useBoolean();
+
+ // Debounce the search term to avoid making a request on every keystroke
+ useEffect(() => {
+ const handler = setTimeout(() => {
+ setDebouncedSearchTerm(searchTerm);
+ }, 500); // Adjust delay as needed
+ return () => {
+ clearTimeout(handler);
+ };
+ }, [searchTerm]);
+
+ const {
+ data,
+ error,
+ refetch,
+ isLoading: depositHistoryLoading,
+ } = useGetBankDepositMasterQuery(
+ {
+ page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
+ size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
+ search: debouncedSearchTerm,
+ },
+ {
+ skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
+ }
+ );
+
+ // Use useEffect to refetch data when the component mounts
+ useEffect(() => {
+ refetch();
+ }, [refetch]);
+
+ // ====================================================[Table Setup]================================================================
+ const tableHeadRow = [
+ "Sr.no",
+ "Request Date",
+ "Client ID",
+ "First Name",
+ "Last Name",
+ "Country",
+ "Phone Number",
+ "Deposit Amount",
+ "Action",
+ ];
+
+ const handleUpdateStatus = debounce((id) => {
+ setDepositHistory((prevDepositHistory) =>
+ prevDepositHistory.map((depositHistory) =>
+ depositHistory.id === id
+ ? { ...depositHistory, status: !depositHistory.status }
+ : depositHistory
+ )
+ );
+ toast({
+ render: () => ,
+ });
+ }, 300);
+
+ const filteredData = data?.data?.rows
+ .filter((item) => {
+ // Filter by name (case insensitive)
+ const name = [item.firstName, item.lastName, item.countryName]
+ .filter(Boolean)
+ .join(" ");
+ const searchLower = searchTerm.toLowerCase();
+ const nameMatches = name.toLowerCase().includes(searchLower);
+
+ // Filter by status (Uncomment and use if needed)
+ // const status = item.status;
+ // const statusLower = status ? "active" : "inactive";
+
+ // const statusMatches =
+ // statusFilter === "all" ||
+ // (statusFilter === "active" && status === true) ||
+ // (statusFilter === "inactive" && status === false);
+
+ return nameMatches;
+ })
+ .sort((b, a) => new Date(a.createdAt) - new Date(b.createdAt));
+
+ // const handleView = (id) => {
+ // setActionId(id);
+ // onViewOpen();
+ // };
+
+ const extractedArray = data?.data?.rows?.map((item, idx) => ({
+ "Sr.no": (
+
+ {generateSerialNumber(idx, currentPage, pageSize)}
+
+ ),
+ "Request Date": (
+
+ {formatDate(item?.isReversalDate)}
+
+ ),
+ "Client ID": (
+
+ {item?.clientReference_id}
+
+ ),
+ "First Name": (
+
+
+ {item?.firstName}
+
+
+ ),
+ "Last Name": (
+
+
+ {item?.lastName}
+
+
+ ),
+ Country: (
+
+
+ {item?.countryName}
+
+
+ ),
+ "Phone Number": (
+
+
+ {item?.ISDCode} {item?.mobileNumber}
+ {/* {item?.ISDcode + " " + item?.mobileNumber} */}
+
+
+ ),
+ "Deposit Amount": (
+
+
+ {parseFloat(item?.investorAmount || 0).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}
+
+ {item?.currencyCode}
+
+
+
+ ),
+ Action: (
+
+
+
+
+
+
+
+
+ ),
+ }));
+
+ const handleDelete = () => {
+ const IOtype = investmentType.filter(
+ (investmentType) => investmentType.id !== actionId
+ );
+
+ setTimeout(() => {
+ setInvestmentType(IOtype);
+ setDeleteAlert(false);
+ setIsLoading(false);
+ }, 100);
+ setIsLoading(true);
+ };
+
+ const handleApproved = async (data) => {
+ setIsReversalLoading.on(); // Start loading
+ try {
+ const { error, data: responseData } = await rejectbankDepositRequest({
+ id: actionId,
+ data,
+ });
+
+ if (error) {
+ throw error; // Explicitly handle the error
+ }
+
+ // Success: Perform necessary actions
+ refetch();
+ toast({
+ render: () => (
+
+ ),
+ });
+ onRejectClose();
+ } catch (error) {
+ // Handle errors
+ toast({
+ render: () => (
+
+ ),
+ });
+ console.error("Error:", error);
+ } finally {
+ setIsReversalLoading.off(); // Ensure loading is toggled off
+ }
+ };
+
+ const handleConfirm = async (data) => {
+
+ setIsReversalLoading.on(); // Start loading
+ try {
+ const { error, data: responseData } = await approveBankDepositRequest({
+ id: actionId,
+ data,
+ });
+
+ if (error) {
+ throw error; // Explicitly handle the error
+ }
+
+ // Success: Perform necessary actions
+ refetch();
+ toast({
+ render: () => (
+
+ ),
+ });
+ onRejectClose();
+ } catch (error) {
+ // Handle errors
+ toast({
+ render: () => (
+
+ ),
+ });
+ console.error("Error:", error);
+ } finally {
+ setIsReversalLoading.off(); // Ensure loading is toggled off
+ }
+ };
+
+ return (
+
+ {/* */}
+
+
+
+
+ setSearchTerm(e.target.value)}
+ />
+
+
+
+
+
+
+
+
+
+ setDeleteAlert(false)}
+ isOpen={deleteAlert}
+ message={"Are you sure you want to delete sponers?"}
+ alertHandler={handleDelete}
+ isLoading={isLoading}
+ />
+
+ );
+};
+
+export default BankDepositRequest;
diff --git a/src/Pages/BankDepositRequest/ConfirmModal.jsx b/src/Pages/BankDepositRequest/ConfirmModal.jsx
new file mode 100644
index 0000000..64a4cf1
--- /dev/null
+++ b/src/Pages/BankDepositRequest/ConfirmModal.jsx
@@ -0,0 +1,149 @@
+import {
+ Box,
+ Button,
+ Checkbox,
+ FormControl,
+ FormLabel,
+ Input,
+ Modal,
+ ModalBody,
+ ModalCloseButton,
+ ModalContent,
+ ModalFooter,
+ ModalHeader,
+ ModalOverlay,
+ Text,
+ Textarea,
+ useDisclosure,
+} from "@chakra-ui/react";
+import React, { useState } from "react";
+import * as yup from "yup";
+import { yupResolver } from "@hookform/resolvers/yup";
+import { useForm } from "react-hook-form";
+import ReactQuill from "react-quill";
+
+export const conformModalSchema = yup.object().shape({
+ fees: yup.string().required("File name is required"),
+ totalAmount: yup.string().required("File name is required"),
+});
+
+const ConfirmModal = ({ isOpen, onClose, firstField }) => {
+
+ const [emailApproval,setEmailApproval] = useState(false)
+
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ } = useForm({
+ resolver: yupResolver(conformModalSchema),
+ });
+
+ const onSubmit = (data) => {
+ setFile(data.document[0]);
+
+ const newDocument = {
+ ...data,
+ document: data.document[0].name, // Store the document name
+ status: true,
+ id: uuidv4(),
+ createdAt: new Date().toISOString(),
+ Type: getFileIcon(file.type),
+ };
+
+ setCreate((prevCreate) => [...prevCreate, newDocument]);
+ onClose();
+ };
+
+ const handleFileChange = (event) => {
+ const selectedFile = event.target.files[0];
+ setFile(selectedFile);
+ };
+
+ const modules = {
+ toolbar: [
+ // [{ header: "1" }, { header: "2" },
+ // // { font: [] }
+ // ],
+ // [{ size: [] }],
+ ["bold", "italic", "underline", "strike", "blockquote"],
+ [{ list: "ordered" }, { list: "bullet" }],
+ ["clean"],
+ ],
+ };
+
+ return (
+
+
+
+ Confirm
+
+
+
+
+ Comment
+
+ {errors.comment && (
+
+ {errors.comment.message}
+
+ )}
+
+
+ setEmailApproval(e.target.checked)}
+ >
+ Send an email to the user upon approval
+
+ {emailApproval &&
+
+ Subject
+
+
+
+ Message
+
+
+ }
+
+
+
+
+
+
+
+
+ );
+};
+
+export default ConfirmModal;
diff --git a/src/Pages/BankDepositRequest/RejectModal.jsx b/src/Pages/BankDepositRequest/RejectModal.jsx
new file mode 100644
index 0000000..6a905b1
--- /dev/null
+++ b/src/Pages/BankDepositRequest/RejectModal.jsx
@@ -0,0 +1,139 @@
+import {
+ Box,
+ Button,
+ FormControl,
+ FormLabel,
+ Modal,
+ ModalBody,
+ ModalCloseButton,
+ ModalContent,
+ ModalFooter,
+ ModalHeader,
+ ModalOverlay,
+ Text,
+ Textarea,
+ useToast,
+} from "@chakra-ui/react";
+import React, { useState } from "react";
+import * as yup from "yup";
+import { yupResolver } from "@hookform/resolvers/yup";
+import { useForm } from "react-hook-form";
+import { useRejectbankDepositRequestMutation } from "../../Services/bankdeposit.request.service";
+import ToastBox from "../../Components/ToastBox";
+
+export const conformModalSchema = yup.object().shape({
+ comments: yup.string().required("Comment is required"),
+});
+
+const RejectModal = ({ isOpen, onClose, firstField ,id}) => {
+ const [isBtnLoading , setIsBtnLoading] = useState(false)
+
+ const toast = useToast()
+
+ const {
+ register,
+ reset,
+ handleSubmit,
+ formState: { errors },
+ } = useForm({
+ resolver: yupResolver(conformModalSchema),
+ });
+
+ const [ rejectbankDepositRequest ] = useRejectbankDepositRequestMutation()
+
+ const onSubmit = async(data) => {
+ console.log(id);
+ setIsBtnLoading(true)
+ try {
+ const res = await rejectbankDepositRequest({ id ,data})
+ console.log(res);
+
+ if (res?.error) {
+ toast({
+ render: () => (
+
+ ),
+ });
+ heandleOnClose()
+
+ }else if(res?.data) {
+ toast({
+ render: () => (
+
+ ),
+ });
+ heandleOnClose()
+ }
+
+ } catch (error) {
+ console.log(error);
+
+ }
+
+ };
+
+
+ const heandleOnClose = () =>{
+ reset()
+ onClose()
+ setIsBtnLoading(false)
+ }
+
+ return (
+
+
+
+ Reject
+
+
+
+
+ Comment
+
+ {errors.comments && (
+
+ {errors.comments.message}
+
+ )}
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default RejectModal;
diff --git a/src/Pages/Dashbaord.jsx b/src/Pages/DashbaordOld.jsx
similarity index 99%
rename from src/Pages/Dashbaord.jsx
rename to src/Pages/DashbaordOld.jsx
index 1ed8b29..692892b 100644
--- a/src/Pages/Dashbaord.jsx
+++ b/src/Pages/DashbaordOld.jsx
@@ -135,9 +135,6 @@ const Dashbaord = () => {
-
-
-
IO Status
@@ -151,9 +148,6 @@ const Dashbaord = () => {
-
-
-
)
diff --git a/src/Pages/Dashboard/Dashbaord.jsx b/src/Pages/Dashboard/Dashbaord.jsx
new file mode 100644
index 0000000..d0e6d63
--- /dev/null
+++ b/src/Pages/Dashboard/Dashbaord.jsx
@@ -0,0 +1,504 @@
+import {
+ Box,
+ Divider,
+ Flex,
+ Heading,
+ HStack,
+ Image,
+ Select,
+ SimpleGrid,
+ Text,
+} from "@chakra-ui/react";
+import React, { useState } from "react";
+import {
+ BsArrowsAngleContract,
+ BsBoxArrowDown,
+ BsBoxArrowUp,
+} from "react-icons/bs";
+import { FaRegPenToSquare } from "react-icons/fa6";
+import { LuContact } from "react-icons/lu";
+import { Link } from "react-router-dom";
+import { useGetDashboardMasterQuery } from "../../Services/dashboard.service";
+import InvestmentOpportunities from "./InvestmentOpportunities";
+import IconOne from '../../Images/dash_icon_1.svg';
+import IconTwo from '../../Images/dash_icon_2.svg';
+import IconThree from '../../Images/dash_icon_3n.png';
+import IconFour from '../../Images/dash_icon_4.svg'
+import IconFive from '../../Images/dash_icon_5.svg';
+import IconSix from '../../Images/dash_icon_6n.png';
+import IconSeven from '../../Images/dash_icon_7.svg'
+
+// const panddingReguest = [
+// {
+// icon: ,
+// label: "Pending deposit requests",
+// count: 27,
+// },
+// {
+// icon: ,
+// label: "Pending withdrawal requests",
+// count: 27,
+// },
+// {
+// icon: ,
+// label: "Pending KYC review request",
+// count: 27,
+// },
+// {
+// icon: ,
+// label: "Pending Acc modification request",
+// count: 27,
+// },
+// ];
+
+const Dashbaord = ({ showSearch = false }) => {
+ const [filter, setFilter] = useState("today");
+ const { data, error, isLoading } = useGetDashboardMasterQuery();
+ console.log(data);
+
+ const panddingReguest = [
+ {
+ icon: IconOne,
+ label: "Pending deposit requests",
+ count: parseFloat(
+ data?.data?.pendingRequests?.pendingDepositReq?.totalDepositReq || 0
+ ).toLocaleString(),
+ },
+ {
+ icon: IconTwo,
+ label: "Pending withdrawal requests",
+ count: parseFloat(
+ data?.data?.pendingRequests?.pendingWithdrawalReq || 0
+ ).toLocaleString(),
+ },
+ {
+ icon: IconThree,
+ label: "Pending KYC review request",
+ count: parseFloat(
+ data?.data?.pendingRequests?.pendingKYCReviewReq || 0
+ ).toLocaleString(),
+ },
+ {
+ icon: IconFour,
+ label: "Pending Acc modification request",
+ count: parseFloat(
+ data?.data?.pendingRequests?.pendingAccModReq?.totalAccModReq || 0
+ ).toLocaleString(),
+ },
+ ];
+
+ const userActivity = [
+ {
+ icon: IconFive,
+ label: "Total number of users",
+ count: data?.data?.userActivity?.totalCount, //totalCount
+ },
+ {
+ icon: IconSix,
+ label: "Total number of users with completed KYC (%)",
+ count: data?.data?.userActivity?.KYCCompletedCount, //KYCCompletedCount
+ percentage: data?.data?.userActivity?.completedKYCPer, //completedKYCPer
+ },
+ {
+ icon: IconSeven,
+ label: "Total number of Active users",
+ count: data?.data?.userActivity?.ActiveUsers, //ActiveUsers
+ },
+ ];
+
+ const closedOpportunities = [
+ {
+ icon: IconOne,
+ label: "Closed Opportunities",
+ count: parseFloat(
+ data?.data?.investmentOpportunity?.closedOpportunityDetails
+ ?.numberOfClosedOpportunities || 0
+ ).toLocaleString(),
+ },
+ {
+ icon: IconOne,
+ label: "Total assets under management",
+ count: `$ ${parseFloat(
+ data?.data?.investmentOpportunity?.closedOpportunityDetails?.totalAUM ||
+ 0
+ ).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}`,
+ },
+ {
+ icon: IconOne,
+ label: "Total number of investors",
+ count: parseFloat(
+ data?.data?.investmentOpportunity?.closedOpportunityDetails
+ ?.totalNumberOfInvestors || 0
+ ).toLocaleString(),
+ },
+ {
+ icon: IconOne,
+ label: "Total number of unique investors",
+ count: parseFloat(
+ data?.data?.investmentOpportunity?.closedOpportunityDetails
+ ?.numberOfUniqueInvestors || 0
+ ).toLocaleString(),
+ },
+ ];
+
+ const walletCase = [
+ {
+ amount: `$ ${parseFloat(
+ data?.data?.walletBalance?.usersWalletCashInUSD || 0
+ ).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}`,
+ currency: "USD",
+ },
+ {
+ amount: ` د. ب. ${parseFloat(
+ data?.data?.walletBalance?.usersWalletCashInBHD || 0
+ ).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}`,
+ currency: "BHD",
+ },
+ {
+ amount: ` ﷼. ${parseFloat(
+ data?.data?.walletBalance?.usersWalletCashInSAR || 0
+ ).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}`,
+ currency: "SAR",
+ },
+ {
+ amount: ` د.ك ${parseFloat(
+ data?.data?.walletBalance?.usersWalletCashInKWD || 0
+ ).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}`,
+ currency: "KWD",
+ },
+ {
+ amount: ` د.إ ${parseFloat(
+ data?.data?.walletBalance?.usersWalletCashInAED || 0
+ ).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}`,
+ currency: "AED",
+ },
+ {
+ amount: ` ﷼. ${parseFloat(
+ data?.data?.walletBalance?.usersWalletCashInOMR || 0
+ ).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}`,
+ currency: "OMR",
+ },
+ {
+ amount: ` ر. ق. ${parseFloat(
+ data?.data?.walletBalance?.usersWalletCashInQAR || 0
+ ).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}`,
+ currency: "QAR",
+ },
+ ];
+
+ return (
+
+
+
+
+ Pending Request
+
+
+
+ {panddingReguest.map((item, index) => (
+
+
+
+
+
+ {item.label}
+
+
+ {item.count}
+
+
+ ))}
+
+
+
+
+ User Activity
+
+
+
+ {userActivity.map((item, index) => (
+
+
+
+ {item.icon === IconSix ? (
+
+ ) : item.icon === IconSeven ? (
+
+ ) : (
+
+ )}
+
+
+
+ {item.label}
+
+
+
+ {item?.count}
+ {item?.percentage && (
+
+ {` (${item?.percentage}) %`}
+
+ )}
+
+
+ ))}
+
+
+
+
+
+
+
+ {data?.data?.userActivity?.openedAppToday?.percentage} %
+
+
+ Users that opened the app today
+
+
+
+
+
+ {parseFloat(
+ data?.data?.userActivity?.loggedInWithInLastMonth
+ ?.number || 0
+ ).toLocaleString()}
+
+
+ Users who logged in during the last month
+
+
+
+
+
+
+
+
+
+
+
+ {filter === "today"
+ ? data?.data?.userActivity?.newSignUps?.today
+ : filter === "last7days"
+ ? data?.data?.userActivity?.newSignUps?.last7days
+ : data?.data?.userActivity?.newSignUps?.last30days}
+
+
+ New sign-ups{" "}
+
+
+
+
+
+ {filter === "today"
+ ? data?.data?.userActivity?.newKYCVerifications?.today
+ : filter === "last7days"
+ ? data?.data?.userActivity?.newKYCVerifications?.last7days
+ : data?.data?.userActivity?.newKYCVerifications
+ ?.last30days}
+
+
+ New KYC verification
+
+
+
+
+
+
+
+
+
+
+ Investment Opportunities
+
+
+
+
+
+ Open Opportunities
+
+
+
+
+
+
+
+
+
+
+ {closedOpportunities.map((item, index) => (
+
+
+
+
+
+
+ {item.label}
+
+
+
+ {/* {parseFloat(item?.count || 0).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })} */}
+ {item.count}
+
+
+ ))}
+
+
+
+
+ Wallet Balances
+
+
+
+
+ ${" "}
+ {parseFloat(
+ data?.data?.walletBalance?.totalCashAvailAcrossAllUSD || 0
+ ).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}
+ {/* {data?.data?.walletBalance?.totalCashAvailAcrossAllUSD} */}
+
+
+ TOTAL CASH AVAILABLE ACROSS ALL WALLETS USD
+
+
+
+ Sum of users available wallet cash in
+
+
+ {walletCase.slice(0, 4).map((item, index) => (
+
+
+ {item.amount}
+
+
+ {item.currency}
+
+
+ ))}
+
+
+
+ {walletCase.slice(4).map((item, index) => (
+
+
+ {item.amount}
+
+
+ {item.currency}
+
+
+ ))}
+
+
+
+
+ );
+};
+
+export default Dashbaord;
diff --git a/src/Pages/Dashboard/InvestmentOpportunities.jsx b/src/Pages/Dashboard/InvestmentOpportunities.jsx
new file mode 100644
index 0000000..f2e823c
--- /dev/null
+++ b/src/Pages/Dashboard/InvestmentOpportunities.jsx
@@ -0,0 +1,169 @@
+import { Badge, Box, HStack, Input, Select, Text, useToast } from "@chakra-ui/react";
+import React, { useContext, useEffect, useState } from "react";
+import { OPACITY_ON_LOAD } from "../../Layout/animations";
+import GlobalStateContext from "../../Contexts/GlobalStateContext";
+import CustomAlertDialog from "../../Components/CustomAlertDialog";
+import NormalTable from "../../Components/DataTable/NormalTable";
+import { useGetDashboardMasterQuery } from "../../Services/dashboard.service";
+import { generateSerialNumber } from "../../Constants/Constants";
+
+const formatDate = (date) => new Date(date).toLocaleDateString();
+
+const InvestmentOpportunities = ({ showSearch = true, selectStyle = {} }) => {
+ const toast = useToast();
+ const { opportunities, setOpportunities, slideFromRight } =
+ useContext(GlobalStateContext);
+ const [searchTerm, setSearchTerm] = useState("");
+ const [isLoading, setIsLoading] = useState(true);
+ const [deleteAlert, setDeleteAlert] = useState(false);
+ const [actionId, setActionId] = useState(null);
+ const [filter, setFilter] = useState(null);
+
+ const { data, error } = useGetDashboardMasterQuery();
+
+ useEffect(() => {
+ const timer = setTimeout(() => setIsLoading(false), 1500);
+ return () => clearTimeout(timer);
+ }, []);
+
+ const tableHeadRow = [
+ "Sr No",
+ "Investors",
+ "Amount Remaining %",
+ "Total Deal Size",
+ "No of Views",
+ ];
+
+ const filteredData =
+ data?.data?.investmentOpportunity?.openOpportunityDetails?.filter((item) =>
+ item?.Investment_name?.toLowerCase().includes(searchTerm.toLowerCase())
+ );
+
+ const extractedArray = filteredData?.map((item, index) => ({
+ id: item?.id,
+ "Sr No": (
+
+ {index + 1}
+
+ ),
+ Investors: (
+
+
+ {item?.Investment_name}
+
+
+ ),
+ "Amount Remaining %": (
+
+
+ {parseFloat(item?.Amount_remaining_per || 0).toLocaleString(
+ undefined,
+ {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ }
+ )}%
+
+
+ ),
+ "Total Deal Size": (
+
+
+ ${parseFloat(item?.Deal_size || 0).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}
+
+
+ ),
+ "No of Views": (
+
+
+ {filter === "last30days"
+ ? item?.Views_mtd
+ : filter === "last7days"
+ ? item?.Views_last_7_days
+ : item?.Views_today}
+
+
+ ),
+ }));
+
+ return (
+
+
+ {showSearch && (
+
+ setSearchTerm(e.target.value)}
+ />
+
+ )}
+
+
+
+
+
+
+
+ setDeleteAlert(false)}
+ isOpen={deleteAlert}
+ message={"Are you sure you want to delete this opportunity?"}
+ isLoading={isLoading}
+ />
+
+ );
+};
+
+export default InvestmentOpportunities;
diff --git a/src/Pages/Deposit/DepositViewHistory/DepositHistory.jsx b/src/Pages/Deposit/DepositViewHistory/DepositHistory.jsx
index 787fddf..0b7d8f7 100644
--- a/src/Pages/Deposit/DepositViewHistory/DepositHistory.jsx
+++ b/src/Pages/Deposit/DepositViewHistory/DepositHistory.jsx
@@ -4,39 +4,34 @@ import {
Button,
HStack,
Input,
- Switch,
- Text,
- Tooltip,
- useToast,
- useDisclosure,
Link,
+ Text,
+ useBoolean,
+ useDisclosure,
+ useToast,
} from "@chakra-ui/react";
import React, { useContext, useEffect, useState } from "react";
-import { HiDotsVertical } from "react-icons/hi";
import { useNavigate } from "react-router-dom";
-import { debounce } from "../../Master/Sponser/AddSponser";
-import { OPACITY_ON_LOAD } from "../../../Layout/animations";
-import Pagination from "../../../Components/Pagination";
-import GlobalStateContext from "../../../Contexts/GlobalStateContext";
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
-import ToastBox from "../../../Components/ToastBox";
import NormalTable from "../../../Components/DataTable/NormalTable";
-import ConfirmModal from "./ConfirmModal";
-import RejectModal from "./RejectModal";
-import {
- useDepositRejectMutation,
- useGetDepositHistoryQuery,
-} from "../../../Services/deposit.request.service";
+import Pagination from "../../../Components/Pagination";
+import ToastBox from "../../../Components/ToastBox";
+import GlobalStateContext from "../../../Contexts/GlobalStateContext";
+import { OPACITY_ON_LOAD } from "../../../Layout/animations";
+import { useGetDepositHistoryQuery } from "../../../Services/deposit.request.service";
+import { debounce } from "../../Master/Sponser/AddSponser";
import { ExternalLinkIcon } from "@chakra-ui/icons";
+import InitiateReversalPopup from "../../../Components/Popups/InitiateReversalPopups";
+import { generateSerialNumber, isMaker } from "../../../Constants/Constants";
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
-import { generateSerialNumber } from "../../../Constants/Constants";
+import { useCreateBankDepositReversalRequestMutation } from "../../../Services/bankdeposit.request.service";
const formatDate = (date) => {
- return new Date(date).toLocaleDateString('en-GB', {
- day: '2-digit',
- month: '2-digit',
- year: 'numeric',
+ return new Date(date).toLocaleDateString("en-GB", {
+ day: "2-digit",
+ month: "2-digit",
+ year: "numeric",
});
}; // Simple date formatter
@@ -50,22 +45,22 @@ const DepositHistory = () => {
const [actionId, setActionId] = useState(false);
const [mouseEntered, setMouseEntered] = useState(false);
const [mouseEnteredId, setMouseEnteredId] = useState("");
- // const {
- // isOpen: isConfirmOpen,
- // onOpen: onConfirmOpen,
- // onClose: onConfirmClose,
- // } = useDisclosure();
- // const {
- // isOpen: isRejectOpen,
- // onOpen: onRejectOpen,
- // onClose: onRejectClose,
- // } = useDisclosure();
- // =========================== [Use State] =============================
+ const [createBankDepositReversalRequest] =
+ useCreateBankDepositReversalRequestMutation();
+
+ // =========================== [Use State] =============================
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
const [searchTerm, setSearchTerm] = useState("");
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
+ const [reversalId, setReversalId] = useState();
+ const {
+ isOpen: isOpenInRev,
+ onOpen: onOpenInRev,
+ onClose: onCloseInRev,
+ } = useDisclosure();
+ const [isReversalLoading, setIsReversalLoading] = useBoolean();
// Debounce the search term to avoid making a request on every keystroke
useEffect(() => {
@@ -77,20 +72,21 @@ const DepositHistory = () => {
};
}, [searchTerm]);
-
const {
data,
error,
refetch,
isLoading: depositHistoryLoading,
- } = useGetDepositHistoryQuery({
- page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
- size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
- search: debouncedSearchTerm,
- },
- {
- skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
- });
+ } = useGetDepositHistoryQuery(
+ {
+ page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
+ size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
+ search: debouncedSearchTerm,
+ },
+ {
+ skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
+ }
+ );
// Use useEffect to refetch data when the component mounts
useEffect(() => {
@@ -109,6 +105,7 @@ const DepositHistory = () => {
"Deposit Date",
"Status",
"Supporting's",
+ isMaker() && "Reversal Action",
];
const handleUpdateStatus = debounce((id) => {
@@ -161,7 +158,7 @@ const DepositHistory = () => {
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
- {generateSerialNumber(idx,currentPage, pageSize )}
+ {generateSerialNumber(idx, currentPage, pageSize)}
),
"Client ID": (
@@ -205,11 +202,7 @@ const DepositHistory = () => {
),
"Deposit Amount": (
-
+
{parseFloat(item?.investorAmount || 0).toLocaleString(undefined, {
minimumFractionDigits: 2,
@@ -283,31 +276,91 @@ const DepositHistory = () => {
) : (
""
),
+ "Reversal Action": (
+
+ {item.transactionStatus === "Approved" ? (
+
+ {!item.isReversal ? (
+
+ ) : (
+ "Under process"
+ )}
+
+ ) : (
+ ""
+ )}
+
+ ),
}));
- const handleDelete = () => {
- const IOtype = investmentType.filter(
- (investmentType) => investmentType.id !== actionId
- );
+ // const handleDelete = () => {
+ // const IOtype = investmentType.filter(
+ // (investmentType) => investmentType.id !== actionId
+ // );
- setTimeout(() => {
- setInvestmentType(IOtype);
- setDeleteAlert(false);
- setIsLoading(false);
- }, 100);
- setIsLoading(true);
+ // setTimeout(() => {
+ // setInvestmentType(IOtype);
+ // setDeleteAlert(false);
+ // setIsLoading(false);
+ // }, 100);
+ // setIsLoading(true);
+ // };
+
+ const handleApproved = async (data) => {
+ setIsReversalLoading.on(); // Start loading
+ try {
+ const { error, data: responseData } =
+ await createBankDepositReversalRequest({
+ id: reversalId,
+ data,
+ });
+
+ if (error) {
+ throw error; // Explicitly handle the error
+ }
+
+ // Success: Perform necessary actions
+ refetch();
+ toast({
+ render: () => (
+
+ ),
+ });
+ onCloseInRev();
+ } catch (error) {
+ // Handle errors
+ toast({
+ render: () => (
+
+ ),
+ });
+ console.error("Error:", error);
+ } finally {
+ setIsReversalLoading.off(); // Ensure loading is toggled off
+ }
};
return (
- {/*
- */}
{
setMouseEntered={setMouseEntered}
/>
- setDeleteAlert(false)}
isOpen={deleteAlert}
message={"Are you sure you want to delete sponers?"}
alertHandler={handleDelete}
isLoading={isLoading}
+ /> */}
+
+
);
diff --git a/src/Pages/EmailNotification/EmailNotification.jsx b/src/Pages/EmailNotification/EmailNotification.jsx
index 22d5c98..ad456ab 100644
--- a/src/Pages/EmailNotification/EmailNotification.jsx
+++ b/src/Pages/EmailNotification/EmailNotification.jsx
@@ -277,7 +277,7 @@ const EmailNotification = () => {
Create Custom body
- {
const navigate = useNavigate();
@@ -60,8 +39,7 @@ const FawateerRequest = () => {
} = useDisclosure();
const btnRef = React.useRef();
-
- // =========================== [Use State] =============================
+ // =========================== [Use State] =============================
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
const [searchTerm, setSearchTerm] = useState("");
@@ -77,21 +55,20 @@ const FawateerRequest = () => {
};
}, [searchTerm]);
-
const {
data: investorDetails,
isLoading: investorDetailsLoading,
error,
- } = useGetInvestorsQuery({
- page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
- size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
- search: debouncedSearchTerm,
- },
- {
- skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
- }
-);
-
+ } = useGetInvestorsQuery(
+ {
+ page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
+ size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
+ search: debouncedSearchTerm,
+ },
+ {
+ skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
+ }
+ );
useEffect(() => {
// Simulate loading
@@ -109,10 +86,10 @@ const FawateerRequest = () => {
"Client ID",
"First Name",
"Last Name",
- "Country",
+ "Country",
"Phone Number",
"E-mail ID",
- // "Type",
+ // "Type",
// "KYC Status",
"Approval Status",
];
@@ -131,7 +108,15 @@ const FawateerRequest = () => {
// ====================================================[Table Filter]================================================================
const filteredData = investorDetails?.data?.rows?.filter((item) => {
// Filter by name (case insensitive)
- const name = [item?.principal?.firstName, item?.principal?.lastName, item?.country?.countryName, item?.principal?.mobileNumber, item?.principal?.emailAddress].filter(Boolean).join(' ');
+ const name = [
+ item?.principal?.firstName,
+ item?.principal?.lastName,
+ item?.country?.countryName,
+ item?.principal?.mobileNumber,
+ item?.principal?.emailAddress,
+ ]
+ .filter(Boolean)
+ .join(" ");
const searchLower = searchTerm.toLowerCase();
const nameMatches = name?.toLowerCase().includes(searchLower);
@@ -147,35 +132,31 @@ const FawateerRequest = () => {
return nameMatches;
});
-
-
const customHeaders = [
{ label: "ID", key: "id" },
{ label: "Client ID", key: "clientReference_id" },
- { label: "First Name", key: "principal.firstName" }, // Nested property
- { label: "Last Name", key: "principal.lastName" }, // Nested property
- { label: "Country", key: "country.countryName" }, // Nested property
+ { label: "First Name", key: "principal.firstName" }, // Nested property
+ { label: "Last Name", key: "principal.lastName" }, // Nested property
+ { label: "Country", key: "country.countryName" }, // Nested property
{ label: "Phone Number", key: "principal.mobileNumber" }, // Nested property
- { label: "E-mail ID", key: "principal.emailAddress" }, // Nested property
+ { label: "E-mail ID", key: "principal.emailAddress" }, // Nested property
{ label: "Type", key: "investor_type.investorTypeName" }, // Nested property
- { label: "Status", key: "ioStatus" }, // Simple property
- { label: "KYC Status", key: "KYCStatus" }, // Simple property
+ { label: "Status", key: "ioStatus" }, // Simple property
+ { label: "KYC Status", key: "KYCStatus" }, // Simple property
];
-
const extractedArray = investorDetails?.data?.rows?.map((item, idx) => ({
id: item?.id,
"Sr No": (
{/* {item.id} */}
- {generateSerialNumber(idx,currentPage, pageSize )}
-
+ {generateSerialNumber(idx, currentPage, pageSize)}
),
"Client ID": (
@@ -183,7 +164,7 @@ const FawateerRequest = () => {
{item.clientReference_id}
-
+
),
"First Name": (
@@ -220,27 +201,33 @@ const FawateerRequest = () => {
),
- "Type": (
+ Type: (
-
-
+
+
{item?.investor_type?.investorTypeName}
),
"Approval Status": (
-
-
- Approved
-
-
+
+
+ Approved
+
+
),
}));
@@ -264,8 +251,6 @@ const FawateerRequest = () => {
console.log(investorDetails?.data?.totalItems);
-
-
return (
@@ -290,23 +275,17 @@ const FawateerRequest = () => {
onChange={(e) => setSearchTerm(e.target.value)}
/>
-
-
-
-
-
-{/*
+ {/*
}
colorScheme="forestGreen"
@@ -317,7 +296,6 @@ const FawateerRequest = () => {
>
Create request
*/}
-
@@ -345,4 +323,4 @@ const FawateerRequest = () => {
);
};
-export default FawateerRequest
\ No newline at end of file
+export default FawateerRequest;
diff --git a/src/Pages/FawateerChecker/ApproveHistory/ApproveHistoryChecker.jsx b/src/Pages/FawateerChecker/ApproveHistory/ApproveHistoryChecker.jsx
index 58d792e..9961cab 100644
--- a/src/Pages/FawateerChecker/ApproveHistory/ApproveHistoryChecker.jsx
+++ b/src/Pages/FawateerChecker/ApproveHistory/ApproveHistoryChecker.jsx
@@ -37,6 +37,7 @@ const ApproveHistory = () => {
const [actionId, setActionId] = useState(false);
const [mouseEntered, setMouseEntered] = useState(false);
const [mouseEnteredId, setMouseEnteredId] = useState("");
+ const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
@@ -60,12 +61,31 @@ const ApproveHistory = () => {
onClose: onRejectClose,
} = useDisclosure();
+ // Debounce the search term to avoid making a request on every keystroke
+ useEffect(() => {
+ const handler = setTimeout(() => {
+ setDebouncedSearchTerm(searchTerm);
+ }, 500); // Adjust delay as needed
+ return () => {
+ clearTimeout(handler);
+ };
+ }, [searchTerm]);
+
const {
data,
isLoading: drawalRequestLoading,
error,
refetch,
- } = useGetApproveHistoryQuery();
+ } = useGetApproveHistoryQuery(
+ {
+ page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
+ size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
+ searchTerm: debouncedSearchTerm,
+ },
+ {
+ skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
+ }
+ );
console.log(data?.data?.rows);
@@ -84,6 +104,15 @@ const ApproveHistory = () => {
return () => clearTimeout(timer);
}, []);
+
+ useEffect(() => {
+ const handler = setTimeout(() => {
+ setDebouncedSearchTerm(searchTerm);
+ }, 500); // Adjust delay as needed
+ return () => {
+ clearTimeout(handler);
+ };
+ }, [searchTerm]);
// ====================================================[Table Filter]================================================================
const filteredData = data?.data?.rows?.filter((item) => {
// Filter by name (case insensitive)
@@ -117,7 +146,7 @@ const ApproveHistory = () => {
"Status",
];
- const extractedArray = filteredData?.map((item, idx) => ({
+ const extractedArray = data?.data?.rows?.map((item, idx) => ({
// id: item?.id,
"Sr.no": (
{
),
"Deposit Date": (
-
+
{formatDate(item?.transaction_date)}
@@ -202,28 +227,27 @@ const ApproveHistory = () => {
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
- {item?.spportFile_path&&
-
-
- View
-
-
-
- }
+
+ View
+
+
+
+
+ )}
),
Status: (
@@ -236,12 +260,12 @@ const ApproveHistory = () => {
rounded={4}
colorScheme={
item?.transactionStatus === "Approved"
- ? "green"
- : item?.transactionStatus === "Pending"
- ? "yellow"
- : item?.transactionStatus === "Reject"
- ? "red"
- : "gray" // default border color if status doesn't match any condition
+ ? "green"
+ : item?.transactionStatus === "Pending"
+ ? "yellow"
+ : item?.transactionStatus === "Reject"
+ ? "red"
+ : "gray" // default border color if status doesn't match any condition
}
>
{item.transactionStatus}
diff --git a/src/Pages/FawateerChecker/ApproveHistory/ApproveHistoryMaker.jsx b/src/Pages/FawateerChecker/ApproveHistory/ApproveHistoryMaker.jsx
index f0d0e25..b2e2739 100644
--- a/src/Pages/FawateerChecker/ApproveHistory/ApproveHistoryMaker.jsx
+++ b/src/Pages/FawateerChecker/ApproveHistory/ApproveHistoryMaker.jsx
@@ -1,229 +1,239 @@
import {
- Avatar,
- Badge,
- Box,
- Button,
- HStack,
- Input,
- Link,
- Text,
- Tooltip,
- useDisclosure,
- useToast,
- } from "@chakra-ui/react";
- import React, { useContext, useEffect, useState } from "react";
- import { CheckIcon, CloseIcon, ExternalLinkIcon } from "@chakra-ui/icons";
- import Pagination from "../../../Components/Pagination";
- import GlobalStateContext from "../../../Contexts/GlobalStateContext";
- import CustomAlertDialog from "../../../Components/CustomAlertDialog";
- import DrawalRequestReject from "../../WithDrawal/DrawalRequest/DrawalRequestReject";
- import NormalTable from "../../../Components/DataTable/NormalTable";
- import DrawalRequestApprove from "../../WithDrawal/DrawalRequest/DrawalRequestApprove";
- import { generateSerialNumber } from "../../../Constants/Constants";
- import {
- useGetApproveHistoryQuery,
- useGetFawateerForMakerRequestQuery,
- useGetFawateerRequestQuery,
- } from "../../../Services/fawateer.request.service";
- import { TABLE_PAGINATION } from "../../../Constants/Paginations";
- import { OPACITY_ON_LOAD } from "../../../Layout/animations";
-
- const ApproveHistoryMaker = () => {
- const toast = useToast();
- const { slideFromRight, approveHistory, setApproveHistory } =
- useContext(GlobalStateContext);
- const [searchTerm, setSearchTerm] = useState("");
- const [isLoading, setIsLoading] = useState(true);
- const [deleteAlert, setDeleteAlert] = useState(false);
- const [actionId, setActionId] = useState(false);
- const [mouseEntered, setMouseEntered] = useState(false);
- const [mouseEnteredId, setMouseEnteredId] = useState("");
- const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
-
- const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
- const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
-
- const formatDate = (date) => {
- return new Date(date).toLocaleDateString("en-GB", {
- day: "2-digit",
- month: "2-digit",
- year: "numeric",
- });
- };
-
- const {
- isOpen: isConfirmOpen,
- onOpen: onConfirmOpen,
- onClose: onConfirmClose,
- } = useDisclosure();
- const {
- isOpen: isRejectOpen,
- onOpen: onRejectOpen,
- onClose: onRejectClose,
- } = useDisclosure();
+ Avatar,
+ Badge,
+ Box,
+ Button,
+ HStack,
+ Input,
+ Link,
+ Text,
+ Tooltip,
+ useBoolean,
+ useDisclosure,
+ useToast,
+} from "@chakra-ui/react";
+import React, { useContext, useEffect, useState } from "react";
+import { CheckIcon, CloseIcon, ExternalLinkIcon } from "@chakra-ui/icons";
+import Pagination from "../../../Components/Pagination";
+import GlobalStateContext from "../../../Contexts/GlobalStateContext";
+import CustomAlertDialog from "../../../Components/CustomAlertDialog";
+import DrawalRequestReject from "../../WithDrawal/DrawalRequest/DrawalRequestReject";
+import NormalTable from "../../../Components/DataTable/NormalTable";
+import DrawalRequestApprove from "../../WithDrawal/DrawalRequest/DrawalRequestApprove";
+import { generateSerialNumber, isMaker } from "../../../Constants/Constants";
+import {
+ useGetApproveHistoryQuery,
+ useGetFawateerForMakerRequestQuery,
+ useGetFawateerRequestQuery,
+} from "../../../Services/fawateer.request.service";
+import { TABLE_PAGINATION } from "../../../Constants/Paginations";
+import { OPACITY_ON_LOAD } from "../../../Layout/animations";
+import InitiateReversalPopup from "../../../Components/Popups/InitiateReversalPopups";
+import ToastBox from "../../../Components/ToastBox";
+import { useCreateFawateerReversalRequestMutation } from "../../../Services/reversal.fawateer.deposit.service";
- const {
- data,
- isLoading: drawalRequestLoading,
- error,
- refetch
- } = useGetFawateerForMakerRequestQuery(
- {
- page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
- size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
- searchTerm: debouncedSearchTerm,
- },
- {
- skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
- }
- );
-
- console.log(data);
+const ApproveHistoryMaker = () => {
+ const toast = useToast();
+ const { slideFromRight, approveHistory, setApproveHistory } =
+ useContext(GlobalStateContext);
+ const [searchTerm, setSearchTerm] = useState("");
+ const [isLoading, setIsLoading] = useState(true);
+ const [deleteAlert, setDeleteAlert] = useState(false);
+ const [actionId, setActionId] = useState(false);
+ const [mouseEntered, setMouseEntered] = useState(false);
+ const [mouseEnteredId, setMouseEnteredId] = useState("");
+ const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
- useEffect(() => {
- const handler = setTimeout(() => {
- setDebouncedSearchTerm(searchTerm);
- }, 500); // Adjust delay as needed
- return () => {
- clearTimeout(handler);
- };
- }, [searchTerm]);
-
- // Use useEffect to refetch data when the component mounts
- useEffect(() => {
- refetch();
- }, [refetch]);
-
- useEffect(() => {
- // Simulate loading
- const timer = setTimeout(() => {
- setIsLoading(false);
- }, 1500);
-
- // Cleanup the timer on component unmount
- return () => clearTimeout(timer);
- }, []);
-
- // ====================================================[Table Filter]================================================================
- const filteredData = data?.data?.rows?.filter((item) => {
- // Filter by name (case insensitive)
- const name = item.firstName;
- const searchLower = searchTerm.toLowerCase();
- const nameMatches = name.toLowerCase().includes(searchLower);
-
- // Filter by status
- // const status = item.status;
- // const statusLower = status ? "active" : "inactive";
-
- // const statusMatches =
- // statusFilter === "all" ||
- // (statusFilter === "active" && status === true) ||
- // (statusFilter === "inactive" && status === false);
-
- return nameMatches;
+ const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
+ const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
+
+ const [createFawateerReversalRequest] =
+ useCreateFawateerReversalRequestMutation();
+
+ const [reversalId, setReversalId] = useState();
+ const {
+ isOpen: isOpenInRev,
+ onOpen: onOpenInRev,
+ onClose: onCloseInRev,
+ } = useDisclosure();
+ const [isReversalLoading, setIsReversalLoading] = useBoolean();
+
+ const formatDate = (date) => {
+ return new Date(date).toLocaleDateString("en-GB", {
+ day: "2-digit",
+ month: "2-digit",
+ year: "numeric",
});
-
- // ====================================================[Table Setup]================================================================
- const tableHeadRow = [
- "Sr.no",
- "Client ID",
- "First Name",
- "Last Name",
- "E-mail ID",
- "Phone Number",
- "Deposit Date",
- "Deposit Amount (BHD)",
- "Support Image",
- "Status",
- ];
-
- const extractedArray = data?.data?.rows?.map((item, idx) => ({
-
- // id: item?.id,
- "Sr.no": (
-
- {generateSerialNumber(idx, currentPage, pageSize)}
+ };
+
+ const {
+ isOpen: isConfirmOpen,
+ onOpen: onConfirmOpen,
+ onClose: onConfirmClose,
+ } = useDisclosure();
+ const {
+ isOpen: isRejectOpen,
+ onOpen: onRejectOpen,
+ onClose: onRejectClose,
+ } = useDisclosure();
+
+ const {
+ data,
+ isLoading: drawalRequestLoading,
+ error,
+ refetch,
+ } = useGetFawateerForMakerRequestQuery(
+ {
+ page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
+ size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
+ searchTerm: debouncedSearchTerm,
+ },
+ {
+ skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
+ }
+ );
+
+ useEffect(() => {
+ const handler = setTimeout(() => {
+ setDebouncedSearchTerm(searchTerm);
+ }, 500); // Adjust delay as needed
+ return () => {
+ clearTimeout(handler);
+ };
+ }, [searchTerm]);
+
+ // Use useEffect to refetch data when the component mounts
+ useEffect(() => {
+ refetch();
+ }, [refetch]);
+
+ useEffect(() => {
+ // Simulate loading
+ const timer = setTimeout(() => {
+ setIsLoading(false);
+ }, 1500);
+
+ // Cleanup the timer on component unmount
+ return () => clearTimeout(timer);
+ }, []);
+
+ // ====================================================[Table Filter]================================================================
+ const filteredData = data?.data?.rows?.filter((item) => {
+ // Filter by name (case insensitive)
+ const name = item.firstName;
+ const searchLower = searchTerm.toLowerCase();
+ const nameMatches = name.toLowerCase().includes(searchLower);
+
+ // Filter by status
+ // const status = item.status;
+ // const statusLower = status ? "active" : "inactive";
+
+ // const statusMatches =
+ // statusFilter === "all" ||
+ // (statusFilter === "active" && status === true) ||
+ // (statusFilter === "inactive" && status === false);
+
+ return nameMatches;
+ });
+
+ // ====================================================[Table Setup]================================================================
+ const tableHeadRow = [
+ "Sr.no",
+ "Client ID",
+ "First Name",
+ "Last Name",
+ "E-mail ID",
+ "Phone Number",
+ "Deposit Date",
+ "Deposit Amount (BHD)",
+ "Support Image",
+ "Status",
+ isMaker() && "Reversal Action",
+ ];
+
+ const extractedArray = data?.data?.rows?.map((item, idx) => ({
+ // id: item?.id,
+ "Sr.no": (
+
+ {generateSerialNumber(idx, currentPage, pageSize)}
+
+ ),
+ "Client ID": (
+
+ {item.clientReference_id}
+
+ ),
+ "First Name": (
+
+
+ {item.firstName}
- ),
- "Client ID": (
-
- {item.clientReference_id}
+
+ ),
+ "Last Name": (
+
+
+ {item.lastName}
- ),
- "First Name": (
-
-
- {item.firstName}
-
-
- ),
- "Last Name": (
-
-
- {item.lastName}
-
-
- ),
- "E-mail ID": (
-
-
- {item.emailAddress}
-
-
- ),
- "Phone Number": (
-
-
- {item.mobileNumber}
-
-
- ),
- "Deposit Date": (
-
-
- {formatDate(item?.transaction_date)}
-
-
- ),
- "Deposit Amount (BHD)": (
-
-
- {/* {item.investorAmount} */}
- {parseFloat(item?.transaction_amount || 0).toLocaleString(undefined, {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- })}
- {/* {item?.transaction_amount} */}
-
-
- ),
- "Support Image": (
-
- {item?.spportFile_path&&
+ ),
+ "E-mail ID": (
+
+
+ {item.emailAddress}
+
+
+ ),
+ "Phone Number": (
+
+
+ {item.mobileNumber}
+
+
+ ),
+ "Deposit Date": (
+
+
+ {formatDate(item?.transaction_date)}
+
+
+ ),
+ "Deposit Amount (BHD)": (
+
+
+ {/* {item.investorAmount} */}
+ {parseFloat(item?.transaction_amount || 0).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}
+ {/* {item?.transaction_amount} */}
+
+
+ ),
+ "Support Image": (
+
+ {item?.spportFile_path && (
+
-
+
View
- }
-
- ),
- Status: (
-
-
+ )}
+
+ ),
+ Status: (
+
+
- {item.transactionStatus}
-
-
- ),
- }));
-
- const handleDelete = () => {
- const updatedSponsors = sponser.filter(
- (sponsor) => sponsor.id !== actionId
- );
-
- setTimeout(() => {
- setSponser(updatedSponsors);
- setDeleteAlert(false);
- setIsLoading(false);
- }, 100);
- setIsLoading(true);
- };
-
- return (
-
-
-
- setSearchTerm(e.target.value)}
- />
-
-
-
-
-
-
-
- setDeleteAlert(false)}
- isOpen={deleteAlert}
- message={"Are you sure you want to delete sponers?"}
- alertHandler={handleDelete}
- isLoading={isLoading}
- />
-
-
+ }
+ >
+ {item.transactionStatus}
+
+ ),
+ "Reversal Action": (
+
+ {item.transactionStatus === "Approved" ? (
+
+ {!item.isReversal ? (
+
+ ) : (
+ "Under process"
+ )}
+
+ ) : (
+ ""
+ )}
+
+ ),
+ }));
+
+ const handleDelete = () => {
+ const updatedSponsors = sponser.filter(
+ (sponsor) => sponsor.id !== actionId
);
+
+ setTimeout(() => {
+ setSponser(updatedSponsors);
+ setDeleteAlert(false);
+ setIsLoading(false);
+ }, 100);
+ setIsLoading(true);
};
-
- export default ApproveHistoryMaker;
-
\ No newline at end of file
+
+ const handleApproved = async (data) => {
+ setIsReversalLoading.on(); // Start loading
+ try {
+ const { error, data: responseData } = await createFawateerReversalRequest(
+ {
+ id: reversalId,
+ data,
+ }
+ );
+
+ if (error) {
+ throw error; // Explicitly handle the error
+ }
+
+ // Success: Perform necessary actions
+ refetch();
+ toast({
+ render: () => (
+
+ ),
+ });
+ onCloseInRev();
+ } catch (error) {
+ // Handle errors
+ toast({
+ render: () => (
+
+ ),
+ });
+ console.error("Error:", error);
+ } finally {
+ setIsReversalLoading.off(); // Ensure loading is toggled off
+ }
+ };
+
+ return (
+
+
+
+ setSearchTerm(e.target.value)}
+ />
+
+
+
+
+
+
+
+ setDeleteAlert(false)}
+ isOpen={deleteAlert}
+ message={"Are you sure you want to delete sponers?"}
+ alertHandler={handleDelete}
+ isLoading={isLoading}
+ />
+
+
+
+
+
+ );
+};
+
+export default ApproveHistoryMaker;
diff --git a/src/Pages/FawateerChecker/ApproveRequest/RequestApproveModal.jsx b/src/Pages/FawateerChecker/ApproveRequest/RequestApproveModal.jsx
index de219ae..a71b932 100644
--- a/src/Pages/FawateerChecker/ApproveRequest/RequestApproveModal.jsx
+++ b/src/Pages/FawateerChecker/ApproveRequest/RequestApproveModal.jsx
@@ -104,6 +104,12 @@ const RequestApproveModal = ({ isOpen, onClose, firstField ,id}) => {
}
}, [data, reset]);
+ useEffect(() => {
+ if (!isOpen) {
+ reset();
+ }
+ }, [isOpen, reset]);
+
const heandleOnClose = () =>{
reset()
onClose()
@@ -130,11 +136,11 @@ const RequestApproveModal = ({ isOpen, onClose, firstField ,id}) => {
fontSize="sm"
type="textarea"
size="md"
- placeholder={"Enter your checkerComment...."}
+ placeholder={"Enter your checker Comment...."}
rounded={"md"}
resize={"none"}
maxLength={200}
- />
+ />
{errors.checkerComment && (
{errors.checkerComment.message}
diff --git a/src/Pages/FawateerChecker/ApproveRequest/RequestRejectModal.jsx b/src/Pages/FawateerChecker/ApproveRequest/RequestRejectModal.jsx
index 35f8873..b9178fd 100644
--- a/src/Pages/FawateerChecker/ApproveRequest/RequestRejectModal.jsx
+++ b/src/Pages/FawateerChecker/ApproveRequest/RequestRejectModal.jsx
@@ -2,6 +2,7 @@ import {
Box,
Button,
FormControl,
+ FormHelperText,
FormLabel,
Input,
Modal,
@@ -24,8 +25,18 @@ import { useDepositRejectMutation } from "../../../Services/deposit.request.serv
import ToastBox from "../../../Components/ToastBox";
import { useRejectCommentMutation } from "../../../Services/fawateer.request.service";
+// export const conformModalSchema = yup.object().shape({
+// comments: yup.string().required("Comment is required")
+// .max(200, "Approve Comment cannot be more than 200 characters"),
+// });
+
export const conformModalSchema = yup.object().shape({
- comments: yup.string().required("Comment is required"),
+ // checkerComment: yup.string().required("Comment is required")
+ // .max(50, "Investment name cannot be more than 50 characters"),
+ comments: yup
+ .string()
+ .required("Comment is required")
+ .max(200, "Approve Comment cannot be more than 200 characters"),
});
const RequestRejectModal = ({ isOpen, onClose, firstField ,id}) => {
@@ -36,12 +47,20 @@ const RequestRejectModal = ({ isOpen, onClose, firstField ,id}) => {
const {
register,
reset,
+ watch,
handleSubmit,
formState: { errors },
} = useForm({
resolver: yupResolver(conformModalSchema),
});
+ useEffect(() => {
+ if (!isOpen) {
+ reset(); // Clear the form state
+ }
+ }, [isOpen, reset]);
+
+
const [ rejectFawateer ] = useRejectCommentMutation()
@@ -101,7 +120,7 @@ const RequestRejectModal = ({ isOpen, onClose, firstField ,id}) => {
reset()
onClose()
}
-
+
return (
@@ -126,12 +145,17 @@ const RequestRejectModal = ({ isOpen, onClose, firstField ,id}) => {
placeholder={"Enter your comments...."}
rounded={"md"}
resize={"none"}
+ maxLength={200}
/>
{errors.comments && (
{errors.comments.message}
)}
+
+ Maximum length should be 200 characters. You have entered
+ {watch("comments")?.length || 0} characters.
+
diff --git a/src/Pages/IO_Management/ViewIO/HeaderModal/UpdateIOStatus.jsx b/src/Pages/IO_Management/ViewIO/HeaderModal/UpdateIOStatus.jsx
index 1db3014..8b36298 100644
--- a/src/Pages/IO_Management/ViewIO/HeaderModal/UpdateIOStatus.jsx
+++ b/src/Pages/IO_Management/ViewIO/HeaderModal/UpdateIOStatus.jsx
@@ -57,7 +57,7 @@ const UpdateIOStatus = ({ isOpen, onClose, status }) => {
setError("Please select status");
return;
}
- if (!message) {
+ if (selectedStatusId == 6 && !message) {
return setMessageError("message is required");
}
setError("");
diff --git a/src/Pages/Login.jsx b/src/Pages/Login.jsx
index 62837f1..d53844c 100644
--- a/src/Pages/Login.jsx
+++ b/src/Pages/Login.jsx
@@ -78,7 +78,7 @@ const Login = () => {
setIsLoading(false);
setIsAuthenticate(true);
Cookies.set("isAuthenticated", true, { expires: 7 });
- navigate("/sponser");
+ navigate("/");
reset();
}
diff --git a/src/Pages/Master/Sponser/AddSponser.jsx b/src/Pages/Master/Sponser/AddSponser.jsx
index ed3b276..2a86177 100644
--- a/src/Pages/Master/Sponser/AddSponser.jsx
+++ b/src/Pages/Master/Sponser/AddSponser.jsx
@@ -254,7 +254,7 @@ const AddSponser = () => {
} characters.`,
},
{
- label: "Email adress",
+ label: "Email address",
name: "email",
placeHolder: " ",
type: "email",
diff --git a/src/Pages/ReversalAccountDeletion/ConfirmModal.jsx b/src/Pages/ReversalAccountDeletion/ConfirmModal.jsx
new file mode 100644
index 0000000..64a4cf1
--- /dev/null
+++ b/src/Pages/ReversalAccountDeletion/ConfirmModal.jsx
@@ -0,0 +1,149 @@
+import {
+ Box,
+ Button,
+ Checkbox,
+ FormControl,
+ FormLabel,
+ Input,
+ Modal,
+ ModalBody,
+ ModalCloseButton,
+ ModalContent,
+ ModalFooter,
+ ModalHeader,
+ ModalOverlay,
+ Text,
+ Textarea,
+ useDisclosure,
+} from "@chakra-ui/react";
+import React, { useState } from "react";
+import * as yup from "yup";
+import { yupResolver } from "@hookform/resolvers/yup";
+import { useForm } from "react-hook-form";
+import ReactQuill from "react-quill";
+
+export const conformModalSchema = yup.object().shape({
+ fees: yup.string().required("File name is required"),
+ totalAmount: yup.string().required("File name is required"),
+});
+
+const ConfirmModal = ({ isOpen, onClose, firstField }) => {
+
+ const [emailApproval,setEmailApproval] = useState(false)
+
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ } = useForm({
+ resolver: yupResolver(conformModalSchema),
+ });
+
+ const onSubmit = (data) => {
+ setFile(data.document[0]);
+
+ const newDocument = {
+ ...data,
+ document: data.document[0].name, // Store the document name
+ status: true,
+ id: uuidv4(),
+ createdAt: new Date().toISOString(),
+ Type: getFileIcon(file.type),
+ };
+
+ setCreate((prevCreate) => [...prevCreate, newDocument]);
+ onClose();
+ };
+
+ const handleFileChange = (event) => {
+ const selectedFile = event.target.files[0];
+ setFile(selectedFile);
+ };
+
+ const modules = {
+ toolbar: [
+ // [{ header: "1" }, { header: "2" },
+ // // { font: [] }
+ // ],
+ // [{ size: [] }],
+ ["bold", "italic", "underline", "strike", "blockquote"],
+ [{ list: "ordered" }, { list: "bullet" }],
+ ["clean"],
+ ],
+ };
+
+ return (
+
+
+
+ Confirm
+
+
+
+
+ Comment
+
+ {errors.comment && (
+
+ {errors.comment.message}
+
+ )}
+
+
+ setEmailApproval(e.target.checked)}
+ >
+ Send an email to the user upon approval
+
+ {emailApproval &&
+
+ Subject
+
+
+
+ Message
+
+
+ }
+
+
+
+
+
+
+
+
+ );
+};
+
+export default ConfirmModal;
diff --git a/src/Pages/ReversalAccountDeletion/RejectModal.jsx b/src/Pages/ReversalAccountDeletion/RejectModal.jsx
new file mode 100644
index 0000000..df2b79f
--- /dev/null
+++ b/src/Pages/ReversalAccountDeletion/RejectModal.jsx
@@ -0,0 +1,98 @@
+import {
+ Box,
+ Button,
+ FormControl,
+ FormLabel,
+ Input,
+ Modal,
+ ModalBody,
+ ModalCloseButton,
+ ModalContent,
+ ModalFooter,
+ ModalHeader,
+ ModalOverlay,
+ Text,
+ Textarea,
+ useDisclosure,
+} from "@chakra-ui/react";
+import React from "react";
+import * as yup from "yup";
+import { yupResolver } from "@hookform/resolvers/yup";
+import { useForm } from "react-hook-form";
+
+export const conformModalSchema = yup.object().shape({
+ comment: yup.string().required("Comment is required"),
+});
+
+const RejectModal = ({ isOpen, onClose, firstField }) => {
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ } = useForm({
+ resolver: yupResolver(conformModalSchema),
+ });
+
+ const onSubmit = (data) => {
+ setFile(data.document[0]);
+
+ const newDocument = {
+ ...data,
+ document: data.document[0].name, // Store the document name
+ comment: true,
+ id: uuidv4(),
+ Type: getFileIcon(file.type),
+ };
+
+ setCreate((prevCreate) => [...prevCreate, newDocument]);
+ onClose();
+ };
+
+ const handleFileChange = (event) => {
+ const selectedFile = event.target.files[0];
+ setFile(selectedFile);
+ };
+
+ return (
+
+
+
+ Reject
+
+
+
+
+ Comment
+
+ {errors.comment && (
+
+ {errors.comment.message}
+
+ )}
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default RejectModal;
diff --git a/src/Pages/ReversalAccountDeletion/ReversalAccountDeletion.jsx b/src/Pages/ReversalAccountDeletion/ReversalAccountDeletion.jsx
new file mode 100644
index 0000000..4b9df5c
--- /dev/null
+++ b/src/Pages/ReversalAccountDeletion/ReversalAccountDeletion.jsx
@@ -0,0 +1,404 @@
+import { CheckIcon, CloseIcon } from "@chakra-ui/icons";
+import {
+ Box,
+ Button,
+ HStack,
+ Input,
+ Text,
+ Tooltip,
+ useBoolean,
+ useDisclosure,
+ useToast,
+} from "@chakra-ui/react";
+import React, { useContext, useEffect, useState } from "react";
+import CustomAlertDialog from "../../Components/CustomAlertDialog";
+import NormalTable from "../../Components/DataTable/NormalTable";
+import { TABLE_PAGINATION } from "../../Constants/Paginations";
+import GlobalStateContext from "../../Contexts/GlobalStateContext";
+import { OPACITY_ON_LOAD } from "../../Layout/animations";
+import {
+ useApproveAccountDeletionRequestMutation,
+ useGetAccountDeletionMasterQuery,
+ useRejectAccountDeletionRequestMutation,
+} from "../../Services/reversal.account.deletion.service";
+import ConfirmModal from "./ConfirmModal";
+import RejectModal from "./RejectModal";
+import RejectReversalPopups from "../../Components/Popups/RejectReversalPopups";
+import ToastBox from "../../Components/ToastBox";
+import ConfirmReversalPopups from "../../Components/Popups/ConfirmReversalPopups";
+// import { formatDate } from "../../Components/Functions/UTCConvertor";
+
+const ReversalAccountDeletion = () => {
+ const toast = useToast();
+ const { slideFromRight, setDeleteHistory } = useContext(GlobalStateContext);
+ const [deleteAlert, setDeleteAlert] = useState(false);
+ const [actionId, setActionId] = useState(false);
+ const [mouseEntered, setMouseEntered] = useState(false);
+ const [mouseEnteredId, setMouseEnteredId] = useState("");
+
+ // =========================== [Use State] =============================
+ const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
+ const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
+ const [searchTerm, setSearchTerm] = useState("");
+ const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
+
+ const [isReversalLoading, setIsReversalLoading] = useBoolean();
+
+ const {
+ isOpen: isConfirmOpen,
+ onOpen: onConfirmOpen,
+ onClose: onConfirmClose,
+ } = useDisclosure();
+ const {
+ isOpen: isRejectOpen,
+ onOpen: onRejectOpen,
+ onClose: onRejectClose,
+ } = useDisclosure();
+
+ const [rejectAccountDeletionRequest] = useRejectAccountDeletionRequestMutation();
+
+ const [approveAccountDeletionRequest] = useApproveAccountDeletionRequestMutation();
+
+ // Debounce the search term to avoid making a request on every keystroke
+ useEffect(() => {
+ const handler = setTimeout(() => {
+ setDebouncedSearchTerm(searchTerm);
+ }, 500); // Adjust delay as needed
+ return () => {
+ clearTimeout(handler);
+ };
+ }, [searchTerm]);
+
+ const {
+ data: deleteHistory,
+ isLoading,
+ refetch,
+ } = useGetAccountDeletionMasterQuery(
+ {
+ page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
+ size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
+ search: debouncedSearchTerm,
+ },
+ {
+ skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
+ }
+ );
+
+ const formatDate = (date) => {
+ return new Date(date).toLocaleDateString("en-GB", {
+ day: "2-digit",
+ month: "2-digit",
+ year: "numeric",
+ });
+ };
+
+ // Use useEffect to refetch data when the component mounts
+ useEffect(() => {
+ refetch();
+ }, [refetch]);
+
+ // ====================================================[Table Setup]================================================================
+ const tableHeadRow = [
+ "Sr No.",
+ "Request Date",
+ "Client ID",
+ "First Name",
+ "Last Name",
+ "Phone Number",
+ "Country",
+ "Action",
+ ];
+
+ const extractedArray = deleteHistory?.data?.rows?.map((item, index) => ({
+ id: item?.id,
+ "Sr No.": (
+
+ {index + 1}.
+
+ ),
+ "Request Date": (
+
+ {formatDate(item.isReversalDate)}
+
+ ),
+ "Client ID": (
+
+ {item?.iamPrincipal?.investor_details?.clientReference_id}
+
+ ),
+ "First Name": (
+
+ {item?.iamPrincipal?.firstName}
+ {/* {formatDate(item.charge)} */}
+
+ ),
+ "Last Name": (
+
+ {item?.iamPrincipal?.lastName}
+
+ ),
+ "Phone Number": (
+
+ {item?.iamPrincipal?.ISDcode + " " + item?.iamPrincipal?.mobileNumber}
+
+ ),
+ Country: (
+
+ {item?.iamPrincipal?.investor_details?.country?.countryName}
+
+ ),
+ Action: (
+
+
+
+
+
+
+
+
+ ),
+ }));
+
+ const handleDelete = () => {
+ const deleteHistory = sponser.filter((sponsor) => sponsor.id !== actionId);
+
+ setTimeout(() => {
+ setSponser(deleteHistory);
+ setDeleteAlert(false);
+ setIsLoading(false);
+ }, 100);
+ setIsLoading(true);
+ };
+
+ const handleApproved = async (data) => {
+ setIsReversalLoading.on(); // Start loading
+ try {
+ const { error, data: responseData } = await rejectAccountDeletionRequest({
+ id: actionId,
+ data,
+ });
+
+ if (error) {
+ throw error; // Explicitly handle the error
+ }
+
+ // Success: Perform necessary actions
+ refetch();
+ toast({
+ render: () => (
+
+ ),
+ });
+ onRejectClose();
+ } catch (error) {
+ // Handle errors
+ toast({
+ render: () => (
+
+ ),
+ });
+ console.error("Error:", error);
+ } finally {
+ setIsReversalLoading.off(); // Ensure loading is toggled off
+ }
+ };
+
+ const handleConfirm = async (data) => {
+
+ setIsReversalLoading.on(); // Start loading
+ try {
+ const { error, data: responseData } = await approveAccountDeletionRequest({
+ id: actionId,
+ data,
+ });
+
+ if (error) {
+ throw error; // Explicitly handle the error
+ }
+
+ // Success: Perform necessary actions
+ refetch();
+ toast({
+ render: () => (
+
+ ),
+ });
+ onRejectClose();
+ } catch (error) {
+ // Handle errors
+ toast({
+ render: () => (
+
+ ),
+ });
+ console.error("Error:", error);
+ } finally {
+ setIsReversalLoading.off(); // Ensure loading is toggled off
+ }
+ };
+
+
+ return (
+
+
+
+ setSearchTerm(e.target.value)}
+ />
+
+ {/*
+
+ */}
+
+
+
+
+
+ setDeleteAlert(false)}
+ isOpen={deleteAlert}
+ message={"Are you sure you want to delete sponers?"}
+ alertHandler={handleDelete}
+ isLoading={isLoading}
+ />
+
+
+
+ );
+};
+
+export default ReversalAccountDeletion;
diff --git a/src/Pages/ReversalFawateerDeposit/ConfirmModal.jsx b/src/Pages/ReversalFawateerDeposit/ConfirmModal.jsx
new file mode 100644
index 0000000..b2d7317
--- /dev/null
+++ b/src/Pages/ReversalFawateerDeposit/ConfirmModal.jsx
@@ -0,0 +1,149 @@
+import {
+ Box,
+ Button,
+ Checkbox,
+ FormControl,
+ FormLabel,
+ Input,
+ Modal,
+ ModalBody,
+ ModalCloseButton,
+ ModalContent,
+ ModalFooter,
+ ModalHeader,
+ ModalOverlay,
+ Text,
+ Textarea,
+ useDisclosure,
+} from "@chakra-ui/react";
+import React, { useState } from "react";
+import * as yup from "yup";
+import { yupResolver } from "@hookform/resolvers/yup";
+import { useForm } from "react-hook-form";
+import ReactQuill from "react-quill";
+
+export const conformModalSchema = yup.object().shape({
+ fees: yup.string().required("File name is required"),
+ totalAmount: yup.string().required("File name is required"),
+});
+
+const ConfirmModal = ({ isOpen, onClose, firstField }) => {
+
+ const [emailApproval,setEmailApproval] = useState(false)
+
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ } = useForm({
+ resolver: yupResolver(conformModalSchema),
+ });
+
+ const onSubmit = (data) => {
+ setFile(data.document[0]);
+
+ const newDocument = {
+ ...data,
+ document: data.document[0].name, // Store the document name
+ status: true,
+ id: uuidv4(),
+ createdAt: new Date().toISOString(),
+ Type: getFileIcon(file.type),
+ };
+
+ setCreate((prevCreate) => [...prevCreate, newDocument]);
+ onClose();
+ };
+
+ const handleFileChange = (event) => {
+ const selectedFile = event.target.files[0];
+ setFile(selectedFile);
+ };
+
+ const modules = {
+ toolbar: [
+ // [{ header: "1" }, { header: "2" },
+ // // { font: [] }
+ // ],
+ // [{ size: [] }],
+ ["bold", "italic", "underline", "strike", "blockquote"],
+ [{ list: "ordered" }, { list: "bullet" }],
+ ["clean"],
+ ],
+ };
+
+ return (
+
+
+
+ Confirm
+
+
+
+
+ Comment
+
+ {errors.comment && (
+
+ {errors.comment.message}
+
+ )}
+
+
+ setEmailApproval(e.target.checked)}
+ >
+ Send an email to the user upon approval
+
+ {emailApproval &&
+
+ Subject
+
+
+
+ Message
+
+
+ }
+
+
+
+
+
+
+
+
+ );
+};
+
+export default ConfirmModal;
diff --git a/src/Pages/ReversalFawateerDeposit/RejectModal.jsx b/src/Pages/ReversalFawateerDeposit/RejectModal.jsx
new file mode 100644
index 0000000..df2b79f
--- /dev/null
+++ b/src/Pages/ReversalFawateerDeposit/RejectModal.jsx
@@ -0,0 +1,98 @@
+import {
+ Box,
+ Button,
+ FormControl,
+ FormLabel,
+ Input,
+ Modal,
+ ModalBody,
+ ModalCloseButton,
+ ModalContent,
+ ModalFooter,
+ ModalHeader,
+ ModalOverlay,
+ Text,
+ Textarea,
+ useDisclosure,
+} from "@chakra-ui/react";
+import React from "react";
+import * as yup from "yup";
+import { yupResolver } from "@hookform/resolvers/yup";
+import { useForm } from "react-hook-form";
+
+export const conformModalSchema = yup.object().shape({
+ comment: yup.string().required("Comment is required"),
+});
+
+const RejectModal = ({ isOpen, onClose, firstField }) => {
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ } = useForm({
+ resolver: yupResolver(conformModalSchema),
+ });
+
+ const onSubmit = (data) => {
+ setFile(data.document[0]);
+
+ const newDocument = {
+ ...data,
+ document: data.document[0].name, // Store the document name
+ comment: true,
+ id: uuidv4(),
+ Type: getFileIcon(file.type),
+ };
+
+ setCreate((prevCreate) => [...prevCreate, newDocument]);
+ onClose();
+ };
+
+ const handleFileChange = (event) => {
+ const selectedFile = event.target.files[0];
+ setFile(selectedFile);
+ };
+
+ return (
+
+
+
+ Reject
+
+
+
+
+ Comment
+
+ {errors.comment && (
+
+ {errors.comment.message}
+
+ )}
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default RejectModal;
diff --git a/src/Pages/ReversalFawateerDeposit/ReversalFawateerDeposit.jsx b/src/Pages/ReversalFawateerDeposit/ReversalFawateerDeposit.jsx
new file mode 100644
index 0000000..6eb8c3c
--- /dev/null
+++ b/src/Pages/ReversalFawateerDeposit/ReversalFawateerDeposit.jsx
@@ -0,0 +1,427 @@
+import {
+ Avatar,
+ Badge,
+ Box,
+ Button,
+ HStack,
+ Input,
+ Link,
+ Text,
+ Tooltip,
+ useBoolean,
+ useDisclosure,
+ useToast,
+} from "@chakra-ui/react";
+import React, { useContext, useEffect, useState } from "react";
+import { CheckIcon, CloseIcon, ExternalLinkIcon } from "@chakra-ui/icons";
+import Pagination from "../../Components/Pagination";
+import GlobalStateContext from "../../Contexts/GlobalStateContext";
+import CustomAlertDialog from "../../Components/CustomAlertDialog";
+import NormalTable from "../../Components/DataTable/NormalTable";
+import { generateSerialNumber } from "../../Constants/Constants";
+import { TABLE_PAGINATION } from "../../Constants/Paginations";
+import { OPACITY_ON_LOAD } from "../../Layout/animations";
+import { useGetFawateerForMakerRequestQuery } from "../../Services/fawateer.request.service";
+import ConfirmModal from "./ConfirmModal";
+import RejectModal from "./RejectModal";
+import {
+ useApproveFawateerRequestMutation,
+ useGetFawateerDepositMasterQuery,
+ useRejectFawateerRequestMutation,
+} from "../../Services/reversal.fawateer.deposit.service";
+import RejectReversalPopups from "../../Components/Popups/RejectReversalPopups";
+import ToastBox from "../../Components/ToastBox";
+import ConfirmReversalPopups from "../../Components/Popups/ConfirmReversalPopups";
+
+const ReversalFawateerDeposit = () => {
+ const toast = useToast();
+ const { slideFromRight, approveHistory, setApproveHistory } =
+ useContext(GlobalStateContext);
+ const [searchTerm, setSearchTerm] = useState("");
+ const [isLoading, setIsLoading] = useState(true);
+ const [deleteAlert, setDeleteAlert] = useState(false);
+ const [actionId, setActionId] = useState(false);
+ const [mouseEntered, setMouseEntered] = useState(false);
+ const [mouseEnteredId, setMouseEnteredId] = useState("");
+ const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
+ const [isReversalLoading, setIsReversalLoading] = useBoolean();
+
+ const [rejectFawateerRequest] = useRejectFawateerRequestMutation();
+
+ const [approveFawateerRequest] = useApproveFawateerRequestMutation();
+
+ const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
+ const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
+
+ const formatDate = (date) => {
+ return new Date(date).toLocaleDateString("en-GB", {
+ day: "2-digit",
+ month: "2-digit",
+ year: "numeric",
+ });
+ };
+
+ const {
+ isOpen: isConfirmOpen,
+ onOpen: onConfirmOpen,
+ onClose: onConfirmClose,
+ } = useDisclosure();
+ const {
+ isOpen: isRejectOpen,
+ onOpen: onRejectOpen,
+ onClose: onRejectClose,
+ } = useDisclosure();
+
+ const {
+ data,
+ isLoading: drawalRequestLoading,
+ error,
+ refetch,
+ } = useGetFawateerDepositMasterQuery(
+ {
+ page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
+ size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
+ search: debouncedSearchTerm,
+ },
+ {
+ skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
+ }
+ );
+
+ useEffect(() => {
+ const handler = setTimeout(() => {
+ setDebouncedSearchTerm(searchTerm);
+ }, 500); // Adjust delay as needed
+ return () => {
+ clearTimeout(handler);
+ };
+ }, [searchTerm]);
+
+ // Use useEffect to refetch data when the component mounts
+ useEffect(() => {
+ refetch();
+ }, [refetch]);
+
+ useEffect(() => {
+ // Simulate loading
+ const timer = setTimeout(() => {
+ setIsLoading(false);
+ }, 1500);
+
+ // Cleanup the timer on component unmount
+ return () => clearTimeout(timer);
+ }, []);
+
+ // ====================================================[Table Filter]================================================================
+ const filteredData = data?.data?.rows?.filter((item) => {
+ // Filter by name (case insensitive)
+ const name = item.principal?.firstName;
+ const searchLower = searchTerm.toLowerCase();
+ const nameMatches = name.toLowerCase().includes(searchLower);
+
+ return nameMatches;
+ });
+
+ // ====================================================[Table Setup]================================================================
+ const tableHeadRow = [
+ "Sr.no",
+ "Request Date",
+ "Client ID",
+ "First Name",
+ "Last Name",
+ "Phone Number",
+ "Deposit Amount (BHD)",
+ "Action",
+ ];
+
+ const extractedArray = data?.data?.rows?.map((item, idx) => ({
+ // id: item?.id,
+ "Sr.no": (
+
+ {generateSerialNumber(idx, currentPage, pageSize)}
+
+ ),
+ "Request Date": (
+
+ {formatDate(item?.transaction_details?.isReversalDate)}
+
+ ),
+ "Client ID": (
+
+ {item?.principal?.investor_details?.clientReference_id}
+
+ ),
+ "First Name": (
+
+
+ {item?.principal?.firstName}
+
+
+ ),
+ "Last Name": (
+
+
+ {item?.principal?.lastName}
+
+
+ ),
+ "Phone Number": (
+
+
+ {/* {item?.principal?.ISDcode} {item?.principal?.mobileNumber} */}
+ {item?.principal?.ISDcode + " " + item?.principal?.mobileNumber}
+
+
+ ),
+ "Deposit Amount (BHD)": (
+
+
+ {parseFloat(item?.transaction_details?.investorAmount || 0).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}
+
+ {item?.currencyCode}
+
+
+
+ ),
+ Action: (
+
+
+
+
+
+
+
+
+ ),
+ }));
+
+ const handleDelete = () => {
+ const updatedSponsors = sponser.filter(
+ (sponsor) => sponsor.id !== actionId
+ );
+
+ setTimeout(() => {
+ setSponser(updatedSponsors);
+ setDeleteAlert(false);
+ setIsLoading(false);
+ }, 100);
+ setIsLoading(true);
+ };
+
+ const handleApproved = async (data) => {
+ setIsReversalLoading.on(); // Start loading
+ try {
+ const { error, data: responseData } = await rejectFawateerRequest({
+ id: actionId,
+ data,
+ });
+
+ if (error) {
+ throw error; // Explicitly handle the error
+ }
+
+ // Success: Perform necessary actions
+ refetch();
+ toast({
+ render: () => (
+
+ ),
+ });
+ onRejectClose();
+ } catch (error) {
+ // Handle errors
+ toast({
+ render: () => (
+
+ ),
+ });
+ console.error("Error:", error);
+ } finally {
+ setIsReversalLoading.off(); // Ensure loading is toggled off
+ }
+ };
+
+ const handleConfirm = async (data) => {
+ setIsReversalLoading.on(); // Start loading
+ try {
+ const { error, data: responseData } = await approveFawateerRequest({
+ id: actionId,
+ data,
+ });
+
+ if (error) {
+ throw error; // Explicitly handle the error
+ }
+
+ // Success: Perform necessary actions
+ refetch();
+ toast({
+ render: () => (
+
+ ),
+ });
+ onRejectClose();
+ } catch (error) {
+ // Handle errors
+ toast({
+ render: () => (
+
+ ),
+ });
+ console.error("Error:", error);
+ } finally {
+ setIsReversalLoading.off(); // Ensure loading is toggled off
+ }
+ };
+
+ return (
+
+
+
+ setSearchTerm(e.target.value)}
+ />
+
+
+
+
+
+
+
+ setDeleteAlert(false)}
+ isOpen={deleteAlert}
+ message={"Are you sure you want to delete sponers?"}
+ alertHandler={handleDelete}
+ isLoading={isLoading}
+ />
+
+
+
+ );
+};
+
+export default ReversalFawateerDeposit;
diff --git a/src/Pages/WithDrawal/DrawalView/ViewHistory.jsx b/src/Pages/WithDrawal/DrawalView/ViewHistory.jsx
index a8b8929..83b9f71 100644
--- a/src/Pages/WithDrawal/DrawalView/ViewHistory.jsx
+++ b/src/Pages/WithDrawal/DrawalView/ViewHistory.jsx
@@ -133,7 +133,7 @@ const ViewHistory = () => {
"Status",
];
- const extractedArray = filteredData?.map((item, index) => ({
+ const extractedArray = data?.data?.rows?.map((item, index) => ({
// id: item?.id,
"Sr.no": (
({
+ // ======[Get All]=====
+
+ getBankDepositMaster: builder.query({
+ query: ({ size, search, page }) => {
+ let baseURL = `/reversal-transactions/bank-transfer/getAll?search=${search || ""}`
+
+ // Conditionally append page and size parameters if they are defined
+ if (page !== undefined && size !== undefined) {
+ baseURL += `&page=${page}&size=${size}`;
+ }
+
+ return baseURL;
+ },
+ providesTags: ["getBankDeposit"],
+ }),
+
+ approveBankDepositRequest: builder.mutation({
+ query: ({ id, data }) => ({
+ url: `/reversal-transactions/bank-transfer/approve/${id}`,
+ method: "PATCH",
+ body: data,
+ }),
+ invalidatesTags: ["getDepositRequest", "getDepositHistory"],
+ }),
+
+ createBankDepositReversalRequest: builder.mutation({
+ query: ({ id, data }) => ({
+ url: `/reversal-transactions/bank-transfer/create/${id}`,
+ method: "POST",
+ body: data,
+ }),
+ invalidatesTags: ["getDepositRequest", "getDepositHistory"],
+ }),
+
+ rejectbankDepositRequest: builder.mutation({
+ query: ({ id, data }) => ({
+ url: `/reversal-transactions/bank-transfer/reject/${id}`,
+ method: "PATCH",
+ body: data,
+ }),
+ invalidatesTags: ["getDepositRequest", "getDepositHistory"],
+ }),
+ }),
+});
+
+export const {
+ useGetBankDepositMasterQuery,
+ useApproveBankDepositRequestMutation,
+ useRejectbankDepositRequestMutation,
+ useCreateBankDepositReversalRequestMutation,
+} = bankDepositRequestMaster;
diff --git a/src/Services/dashboard.service.js b/src/Services/dashboard.service.js
new file mode 100644
index 0000000..fa1c88f
--- /dev/null
+++ b/src/Services/dashboard.service.js
@@ -0,0 +1,20 @@
+// Need to use the React-specific entry point to import createApi
+import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
+import { baseQuery } from "./token.serivce";
+
+// Define a service using a base URL and expected endpoints
+export const dashboardMaster = createApi({
+ reducerPath: "Dashboard",
+ baseQuery: baseQuery,
+ tagTypes: ["getDashboard"],
+ endpoints: (builder) => ({
+ // ======[Get All]=====
+
+ getDashboardMaster: builder.query({
+ query: () => `/dashboard/admin/`,
+ providesTags: ["getDashboard"],
+ }),
+ }),
+});
+
+export const { useGetDashboardMasterQuery } = dashboardMaster;
diff --git a/src/Services/deposit.request.service.js b/src/Services/deposit.request.service.js
index 1a8ccd2..29cc421 100644
--- a/src/Services/deposit.request.service.js
+++ b/src/Services/deposit.request.service.js
@@ -88,7 +88,7 @@ export const depositRequest = createApi({
// Export hooks for usage in functional components
export const {
useGetDepositRequestQuery,
- useGetDepositRequestByIdQuery,
+ useGetDepositRequestByIdQuery,
useUpdateDepositRequestMutation,
useDepositRejectMutation,
useGetDepositHistoryQuery,
diff --git a/src/Services/fawateer.request.service.js b/src/Services/fawateer.request.service.js
index 1a5e90a..35d8857 100644
--- a/src/Services/fawateer.request.service.js
+++ b/src/Services/fawateer.request.service.js
@@ -9,7 +9,7 @@ import { baseQuery } from "./token.serivce";
export const fawateerRequest = createApi({
reducerPath: "fawateerRequest",
baseQuery: baseQuery,
- tagTypes: ["getFawateerRequest" ,"getApproveHistory","getApproveComment","getRejectComment","getFawateerMakerRequest"],
+ tagTypes: ["getFawateerRequest", "getApproveHistory", "getApproveComment", "getRejectComment", "getFawateerMakerRequest"],
endpoints: (builder) => ({
@@ -37,7 +37,7 @@ export const fawateerRequest = createApi({
}),
-
+
getFawateerForMakerRequest: builder.query({
query: ({ page, size, searchTerm }) => {
@@ -50,8 +50,19 @@ export const fawateerRequest = createApi({
providesTags: ["getFawateerMakerRequest"],
}),
+ // getApproveHistory: builder.query({
+ // query: () => `/fawateer/admin/getAll`,
+ // providesTags: ["getApproveHistory"],
+ // }),
+
getApproveHistory: builder.query({
- query: () => `/fawateer/admin/getAll`,
+ query: ({ page, size, searchTerm }) => {
+ let baseURL = `/fawateer/admin/getAll?search=${searchTerm || ""}`;
+ if (page !== undefined && size !== undefined) {
+ baseURL += `&page=${page}&size=${size}`; // Only add pagination if both are defined
+ }
+ return baseURL;
+ },
providesTags: ["getApproveHistory"],
}),
@@ -72,16 +83,16 @@ export const fawateerRequest = createApi({
}),
invalidatesTags: ["getFawateerRequest"],
}),
-
+
}),
});
// Export hooks for usage in functional components
export const {
- useGetFawateerRequestQuery,
- useGetApproveHistoryQuery,
- useApproveCommentMutation,
- useRejectCommentMutation,
- useGetFawateerForMakerRequestQuery,
- useGetFawateerInvestorsQuery
+ useGetFawateerRequestQuery,
+ useGetApproveHistoryQuery,
+ useApproveCommentMutation,
+ useRejectCommentMutation,
+ useGetFawateerForMakerRequestQuery,
+ useGetFawateerInvestorsQuery
} = fawateerRequest;
diff --git a/src/Services/reversal.account.deletion.service.js b/src/Services/reversal.account.deletion.service.js
new file mode 100644
index 0000000..7b4be45
--- /dev/null
+++ b/src/Services/reversal.account.deletion.service.js
@@ -0,0 +1,61 @@
+// Need to use the React-specific entry point to import createApi
+import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
+import { baseQuery } from "./token.serivce";
+
+// Define a service using a base URL and expected endpoints
+export const reversalAccountDeletionMaster = createApi({
+ reducerPath: "accountDeletion",
+ baseQuery: baseQuery,
+ tagTypes: ["getAccountDeletion", "getHistory"],
+ endpoints: (builder) => ({
+ // ======[Get All]=====
+
+ getAccountDeletionMaster: builder.query({
+ query: ({ page, size, search, }) => {
+ let baseURL = `/reversal-transactions/account-deletion/getAll?search=${search || ""}`
+
+ // Conditionally append page and size parameters if they are defined
+ if (page !== undefined && size !== undefined) {
+ baseURL += `&page=${page}&size=${size}`;
+ }
+
+ return baseURL;
+ },
+ providesTags: ["getAccountDeletion"],
+ }),
+
+ approveAccountDeletionRequest: builder.mutation({
+ query: ({ id, data }) => ({
+ url: `/reversal-transactions/account-deletion/approve/${id}`,
+ method: "PATCH",
+ body: data,
+ }),
+ invalidatesTags: ["getAccountDeletion", "getHistory"],
+ }),
+
+ createAccountDeletionReversalRequest: builder.mutation({
+ query: ({ id, data }) => ({
+ url: `/reversal-transactions/account-deletion/create/${id}`,
+ method: "POST",
+ body: data,
+ }),
+ invalidatesTags: ["getAccountDeletion", "getHistory"],
+ }),
+
+ rejectAccountDeletionRequest: builder.mutation({
+ query: ({ id, data }) => ({
+ url: `/reversal-transactions/account-deletion/reject/${id}`,
+ method: "PATCH",
+ body: data,
+ }),
+ invalidatesTags: ["getAccountDeletion", "getHistory"],
+ }),
+ }),
+});
+
+export const {
+ useGetAccountDeletionMasterQuery,
+ useCreateAccountDeletionReversalRequestMutation,
+ useApproveAccountDeletionRequestMutation,
+ useRejectAccountDeletionRequestMutation
+} = reversalAccountDeletionMaster;
diff --git a/src/Services/reversal.fawateer.deposit.service.js b/src/Services/reversal.fawateer.deposit.service.js
new file mode 100644
index 0000000..891f48b
--- /dev/null
+++ b/src/Services/reversal.fawateer.deposit.service.js
@@ -0,0 +1,60 @@
+// Need to use the React-specific entry point to import createApi
+import { createApi } from "@reduxjs/toolkit/query/react";
+import { baseQuery } from "./token.serivce";
+
+// Define a service using a base URL and expected endpoints
+export const reversalFawateerDepositMaster = createApi({
+ reducerPath: "FawateerDeposit",
+ baseQuery: baseQuery,
+ tagTypes: ["getFawateerDeposit", "getDepositHistory"],
+ endpoints: (builder) => ({
+ // ======[Get All]=====
+
+ getFawateerDepositMaster: builder.query({
+ query: ({ search, page, size }) => {
+ let baseURL = `/reversal-transactions/fawateer/getAll?search=${search || ""}`
+ // Conditionally append page and size parameters if they are defined
+ if (page !== undefined && size !== undefined) {
+ baseURL += `&page=${page}&size=${size}`;
+ }
+
+ return baseURL;
+ },
+ providesTags: ["getFawateerDeposit"],
+ }),
+
+ approveFawateerRequest: builder.mutation({
+ query: ({ id, data }) => ({
+ url: `/reversal-transactions/fawateer/approve/${id}`,
+ method: "PATCH",
+ body: data,
+ }),
+ invalidatesTags: ["getFawateerDeposit", "getDepositHistory"],
+ }),
+
+ createFawateerReversalRequest: builder.mutation({
+ query: ({ id, data }) => ({
+ url: `/reversal-transactions/fawateer/create/${id}`,
+ method: "POST",
+ body: data,
+ }),
+ invalidatesTags: ["getFawateerDeposit", "getDepositHistory"],
+ }),
+
+ rejectFawateerRequest: builder.mutation({
+ query: ({ id, data }) => ({
+ url: `/reversal-transactions/fawateer/reject/${id}`,
+ method: "PATCH",
+ body: data,
+ }),
+ invalidatesTags: ["getFawateerDeposit", "getDepositHistory"],
+ }),
+ }),
+});
+
+export const {
+ useGetFawateerDepositMasterQuery,
+ useApproveFawateerRequestMutation,
+ useCreateFawateerReversalRequestMutation,
+ useRejectFawateerRequestMutation,
+} = reversalFawateerDepositMaster;
diff --git a/src/Store/Store.js b/src/Store/Store.js
index 8d1bc65..c6c2a58 100644
--- a/src/Store/Store.js
+++ b/src/Store/Store.js
@@ -20,6 +20,10 @@ import { fawateerMaker } from "../Services/fawateer.maker.service";
import { sabAdminMaster } from "../Services/subadmin.service";
import { changePasswordMake } from "../Services/change.password.service";
import { forgetPasswordMake } from "../Services/forget.password.service";
+import { dashboardMaster } from "../Services/dashboard.service";
+import { bankDepositRequestMaster } from "../Services/bankdeposit.request.service";
+import { reversalFawateerDepositMaster } from "../Services/reversal.fawateer.deposit.service";
+import { reversalAccountDeletionMaster } from "../Services/reversal.account.deletion.service";
export const store = configureStore({
reducer: {
@@ -41,6 +45,10 @@ export const store = configureStore({
[sabAdminMaster.reducerPath]: sabAdminMaster.reducer,
[changePasswordMake.reducerPath]: changePasswordMake.reducer,
[forgetPasswordMake.reducerPath]: forgetPasswordMake.reducer,
+ [dashboardMaster.reducerPath]: dashboardMaster.reducer,
+ [bankDepositRequestMaster.reducerPath]: bankDepositRequestMaster.reducer,
+ [reversalFawateerDepositMaster.reducerPath]: reversalFawateerDepositMaster.reducer,
+ [reversalAccountDeletionMaster.reducerPath]: reversalAccountDeletionMaster.reducer,
// Add other reducers as needed
},
@@ -68,6 +76,10 @@ export const store = configureStore({
sabAdminMaster.middleware,
changePasswordMake.middleware,
forgetPasswordMake.middleware,
+ dashboardMaster.middleware,
+ bankDepositRequestMaster.middleware,
+ reversalFawateerDepositMaster.middleware,
+ reversalAccountDeletionMaster.middleware,
),
});