Compare commits
1 Commits
bug-fix/9.
...
release/sp
| Author | SHA1 | Date | |
|---|---|---|---|
| 188c77c1e1 |
28
.env.example
28
.env.example
@@ -1,28 +0,0 @@
|
||||
# Default Value Maker
|
||||
VITE_MAKER="Maker"
|
||||
|
||||
# Default Value Checker
|
||||
VITE_CHECKER="Checker"
|
||||
|
||||
# Role Encryption key
|
||||
VITE_ROLE_ENCRYPTION_KEY="export"
|
||||
|
||||
# Super Admin
|
||||
VITE_SUPER_ADMIN_ID=1
|
||||
|
||||
# BaseURL
|
||||
VITE_BAS_URL="your_base_url"
|
||||
|
||||
# BaseURL for Images
|
||||
VITE_IMAGE_URL="your_base_url"
|
||||
|
||||
# Max try re-genrate token
|
||||
VITE_MAX_TRY_REGENRATE_TOKEN=3
|
||||
|
||||
VITE_STATUS_DRAFT="Draft"
|
||||
VITE_STATUS_PROCESSING="Processing"
|
||||
VITE_STATUS_OPEN="Open"
|
||||
VITE_STATUS_CLOSED="Closed"
|
||||
VITE_STATUS_EXITED="Exited"
|
||||
VITE_STATUS_CANCELLED="Cancelled"
|
||||
VITE_STATUS_DEACTIVATE="DeActivate"
|
||||
117
README.md
117
README.md
@@ -1,113 +1,10 @@
|
||||
# **Tanami Capital**
|
||||
# React + Vite
|
||||
|
||||
**Tanami** is a cutting-edge fintech platform designed to streamline investment opportunities for users in the Gulf region. It features two main components:
|
||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||
|
||||
- **Admin Panel:** A web-based dashboard for managing users, monitoring transactions, and overseeing investments efficiently.
|
||||
- **Mobile Application:** A user-friendly app that empowers individuals to invest in diverse asset classes, including real estate, private equity, and other financial instruments located in Gulf countries.
|
||||
|
||||
---
|
||||
|
||||
## **Key Features**
|
||||
- **Regional Focus:** Exclusively operational in Gulf countries, offering investment opportunities tailored to the region.
|
||||
- **Diverse Investment Options:** Enables users to invest in financial instruments like real estate and private equity with ease and transparency.
|
||||
- **Comprehensive Admin Tools:** The admin panel offers robust tools for tracking and managing platform activity.
|
||||
|
||||
---
|
||||
|
||||
## **Current Status**
|
||||
The project is **live and operational**, catering specifically to the investment needs of users in the Gulf region.
|
||||
|
||||
---
|
||||
|
||||
## **Table of Contents**
|
||||
- [Installation](#installation)
|
||||
- [Usage](#usage)
|
||||
- [Environment Variables](#environment-variables)
|
||||
- [Scripts](#scripts)
|
||||
- [License](#license)
|
||||
|
||||
---
|
||||
|
||||
## **Installation**
|
||||
|
||||
### **Prerequisites**
|
||||
- [Node.js](https://nodejs.org/) (version 14 or higher recommended)
|
||||
- [npm](https://www.npmjs.com/) (bundled with Node.js)
|
||||
|
||||
### **Steps**
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone http://git.wdipl.com/Siddhesh.More/tanami-admin-panel.git
|
||||
```
|
||||
2. Navigate to the project directory:
|
||||
```bash
|
||||
cd tanami-admin-panel
|
||||
```
|
||||
3. Install dependencies:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## **Usage**
|
||||
|
||||
### **Development Mode**
|
||||
1. Start the development server:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
2. Open your browser and navigate to:
|
||||
```
|
||||
http://localhost:5173/
|
||||
```
|
||||
|
||||
### **Production Mode**
|
||||
1. Install [PM2](https://pm2.keymetrics.io/) globally for process management:
|
||||
```bash
|
||||
npm install pm2 -g
|
||||
```
|
||||
|
||||
2. Build the application (if applicable):
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
3. Serve the application using PM2:
|
||||
```bash
|
||||
pm2 serve ./dist <port_number> --spa --name=<application_name>
|
||||
```
|
||||
Replace:
|
||||
- `./dist` with your build directory.
|
||||
- `<port_number>` with the desired port (e.g., `3000`).
|
||||
- `<application_name>` with the name of your application.
|
||||
|
||||
4. Save the PM2 process list and enable startup on system reboot:
|
||||
```bash
|
||||
pm2 save
|
||||
pm2 startup
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## **Environment Variables**
|
||||
|
||||
Create a `.env` file in the root directory based on the structure of [`.env.example`](.env.example).
|
||||
|
||||
---
|
||||
|
||||
## **Scripts**
|
||||
|
||||
| Script | Description |
|
||||
|---------------------|-------------------------------------------------------------|
|
||||
| `npm run dev` | Starts the app in development mode with `Vite` server. |
|
||||
| `npm run build` | Builds the app for production. |
|
||||
| `npm run lint` | Runs ESLint to check for code quality issues. |
|
||||
| `npm run preview` | Previews the production build locally. |
|
||||
|
||||
---
|
||||
|
||||
## **License**
|
||||
|
||||
This project is licensed under the [MIT License](LICENSE).
|
||||
Currently, two official plugins are available:
|
||||
|
||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
||||
# rubix-admin-panel
|
||||
# tanami-admin-panel
|
||||
|
||||
@@ -63,8 +63,8 @@ const App = () => {
|
||||
path="/*"
|
||||
element={
|
||||
// isOnline ? (
|
||||
isAuthenticate || isAuthenticatedInCookie === "true" ? (
|
||||
// localStorage.getItem('accessToken') && localStorage.getItem('refreshToken') ? (
|
||||
// isAuthenticate || isAuthenticatedInCookie === "true" ? (
|
||||
localStorage.getItem('accessToken') && localStorage.getItem('refreshToken') ? (
|
||||
// true ? (
|
||||
<DefaultLayout isOnline={isOnline} />
|
||||
) : (
|
||||
|
||||
@@ -31,7 +31,6 @@ import Header from "../Header";
|
||||
import ToastBox from "../ToastBox";
|
||||
import BannerMainCard from "./BannerMainCard";
|
||||
|
||||
|
||||
const AddBanner = ({ createApi, navigateLink, title, center }) => {
|
||||
const toast = useToast();
|
||||
const navigate = useNavigate();
|
||||
|
||||
@@ -13,9 +13,8 @@ import {
|
||||
Portal,
|
||||
Text,
|
||||
useColorMode,
|
||||
useDisclosure,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useContext, useRef } from "react";
|
||||
import React, { useContext } from "react";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { IoMdDownload } from "react-icons/io";
|
||||
import * as XLSX from "xlsx";
|
||||
@@ -24,7 +23,6 @@ import GlobalStateContext from "../Contexts/GlobalStateContext";
|
||||
import { MdOutlineDarkMode, MdOutlineLightMode } from "react-icons/md";
|
||||
import logoMini from "../assets/propic.png";
|
||||
import { BsBack } from "react-icons/bs";
|
||||
import ChangePassword from "../Pages/ChangePassword";
|
||||
|
||||
const HeaderMain = ({
|
||||
link,
|
||||
@@ -37,8 +35,6 @@ const HeaderMain = ({
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const { colorMode, toggleColorMode } = useContext(GlobalStateContext);
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const firstField = useRef();
|
||||
|
||||
return (
|
||||
<Box
|
||||
@@ -70,11 +66,11 @@ const HeaderMain = ({
|
||||
<PopoverBody onClick={()=> navigate('/profile')} className="web-text-medium pointer link">
|
||||
Profile
|
||||
</PopoverBody>
|
||||
<Box onClick={onOpen}>
|
||||
<Link to={"/help-and-support"}>
|
||||
<PopoverBody className="web-text-medium pointer ">
|
||||
Change Password
|
||||
Help & Support
|
||||
</PopoverBody>
|
||||
</Box>
|
||||
</Link>
|
||||
<PopoverFooter
|
||||
onClick={logOutHandler}
|
||||
className="web-text-medium pointer link"
|
||||
@@ -116,11 +112,6 @@ const HeaderMain = ({
|
||||
{/* <Box onClick={() => toggleColorMode()} as="span" p={2} rounded={'lg'} className="link pointer">
|
||||
{colorMode === "light"? <MdOutlineDarkMode /> :<MdOutlineLightMode />}
|
||||
</Box> */}
|
||||
<ChangePassword
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
firstField={firstField}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { Box, Spinner, Text } from "@chakra-ui/react";
|
||||
import React from "react";
|
||||
import "./FullscreenLoaders.css";
|
||||
import './FullscreenLoaders.css'
|
||||
|
||||
const FullscreenLoaders = ({ height }) => {
|
||||
const FullscreenLoaders = ({height}) => {
|
||||
return (
|
||||
<Box
|
||||
display={"flex"}
|
||||
justifyContent={"center"}
|
||||
flexDirection={"column"}
|
||||
flexDirection={'column'}
|
||||
alignItems={"center"}
|
||||
w={"100%"}
|
||||
h={height ? height : "100vh"}
|
||||
h={height ? height: "100vh"}
|
||||
gap={4}
|
||||
>
|
||||
{/* <div className="dot-spinner">
|
||||
@@ -23,16 +23,8 @@ const FullscreenLoaders = ({ height }) => {
|
||||
<div className="dot-spinner__dot"></div>
|
||||
<div className="dot-spinner__dot"></div>
|
||||
</div> */}
|
||||
{/* <Text color='#004717' fontSize={'md'} fontWeight={500}>Loading...</Text> */}
|
||||
{/* <div className="spinner-grow" style={{backgroundColor:"#004118"}} role="status" /> */}
|
||||
|
||||
<Spinner
|
||||
thickness="4px"
|
||||
speed="0.65s"
|
||||
emptyColor="#fff"
|
||||
color="#004118"
|
||||
size="lg"
|
||||
/>
|
||||
{/* <Text color='#004717' fontSize={'md'} fontWeight={500}>Loading...</Text> */}
|
||||
<Spinner />
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -4,16 +4,6 @@ import { Spinner } from "@chakra-ui/react";
|
||||
|
||||
const Loader01 = () => {
|
||||
return (
|
||||
// <div className="dot-spinner">
|
||||
// <div className="dot-spinner__dot"></div>
|
||||
// <div className="dot-spinner__dot"></div>
|
||||
// <div className="dot-spinner__dot"></div>
|
||||
// <div className="dot-spinner__dot"></div>
|
||||
// <div className="dot-spinner__dot"></div>
|
||||
// <div className="dot-spinner__dot"></div>
|
||||
// <div className="dot-spinner__dot"></div>
|
||||
// <div className="dot-spinner__dot"></div>
|
||||
// </div>
|
||||
|
||||
// <div className="dot-spinner">
|
||||
// <div className="dot-spinner__dot"></div>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ChevronLeftIcon, ChevronRightIcon } from "@chakra-ui/icons";
|
||||
const Pagination = ({
|
||||
pageSize,
|
||||
setPageSize,
|
||||
totalItems = 1,
|
||||
totalItems,
|
||||
isLoading,
|
||||
setCurrentPage,
|
||||
currentPage,
|
||||
@@ -49,7 +49,7 @@ const Pagination = ({
|
||||
value={pageSize}
|
||||
onChange={handlePageSizeChange}
|
||||
>
|
||||
{[15, 20, 30, 500]?.map((size) => (
|
||||
{[15, 20, 30]?.map((size) => (
|
||||
<option key={size} value={size}>
|
||||
{size}
|
||||
</option>
|
||||
@@ -84,7 +84,7 @@ const Pagination = ({
|
||||
onClick={paginationNext}
|
||||
className="link pointer"
|
||||
isDisabled={currentPage === totalPages}
|
||||
aria-label="Next Page"
|
||||
aria-label="Next Page"
|
||||
/>
|
||||
</HStack>
|
||||
</HStack>
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
import { Box, Text } from "@chakra-ui/react";
|
||||
import React from "react";
|
||||
|
||||
const RoleSwitchButton = ({ isSwitchOn, setIsSwitchOn }) => {
|
||||
|
||||
// const [isSwitchOn, setIsSwitchOn] = useState(false);
|
||||
|
||||
// const audio = useRef();
|
||||
|
||||
const switchOnChangeHandle = () => {
|
||||
setIsSwitchOn(!isSwitchOn);
|
||||
// if (audio.current) {
|
||||
// audio.current.play();
|
||||
// }
|
||||
};
|
||||
|
||||
return (
|
||||
<Box display="flex" alignItems="center">
|
||||
<Box
|
||||
as="button"
|
||||
display="flex"
|
||||
justifyContent="normal"
|
||||
alignItems="center"
|
||||
// justifyContent={isSwitchOn ? "flex-end" : "flex-start"}
|
||||
width="85px"
|
||||
height="24px"
|
||||
borderRadius="20px"
|
||||
backgroundColor={isSwitchOn ? "#00ffcc" : "#b3ff99"}
|
||||
onClick={switchOnChangeHandle}
|
||||
position="relative"
|
||||
fontSize="12px"
|
||||
fontWeight="100"
|
||||
transition="background-color 0.2s"
|
||||
_before={{
|
||||
content: '""',
|
||||
position: "absolute",
|
||||
width: "20px",
|
||||
height: "20px",
|
||||
borderRadius: "50%",
|
||||
backgroundColor: "#fff",
|
||||
boxShadow: "0 2px 4px rgba(0, 0, 0, 0.2)",
|
||||
transform: isSwitchOn ? "translateX(61px)" : "translateX(0)",
|
||||
transition: "transform 0.2s",
|
||||
left:'2px',
|
||||
top:'2px'
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
fontWeight="500"
|
||||
zIndex={1}
|
||||
position="absolute"
|
||||
mb={0}
|
||||
color={isSwitchOn ? "#000" : "#000"}
|
||||
left={isSwitchOn ? "10px" : "auto"}
|
||||
right={isSwitchOn ? "auto" : "10px"}
|
||||
>
|
||||
{isSwitchOn ? "Maker" : "Checker"}
|
||||
</Text>
|
||||
</Box>
|
||||
{/* <audio ref={audio} src={audioClick} /> */}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default RoleSwitchButton;
|
||||
@@ -1,9 +1,9 @@
|
||||
|
||||
import dns from "node:dns"
|
||||
import * as XLSX from 'xlsx';
|
||||
import CryptoJS from "crypto-js";
|
||||
|
||||
|
||||
export const generateSerialNumber = (index, currentPage = 1, pageSize = 1) => {
|
||||
export const generateSerialNumber = (index, currentPage, pageSize) => {
|
||||
return (currentPage - 1) * pageSize + (index + 1);
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ export function getTomorrowDate() {
|
||||
const today = new Date();
|
||||
const tomorrow = new Date(today);
|
||||
tomorrow.setDate(today.getDate() + 1);
|
||||
|
||||
|
||||
// Format the date as YYYY-MM-DD (ISO 8601)
|
||||
return tomorrow.toISOString().split('T')[0];
|
||||
}
|
||||
@@ -33,7 +33,7 @@ export function removeTrailingZeros(value) {
|
||||
}
|
||||
|
||||
|
||||
export function getCountdownTimer(utcDateString) {
|
||||
export function getCountdownTimer(utcDateString) {
|
||||
// Parse the UTC datetime string into a Date object
|
||||
const targetDate = new Date(utcDateString);
|
||||
const now = new Date();
|
||||
@@ -56,7 +56,7 @@ export function getCountdownTimer(utcDateString) {
|
||||
const remainingMinutes = minutes % 60;
|
||||
const remainingSeconds = seconds % 60;
|
||||
|
||||
return `${remainingDays === 0 ? "" : remainingDays + "d"} ${remainingHours === 0 ? "" : remainingHours + "h"} ${remainingMinutes}m ${remainingSeconds}s `;
|
||||
return `${remainingDays === 0 ? "": remainingDays+"d"} ${remainingHours === 0 ? "": remainingHours+"h"} ${remainingMinutes}m ${remainingSeconds}s `;
|
||||
}
|
||||
|
||||
|
||||
@@ -94,33 +94,30 @@ export function debounce(func, delay) {
|
||||
|
||||
|
||||
|
||||
async function resolveMx(domain) {
|
||||
async function resolveMx(domain, recordType) {
|
||||
return new Promise((resolve, reject) => {
|
||||
dns.resolveMx(domain, (err, mxRecords) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
const addresses = mxRecords.map((mxRecord) => mxRecord.exchange);
|
||||
resolve(addresses);
|
||||
});
|
||||
dns.resolveMx(domain, (err, mxRecords) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
const addresses = mxRecords.map((mxRecord) => mxRecord.exchange);
|
||||
resolve(addresses);
|
||||
});
|
||||
});
|
||||
}
|
||||
// Async function to check email address validity
|
||||
export async function checkEmailValidity(email) {
|
||||
try {
|
||||
const domain = email?.split('@')[1];
|
||||
const addresses = await resolveMx(domain, 'MX');
|
||||
console.log(addresses);
|
||||
const domain = email?.split("@")[1];
|
||||
const addresses = await resolveMx(domain, "MX");
|
||||
|
||||
if (addresses && addresses?.length > 0) {
|
||||
return true;
|
||||
}
|
||||
return false; // No MX record exists
|
||||
if (addresses && addresses?.length > 0) {
|
||||
return true;
|
||||
}
|
||||
return false; // No MX record exists
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
|
||||
return false; // Error occurred
|
||||
return false; // Error occurred
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,15 +125,15 @@ export async function checkEmailValidity(email) {
|
||||
// Function to convert timestamp to readable date format in Gulf timezone
|
||||
export function formatTimestampInGulfTimezone(timestamp) {
|
||||
const date = new Date(timestamp);
|
||||
const options = {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
timeZone: 'Asia/Dubai', // Gulf Standard Time (GST) timezone
|
||||
timeZoneName: 'short'
|
||||
const options = {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
timeZone: 'Asia/Dubai', // Gulf Standard Time (GST) timezone
|
||||
timeZoneName: 'short'
|
||||
};
|
||||
return date.toLocaleDateString('en-GB', options);
|
||||
}
|
||||
@@ -166,7 +163,7 @@ const getNestedValue = (obj, key) => {
|
||||
export const exportToExcel = (data, headers) => {
|
||||
const flattenedData = data.map((item) => {
|
||||
const newItem = {};
|
||||
|
||||
|
||||
// Loop through customHeaders and get the correct values
|
||||
headers.forEach((header) => {
|
||||
newItem[header.label] = getNestedValue(item, header.key); // Use the helper function
|
||||
@@ -177,7 +174,7 @@ export const exportToExcel = (data, headers) => {
|
||||
|
||||
// Now pass flattenedData to your Excel library to generate the file
|
||||
// Assuming you're using a library like `xlsx` for this part:
|
||||
|
||||
|
||||
const worksheet = XLSX.utils.json_to_sheet(flattenedData);
|
||||
const workbook = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");
|
||||
@@ -221,25 +218,4 @@ export function formatDateToYYYYMMDD(dateString) {
|
||||
|
||||
// Combine the formatted parts
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
|
||||
|
||||
// Encrypt a string
|
||||
export const encryptString = (text) => {
|
||||
const ciphertext = CryptoJS.AES.encrypt(text, import.meta.env.VITE_ROLE_ENCRYPTION_KEY).toString();
|
||||
return ciphertext;
|
||||
};
|
||||
|
||||
// Decrypt a string
|
||||
export const decryptString = (ciphertext) => {
|
||||
const bytes = CryptoJS.AES.decrypt(ciphertext, import.meta.env.VITE_ROLE_ENCRYPTION_KEY);
|
||||
const originalText = bytes.toString(CryptoJS.enc.Utf8);
|
||||
return originalText;
|
||||
};
|
||||
|
||||
export const SUPER_ADMIN_ID = Number(import.meta.env.VITE_SUPER_ADMIN_ID) || 1
|
||||
export const MAKER_ID = import.meta.env.VITE_MAKER_ID || 1
|
||||
export const CHECKER_ID = import.meta.env.VITE_CHECKER_ID || 2
|
||||
|
||||
export const isMaker = (role = decryptString(localStorage?.getItem("role"))) => role === import.meta.env.VITE_MAKER;
|
||||
export const isChecker = (role = decryptString(localStorage?.getItem("role"))) => role === import.meta.env.VITE_CHECKER;
|
||||
}
|
||||
@@ -1,3 +1,2 @@
|
||||
export const TABLE_PAGINATION = { page: 1, size: 20 }
|
||||
export const IMAGE_URI = import.meta.env.VITE_API_IMAGE_URL
|
||||
export const INVESTOR_TABLE_PAGINATION = { page: 1, size: 500 }
|
||||
export const TABLE_PAGINATION = { page: 1, size:20 }
|
||||
export const IMAGE_URI = import.meta.env.VITE_API_IMAGE_URL
|
||||
@@ -1,48 +1,21 @@
|
||||
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";
|
||||
import logo from "../assets/logo2.png";
|
||||
import logoDark from "../assets/logo.png";
|
||||
import logoMini from "../assets/logo-min.png";
|
||||
import logoMiniDark from "../assets/favicon.png";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { loginUser } from "../Redux/Slice/auth";
|
||||
import Button02 from "../Components/Buttons/Button02";
|
||||
import { CgProfile } from "react-icons/cg";
|
||||
|
||||
import {
|
||||
ArrowBackIcon,
|
||||
ArrowLeftIcon,
|
||||
ArrowRightIcon,
|
||||
AtSignIcon,
|
||||
} from "@chakra-ui/icons";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionButton,
|
||||
AccordionIcon,
|
||||
AccordionItem,
|
||||
AccordionPanel,
|
||||
Alert,
|
||||
AlertIcon,
|
||||
Box,
|
||||
Button,
|
||||
Image,
|
||||
Text,
|
||||
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 { LuContact } from "react-icons/lu";
|
||||
import { MdNotificationsNone, MdOutlineAddChart } from "react-icons/md";
|
||||
import {
|
||||
RiBankLine,
|
||||
RiExchangeBoxLine,
|
||||
RiFileUserLine,
|
||||
RiMoneyDollarBoxLine,
|
||||
} from "react-icons/ri";
|
||||
import {
|
||||
TbArrowBadgeLeftFilled,
|
||||
TbListDetails,
|
||||
TbReportMoney,
|
||||
TbTransactionDollar
|
||||
TbTransactionDollar,
|
||||
} from "react-icons/tb";
|
||||
import { VscSymbolClass } from "react-icons/vsc";
|
||||
import { TbArrowBadgeRightFilled } from "react-icons/tb";
|
||||
import { ArrowBackIcon, ArrowLeftIcon, ArrowRightIcon, AtSignIcon } from "@chakra-ui/icons";
|
||||
import {
|
||||
Link,
|
||||
NavLink,
|
||||
@@ -51,21 +24,70 @@ import {
|
||||
useLocation,
|
||||
useNavigate,
|
||||
} from "react-router-dom";
|
||||
import HeaderMain from "../Components/HeaderMain";
|
||||
import GlobalStateContext from "../Contexts/GlobalStateContext";
|
||||
import CreateRequest from "../Pages/Fawateer/CreateRequest";
|
||||
import ApproveHistory from "../Pages/FawateerChecker/ApproveHistory/ApproveHistoryChecker";
|
||||
import ApproveHistoryMaker from "../Pages/FawateerChecker/ApproveHistory/ApproveHistoryMaker";
|
||||
import ApproveRequest from "../Pages/FawateerChecker/ApproveRequest/ApproveRequest";
|
||||
import NotFound from "../Pages/NotFound";
|
||||
import SplashScreen from "../Pages/SplashScreen";
|
||||
import { nav } from "../Routes/Nav";
|
||||
import { RouteLink } from "../Routes/Routes";
|
||||
import { useProfileQuery } from "../Services/io.service";
|
||||
import NotFound from "../Pages/NotFound";
|
||||
import { nav } from "../Routes/Nav";
|
||||
import {
|
||||
Avatar,
|
||||
Box,
|
||||
Button,
|
||||
PopoverArrow,
|
||||
PopoverBody,
|
||||
PopoverCloseButton,
|
||||
PopoverContent,
|
||||
PopoverFooter,
|
||||
PopoverHeader,
|
||||
PopoverTrigger,
|
||||
Portal,
|
||||
Text,
|
||||
WrapItem,
|
||||
Popover,
|
||||
Tag,
|
||||
Accordion,
|
||||
AccordionItem,
|
||||
AccordionButton,
|
||||
AccordionIcon,
|
||||
AccordionPanel,
|
||||
Image,
|
||||
Alert,
|
||||
AlertIcon,
|
||||
Breadcrumb,
|
||||
Divider,
|
||||
Tooltip,
|
||||
useRadio,
|
||||
} from "@chakra-ui/react";
|
||||
import GlobalStateContext from "../Contexts/GlobalStateContext";
|
||||
import Cookies from "js-cookie"; // Import the Cookies library
|
||||
import Header from "../Components/Header";
|
||||
import HeaderMain from "../Components/HeaderMain";
|
||||
import { IoMdSwap } from "react-icons/io";
|
||||
import {
|
||||
RiBankLine,
|
||||
RiExchangeBoxLine,
|
||||
RiFileUserLine,
|
||||
RiMoneyDollarBoxLine,
|
||||
} from "react-icons/ri";
|
||||
import { VscSymbolClass } from "react-icons/vsc";
|
||||
import { MdNotificationsNone, MdOutlineAddChart } from "react-icons/md";
|
||||
import { HiOutlineChartSquareBar } from "react-icons/hi";
|
||||
import { GrManual } from "react-icons/gr";
|
||||
import { LuContact } from "react-icons/lu";
|
||||
import shield from "../assets/shield.png";
|
||||
import SplashScreen from "../Pages/SplashScreen";
|
||||
import CutomBreadcrumb from "../Components/CutomBreadcrumb";
|
||||
import CustomBreadcrumb from "../Components/CutomBreadcrumb";
|
||||
import { getCountdownTimer } from "../Constants/Constants";
|
||||
import { useLogoutMutation } from "../Services/token.serivce";
|
||||
import CreateRequest from "../Pages/Fawateer/CreateRequest";
|
||||
import ApproveRequest from "../Pages/FawateerChecker/ApproveRequest/ApproveRequest";
|
||||
import ApproveHistoryMaker from "../Pages/FawateerChecker/ApproveHistory/ApproveHistoryMaker";
|
||||
import ApproveHistory from "../Pages/FawateerChecker/ApproveHistory/ApproveHistoryChecker";
|
||||
import { useProfileQuery } from "../Services/io.service";
|
||||
|
||||
const DashboardLayout = ({ isOnline }) => {
|
||||
const userRole = localStorage.getItem("role");
|
||||
const navigate = useNavigate();
|
||||
const dispach = useDispatch();
|
||||
const location = useLocation();
|
||||
const path = location.pathname;
|
||||
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
||||
@@ -82,15 +104,15 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
|
||||
const { data, refetch } = useProfileQuery();
|
||||
|
||||
// useEffect(() => {
|
||||
// if (
|
||||
// !localStorage.getItem("accessToken") &&
|
||||
// !localStorage.getItem("refreshToken")
|
||||
// ) {
|
||||
// logOutHandler();
|
||||
// return navigate("/login");
|
||||
// }
|
||||
// }, []);
|
||||
useEffect(() => {
|
||||
if (
|
||||
!localStorage.getItem("accessToken") &&
|
||||
!localStorage.getItem("refreshToken")
|
||||
) {
|
||||
logOutHandler();
|
||||
return navigate("/login");
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const savedIndex = localStorage.getItem("openAccordionIndex");
|
||||
@@ -129,9 +151,7 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
await logout();
|
||||
localStorage.clear();
|
||||
navigate("/login");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
// // Function to get the title based on the route
|
||||
@@ -145,24 +165,24 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
<RiMoneyDollarBoxLine className="h4 m-0" /> Sponsor
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/email"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<AtSignIcon className="h4 m-0" /> Email Notifiation
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/email"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<AtSignIcon className="h4 m-0" /> Email Notifiation
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/investment-type"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<VscSymbolClass className="h4 m-0" /> Investment Type
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/profile"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<CgProfile className="h4 m-0" /> Profile
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/profile"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<CgProfile className="h4 m-0" /> Profile
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/exchange-rate"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
@@ -221,7 +241,7 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
Deposite Request
|
||||
</span>
|
||||
);
|
||||
|
||||
|
||||
case path.startsWith("/fawateer"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
@@ -229,13 +249,13 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
Fawateer Deposit
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/fawateer-history"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
|
||||
Fawateer Deposit
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/fawateer-history"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
|
||||
Fawateer Deposit
|
||||
</span>
|
||||
);
|
||||
|
||||
case path.startsWith("/withdraw-request"):
|
||||
return (
|
||||
@@ -349,13 +369,6 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
Deletion request
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/subadmin"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
|
||||
Manage SubAdmin
|
||||
</span>
|
||||
);
|
||||
|
||||
default:
|
||||
if (path.startsWith("/community/view/")) {
|
||||
@@ -385,19 +398,6 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
return <SplashScreen />;
|
||||
}
|
||||
|
||||
const filteredNav = nav.map((item) => {
|
||||
if (item.submenu) {
|
||||
return {
|
||||
...item,
|
||||
submenu: item.submenu.filter(
|
||||
(submenuItem) =>
|
||||
!(!data?.data?.superAdmin && submenuItem.title === "Sub Admin")
|
||||
),
|
||||
};
|
||||
}
|
||||
return item;
|
||||
});
|
||||
|
||||
return (
|
||||
<Box
|
||||
style={{
|
||||
@@ -515,7 +515,7 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
index={openIndex}
|
||||
onChange={handleAccordionChange}
|
||||
>
|
||||
{filteredNav.map(({ title, type, Icon, submenu, path }, index) => {
|
||||
{nav.map(({ title, type, Icon, submenu, path }, index) => {
|
||||
if (type === "accordion") {
|
||||
return (
|
||||
<AccordionItem key={index} border={"none"}>
|
||||
@@ -788,7 +788,6 @@ const AppContent = ({ data }) => {
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
||||
<Route path="*" element={<NotFound />} />
|
||||
</Routes>
|
||||
);
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
import {
|
||||
Avatar,
|
||||
Badge,
|
||||
Box,
|
||||
HStack,
|
||||
Input,
|
||||
Select,
|
||||
Switch,
|
||||
Text,
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useContext, useEffect, useRef, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import CustomAlertDialog from "../../../../Components/CustomAlertDialog";
|
||||
import NormalTable from "../../../../Components/DataTable/NormalTable";
|
||||
import ToastBox from "../../../../Components/ToastBox";
|
||||
import { TABLE_PAGINATION } from "../../../../Constants/Paginations";
|
||||
import React, { useContext, useEffect, useState, useRef } from "react";
|
||||
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
|
||||
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
|
||||
import { OPACITY_ON_LOAD } from "../../../../Layout/animations";
|
||||
import { useGetbanInvestorQuery } from "../../../../Services/ban.investor.service";
|
||||
import { debounce } from "../../../Master/Sponser/AddSponser";
|
||||
import ReasonBanModal from "./ReasonBanModal";
|
||||
import { OPACITY_ON_LOAD } from "../../../../Layout/animations";
|
||||
import NormalTable from "../../../../Components/DataTable/NormalTable";
|
||||
import CustomAlertDialog from "../../../../Components/CustomAlertDialog";
|
||||
import Pagination from "../../../../Components/Pagination";
|
||||
import ToastBox from "../../../../Components/ToastBox";
|
||||
import ReasonBanModal from "./ReasonBanModal";
|
||||
import { useGetbanInvestorQuery } from "../../../../Services/ban.investor.service";
|
||||
import { TABLE_PAGINATION } from "../../../../Constants/Paginations";
|
||||
|
||||
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
||||
|
||||
@@ -231,6 +233,8 @@ const BankInvestor = () => {
|
||||
),
|
||||
}));
|
||||
|
||||
console.log(extractedArray);
|
||||
|
||||
const handleDelete = () => {
|
||||
const updatedInvestorDetails = InvestorDetails.filter(
|
||||
(sponsor) => sponsor.id !== actionId
|
||||
@@ -274,14 +278,6 @@ const BankInvestor = () => {
|
||||
/>
|
||||
|
||||
<HStack display={"flex"} alignItems={"center"}>
|
||||
<Pagination
|
||||
isLoading={unbanLoading}
|
||||
pageSize={pageSize}
|
||||
setPageSize={setPageSize}
|
||||
currentPage={currentPage}
|
||||
setCurrentPage={setCurrentPage}
|
||||
totalItems={data?.data?.totalItems}
|
||||
/>
|
||||
{/* <Select
|
||||
focusBorderColor="green.500"
|
||||
size={"sm"}
|
||||
|
||||
@@ -1,26 +1,31 @@
|
||||
import {
|
||||
Avatar,
|
||||
Badge,
|
||||
Box,
|
||||
HStack,
|
||||
Input,
|
||||
Select,
|
||||
Switch,
|
||||
Text,
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useContext, useEffect, useRef, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import CustomAlertDialog from "../../../../Components/CustomAlertDialog";
|
||||
import React, { useContext, useEffect, useState, useRef } from "react";
|
||||
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
|
||||
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
|
||||
import { debounce } from "../../../Master/Sponser/AddSponser";
|
||||
import { OPACITY_ON_LOAD } from "../../../../Layout/animations";
|
||||
import DataTable from "../../../../Components/DataTable/NormalTable";
|
||||
import CustomAlertDialog from "../../../../Components/CustomAlertDialog";
|
||||
import Pagination from "../../../../Components/Pagination";
|
||||
import ToastBox from "../../../../Components/ToastBox";
|
||||
import ReasonBanModal from "./ReasonBanModal";
|
||||
import {
|
||||
useGetInvestorQuery,
|
||||
useGetUnbanInvestorQuery,
|
||||
} from "../../../../Services/ban.investor.service";
|
||||
import { generateSerialNumber } from "../../../../Constants/Constants";
|
||||
import { TABLE_PAGINATION } from "../../../../Constants/Paginations";
|
||||
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
|
||||
import { OPACITY_ON_LOAD } from "../../../../Layout/animations";
|
||||
import { useGetUnbanInvestorQuery } from "../../../../Services/ban.investor.service";
|
||||
import { debounce } from "../../../Master/Sponser/AddSponser";
|
||||
import ReasonBanModal from "./ReasonBanModal";
|
||||
import Pagination from "../../../../Components/Pagination";
|
||||
|
||||
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
||||
|
||||
@@ -265,14 +270,6 @@ const UnbanInvestor = () => {
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
/>
|
||||
<HStack display={"flex"} alignItems={"center"}>
|
||||
<Pagination
|
||||
isLoading={unbanLoading}
|
||||
pageSize={pageSize}
|
||||
setPageSize={setPageSize}
|
||||
currentPage={currentPage}
|
||||
setCurrentPage={setCurrentPage}
|
||||
totalItems={data?.data?.totalItems}
|
||||
/>
|
||||
{/* <Select
|
||||
focusBorderColor="green.500"
|
||||
size={"sm"}
|
||||
|
||||
@@ -1,245 +0,0 @@
|
||||
import {
|
||||
Button,
|
||||
DrawerFooter,
|
||||
FormControl,
|
||||
FormErrorMessage,
|
||||
FormLabel,
|
||||
Input,
|
||||
InputGroup,
|
||||
InputRightElement,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Stack,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import React, { useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import * as yup from "yup";
|
||||
import CustomAlertDialog from "../Components/CustomAlertDialog";
|
||||
import ToastBox from "../Components/ToastBox";
|
||||
import { useUpdatePasswordMutation } from "../Services/change.password.service";
|
||||
|
||||
// Validation schema
|
||||
const passwordSchema = yup.object().shape({
|
||||
oldPassword: yup.string().required("Current Password is required"),
|
||||
newPassword: yup
|
||||
.string()
|
||||
.required("New Password is required")
|
||||
.min(8, "Password must be at least 8 characters long")
|
||||
.max(16, "Password must be at most 50 characters long")
|
||||
.matches(/[A-Z]/, "Password must contain at least one uppercase letter")
|
||||
.matches(/[a-z]/, "Password must contain at least one lowercase letter")
|
||||
.matches(/[0-9]/, "Password must contain at least one number")
|
||||
.matches(
|
||||
/[@$!%*?&#]/,
|
||||
"Password must contain at least one special character"
|
||||
),
|
||||
confirmNewPassword: yup
|
||||
.string()
|
||||
.required("Confirm New Password is required")
|
||||
.oneOf([yup.ref("newPassword")], "Password do not match"),
|
||||
});
|
||||
|
||||
const ChangePassword = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
firstField,
|
||||
actionId,
|
||||
setActionId,
|
||||
}) => {
|
||||
const initialValue = {
|
||||
oldPassword: "",
|
||||
newPassword: "",
|
||||
confirmNewPassword: "",
|
||||
};
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [alert, setAlert] = useState(false);
|
||||
const [showCurrentPassword, setShowCurrentPassword] = useState(false);
|
||||
const [showNewPassword, setShowNewPassword] = useState(false);
|
||||
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
|
||||
const toast = useToast();
|
||||
const [input, setInput] = useState(initialValue);
|
||||
|
||||
const [updatePassword] = useUpdatePasswordMutation();
|
||||
|
||||
// Form handling
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
reset,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: yupResolver(passwordSchema),
|
||||
mode: "all",
|
||||
});
|
||||
|
||||
// Form submit handler
|
||||
const onSubmit = async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const res = await updatePassword(input); // Assuming API request works as expected
|
||||
if (res?.data?.statusCode === 200) {
|
||||
toast({
|
||||
render: () => <ToastBox message={res?.data?.message} />,
|
||||
});
|
||||
handleClose();
|
||||
} else if (res?.error) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||
),
|
||||
});
|
||||
setAlert(false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmitFrom = (data) => {
|
||||
setAlert(true);
|
||||
setInput(data);
|
||||
};
|
||||
|
||||
// Handle modal close
|
||||
const handleClose = () => {
|
||||
setAlert(false);
|
||||
onClose();
|
||||
reset();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal isOpen={isOpen} onClose={handleClose} initialFocusRef={firstField}>
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader fontSize="md">Change Password</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody pb={6}>
|
||||
<Stack spacing={4}>
|
||||
{/* Current Password */}
|
||||
<FormControl isInvalid={errors.oldPassword} isRequired>
|
||||
<FormLabel fontSize="sm" mb={1} fontWeight={500}>
|
||||
Current Password
|
||||
</FormLabel>
|
||||
<InputGroup size="sm">
|
||||
<Input
|
||||
{...register("oldPassword")}
|
||||
fontSize="sm"
|
||||
type={showCurrentPassword ? "text" : "password"}
|
||||
focusBorderColor="forestGreen.300"
|
||||
/>
|
||||
<InputRightElement width="4.5rem">
|
||||
<Button
|
||||
h="1.5rem"
|
||||
size="xs"
|
||||
onClick={() => setShowCurrentPassword((prev) => !prev)}
|
||||
>
|
||||
{showCurrentPassword ? "Hide" : "Show"}
|
||||
</Button>
|
||||
</InputRightElement>
|
||||
</InputGroup>
|
||||
<FormErrorMessage>
|
||||
{errors.oldPassword?.message}
|
||||
</FormErrorMessage>
|
||||
</FormControl>
|
||||
|
||||
{/* New Password */}
|
||||
<FormControl isInvalid={errors.newPassword} isRequired>
|
||||
<FormLabel fontSize="sm" mb={1}>
|
||||
New Password
|
||||
</FormLabel>
|
||||
<InputGroup size="sm">
|
||||
<Input
|
||||
{...register("newPassword")}
|
||||
fontSize="sm"
|
||||
type={showNewPassword ? "text" : "password"}
|
||||
focusBorderColor="forestGreen.300"
|
||||
/>
|
||||
<InputRightElement width="4.5rem">
|
||||
<Button
|
||||
h="1.5rem"
|
||||
size="xs"
|
||||
onClick={() => setShowNewPassword((prev) => !prev)}
|
||||
>
|
||||
{showNewPassword ? "Hide" : "Show"}
|
||||
</Button>
|
||||
</InputRightElement>
|
||||
</InputGroup>
|
||||
<FormErrorMessage>
|
||||
{errors.newPassword?.message}
|
||||
</FormErrorMessage>
|
||||
</FormControl>
|
||||
|
||||
{/* Confirm Password */}
|
||||
<FormControl isInvalid={errors.confirmNewPassword} isRequired>
|
||||
<FormLabel fontSize="sm" mb={1}>
|
||||
Confirm New Password
|
||||
</FormLabel>
|
||||
<InputGroup size="sm">
|
||||
<Input
|
||||
{...register("confirmNewPassword")}
|
||||
fontSize="sm"
|
||||
type={showConfirmPassword ? "text" : "password"}
|
||||
focusBorderColor="forestGreen.300"
|
||||
/>
|
||||
<InputRightElement width="4.5rem">
|
||||
<Button
|
||||
h="1.5rem"
|
||||
size="xs"
|
||||
onClick={() => setShowConfirmPassword((prev) => !prev)}
|
||||
>
|
||||
{showConfirmPassword ? "Hide" : "Show"}
|
||||
</Button>
|
||||
</InputRightElement>
|
||||
</InputGroup>
|
||||
<FormErrorMessage>
|
||||
{errors.confirmNewPassword?.message}
|
||||
</FormErrorMessage>
|
||||
</FormControl>
|
||||
</Stack>
|
||||
</ModalBody>
|
||||
|
||||
<DrawerFooter mb={5}>
|
||||
<Button
|
||||
onClick={handleClose}
|
||||
bg="#e0ebeb"
|
||||
size="sm"
|
||||
mr={3}
|
||||
rounded={"sm"}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
colorScheme="forestGreen"
|
||||
size="sm"
|
||||
// onClick={() => setAlert(true)}
|
||||
onClick={handleSubmit(handleSubmitFrom)}
|
||||
isLoading={isLoading}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</DrawerFooter>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
|
||||
<CustomAlertDialog
|
||||
isOpen={alert}
|
||||
onClose={() => setAlert(false)}
|
||||
alertHandler={onSubmit}
|
||||
message={"Are you sure you want to change the password?"}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChangePassword;
|
||||
@@ -1,138 +0,0 @@
|
||||
import {
|
||||
Button,
|
||||
DrawerFooter,
|
||||
FormControl,
|
||||
FormErrorMessage,
|
||||
FormLabel,
|
||||
Input,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Stack,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import * as yup from "yup";
|
||||
import React, { useState } from "react";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import { useForgetPasswordMutation } from "../Services/forget.password.service";
|
||||
import ToastBox from "../Components/ToastBox";
|
||||
|
||||
const validationSchema = yup.object().shape({
|
||||
emailAddress: yup
|
||||
.string()
|
||||
.email("Invalid email format")
|
||||
.required("Email address is required")
|
||||
.min(6, "Email address must be at least 6 characters long")
|
||||
.max(255, "Email address can be at most 255 characters long"),
|
||||
});
|
||||
|
||||
const ForgetPassword = ({ isOpen, onClose, firstField }) => {
|
||||
const toast = useToast();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const [forgetPassword] = useForgetPasswordMutation();
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
reset, // Add reset from useForm
|
||||
} = useForm({
|
||||
resolver: yupResolver(validationSchema),
|
||||
});
|
||||
|
||||
const onSubmit = async (formData) => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const res = await forgetPassword(formData);
|
||||
if (res?.data?.statusCode === 200) {
|
||||
toast({
|
||||
render: () => <ToastBox message={res?.data?.message} />,
|
||||
});
|
||||
handleClose();
|
||||
} else if (res?.error?.status === 400) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={res?.error?.data?.message} status="error" />
|
||||
),
|
||||
});
|
||||
handleClose();
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setIsLoading(false);
|
||||
onClose();
|
||||
reset(); // Reset form state when modal closes
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isCentered
|
||||
isOpen={isOpen}
|
||||
onClose={handleClose}
|
||||
initialFocusRef={firstField}
|
||||
>
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<ModalHeader fontSize="md">Forgot Password</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody pb={4}>
|
||||
<Stack spacing={4}>
|
||||
<FormControl isInvalid={errors.emailAddress} isRequired>
|
||||
<FormLabel fontSize="sm" mb={3} fontWeight={500}>
|
||||
Please Enter Email Address
|
||||
</FormLabel>
|
||||
<Controller
|
||||
name="emailAddress"
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<Input
|
||||
{...field}
|
||||
size="md"
|
||||
fontSize="sm"
|
||||
focusBorderColor="forestGreen.300"
|
||||
rounded={4}
|
||||
type="text"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<FormErrorMessage fontSize="xs" fontWeight={500}>
|
||||
{errors.emailAddress?.message}
|
||||
</FormErrorMessage>
|
||||
</FormControl>
|
||||
</Stack>
|
||||
</ModalBody>
|
||||
|
||||
<DrawerFooter mb={5}>
|
||||
<Button
|
||||
w="100%"
|
||||
colorScheme="forestGreen"
|
||||
rounded="md"
|
||||
size="md"
|
||||
type="submit"
|
||||
isLoading={isLoading}
|
||||
fontWeight={400}
|
||||
fontSize="sm"
|
||||
>
|
||||
Reset Password
|
||||
</Button>
|
||||
</DrawerFooter>
|
||||
</form>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ForgetPassword;
|
||||
@@ -217,7 +217,7 @@ const IOArtifactsAdd = ({ isOpen, onClose, firstField, actionId, setActionId, da
|
||||
isOpen={alert}
|
||||
onClose={() => setAlert(false)}
|
||||
alertHandler={handleSave}
|
||||
message={"Are you sure you want to add this artifact?"}
|
||||
message={"Are you sure you want to update this artifact?"}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -20,7 +20,6 @@ import AddCaseDetails from "./AddCaseDetails";
|
||||
import { useUpdateIOCaseMutation } from "../../../../Services/io.service";
|
||||
import ToastBox from "../../../../Components/ToastBox";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { encryptString, isMaker } from "../../../../Constants/Constants";
|
||||
|
||||
const IOCashDetails = () => {
|
||||
const params = useParams();
|
||||
@@ -88,8 +87,7 @@ const IOCashDetails = () => {
|
||||
Pending
|
||||
{IODetails?.ioCashStatusHistory?.Pending.length > 0 && (
|
||||
<Badge rounded={"sm"} colorScheme="forestGreen" ms={2}>
|
||||
{IODetails?.ioCashStatusHistory?.Pending.length !== 0 &&
|
||||
IODetails?.ioCashStatusHistory?.Pending.length}
|
||||
{IODetails?.ioCashStatusHistory?.Pending.length !== 0 && IODetails?.ioCashStatusHistory?.Pending.length}
|
||||
</Badge>
|
||||
)}
|
||||
{/* <Badge rounded={"sm"} colorScheme="forestGreen" ms={2}>
|
||||
@@ -107,8 +105,7 @@ const IOCashDetails = () => {
|
||||
</Tab>
|
||||
</TabList>
|
||||
{IODetails?.isInvestedAmount
|
||||
? isMaker() &&
|
||||
IODetails?.ioSatatus !== "Exited" && (
|
||||
? localStorage?.getItem("role") === "Maker" && (
|
||||
<Button
|
||||
onClick={handleAdd}
|
||||
leftIcon={<AddIcon />}
|
||||
|
||||
@@ -38,7 +38,6 @@ import { useUpdateIOCaseMutation } from "../../../../Services/io.service";
|
||||
import RequestApproveModal from "./RequestApproveModal";
|
||||
import RequestRejectModal from "./RequestRejectModal";
|
||||
import AddCaseDetails from "./AddCaseDetails";
|
||||
import { encryptString, isMaker } from "../../../../Constants/Constants";
|
||||
|
||||
const formatDate = (date) => new Date(date).toLocaleDateString();
|
||||
|
||||
@@ -105,7 +104,8 @@ const Pending = () => {
|
||||
"Comments",
|
||||
"Update By",
|
||||
"Update On",
|
||||
...(!isMaker() ? ["Actions"] : []),
|
||||
...(localStorage?.getItem('role')!=="Maker" ? ["Actions"] : []),
|
||||
|
||||
];
|
||||
|
||||
const extractedArray = filteredData?.map((item, index) => ({
|
||||
@@ -131,9 +131,9 @@ const Pending = () => {
|
||||
$
|
||||
</Badge>
|
||||
{parseFloat(item?.transactionAmount || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
</Text>
|
||||
),
|
||||
Comments: (
|
||||
@@ -166,69 +166,64 @@ const Pending = () => {
|
||||
),
|
||||
Actions: (
|
||||
<Box display={"flex"} justifyContent={"center"}>
|
||||
{!isMaker() ? (
|
||||
<Box>
|
||||
{index === 0 && (
|
||||
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||
<Tooltip
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
label="Approve"
|
||||
bg="#fff"
|
||||
color={"green.500"}
|
||||
placement="left-start"
|
||||
>
|
||||
<Button
|
||||
// colorScheme="forestGreen"
|
||||
// color="green.500"
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={2}
|
||||
py={1}
|
||||
onClick={() => {
|
||||
setActionId(item.id);
|
||||
onConfirmOpen();
|
||||
}}
|
||||
colorScheme="green"
|
||||
variant={"solid"}
|
||||
cursor={"pointer"}
|
||||
>
|
||||
<CheckIcon fontSize={"12px"} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
label="Reject"
|
||||
bg="#fff"
|
||||
color={"red.500"}
|
||||
placement="left-start"
|
||||
>
|
||||
<Button
|
||||
colorScheme="red"
|
||||
// color="red.500"
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={2}
|
||||
onClick={() => {
|
||||
setActionId(item.id);
|
||||
onRejectOpen();
|
||||
}}
|
||||
py={1}
|
||||
// variant={"solid"}
|
||||
>
|
||||
<CloseIcon fontSize={"10px"} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
) : (
|
||||
{localStorage?.getItem("role") !== "Maker" ? <Box>
|
||||
{index===0&&<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||
<Tooltip
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
label="Approve"
|
||||
bg="#fff"
|
||||
color={"green.500"}
|
||||
placement="left-start"
|
||||
>
|
||||
<Button
|
||||
// colorScheme="forestGreen"
|
||||
// color="green.500"
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={2}
|
||||
py={1}
|
||||
onClick={() => {
|
||||
setActionId(item.id);
|
||||
onConfirmOpen();
|
||||
}}
|
||||
colorScheme="green"
|
||||
variant={"solid"}
|
||||
cursor={"pointer"}
|
||||
>
|
||||
<CheckIcon fontSize={"12px"} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
label="Reject"
|
||||
bg="#fff"
|
||||
color={"red.500"}
|
||||
placement="left-start"
|
||||
>
|
||||
<Button
|
||||
colorScheme="red"
|
||||
// color="red.500"
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={2}
|
||||
onClick={() => {
|
||||
setActionId(item.id);
|
||||
onRejectOpen();
|
||||
}}
|
||||
py={1}
|
||||
// variant={"solid"}
|
||||
>
|
||||
<CloseIcon fontSize={"10px"} />
|
||||
</Button>
|
||||
</Tooltip></Box>}
|
||||
|
||||
</Box> : <Button
|
||||
colorScheme="green"
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
@@ -240,8 +235,7 @@ const Pending = () => {
|
||||
}}
|
||||
>
|
||||
<ViewIcon me={"4px"} /> View
|
||||
</Button>
|
||||
)}
|
||||
</Button>}
|
||||
</Box>
|
||||
),
|
||||
}));
|
||||
@@ -319,9 +313,9 @@ const Pending = () => {
|
||||
$
|
||||
</Badge>
|
||||
{parseFloat(IODetails?.ioCash || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
</Th>
|
||||
<Th
|
||||
textAlign={"center"}
|
||||
|
||||
@@ -12,12 +12,11 @@ import {
|
||||
useUpdateIOMutation,
|
||||
} from "../../../Services/io.service";
|
||||
import ToastBox from "../../../Components/ToastBox";
|
||||
import { useToast } from "@chakra-ui/react";
|
||||
import { formatDatee } from "../../../Components/FormField";
|
||||
import {
|
||||
formatDateToYYYYMMDD,
|
||||
removeTrailingZeros,
|
||||
} from "../../../Constants/Constants";
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import { formatDatee } from "../../../Components/FormField";
|
||||
import { formatDateToYYYYMMDD, removeTrailingZeros } from "../../../Constants/Constants";
|
||||
|
||||
const schema = yup.object().shape({
|
||||
investmentNameEnglish: yup
|
||||
@@ -26,7 +25,7 @@ const schema = yup.object().shape({
|
||||
.min(3, "IO name in English must be at least 3 characters long")
|
||||
.max(150, "IO name in English must be at most 150 characters long"),
|
||||
|
||||
investmentNameArabic: yup
|
||||
investmentNameArabic: yup
|
||||
.string()
|
||||
.required("IO name in Arabic is required")
|
||||
.min(3, "IO name in Arabic must be at least 3 characters long")
|
||||
@@ -43,15 +42,15 @@ const schema = yup.object().shape({
|
||||
.required("Description in Arabic is required")
|
||||
.min(10, "Description in Arabic must be at least 10 characters long")
|
||||
.max(2000, "Description in Arabic must be at most 500 characters long"),
|
||||
expectedReturnArabic: yup
|
||||
.string()
|
||||
.required("Expected return in Arabic is required"),
|
||||
expectedReturnArabic: yup
|
||||
.string()
|
||||
.required("Expected return in Arabic is required"),
|
||||
|
||||
goalAmount: yup
|
||||
.number()
|
||||
.typeError("Goal Amount is must be number")
|
||||
.required("Goal amount is required")
|
||||
.positive("Goal amount must be a positive number"),
|
||||
goalAmount: yup
|
||||
.number()
|
||||
.typeError("Goal Amount is must be number")
|
||||
.required('Goal amount is required')
|
||||
.positive('Goal amount must be a positive number'),
|
||||
closingDate: yup
|
||||
.date()
|
||||
.notRequired("Closing date is required")
|
||||
@@ -70,25 +69,28 @@ const schema = yup.object().shape({
|
||||
|
||||
InvestmentDetails: yup.string().notRequired(),
|
||||
|
||||
comment: yup
|
||||
.string()
|
||||
.notRequired()
|
||||
// .min(10, "Comment must be at least 10 characters long")
|
||||
.max(100, "Comment must be at most 100 characters long"),
|
||||
comment: yup.string().notRequired()
|
||||
// .min(10, "Comment must be at least 10 characters long")
|
||||
.max(100, "Comment must be at most 100 characters long"),
|
||||
|
||||
expectedReturn: yup.string().required("Expected return is required"),
|
||||
expectedReturn: yup
|
||||
.string()
|
||||
.required("Expected return is required"),
|
||||
});
|
||||
|
||||
const IODetails = ({ enableNextTab, index, data }) => {
|
||||
|
||||
const params = useParams();
|
||||
const navigate = useNavigate();
|
||||
const toast = useToast();
|
||||
|
||||
|
||||
const handleInputChangeCreate = (index, newValue) => {
|
||||
|
||||
const updatedValues = [...values];
|
||||
updatedValues[index].value = newValue;
|
||||
setValues(updatedValues);
|
||||
console.log(values);
|
||||
console.log(values);
|
||||
};
|
||||
|
||||
const handleInputChangeEdit = (index, newValue) => {
|
||||
@@ -141,12 +143,9 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
});
|
||||
|
||||
const miniValue = data?.country?.map(
|
||||
(
|
||||
{ countryName, flagIcon, minInvestmentAmt, countryCode, id, currency },
|
||||
index
|
||||
) => {
|
||||
({ countryName, flagIcon, minInvestmentAmt, countryCode, id, currency }, index) => {
|
||||
return {
|
||||
id: id,
|
||||
id:id,
|
||||
country: countryName,
|
||||
value: minInvestmentAmt,
|
||||
logo: flagIcon,
|
||||
@@ -155,19 +154,18 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
}
|
||||
);
|
||||
|
||||
const minInvestmentById = IObyID?.data?.minInvestmentAmt?.map(
|
||||
({ minInvestmentAmt, country, currencyCode, country_xid, id }) => {
|
||||
console.log(currencyCode);
|
||||
return {
|
||||
_id: id,
|
||||
id: country_xid,
|
||||
country: country?.countryName,
|
||||
value: removeTrailingZeros(minInvestmentAmt),
|
||||
logo: country?.flagIcon,
|
||||
curr: currencyCode,
|
||||
};
|
||||
const minInvestmentById = IObyID?.data?.minInvestmentAmt?.map(({minInvestmentAmt, country, currencyCode, country_xid,id })=>{
|
||||
console.log(currencyCode);
|
||||
return{
|
||||
_id:id,
|
||||
id:country_xid,
|
||||
country: country?.countryName,
|
||||
value: removeTrailingZeros(minInvestmentAmt),
|
||||
logo: country?.flagIcon,
|
||||
curr: currencyCode,
|
||||
}
|
||||
);
|
||||
})
|
||||
|
||||
|
||||
const schemaEdit = yup.object().shape({
|
||||
investmentNameEnglish: yup
|
||||
@@ -175,67 +173,74 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
.required("IO name in English is required")
|
||||
.min(3, "IO name in English must be at least 3 characters long")
|
||||
.max(150, "IO name in English must be at most 150 characters long"),
|
||||
|
||||
|
||||
investmentNameArabic: yup
|
||||
.string()
|
||||
.required("IO name in Arabic is required")
|
||||
.min(3, "IO name in Arabic must be at least 3 characters long")
|
||||
.max(50, "IO name in Arabic must be at most 50 characters long"),
|
||||
|
||||
|
||||
descriptionEnglish: yup
|
||||
.string()
|
||||
.required("Description in English is required")
|
||||
.min(10, "Description in English must be at least 10 characters long")
|
||||
.max(1000, "Description in English must be at most 1000 characters long"),
|
||||
|
||||
|
||||
descriptionArabic: yup
|
||||
.string()
|
||||
.required("Description in Arabic is required")
|
||||
.min(10, "Description in Arabic must be at least 10 characters long")
|
||||
.max(2000, "Description in Arabic must be at most 500 characters long"),
|
||||
expectedReturnArabic: yup
|
||||
.string()
|
||||
.required("Expected return in Arabic is required"),
|
||||
|
||||
goalAmount: yup
|
||||
.number()
|
||||
.typeError("Goal Amount is must be number")
|
||||
.required("Goal amount is required")
|
||||
.positive("Goal amount must be a positive number")
|
||||
.min(
|
||||
IObyID?.data?.totalAmtInvestmentInUSD,
|
||||
`Goal amount should not be lesser then amount raised ${IObyID?.data?.totalAmtInvestmentInUSD}`
|
||||
),
|
||||
closingDate: yup.date().notRequired("Closing date is required"),
|
||||
|
||||
expectedReturnArabic: yup
|
||||
.string()
|
||||
.required("Expected return in Arabic is required"),
|
||||
|
||||
goalAmount: yup
|
||||
.number()
|
||||
.typeError("Goal Amount is must be number")
|
||||
.required('Goal amount is required')
|
||||
.positive('Goal amount must be a positive number')
|
||||
.min(IObyID?.data?.totalAmtInvestmentInUSD, `Goal amount should not be lesser then amount raised ${IObyID?.data?.totalAmtInvestmentInUSD}`),
|
||||
closingDate: yup
|
||||
.date()
|
||||
.notRequired("Closing date is required")
|
||||
.min(new Date(), "Closing date cannot be in the past"),
|
||||
|
||||
holdingPeriod: yup.string().required("Holding period is required"),
|
||||
holdingPeriodArabic: yup.string().required("Holding period is required"),
|
||||
isShariah: yup.string().required("CheckBox is required"),
|
||||
|
||||
|
||||
// minInvestmentAmount: yup
|
||||
// .number()
|
||||
// .required("Minimum investment is required")
|
||||
// .positive("Minimum investment must be a positive number")
|
||||
// .min(1, "Minimum investment must be at least 1"),
|
||||
|
||||
|
||||
ISIN: yup.string().notRequired(),
|
||||
|
||||
|
||||
InvestmentDetails: yup.string().notRequired(),
|
||||
|
||||
comment: yup
|
||||
|
||||
comment: yup.string().notRequired()
|
||||
.min(10, "Comment must be at least 10 characters long")
|
||||
.max(100, "Comment must be at most 100 characters long"),
|
||||
|
||||
expectedReturn: yup
|
||||
.string()
|
||||
.notRequired()
|
||||
.min(10, "Comment must be at least 10 characters long")
|
||||
.max(100, "Comment must be at most 100 characters long"),
|
||||
|
||||
expectedReturn: yup.string().required("Expected return is required"),
|
||||
.required("Expected return is required"),
|
||||
});
|
||||
|
||||
|
||||
|
||||
const [values, setValues] = useState(id ? minInvestmentById : miniValue);
|
||||
|
||||
const [values, setValues] = useState(id?minInvestmentById:miniValue);
|
||||
|
||||
console.log(values);
|
||||
|
||||
const formatNumber = (num) => {
|
||||
// Remove non-numeric characters and format with commas
|
||||
return num.replace(/\D/g, "").replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
return num.replace(/\D/g, '')
|
||||
.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
};
|
||||
// console.log(values);
|
||||
|
||||
@@ -249,11 +254,10 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: yupResolver(id ? schemaEdit : schema),
|
||||
mode: "all",
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setIOloading(IObyIDisLoading);
|
||||
setIOloading(IObyIDisLoading)
|
||||
setIODetails({
|
||||
...IObyID?.data,
|
||||
});
|
||||
@@ -274,9 +278,10 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
minInvestmentAmount: IObyID?.data?.minInvestmentAmount,
|
||||
holdingPeriodArabic: IObyID?.data?.minInvestmentAmount,
|
||||
expectedReturnArabic: IObyID?.data?.minInvestmentAmount,
|
||||
isShariah: IObyID?.data?.isShariah,
|
||||
isShariah: IObyID?.data?.isShariah
|
||||
});
|
||||
}
|
||||
|
||||
}, [id, IObyID]);
|
||||
|
||||
//=======================[ Creator ]
|
||||
@@ -289,10 +294,8 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
isRequired: true,
|
||||
section: " ",
|
||||
width: "49%",
|
||||
maxLength: 150,
|
||||
helperText: `Maximum length should be 150 characters. You have entered ${
|
||||
watch()?.investmentNameEnglish?.length || 0
|
||||
} characters.`,
|
||||
maxLength:150,
|
||||
helperText:`Maximum length should be 150 characters. You have entered ${watch()?.investmentNameEnglish?.length || 0} characters.`
|
||||
},
|
||||
{
|
||||
label: "IO Name (Arabic)",
|
||||
@@ -303,10 +306,8 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
arabic: true,
|
||||
section: " ",
|
||||
width: "49%",
|
||||
maxLength: 150,
|
||||
helperText: `Maximum length should be 150 characters. You have entered ${
|
||||
watch()?.investmentNameArabic?.length || 0
|
||||
} characters.`,
|
||||
maxLength:150,
|
||||
helperText:`Maximum length should be 150 characters. You have entered ${watch()?.investmentNameArabic?.length || 0} characters.`
|
||||
},
|
||||
{
|
||||
label: "Description",
|
||||
@@ -316,10 +317,8 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
isRequired: true,
|
||||
section: " ",
|
||||
width: "49%",
|
||||
maxLength: 1000,
|
||||
helperText: `Maximum length should be 1000 characters. You have entered ${
|
||||
watch()?.descriptionEnglish?.length || 0
|
||||
} characters.`,
|
||||
maxLength:1000,
|
||||
helperText:`Maximum length should be 1000 characters. You have entered ${watch()?.descriptionEnglish?.length || 0} characters.`
|
||||
},
|
||||
{
|
||||
label: "Description (Arabic)",
|
||||
@@ -330,10 +329,9 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
arabic: true,
|
||||
section: " ",
|
||||
width: "49%",
|
||||
maxLength: 1000,
|
||||
helperText: `Maximum length should be 1000 characters. You have entered ${
|
||||
watch()?.descriptionArabic?.length || 0
|
||||
} characters.`,
|
||||
maxLength:1000,
|
||||
helperText:`Maximum length should be 1000 characters. You have entered ${watch()?.descriptionArabic?.length || 0} characters.`
|
||||
|
||||
},
|
||||
{
|
||||
label: "Holding Period",
|
||||
@@ -344,10 +342,8 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
section: " ",
|
||||
width: "49%",
|
||||
value: IObyID?.data?.holdingPeriod,
|
||||
maxLength: 20,
|
||||
helperText: `Maximum length should be 20 characters. You have entered ${
|
||||
watch()?.holdingPeriod?.length || 0
|
||||
} characters.`,
|
||||
maxLength:20,
|
||||
helperText:`Maximum length should be 20 characters. You have entered ${watch()?.holdingPeriod?.length || 0} characters.`
|
||||
},
|
||||
{
|
||||
label: "Holding Period (Arabic)",
|
||||
@@ -359,12 +355,11 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
section: " ",
|
||||
width: "49%",
|
||||
value: IObyID?.data?.holdingPeriodArabic,
|
||||
maxLength: 20,
|
||||
helperText: `Maximum length should be 20 characters. You have entered ${
|
||||
watch()?.holdingPeriodArabic?.length || 0
|
||||
} characters.`,
|
||||
maxLength:20,
|
||||
helperText:`Maximum length should be 20 characters. You have entered ${watch()?.holdingPeriodArabic?.length || 0} characters.`
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
label: "Expected Return",
|
||||
name: "expectedReturn",
|
||||
@@ -377,7 +372,7 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
|
||||
{
|
||||
label: "Expected Return (Arabic)",
|
||||
name: "expectedReturnArabic",
|
||||
name: "expectedReturnArabic",
|
||||
type: "text",
|
||||
isRequired: true,
|
||||
arabic: true,
|
||||
@@ -387,15 +382,16 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
},
|
||||
{
|
||||
label: "Shariah",
|
||||
name: "isShariah",
|
||||
name: "isShariah",
|
||||
type: "checkBox",
|
||||
value: IObyID?.data?.isShariah,
|
||||
value:IObyID?.data?.isShariah,
|
||||
// isRequired: true,
|
||||
section: " ",
|
||||
width: "32.3%",
|
||||
value: IObyID?.data?.isShariah,
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
label: "Investment Type",
|
||||
placeHolder: "Select option",
|
||||
@@ -433,19 +429,19 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
name: "closingDate",
|
||||
// value: "IObyID?.data?.closingDate",
|
||||
type: "date",
|
||||
// isRequired: true,
|
||||
isRequired: true,
|
||||
section: " ",
|
||||
width: "32.3%",
|
||||
dateValue: formatDatee(IObyID?.data?.closingDate),
|
||||
dateValue:formatDatee(IObyID?.data?.closingDate),
|
||||
// helperText: IObyID && `Current closing date is : ${formatDate(IObyID?.data?.closingDate)}`
|
||||
closingDate:id ? null : true
|
||||
closingDate:true
|
||||
},
|
||||
{
|
||||
label: "ISIN",
|
||||
placeHolder: "",
|
||||
name: "ISIN",
|
||||
type: "text",
|
||||
align: "right",
|
||||
align:"right",
|
||||
section: " ",
|
||||
width: "32.3%",
|
||||
},
|
||||
@@ -457,10 +453,8 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
section: " ",
|
||||
width: "32.3%",
|
||||
value: IObyID?.data?.InvestmentDetails,
|
||||
maxLength: 20,
|
||||
helperText: `Maximum length should be 20 characters. You have entered ${
|
||||
watch()?.InvestmentDetails?.length || 0
|
||||
} characters.`,
|
||||
maxLength:20,
|
||||
helperText:`Maximum length should be 20 characters. You have entered ${watch()?.InvestmentDetails?.length || 0} characters.`
|
||||
},
|
||||
|
||||
{
|
||||
@@ -469,10 +463,10 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
name: "table",
|
||||
type: "table",
|
||||
section: " ",
|
||||
width: "100%",
|
||||
width: "100%",
|
||||
isRequired: true,
|
||||
options: investmentTypeOptions,
|
||||
handleInputChange: id ? handleInputChangeEdit : handleInputChangeCreate,
|
||||
handleInputChange:id ? handleInputChangeEdit : handleInputChangeCreate,
|
||||
value: values,
|
||||
},
|
||||
|
||||
@@ -485,10 +479,8 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
width: "100%",
|
||||
options: investmentTypeOptions,
|
||||
value: IObyID?.data?.comment,
|
||||
maxLength: 100,
|
||||
helperText: `Maximum length should be 100 characters. You have entered ${
|
||||
watch()?.comment?.length || 0
|
||||
} characters.`,
|
||||
maxLength:100,
|
||||
helperText:`Maximum length should be 100 characters. You have entered ${watch()?.comment?.length || 0} characters.`
|
||||
},
|
||||
];
|
||||
const groupedFields = formFields.reduce((groups, field) => {
|
||||
@@ -501,29 +493,30 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
}, {});
|
||||
|
||||
const onSubmit = async (data) => {
|
||||
|
||||
delete data.table;
|
||||
|
||||
setIsLoading(true);
|
||||
const updatedMinAmount = values?.map(({ id, value, _id }) => {
|
||||
const updatedMinAmount = values?.map(({id, value, _id})=>{
|
||||
return {
|
||||
id: _id,
|
||||
country_xid: id,
|
||||
minInvestmentAmt: Number(value),
|
||||
};
|
||||
});
|
||||
id:_id,
|
||||
country_xid:id,
|
||||
minInvestmentAmt: Number(value)
|
||||
}
|
||||
})
|
||||
|
||||
// console.log(formatDateToYYYYMMDD(data.closingDate));
|
||||
const formData = {
|
||||
...data,
|
||||
investmentType_xid: Number(data.investmentType),
|
||||
sponsor_xid: Number(data.sponserName),
|
||||
minInvestmentAmt: updatedMinAmount,
|
||||
closingDate: formatDateToYYYYMMDD(data.closingDate),
|
||||
minInvestmentAmt:updatedMinAmount,
|
||||
closingDate: formatDateToYYYYMMDD(data.closingDate)
|
||||
};
|
||||
|
||||
// console.log(formData);
|
||||
if (id) {
|
||||
console.log("========================", formData);
|
||||
console.log("========================",formData);
|
||||
const res = await updateIO({ data: formData, id });
|
||||
console.log(res);
|
||||
if (res?.data?.statusCode === 200) {
|
||||
@@ -533,24 +526,20 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
});
|
||||
navigate(`/view-io/${id}`);
|
||||
enableNextTab(index);
|
||||
} else if (res?.error?.status === 400) {
|
||||
} else if(res?.error?.status === 400){
|
||||
setIsLoading(false);
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||
),
|
||||
});
|
||||
} else if (res?.error?.status === 500) {
|
||||
render: () => <ToastBox message={res?.error?.data?.message } status={"error"} />,
|
||||
});
|
||||
} else if(res?.error?.status === 500){
|
||||
setIsLoading(false);
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||
),
|
||||
render: () => <ToastBox message={res?.error?.data?.message } status={"error"} />,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
console.log("========================", formData);
|
||||
console.log("========================",formData);
|
||||
const res = await creatIO(formData);
|
||||
console.log(res?.error?.status);
|
||||
if (res?.data?.statusCode === 200) {
|
||||
@@ -560,19 +549,15 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
});
|
||||
navigate(`/view-io/${res?.data?.data}`);
|
||||
enableNextTab(index);
|
||||
} else if (res?.error?.status === 400) {
|
||||
} else if(res?.error?.status === 400){
|
||||
setIsLoading(false);
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||
),
|
||||
render: () => <ToastBox message={res?.error?.data?.message } status={"error"} />,
|
||||
});
|
||||
} else if (res?.error?.status === 500) {
|
||||
}else if(res?.error?.status === 500){
|
||||
setIsLoading(false);
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||
),
|
||||
render: () => <ToastBox message={res?.error?.data?.message } status={"error"} />,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -581,6 +566,7 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ==========================
|
||||
// if (params?.id) {
|
||||
// return enableNextTab(index);
|
||||
@@ -598,8 +584,9 @@ const IODetails = ({ enableNextTab, index, data }) => {
|
||||
};
|
||||
|
||||
return IObyIDisLoading ? (
|
||||
<FullscreenLoaders height={"70vh"} />
|
||||
<FullscreenLoaders height={'70vh'} />
|
||||
) : (
|
||||
|
||||
<FormInputMain
|
||||
p={0.1}
|
||||
w={250}
|
||||
|
||||
@@ -4,7 +4,10 @@ import {
|
||||
Box,
|
||||
Button,
|
||||
HStack,
|
||||
Input,
|
||||
Input,
|
||||
Table,
|
||||
Tag,
|
||||
Tbody,
|
||||
Text,
|
||||
Th,
|
||||
Tooltip,
|
||||
@@ -19,7 +22,7 @@ import { OPACITY_ON_LOAD } from "../../../../Layout/animations";
|
||||
import NormalTable from "../../../../Components/DataTable/NormalTable";
|
||||
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
|
||||
import CustomAlertDialog from "../../../../Components/CustomAlertDialog";
|
||||
import * as XLSX from "xlsx";
|
||||
import * as XLSX from "xlsx";
|
||||
import ToastBox from "../../../../Components/ToastBox";
|
||||
import AddCashDetails from "../AddCashDetails";
|
||||
import { debounce } from "../../../Admin/Contact";
|
||||
|
||||
@@ -75,7 +75,6 @@ import ToastBox from "../../../../Components/ToastBox";
|
||||
import { useParams } from "react-router-dom";
|
||||
import AddNavDetails from "./AddNavDetails";
|
||||
import { useUpdateIOCaseMutation } from "../../../../Services/io.service";
|
||||
import { encryptString, isMaker } from "../../../../Constants/Constants";
|
||||
|
||||
const IONAVDetails = () => {
|
||||
const params = useParams();
|
||||
@@ -153,8 +152,7 @@ const IONAVDetails = () => {
|
||||
</Tab>
|
||||
</TabList>
|
||||
{IODetails?.isInvestedAmount
|
||||
? isMaker() &&
|
||||
IODetails?.ioSatatus !== "Exited" && (
|
||||
? localStorage?.getItem("role") === "Maker" && (
|
||||
<Button
|
||||
onClick={handleAdd}
|
||||
leftIcon={<AddIcon />}
|
||||
|
||||
@@ -22,7 +22,6 @@ import ToastBox from "../../../../Components/ToastBox";
|
||||
import AddNavDetails from "./AddNavDetails";
|
||||
import RequestApproveModal from "./RequestApproveModal";
|
||||
import RequestRejectModal from "./RequestRejectModal";
|
||||
import { encryptString, isMaker } from "../../../../Constants/Constants";
|
||||
|
||||
const formatDate = (date) => new Date(date).toLocaleDateString();
|
||||
|
||||
@@ -91,7 +90,7 @@ const Pending = () => {
|
||||
"Investment Closed",
|
||||
"Comments",
|
||||
"Updated By",
|
||||
...(!isMaker() ? ["Status"] : []),
|
||||
...(localStorage?.getItem("role") !== "Maker" ? ["Status"] : []),
|
||||
];
|
||||
|
||||
const extractedArray = filteredData?.map((item, index) => ({
|
||||
@@ -112,9 +111,9 @@ const Pending = () => {
|
||||
$
|
||||
</Badge>
|
||||
{parseFloat(item?.transactionAmount || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
</Text>
|
||||
),
|
||||
"Last Nav Update": (
|
||||
@@ -162,80 +161,66 @@ const Pending = () => {
|
||||
{item?.modifier?.firstName}
|
||||
</Text>
|
||||
),
|
||||
Status: isMaker() ? (
|
||||
<Button
|
||||
colorScheme="green"
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
px={2}
|
||||
py={1}
|
||||
fontWeight={500}
|
||||
onClick={() => {
|
||||
setActionId(item.id);
|
||||
}}
|
||||
>
|
||||
<ViewIcon me={"4px"} /> View
|
||||
</Button>
|
||||
) : (
|
||||
Status: (
|
||||
<Box display={"flex"} justifyContent={"center"}>
|
||||
<Box>
|
||||
<Box>
|
||||
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||
<Tooltip
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
label="Approve"
|
||||
bg="#fff"
|
||||
color={"green.500"}
|
||||
placement="left-start"
|
||||
>
|
||||
<Button
|
||||
// colorScheme="forestGreen"
|
||||
// color="green.500"
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={2}
|
||||
py={1}
|
||||
onClick={() => {
|
||||
setActionId(item.id);
|
||||
onConfirmOpen();
|
||||
}}
|
||||
colorScheme="green"
|
||||
variant={"solid"}
|
||||
cursor={"pointer"}
|
||||
>
|
||||
<CheckIcon fontSize={"12px"} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
label="Reject"
|
||||
bg="#fff"
|
||||
color={"red.500"}
|
||||
placement="left-start"
|
||||
>
|
||||
<Button
|
||||
colorScheme="red"
|
||||
// color="red.500"
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={2}
|
||||
onClick={() => {
|
||||
setActionId(item.id);
|
||||
onRejectOpen();
|
||||
}}
|
||||
py={1}
|
||||
// variant={"solid"}
|
||||
>
|
||||
<CloseIcon fontSize={"10px"} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
<Tooltip
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
label="Approve"
|
||||
bg="#fff"
|
||||
color={"green.500"}
|
||||
placement="left-start"
|
||||
>
|
||||
<Button
|
||||
// colorScheme="forestGreen"
|
||||
// color="green.500"
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={2}
|
||||
py={1}
|
||||
onClick={() => {
|
||||
setActionId(item.id);
|
||||
onConfirmOpen();
|
||||
}}
|
||||
colorScheme="green"
|
||||
variant={"solid"}
|
||||
cursor={"pointer"}
|
||||
>
|
||||
<CheckIcon fontSize={"12px"} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
label="Reject"
|
||||
bg="#fff"
|
||||
color={"red.500"}
|
||||
placement="left-start"
|
||||
>
|
||||
<Button
|
||||
colorScheme="red"
|
||||
// color="red.500"
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={2}
|
||||
onClick={() => {
|
||||
setActionId(item.id);
|
||||
onRejectOpen();
|
||||
}}
|
||||
py={1}
|
||||
// variant={"solid"}
|
||||
>
|
||||
<CloseIcon fontSize={"10px"} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
),
|
||||
}));
|
||||
|
||||
@@ -1,26 +1,32 @@
|
||||
import { ViewIcon } from "@chakra-ui/icons";
|
||||
import {
|
||||
Avatar,
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
HStack,
|
||||
Input,
|
||||
Table,
|
||||
Tag,
|
||||
Tbody,
|
||||
Text,
|
||||
Th,
|
||||
Tooltip,
|
||||
Tr,
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useContext, useEffect, useRef, useState } from "react";
|
||||
import CustomAlertDialog from "../../../../Components/CustomAlertDialog";
|
||||
import NormalTable from "../../../../Components/DataTable/NormalTable";
|
||||
import { isMaker } from "../../../../Constants/Constants";
|
||||
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
|
||||
import { OPACITY_ON_LOAD } from "../../../../Layout/animations";
|
||||
import NormalTable from "../../../../Components/DataTable/NormalTable";
|
||||
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
|
||||
import CustomAlertDialog from "../../../../Components/CustomAlertDialog";
|
||||
import { CheckIcon, CloseIcon, ViewIcon } from "@chakra-ui/icons";
|
||||
import RequestApproveModal from "./RequestApproveModal";
|
||||
import RequestRejectModal from "./RequestRejectModal";
|
||||
import ViewAmountInvested from "./ViewAmountInvested";
|
||||
import ViewCancel from "./ViewCancel";
|
||||
import ViewDistributionInvestor from "./ViewDistributionInvestor";
|
||||
import ViewExit from "./ViewExit";
|
||||
import ViewCancel from "./ViewCancel";
|
||||
|
||||
const formatDate = (date) => new Date(date).toLocaleDateString();
|
||||
|
||||
@@ -36,7 +42,6 @@ const Pending = () => {
|
||||
const [actionId, setActionId] = useState(false);
|
||||
const [mouseEntered, setMouseEntered] = useState(false);
|
||||
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||
const [distributedAmt, setDistributedAmt] = useState();
|
||||
|
||||
const {
|
||||
isOpen: isConfirmOpen,
|
||||
@@ -87,6 +92,11 @@ const Pending = () => {
|
||||
});
|
||||
};
|
||||
|
||||
console.log(
|
||||
"==============panding",
|
||||
IODetails?.ioTransactionRecords?.Pending
|
||||
);
|
||||
|
||||
// Table filter
|
||||
// const filteredData = IODetails?.ioTransactionRecords?.Pending?.filter((item) => {
|
||||
// // Filter by name (case insensitive)
|
||||
@@ -117,7 +127,11 @@ const Pending = () => {
|
||||
</Text>
|
||||
),
|
||||
"Transaction Date": (
|
||||
<Text as={"span"} color={"gray.600"} fontWeight={"500"}>
|
||||
<Text
|
||||
as={"span"}
|
||||
color={"gray.600"}
|
||||
fontWeight={"500"}
|
||||
>
|
||||
{formatDate(item?.transactionDate)}
|
||||
</Text>
|
||||
),
|
||||
@@ -137,19 +151,9 @@ const Pending = () => {
|
||||
})}
|
||||
</Text>
|
||||
),
|
||||
// Amount:(
|
||||
// <div>
|
||||
// <ViewDistributionInvestor amount={item?.transactionAmount} />
|
||||
// </div>
|
||||
// ),
|
||||
"Created By": (
|
||||
<Text
|
||||
textTransform={"capitalize"}
|
||||
w={"100px"}
|
||||
as={"span"}
|
||||
color={"gray.800"}
|
||||
fontWeight={"500"}
|
||||
>
|
||||
<Text
|
||||
textTransform={'capitalize'} w={"100px"} as={"span"} color={"gray.800"} fontWeight={"500"}>
|
||||
{item?.creator?.firstName}
|
||||
</Text>
|
||||
),
|
||||
@@ -159,13 +163,8 @@ const Pending = () => {
|
||||
</Text>
|
||||
),
|
||||
"Approved By": (
|
||||
<Text
|
||||
textTransform={"capitalize"}
|
||||
w={"100px"}
|
||||
as={"span"}
|
||||
color={"gray.800"}
|
||||
fontWeight={"500"}
|
||||
>
|
||||
<Text
|
||||
textTransform={'capitalize'} w={"100px"} as={"span"} color={"gray.800"} fontWeight={"500"}>
|
||||
{item?.modifier?.firstName}
|
||||
</Text>
|
||||
),
|
||||
@@ -189,7 +188,6 @@ const Pending = () => {
|
||||
onInvestmentOpen();
|
||||
} else if (item?.transactionType === "Distribution To Investor") {
|
||||
onDistInvestorOpen();
|
||||
setDistributedAmt(item?.transactionAmount);
|
||||
} else if (item?.transactionType === "Exit") {
|
||||
onExitOpen();
|
||||
} else if (item?.transactionType === "Cancel") {
|
||||
@@ -197,16 +195,13 @@ const Pending = () => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
{isMaker() ? <ViewIcon me={"4px"} /> : null}{" "}
|
||||
{isMaker() ? "View" : "Approve / Reject"}
|
||||
{localStorage?.getItem("role") === "Maker" ? <ViewIcon me={"4px"} /> : null} {localStorage?.getItem("role") === "Maker" ? "View" : "Approve / Reject"}
|
||||
</Button>
|
||||
</Box>
|
||||
),
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
|
||||
const handleDelete = () => {
|
||||
const updatedSponsors = sponser.filter(
|
||||
(sponsor) => sponsor.id !== actionId
|
||||
@@ -267,13 +262,20 @@ const Pending = () => {
|
||||
id={actionId}
|
||||
/>
|
||||
<ViewDistributionInvestor
|
||||
isOpen={isDistInvestorOpen}
|
||||
onClose={onDistInvestorClose}
|
||||
isOpen={isDistInvestorOpen}
|
||||
onClose={onDistInvestorClose}
|
||||
id={actionId}
|
||||
/>
|
||||
<ViewExit
|
||||
isOpen={isExitOpen}
|
||||
onClose={onExitClose}
|
||||
id={actionId}
|
||||
amount={distributedAmt}
|
||||
/>
|
||||
<ViewExit isOpen={isExitOpen} onClose={onExitClose} id={actionId} />
|
||||
<ViewCancel isOpen={isCancelOpen} onClose={onCancelClose} id={actionId} />
|
||||
<ViewCancel
|
||||
isOpen={isCancelOpen}
|
||||
onClose={onCancelClose}
|
||||
id={actionId}
|
||||
/>
|
||||
<RequestApproveModal
|
||||
// data={data?.data?.rows}
|
||||
isOpen={isConfirmOpen}
|
||||
|
||||
@@ -27,7 +27,6 @@ import CurrencyInput from "../../../../Components/CurrencyInput";
|
||||
import RequestRejectModal from "./RequestRejectModal";
|
||||
import ApproveInvestedModal from "./ApproveInvestedModal";
|
||||
import { formatDate } from "../../../Master/Sponser/Sponsers";
|
||||
import { encryptString, isMaker } from "../../../../Constants/Constants";
|
||||
|
||||
// Validation schema
|
||||
const validationSchema = yup.object().shape({
|
||||
@@ -117,6 +116,7 @@ const ViewAmountInvested = ({ isOpen, onClose, id: investorId }) => {
|
||||
};
|
||||
|
||||
// const formatDate = (date) => new Date(date).toLocaleDateString();
|
||||
|
||||
|
||||
const handleAmountChange = (e) => {
|
||||
// e might be an object or just a value, handle both cases
|
||||
@@ -236,43 +236,41 @@ const ViewAmountInvested = ({ isOpen, onClose, id: investorId }) => {
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
{!isMaker() && (
|
||||
<ModalFooter>
|
||||
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={3}
|
||||
py={2}
|
||||
onClick={() => {
|
||||
setActionId(id); // Use the `id` variable from params
|
||||
onConfirmOpen();
|
||||
}}
|
||||
colorScheme="forestGreen"
|
||||
variant={"solid"}
|
||||
cursor={"pointer"}
|
||||
>
|
||||
Approve
|
||||
</Button>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={3}
|
||||
py={2}
|
||||
onClick={() => {
|
||||
setActionId(id); // Use the `id` variable from params
|
||||
onRejectOpen();
|
||||
}}
|
||||
>
|
||||
Reject
|
||||
</Button>
|
||||
</Box>
|
||||
</ModalFooter>
|
||||
)}
|
||||
{localStorage?.getItem("role") !== "Maker" && <ModalFooter>
|
||||
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={3}
|
||||
py={2}
|
||||
onClick={() => {
|
||||
setActionId(id); // Use the `id` variable from params
|
||||
onConfirmOpen();
|
||||
}}
|
||||
colorScheme="forestGreen"
|
||||
variant={"solid"}
|
||||
cursor={"pointer"}
|
||||
>
|
||||
Approve
|
||||
</Button>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={3}
|
||||
py={2}
|
||||
onClick={() => {
|
||||
setActionId(id); // Use the `id` variable from params
|
||||
onRejectOpen();
|
||||
}}
|
||||
>
|
||||
Reject
|
||||
</Button>
|
||||
</Box>
|
||||
</ModalFooter>}
|
||||
</form>
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
|
||||
@@ -1,128 +1,127 @@
|
||||
import {
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
HStack,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Table,
|
||||
Tbody,
|
||||
Text,
|
||||
Th,
|
||||
Tr,
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import NormalData from "../../../../Components/DataTable/NormalTable";
|
||||
import { useContext, useState } from "react";
|
||||
import {
|
||||
useExitIOTransactionMutation,
|
||||
useGetDistributedToInvestorMutation,
|
||||
useGetDistributionInvestorMutation,
|
||||
useGetIOByIdQuery,
|
||||
} from "../../../../Services/io.service";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import * as yup from "yup";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import ToastBox from "../../../../Components/ToastBox";
|
||||
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
HStack,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Table,
|
||||
Tbody,
|
||||
Text,
|
||||
Th,
|
||||
Tr,
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import NormalData from "../../../../Components/DataTable/NormalTable";
|
||||
import { useContext, useState } from "react";
|
||||
import {
|
||||
useExitIOTransactionMutation,
|
||||
useGetDistributedToInvestorMutation,
|
||||
useGetDistributionInvestorMutation,
|
||||
useGetIOByIdQuery,
|
||||
} from "../../../../Services/io.service";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import * as yup from "yup";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import ToastBox from "../../../../Components/ToastBox";
|
||||
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
|
||||
import ApprovedCancelTransaction from "./ApprovedCancelTransaction";
|
||||
import RequestRejectModal from "./RequestRejectModal";
|
||||
import { encryptString, isMaker } from "../../../../Constants/Constants";
|
||||
|
||||
const ViewCancel = ({ isOpen, onClose, id: cancleId }) => {
|
||||
const params = useParams();
|
||||
const toast = useToast();
|
||||
const id = params?.id;
|
||||
const [isCalculateLoading, setIsCalculateLoading] = useState(false);
|
||||
const [isFinalCalculateLoading, setIsFinalCalculateLoading] = useState(false);
|
||||
const [calcualtedData, setCalculatedDate] = useState(null);
|
||||
const [isCalcualtedData, setIsCalcualtedData] = useState(false);
|
||||
const { investors, setInvestors, slideFromRight, IODetails } =
|
||||
|
||||
const ViewCancel = ({ isOpen, onClose,id:cancleId }) => {
|
||||
const params = useParams();
|
||||
const toast = useToast();
|
||||
const id = params?.id;
|
||||
const [isCalculateLoading, setIsCalculateLoading] = useState(false);
|
||||
const [isFinalCalculateLoading, setIsFinalCalculateLoading] = useState(false);
|
||||
const [calcualtedData, setCalculatedDate] = useState(null);
|
||||
const [isCalcualtedData, setIsCalcualtedData] = useState(false);
|
||||
const { investors, setInvestors, slideFromRight, IODetails } =
|
||||
useContext(GlobalStateContext);
|
||||
|
||||
const [actionId, setActionId] = useState(false);
|
||||
const [actionId, setActionId] = useState(false);
|
||||
|
||||
const {
|
||||
isOpen: isConfirmOpen,
|
||||
onOpen: onConfirmOpen,
|
||||
onClose: onConfirmClose,
|
||||
} = useDisclosure();
|
||||
const {
|
||||
isOpen: isRejectOpen,
|
||||
onOpen: onRejectOpen,
|
||||
onClose: onRejectClose,
|
||||
} = useDisclosure();
|
||||
|
||||
const investorExit = yup.object().shape({
|
||||
amount: yup
|
||||
.string()
|
||||
.required("Amount is required")
|
||||
.test(
|
||||
"max",
|
||||
`Distribution amount should not be greater than IO cash amount ${IODetails?.ioCash}`,
|
||||
function (value) {
|
||||
const { ioCash } = IODetails || {}; // Safely get ioCash
|
||||
if (value && ioCash) {
|
||||
return parseFloat(value) <= parseFloat(ioCash); // Ensure both are compared as numbers
|
||||
const {
|
||||
isOpen: isConfirmOpen,
|
||||
onOpen: onConfirmOpen,
|
||||
onClose: onConfirmClose,
|
||||
} = useDisclosure();
|
||||
const {
|
||||
isOpen: isRejectOpen,
|
||||
onOpen: onRejectOpen,
|
||||
onClose: onRejectClose,
|
||||
} = useDisclosure();
|
||||
|
||||
const investorExit = yup.object().shape({
|
||||
amount: yup
|
||||
.string()
|
||||
.required("Amount is required")
|
||||
.test(
|
||||
"max",
|
||||
`Distribution amount should not be greater than IO cash amount ${IODetails?.ioCash}`,
|
||||
function (value) {
|
||||
const { ioCash } = IODetails || {}; // Safely get ioCash
|
||||
if (value && ioCash) {
|
||||
return parseFloat(value) <= parseFloat(ioCash); // Ensure both are compared as numbers
|
||||
}
|
||||
return true; // If ioCash is not available, skip validation
|
||||
}
|
||||
return true; // If ioCash is not available, skip validation
|
||||
}
|
||||
),
|
||||
});
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
reset,
|
||||
} = useForm({
|
||||
resolver: yupResolver(investorExit),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
console.log("hiit useEffectc");
|
||||
if (id && IODetails) {
|
||||
handleCalculate(id, {
|
||||
),
|
||||
});
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
reset,
|
||||
} = useForm({
|
||||
resolver: yupResolver(investorExit),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
console.log("hiit useEffectc");
|
||||
if (id && IODetails) {
|
||||
handleCalculate(id, {
|
||||
amount: IODetails?.ioMVNAV,
|
||||
});
|
||||
}
|
||||
reset({
|
||||
amount: IODetails?.ioMVNAV,
|
||||
});
|
||||
}
|
||||
reset({
|
||||
amount: IODetails?.ioMVNAV,
|
||||
}, [IODetails, id]);
|
||||
|
||||
const handleCalculate = async (id, data) => {
|
||||
try {
|
||||
const res = await getDistributionInvestment({ id, data });
|
||||
console.log(res?.data?.data);
|
||||
|
||||
if (res?.error?.status === 401) {
|
||||
setIsCalculateLoading(false);
|
||||
setIsCalcualtedData(false);
|
||||
} else if (res?.data?.statusCode === 200) {
|
||||
setCalculatedDate(res?.data?.data);
|
||||
setIsCalculateLoading(false);
|
||||
setIsCalcualtedData(true);
|
||||
}
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
const [getDistributionInvestment] = useGetDistributionInvestorMutation();
|
||||
|
||||
const investor = yup.object().shape({
|
||||
amount: yup.string().required("Amount is required"),
|
||||
});
|
||||
}, [IODetails, id]);
|
||||
|
||||
const handleCalculate = async (id, data) => {
|
||||
try {
|
||||
const res = await getDistributionInvestment({ id, data });
|
||||
console.log(res?.data?.data);
|
||||
|
||||
if (res?.error?.status === 401) {
|
||||
setIsCalculateLoading(false);
|
||||
setIsCalcualtedData(false);
|
||||
} else if (res?.data?.statusCode === 200) {
|
||||
setCalculatedDate(res?.data?.data);
|
||||
setIsCalculateLoading(false);
|
||||
setIsCalcualtedData(true);
|
||||
}
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
const [getDistributionInvestment] = useGetDistributionInvestorMutation();
|
||||
|
||||
const investor = yup.object().shape({
|
||||
amount: yup.string().required("Amount is required"),
|
||||
});
|
||||
|
||||
// ====================================================[Table Setup]================================================================
|
||||
const tableHeadRow = [
|
||||
|
||||
// ====================================================[Table Setup]================================================================
|
||||
const tableHeadRow = [
|
||||
"Client ID",
|
||||
"First name",
|
||||
"Last name",
|
||||
@@ -134,223 +133,221 @@ const ViewCancel = ({ isOpen, onClose, id: cancleId }) => {
|
||||
"Distribution Percent",
|
||||
"Total Return",
|
||||
"Total return on Investment",
|
||||
];
|
||||
|
||||
const extractedArray = IODetails?.investors?.map((item, index) => ({
|
||||
id: item?.id,
|
||||
"Client ID": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "center"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item?.clientReference_id}
|
||||
</Text>
|
||||
),
|
||||
"First name": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "center"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item.firstName}
|
||||
</Text>
|
||||
),
|
||||
"Last name": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "center"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item.lastName}
|
||||
</Text>
|
||||
),
|
||||
"Investment amount": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
<Badge ms={1} colorScheme="green" me={1}>
|
||||
$
|
||||
</Badge>
|
||||
{/* {`$${formatCurrency(item.InvestedAmount_USD)}`} */}
|
||||
{`${parseFloat(item.InvestedAmount_USD || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`}
|
||||
</Text>
|
||||
),
|
||||
Percentage: (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "center"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item.Investor_Holidings} %
|
||||
</Text>
|
||||
),
|
||||
"Market Value": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
<Badge ms={1} colorScheme="green" me={1}>
|
||||
$
|
||||
</Badge>
|
||||
{`${parseFloat(item.Market_Value || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`}
|
||||
</Text>
|
||||
),
|
||||
"Return on Investment": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "center"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
h={6}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item.Return_On_Investment || 0} %
|
||||
</Text>
|
||||
),
|
||||
Distribution: (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
<Badge ms={1} colorScheme="green" me={1}>
|
||||
$
|
||||
</Badge>
|
||||
{/* {`$${item.Distribution_Amt}`} */}
|
||||
{`${parseFloat(item.Distribution_Amt || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`}
|
||||
</Text>
|
||||
),
|
||||
"Distribution Percent": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "center"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{/* {`$${item.Distribution_Amt}`} */}
|
||||
{`${parseFloat(item.Distribution_Per || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})} %`}
|
||||
</Text>
|
||||
),
|
||||
"Total Return": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
<Badge ms={1} colorScheme="green" me={1}>
|
||||
$
|
||||
</Badge>
|
||||
{/* {`$${formatCurrency(item.Total_Return) || 0}`} */}
|
||||
{`${parseFloat(item.Total_Return || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`}
|
||||
</Text>
|
||||
),
|
||||
"Total return on Investment": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "center"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item.Total_Return_On_Investment || 0} %
|
||||
</Text>
|
||||
),
|
||||
}));
|
||||
|
||||
const handleClose = () => {
|
||||
onClose();
|
||||
setIsFinalCalculateLoading(false);
|
||||
setIsCalcualtedData(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal size={"xl"} isOpen={isOpen} onClose={handleClose}>
|
||||
<ModalOverlay />
|
||||
<ModalContent maxW={1000}>
|
||||
<ModalHeader fontSize={"md"}>Cancel Transaction</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<NormalData
|
||||
emptyMessage={`We don't have any Sponers `}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={extractedArray}
|
||||
/>
|
||||
</ModalBody>
|
||||
{!isMaker() && (
|
||||
<ModalFooter pt={0}>
|
||||
];
|
||||
|
||||
const extractedArray = IODetails?.investors?.map((item, index) => ({
|
||||
id: item?.id,
|
||||
"Client ID": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "center"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item?.clientReference_id}
|
||||
</Text>
|
||||
),
|
||||
"First name": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "center"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item.firstName}
|
||||
</Text>
|
||||
),
|
||||
"Last name": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "center"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item.lastName}
|
||||
</Text>
|
||||
),
|
||||
"Investment amount": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
<Badge ms={1} colorScheme="green" me={1}>
|
||||
$
|
||||
</Badge>
|
||||
{/* {`$${formatCurrency(item.InvestedAmount_USD)}`} */}
|
||||
{`${parseFloat(item.InvestedAmount_USD || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`}
|
||||
</Text>
|
||||
),
|
||||
Percentage: (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "center"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item.Investor_Holidings} %
|
||||
</Text>
|
||||
),
|
||||
"Market Value": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
<Badge ms={1} colorScheme="green" me={1}>
|
||||
$
|
||||
</Badge>
|
||||
{`${parseFloat(item.Market_Value || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`}
|
||||
</Text>
|
||||
),
|
||||
"Return on Investment": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "center"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
h={6}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item.Return_On_Investment || 0} %
|
||||
</Text>
|
||||
),
|
||||
Distribution: (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
<Badge ms={1} colorScheme="green" me={1}>
|
||||
$
|
||||
</Badge>
|
||||
{/* {`$${item.Distribution_Amt}`} */}
|
||||
{`${parseFloat(item.Distribution_Amt || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`}
|
||||
</Text>
|
||||
),
|
||||
"Distribution Percent": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "center"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{/* {`$${item.Distribution_Amt}`} */}
|
||||
{`${parseFloat(item.Distribution_Per || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})} %`}
|
||||
</Text>
|
||||
),
|
||||
"Total Return": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
<Badge ms={1} colorScheme="green" me={1}>
|
||||
$
|
||||
</Badge>
|
||||
{/* {`$${formatCurrency(item.Total_Return) || 0}`} */}
|
||||
{`${parseFloat(item.Total_Return || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`}
|
||||
</Text>
|
||||
),
|
||||
"Total return on Investment": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "center"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item.Total_Return_On_Investment || 0} %
|
||||
</Text>
|
||||
),
|
||||
}));
|
||||
|
||||
const handleClose = () => {
|
||||
onClose();
|
||||
setIsFinalCalculateLoading(false);
|
||||
setIsCalcualtedData(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal size={"xl"} isOpen={isOpen} onClose={handleClose} >
|
||||
<ModalOverlay />
|
||||
<ModalContent maxW={1000}>
|
||||
<ModalHeader fontSize={"md"}>Cancel Transaction</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<NormalData
|
||||
emptyMessage={`We don't have any Sponers `}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={extractedArray}
|
||||
/>
|
||||
</ModalBody>
|
||||
{localStorage?.getItem("role") !== "Maker" && <ModalFooter pt={0}>
|
||||
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={3}
|
||||
py={2}
|
||||
onClick={() => {
|
||||
setActionId(id); // Use the `id` variable from params
|
||||
onConfirmOpen();
|
||||
}}
|
||||
colorScheme="forestGreen"
|
||||
variant={"solid"}
|
||||
cursor={"pointer"}
|
||||
>
|
||||
Approve
|
||||
</Button>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={3}
|
||||
py={2}
|
||||
onClick={() => {
|
||||
setActionId(id); // Use the `id` variable from params
|
||||
onRejectOpen();
|
||||
}}
|
||||
>
|
||||
Reject
|
||||
</Button>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={3}
|
||||
py={2}
|
||||
onClick={() => {
|
||||
setActionId(id); // Use the `id` variable from params
|
||||
onConfirmOpen();
|
||||
}}
|
||||
colorScheme="forestGreen"
|
||||
variant={"solid"}
|
||||
cursor={"pointer"}
|
||||
>
|
||||
Approve
|
||||
</Button>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={3}
|
||||
py={2}
|
||||
onClick={() => {
|
||||
setActionId(id); // Use the `id` variable from params
|
||||
onRejectOpen();
|
||||
}}
|
||||
>
|
||||
Reject
|
||||
</Button>
|
||||
</Box>
|
||||
</ModalFooter>
|
||||
)}
|
||||
</ModalContent>
|
||||
<ApprovedCancelTransaction
|
||||
</ModalFooter>}
|
||||
</ModalContent>
|
||||
<ApprovedCancelTransaction
|
||||
isOpen={isConfirmOpen}
|
||||
onClose={onConfirmClose}
|
||||
onBigModalClose={onClose}
|
||||
@@ -362,8 +359,9 @@ const ViewCancel = ({ isOpen, onClose, id: cancleId }) => {
|
||||
onBigModalClose={onClose}
|
||||
id={cancleId}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ViewCancel;
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ViewCancel;
|
||||
|
||||
@@ -23,9 +23,8 @@ import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
|
||||
import ApproveDistrubationModal from "./ApproveDistrubationModal";
|
||||
import RequestRejectModal from "./RequestRejectModal";
|
||||
import { encryptString, isMaker } from "../../../../Constants/Constants";
|
||||
|
||||
const ViewDistributionInvestor = ({ isOpen, onClose, id: exitId, amount }) => {
|
||||
const ViewDistributionInvestor = ({ isOpen, onClose,id:exitId }) => {
|
||||
const params = useParams();
|
||||
const toast = useToast();
|
||||
const id = params?.id;
|
||||
@@ -72,15 +71,19 @@ const ViewDistributionInvestor = ({ isOpen, onClose, id: exitId, amount }) => {
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
console.log("hiit useEffectc");
|
||||
// handleCalculate(id, {
|
||||
// amount: IODetails?.ioMVNAV,
|
||||
// });
|
||||
if (id && IODetails) {
|
||||
handleCalculate(id, {
|
||||
amount: Math.abs(amount),
|
||||
amount: IODetails?.ioMVNAV,
|
||||
});
|
||||
}
|
||||
}
|
||||
reset({
|
||||
amount: amount,
|
||||
amount: IODetails?.ioMVNAV,
|
||||
});
|
||||
}, [IODetails, id, amount]);
|
||||
}, [IODetails, id]);
|
||||
|
||||
const handleCalculate = async (id, data) => {
|
||||
try {
|
||||
@@ -172,7 +175,7 @@ const ViewDistributionInvestor = ({ isOpen, onClose, id: exitId, amount }) => {
|
||||
"Distriution Amt($)": (
|
||||
<Box minW={24} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{IODetails?.ioTransactionRecords?.Pending[index]?.transactionAmount?.toLocaleString(undefined, {
|
||||
{item?.distribution_amt?.toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
@@ -197,6 +200,7 @@ const ViewDistributionInvestor = ({ isOpen, onClose, id: exitId, amount }) => {
|
||||
setIsFinalCalculateLoading(false);
|
||||
setIsCalcualtedData(false);
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<Modal size={"xl"} isOpen={isOpen} onClose={handleClose}>
|
||||
@@ -214,43 +218,41 @@ const ViewDistributionInvestor = ({ isOpen, onClose, id: exitId, amount }) => {
|
||||
/>
|
||||
</ModalBody>
|
||||
{/* ...(localStorage?.getItem("role") !== "Maker" ? ["Status"] : []), */}
|
||||
{!isMaker() && (
|
||||
<ModalFooter pt={0}>
|
||||
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={3}
|
||||
py={2}
|
||||
onClick={() => {
|
||||
setActionId(id); // Use the `id` variable from params
|
||||
onConfirmOpen();
|
||||
}}
|
||||
colorScheme="forestGreen"
|
||||
variant={"solid"}
|
||||
cursor={"pointer"}
|
||||
>
|
||||
Approve
|
||||
</Button>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={3}
|
||||
py={2}
|
||||
onClick={() => {
|
||||
setActionId(id); // Use the `id` variable from params
|
||||
onRejectOpen();
|
||||
}}
|
||||
>
|
||||
Reject
|
||||
</Button>
|
||||
</Box>
|
||||
</ModalFooter>
|
||||
)}
|
||||
{localStorage?.getItem("role") !== "Maker" &&<ModalFooter pt={0}>
|
||||
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={3}
|
||||
py={2}
|
||||
onClick={() => {
|
||||
setActionId(id); // Use the `id` variable from params
|
||||
onConfirmOpen();
|
||||
}}
|
||||
colorScheme="forestGreen"
|
||||
variant={"solid"}
|
||||
cursor={"pointer"}
|
||||
>
|
||||
Approve
|
||||
</Button>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={3}
|
||||
py={2}
|
||||
onClick={() => {
|
||||
setActionId(id); // Use the `id` variable from params
|
||||
onRejectOpen();
|
||||
}}
|
||||
>
|
||||
Reject
|
||||
</Button>
|
||||
</Box>
|
||||
</ModalFooter>}
|
||||
</ModalContent>
|
||||
<ApproveDistrubationModal
|
||||
isOpen={isConfirmOpen}
|
||||
|
||||
@@ -1,332 +1,329 @@
|
||||
import {
|
||||
Alert,
|
||||
AlertIcon,
|
||||
Box,
|
||||
Button,
|
||||
FormControl,
|
||||
FormErrorMessage,
|
||||
FormLabel,
|
||||
HStack,
|
||||
Input,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Switch,
|
||||
Table,
|
||||
Tbody,
|
||||
Text,
|
||||
Textarea,
|
||||
Th,
|
||||
Tr,
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import NormalData from "../../../../Components/DataTable/NormalTable";
|
||||
import { useContext, useState } from "react";
|
||||
import { AddIcon } from "@chakra-ui/icons";
|
||||
import {
|
||||
useExitIOTransactionMutation,
|
||||
useGetDistributedToInvestorMutation,
|
||||
useGetDistributionInvestorMutation,
|
||||
useUpdateExitToInvestorMutation,
|
||||
} from "../../../../Services/io.service";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useEffect } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import * as yup from "yup";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import ToastBox from "../../../../Components/ToastBox";
|
||||
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
|
||||
Alert,
|
||||
AlertIcon,
|
||||
Box,
|
||||
Button,
|
||||
FormControl,
|
||||
FormErrorMessage,
|
||||
FormLabel,
|
||||
HStack,
|
||||
Input,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Switch,
|
||||
Table,
|
||||
Tbody,
|
||||
Text,
|
||||
Textarea,
|
||||
Th,
|
||||
Tr,
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import NormalData from "../../../../Components/DataTable/NormalTable";
|
||||
import { useContext, useState } from "react";
|
||||
import { AddIcon } from "@chakra-ui/icons";
|
||||
import {
|
||||
useExitIOTransactionMutation,
|
||||
useGetDistributedToInvestorMutation,
|
||||
useGetDistributionInvestorMutation,
|
||||
useUpdateExitToInvestorMutation,
|
||||
} from "../../../../Services/io.service";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useEffect } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import * as yup from "yup";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import ToastBox from "../../../../Components/ToastBox";
|
||||
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
|
||||
import ApprovedExit from "./ApprovedExit";
|
||||
import RequestRejectModal from "./RequestRejectModal";
|
||||
import { encryptString, isMaker } from "../../../../Constants/Constants";
|
||||
|
||||
const ViewExit = ({ isOpen, onClose ,id:investerId}) => {
|
||||
const params = useParams();
|
||||
const toast = useToast();
|
||||
const id = params?.id;
|
||||
const [isCalculateLoading, setIsCalculateLoading] = useState(false);
|
||||
const [isFinalCalculateLoading, setIsFinalCalculateLoading] = useState(false);
|
||||
const [calcualtedData, setCalculatedDate] = useState(null);
|
||||
const [isCalcualtedData, setIsCalcualtedData] = useState(false);
|
||||
const { IODetails } = useContext(GlobalStateContext);
|
||||
const [actionId, setActionId] = useState(false);
|
||||
|
||||
const ViewExit = ({ isOpen, onClose, id: investerId }) => {
|
||||
const params = useParams();
|
||||
const toast = useToast();
|
||||
const id = params?.id;
|
||||
const [isCalculateLoading, setIsCalculateLoading] = useState(false);
|
||||
const [isFinalCalculateLoading, setIsFinalCalculateLoading] = useState(false);
|
||||
const [calcualtedData, setCalculatedDate] = useState(null);
|
||||
const [isCalcualtedData, setIsCalcualtedData] = useState(false);
|
||||
const { IODetails } = useContext(GlobalStateContext);
|
||||
const [actionId, setActionId] = useState(false);
|
||||
|
||||
const {
|
||||
isOpen: isConfirmOpen,
|
||||
onOpen: onConfirmOpen,
|
||||
onClose: onConfirmClose,
|
||||
} = useDisclosure();
|
||||
const {
|
||||
isOpen: isRejectOpen,
|
||||
onOpen: onRejectOpen,
|
||||
onClose: onRejectClose,
|
||||
} = useDisclosure();
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
reset,
|
||||
} = useForm({
|
||||
resolver: yupResolver(),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
console.log("hiit useEffectc");
|
||||
if (id && IODetails) {
|
||||
const {
|
||||
isOpen: isConfirmOpen,
|
||||
onOpen: onConfirmOpen,
|
||||
onClose: onConfirmClose,
|
||||
} = useDisclosure();
|
||||
const {
|
||||
isOpen: isRejectOpen,
|
||||
onOpen: onRejectOpen,
|
||||
onClose: onRejectClose,
|
||||
} = useDisclosure();
|
||||
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
reset,
|
||||
} = useForm({
|
||||
resolver: yupResolver(),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
console.log("hiit useEffectc");
|
||||
if (id && IODetails) {
|
||||
handleCalculate(id, {
|
||||
amount: IODetails?.ioMVNAV,
|
||||
});
|
||||
}
|
||||
reset({
|
||||
amount: IODetails?.ioMVNAV,
|
||||
}
|
||||
reset({
|
||||
amount: IODetails?.ioMVNAV,
|
||||
});
|
||||
}, [IODetails, id]);
|
||||
|
||||
const handleCalculate = async (id, data) => {
|
||||
try {
|
||||
|
||||
const res = await getDistributionInvestment({ id, data });
|
||||
console.log(res?.data?.data);
|
||||
|
||||
if (res?.error?.status === 401) {
|
||||
setIsCalculateLoading(false);
|
||||
setIsCalcualtedData(false);
|
||||
} else if (res?.data?.statusCode === 200) {
|
||||
setCalculatedDate(res?.data?.data);
|
||||
setIsCalculateLoading(false);
|
||||
setIsCalcualtedData(true);
|
||||
}
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
const [getDistributionInvestment] = useGetDistributionInvestorMutation();
|
||||
|
||||
const investor = yup.object().shape({
|
||||
amount: yup.string().required("Amount is required"),
|
||||
});
|
||||
}, [IODetails, id]);
|
||||
|
||||
// ====================================================[Table Setup]================================================================
|
||||
const tableHeadRow = [
|
||||
"Sr No.",
|
||||
"Client Id",
|
||||
"First name",
|
||||
"Last Name",
|
||||
"Amount",
|
||||
"Holding (%)",
|
||||
"Exit Amt($)",
|
||||
];
|
||||
|
||||
const handleCalculate = async (id, data) => {
|
||||
try {
|
||||
const res = await getDistributionInvestment({ id, data });
|
||||
console.log(res?.data?.data);
|
||||
|
||||
|
||||
const extractedArray = calcualtedData?.data?.map((item, index) => ({
|
||||
id: item?.id,
|
||||
"Sr No.": (
|
||||
<Box
|
||||
w={9}
|
||||
display={"flex"}
|
||||
alignItems={"center"}
|
||||
isTruncated={true}
|
||||
h={25}
|
||||
>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{index + 1}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Client Id": (
|
||||
<Box w={100} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{item?.clientId}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"First name": (
|
||||
<Box minW={24} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{item?.firstName}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Last Name": (
|
||||
<Box minW={24} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{item?.lastName}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
Amount: (
|
||||
<Box minW={24} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{item?.amount?.toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Holding (%)": (
|
||||
<Box minW={24} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{item?.investor_holidings?.toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}%
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Exit Amt($)": (
|
||||
<Box minW={24} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{item?.distribution_amt?.toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
}));
|
||||
|
||||
const onSubmit = async (data) => {
|
||||
setIsCalculateLoading(true);
|
||||
|
||||
try {
|
||||
const res = await getDistributionInvestment({ id, data });
|
||||
console.log(res?.data?.data);
|
||||
|
||||
if (res?.error?.status === 401) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||
),
|
||||
});
|
||||
setIsCalculateLoading(false);
|
||||
setIsCalcualtedData(false);
|
||||
} else if (res?.data?.statusCode === 200) {
|
||||
setCalculatedDate(res?.data?.data);
|
||||
toast({
|
||||
render: () => <ToastBox message={res?.data?.message} />,
|
||||
});
|
||||
setIsCalculateLoading(false);
|
||||
setIsCalcualtedData(true);
|
||||
}
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
onClose();
|
||||
setIsFinalCalculateLoading(false);
|
||||
setIsCalcualtedData(false);
|
||||
};
|
||||
|
||||
console.log(id);
|
||||
|
||||
|
||||
if (res?.error?.status === 401) {
|
||||
setIsCalculateLoading(false);
|
||||
setIsCalcualtedData(false);
|
||||
} else if (res?.data?.statusCode === 200) {
|
||||
setCalculatedDate(res?.data?.data);
|
||||
setIsCalculateLoading(false);
|
||||
setIsCalcualtedData(true);
|
||||
}
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
const [getDistributionInvestment] = useGetDistributionInvestorMutation();
|
||||
|
||||
const investor = yup.object().shape({
|
||||
amount: yup.string().required("Amount is required"),
|
||||
});
|
||||
|
||||
// ====================================================[Table Setup]================================================================
|
||||
const tableHeadRow = [
|
||||
"Sr No.",
|
||||
"Client Id",
|
||||
"First name",
|
||||
"Last Name",
|
||||
"Amount",
|
||||
"Holding (%)",
|
||||
"Exit Amt($)",
|
||||
];
|
||||
|
||||
const extractedArray = calcualtedData?.data?.map((item, index) => ({
|
||||
id: item?.id,
|
||||
"Sr No.": (
|
||||
<Box
|
||||
w={9}
|
||||
display={"flex"}
|
||||
alignItems={"center"}
|
||||
isTruncated={true}
|
||||
h={25}
|
||||
>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{index + 1}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Client Id": (
|
||||
<Box w={100} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{item?.clientId}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"First name": (
|
||||
<Box minW={24} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{item?.firstName}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Last Name": (
|
||||
<Box minW={24} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{item?.lastName}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
Amount: (
|
||||
<Box minW={24} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{item?.amount?.toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Holding (%)": (
|
||||
<Box minW={24} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{item?.investor_holidings?.toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
%
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Exit Amt($)": (
|
||||
<Box minW={24} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{item?.distribution_amt?.toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
}));
|
||||
|
||||
const onSubmit = async (data) => {
|
||||
setIsCalculateLoading(true);
|
||||
|
||||
try {
|
||||
const res = await getDistributionInvestment({ id, data });
|
||||
console.log(res?.data?.data);
|
||||
|
||||
if (res?.error?.status === 401) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||
),
|
||||
});
|
||||
setIsCalculateLoading(false);
|
||||
setIsCalcualtedData(false);
|
||||
} else if (res?.data?.statusCode === 200) {
|
||||
setCalculatedDate(res?.data?.data);
|
||||
toast({
|
||||
render: () => <ToastBox message={res?.data?.message} />,
|
||||
});
|
||||
setIsCalculateLoading(false);
|
||||
setIsCalcualtedData(true);
|
||||
}
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
onClose();
|
||||
setIsFinalCalculateLoading(false);
|
||||
setIsCalcualtedData(false);
|
||||
};
|
||||
|
||||
console.log(id);
|
||||
|
||||
return (
|
||||
<Modal size={"xl"} isOpen={isOpen} onClose={handleClose}>
|
||||
<ModalOverlay />
|
||||
<ModalContent maxW={1000}>
|
||||
<ModalHeader fontSize={"md"}>Exit Transaction</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
{/* <Text as="label" mb="5px" fontSize="sm" fontWeight={500}>
|
||||
return (
|
||||
<Modal size={"xl"} isOpen={isOpen} onClose={handleClose} >
|
||||
<ModalOverlay />
|
||||
<ModalContent maxW={1000}>
|
||||
<ModalHeader fontSize={"md"}>Exit Transaction</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
{/* <Text as="label" mb="5px" fontSize="sm" fontWeight={500}>
|
||||
Amount to Distribute
|
||||
</Text> */}
|
||||
<HStack
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
as={"form"}
|
||||
mb={4}
|
||||
alignItems={"center"}
|
||||
>
|
||||
{/* <Input placeholder="$00.00" size={"sm"} className="col" /> */}
|
||||
{/* <FormControl isInvalid={errors.amount} isRequired>*/}
|
||||
<Text textAlign={"right"} fontSize={"sm"}>
|
||||
Exit Amount :
|
||||
</Text>
|
||||
<Text
|
||||
textAlign={"start"}
|
||||
bg={"green.100"}
|
||||
p={2}
|
||||
rounded={"md"}
|
||||
fontSize={"sm"}
|
||||
pt={1}
|
||||
pb={1}
|
||||
fontWeight={600}
|
||||
>
|
||||
${" "}
|
||||
{parseFloat(IODetails?.ioMVNAV || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
</Text>
|
||||
|
||||
{/* </FormControl> */}
|
||||
</HStack>
|
||||
|
||||
{/* {calcualtedData && ( */}
|
||||
<NormalData
|
||||
emptyMessage={`We don't have any Sponers `}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={extractedArray}
|
||||
// total={<Total />}
|
||||
// isLoading={isLoading}
|
||||
/>
|
||||
{/* ) } */}
|
||||
</ModalBody>
|
||||
{!isMaker() && (
|
||||
<ModalFooter pt={0}>
|
||||
<HStack onSubmit={handleSubmit(onSubmit)} as={"form"} mb={4} alignItems={'center'}>
|
||||
{/* <Input placeholder="$00.00" size={"sm"} className="col" /> */}
|
||||
{/* <FormControl isInvalid={errors.amount} isRequired>*/}
|
||||
<Text textAlign={"right"} fontSize={"sm"}>
|
||||
Exit Amount :
|
||||
</Text>
|
||||
<Text
|
||||
textAlign={"start"}
|
||||
bg={"green.100"}
|
||||
p={2}
|
||||
rounded={"md"}
|
||||
fontSize={"sm"}
|
||||
pt={1}
|
||||
pb={1}
|
||||
fontWeight={600}
|
||||
>
|
||||
${" "}
|
||||
{parseFloat(IODetails?.ioMVNAV || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
</Text>
|
||||
|
||||
{/* </FormControl> */}
|
||||
</HStack>
|
||||
|
||||
{/* {calcualtedData && ( */}
|
||||
<NormalData
|
||||
emptyMessage={`We don't have any Sponers `}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={extractedArray}
|
||||
// total={<Total />}
|
||||
// isLoading={isLoading}
|
||||
/>
|
||||
{/* ) } */}
|
||||
</ModalBody>
|
||||
{localStorage?.getItem("role") !== "Maker" && <ModalFooter pt={0}>
|
||||
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={3}
|
||||
py={2}
|
||||
onClick={() => {
|
||||
setActionId(id); // Use the `id` variable from params
|
||||
onConfirmOpen();
|
||||
}}
|
||||
colorScheme="forestGreen"
|
||||
variant={"solid"}
|
||||
cursor={"pointer"}
|
||||
>
|
||||
Approve
|
||||
</Button>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={3}
|
||||
py={2}
|
||||
onClick={() => {
|
||||
setActionId(id); // Use the `id` variable from params
|
||||
onRejectOpen();
|
||||
}}
|
||||
>
|
||||
Reject
|
||||
</Button>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={3}
|
||||
py={2}
|
||||
onClick={() => {
|
||||
setActionId(id); // Use the `id` variable from params
|
||||
onConfirmOpen();
|
||||
}}
|
||||
colorScheme="forestGreen"
|
||||
variant={"solid"}
|
||||
cursor={"pointer"}
|
||||
>
|
||||
Approve
|
||||
</Button>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={3}
|
||||
py={2}
|
||||
onClick={() => {
|
||||
setActionId(id); // Use the `id` variable from params
|
||||
onRejectOpen();
|
||||
}}
|
||||
>
|
||||
Reject
|
||||
</Button>
|
||||
</Box>
|
||||
</ModalFooter>
|
||||
)}
|
||||
</ModalContent>
|
||||
<ApprovedExit
|
||||
isOpen={isConfirmOpen}
|
||||
onClose={onConfirmClose}
|
||||
onBigModalClose={onClose}
|
||||
id={investerId}
|
||||
/>
|
||||
<RequestRejectModal
|
||||
isOpen={isRejectOpen}
|
||||
onClose={onRejectClose}
|
||||
onBigModalClose={onClose}
|
||||
id={investerId}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ViewExit;
|
||||
</ModalFooter>}
|
||||
</ModalContent>
|
||||
<ApprovedExit
|
||||
isOpen={isConfirmOpen}
|
||||
onClose={onConfirmClose}
|
||||
onBigModalClose={onClose}
|
||||
id={investerId}
|
||||
/>
|
||||
<RequestRejectModal
|
||||
isOpen={isRejectOpen}
|
||||
onClose={onRejectClose}
|
||||
onBigModalClose={onClose}
|
||||
id={investerId}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ViewExit;
|
||||
|
||||
@@ -1,29 +1,57 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||
import {
|
||||
Box,
|
||||
Tab,
|
||||
Divider,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Heading,
|
||||
Input,
|
||||
Select,
|
||||
Textarea,
|
||||
Button,
|
||||
Text,
|
||||
Image,
|
||||
Tabs,
|
||||
TabList,
|
||||
Tab,
|
||||
TabPanel,
|
||||
TabPanels,
|
||||
Tabs,
|
||||
Tooltip,
|
||||
Switch,
|
||||
useDisclosure,
|
||||
} from "@chakra-ui/react";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import * as yup from "yup";
|
||||
import {
|
||||
AddIcon,
|
||||
CloseIcon,
|
||||
DeleteIcon,
|
||||
EditIcon,
|
||||
ViewIcon,
|
||||
WarningTwoIcon,
|
||||
} from "@chakra-ui/icons";
|
||||
import { TiWarning } from "react-icons/ti";
|
||||
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||
import Distribution from "./Destribution";
|
||||
import InvestmentDocument from "./InvestmentDocument";
|
||||
import Investors from "./Investors";
|
||||
import IOArtifacts from "./IOArtifacts";
|
||||
import IOCashDetails from "./IOCashDetails";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import FormField from "../../../Components/FormField";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import AddIOCharges from "../AddIOCharges";
|
||||
import FormInputMain from "../../../Components/FormInputMain";
|
||||
import DataTable from "../../../Components/DataTable/DataTable";
|
||||
import { debounce } from "../../Master/Sponser/AddSponser";
|
||||
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||
import { formatDate } from "../../../Components/Functions/UTCConvertor";
|
||||
import IODetails from "./IODetails";
|
||||
import IONAVDetails from "./IONAVDetails";
|
||||
import KeyMerits from "./KeyMerits";
|
||||
import { useAuthProfileQuery } from "../../Services/token.serivce";
|
||||
import { encryptString } from "../../Constants/Constants";
|
||||
import IOArtifacts from "./IOArtifacts";
|
||||
import Investors from "./Investors";
|
||||
import IOCashDetails from "./IOCashDetails";
|
||||
import IONAVDetails from "./IONAVDetails";
|
||||
import Distribution from "./Destribution";
|
||||
import InvestmentDocuments from "../InvestmentDocuments";
|
||||
import InvestmentDocument from "./InvestmentDocument";
|
||||
|
||||
const schema = yup.object().shape({
|
||||
ioName: yup.string().required("Arabic name is required"),
|
||||
@@ -31,9 +59,7 @@ const schema = yup.object().shape({
|
||||
discription: yup.string().required("Description is required"),
|
||||
discriptionArabic: yup.string().required("Arabic Description is required"),
|
||||
typeName: yup.string().required("Investment type is required"),
|
||||
typeNameArabic: yup
|
||||
.string()
|
||||
.required("Investment type arabic name is required"),
|
||||
typeNameArabic: yup.string().required("Investment type arabic name is required"),
|
||||
sponserName: yup.string().required("Sponsorer name is required"),
|
||||
sponserNameArabic: yup
|
||||
.string()
|
||||
@@ -267,7 +293,7 @@ const EditViewIO = () => {
|
||||
isRequired: true,
|
||||
section: " ",
|
||||
width: "32.3%",
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "Name (Arabic)",
|
||||
placeHolder: " ",
|
||||
|
||||
@@ -360,7 +360,7 @@ const IOArtifactsAdd = ({
|
||||
isOpen={alert}
|
||||
onClose={handleAlertClose}
|
||||
alertHandler={handleSave}
|
||||
message={"Are you sure you want to add this artifact?"}
|
||||
message={"Are you sure you want to update this artifact?"}
|
||||
isLoading={loading}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -112,18 +112,8 @@ const AmountInvested = ({ isOpen, onClose }) => {
|
||||
});
|
||||
};
|
||||
|
||||
const handleModalClose = () => {
|
||||
reset({
|
||||
transactionDate: "",
|
||||
Total_Amount: IODetails?.totalAmtInvestmentInUSD || 0,
|
||||
amountInvested: 0,
|
||||
IoCash: IODetails?.totalAmtInvestmentInUSD || 0,
|
||||
});
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={handleModalClose}>
|
||||
<Modal isOpen={isOpen} onClose={onClose}>
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader fontSize={"md"}>Amount Invested</ModalHeader>
|
||||
@@ -256,7 +246,7 @@ const AmountInvested = ({ isOpen, onClose }) => {
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button size={"sm"} rounded={"sm"} mr={3} onClick={handleModalClose}>
|
||||
<Button size={"sm"} rounded={"sm"} mr={3} onClick={onClose}>
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
|
||||
@@ -495,7 +495,7 @@ const DistributionInvestor = ({ isOpen, onClose }) => {
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button size={"sm"} rounded={"sm"} mr={3} onClick={handleClose}>
|
||||
<Button size={"sm"} rounded={"sm"} mr={3} onClick={onClose}>
|
||||
Close
|
||||
</Button>
|
||||
</>
|
||||
|
||||
@@ -58,7 +58,7 @@ const UpdateIOStatus = ({ isOpen, onClose, status }) => {
|
||||
let res;
|
||||
|
||||
// If selectedItem is 'Cancelled', make the updateCancelStatus API call
|
||||
if (selectedItem === import.meta.env.VITE_STATUS_CANCELLED) {
|
||||
if (selectedItem === "Cancelled") {
|
||||
res = await updateCancleStatus({
|
||||
id
|
||||
});
|
||||
@@ -119,17 +119,17 @@ const UpdateIOStatus = ({ isOpen, onClose, status }) => {
|
||||
mb={1.5}
|
||||
textTransform={"none"}
|
||||
colorScheme={
|
||||
selectedItem === import.meta.env.VITE_STATUS_DRAFT
|
||||
selectedItem === "Draft"
|
||||
? "gray"
|
||||
: selectedItem === import.meta.env.VITE_STATUS_PROCESSING
|
||||
: selectedItem === "Processing"
|
||||
? "yellow"
|
||||
: selectedItem === import.meta.env.VITE_STATUS_OPEN
|
||||
: selectedItem === "Open"
|
||||
? "blue"
|
||||
: selectedItem === import.meta.env.VITE_STATUS_CLOSED
|
||||
: selectedItem === "Closed"
|
||||
? "green"
|
||||
: selectedItem === import.meta.env.VITE_STATUS_EXITED
|
||||
: selectedItem === "Exited"
|
||||
? "red"
|
||||
: selectedItem === import.meta.env.VITE_STATUS_CANCELLED
|
||||
: selectedItem === "Cancelled"
|
||||
? "orange"
|
||||
: "purple"
|
||||
}
|
||||
@@ -154,24 +154,24 @@ const UpdateIOStatus = ({ isOpen, onClose, status }) => {
|
||||
<Badge
|
||||
rounded={"full"}
|
||||
pt={1.5}
|
||||
pb={1.5}
|
||||
pb={1.5}
|
||||
ps={4}
|
||||
pe={4}
|
||||
mt={1.5}
|
||||
mb={1.5}
|
||||
textTransform={"none"}
|
||||
colorScheme={
|
||||
statusAdmin === import.meta.env.VITE_STATUS_DRAFT
|
||||
statusAdmin === "Draft"
|
||||
? "gray"
|
||||
: statusAdmin === import.meta.env.VITE_STATUS_PROCESSING
|
||||
: statusAdmin === "Processing"
|
||||
? "yellow"
|
||||
: statusAdmin === import.meta.env.VITE_STATUS_OPEN
|
||||
: statusAdmin === "Open"
|
||||
? "blue"
|
||||
: statusAdmin === import.meta.env.VITE_STATUS_CLOSED
|
||||
: statusAdmin === "Closed"
|
||||
? "green"
|
||||
: statusAdmin === import.meta.env.VITE_STATUS_EXITED
|
||||
: statusAdmin === "Exited"
|
||||
? "red"
|
||||
: statusAdmin === import.meta.env.VITE_STATUS_CANCELLED
|
||||
: statusAdmin === "Cancelled"
|
||||
? "orange"
|
||||
: "purple"
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@ const ViewIOTable = () => {
|
||||
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||
});
|
||||
|
||||
console.log(data);
|
||||
|
||||
// ===============================[ Table Header ]
|
||||
const tableHeadRow = [
|
||||
@@ -241,17 +242,17 @@ const ViewIOTable = () => {
|
||||
textTransform={"none"}
|
||||
// variant={"solid"}
|
||||
colorScheme={
|
||||
item?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_DRAFT
|
||||
item?.ioStatus?.statusAdmin === "Draft"
|
||||
? "gray"
|
||||
: item?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_PROCESSING
|
||||
: item?.ioStatus?.statusAdmin === "Processing"
|
||||
? "yellow"
|
||||
: item?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_OPEN
|
||||
: item?.ioStatus?.statusAdmin === "Open"
|
||||
? "blue"
|
||||
: item?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_CLOSED
|
||||
: item?.ioStatus?.statusAdmin === "Closed"
|
||||
? "green"
|
||||
: item?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_EXITED
|
||||
: item?.ioStatus?.statusAdmin === "Exited"
|
||||
? "red"
|
||||
: item?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_CANCELLED
|
||||
: item?.ioStatus?.statusAdmin === "Canclled"
|
||||
? "orange"
|
||||
: "purple"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Icon,
|
||||
Input,
|
||||
keyframes,
|
||||
Stack,
|
||||
Tab,
|
||||
@@ -8,29 +10,40 @@ import {
|
||||
TabPanel,
|
||||
TabPanels,
|
||||
Tabs,
|
||||
useDisclosure
|
||||
Text,
|
||||
useDisclosure,
|
||||
} from "@chakra-ui/react";
|
||||
import { useContext, useState } from "react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import FormInputView from "../../../Components/FormInputView";
|
||||
import { useForm } from "react-hook-form"; // assuming react-hook-form is used
|
||||
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||
import InvestmentDocument from "../CreateIO/InvestmentDocument";
|
||||
import Investors from "../CreateIO/Investors";
|
||||
import IOArtifacts from "../CreateIO/IOArtifacts";
|
||||
import KeyMerits from "../CreateIO/KeyMerits";
|
||||
import { ArrowBackIcon, RepeatIcon } from "@chakra-ui/icons";
|
||||
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||
import ViewIOdataHeader from "./ViewIOdataHeader";
|
||||
import ViewIOdetails from "./ViewIOdetails";
|
||||
import ViewIOdocs from "./ViewIOdocs";
|
||||
import ViewKeyMerits from "./ViewKeyMerits";
|
||||
import ViewIOartifacts from "./ViewIOartifacts";
|
||||
import ViewInvestors from "./ViewInvestors";
|
||||
import ViewIOcash from "./ViewIOcash";
|
||||
import ViewIOnav from "./ViewIOnav";
|
||||
import ViewDistribution from "./ViewDistribution";
|
||||
import InvestmentDocument from "../CreateIO/InvestmentDocument";
|
||||
import KeyMerits from "../CreateIO/KeyMerits";
|
||||
import Investors from "../CreateIO/Investors";
|
||||
import EditIO from "../EditIO/EditIO";
|
||||
import IOArtifacts from "../CreateIO/IOArtifacts";
|
||||
// import IOCashDetails from "../CreateIO/IOCashDetailsold";
|
||||
// import IONAVDetails from "../CreateIO/IONAVDetailsOld";
|
||||
import { GoDotFill } from "react-icons/go";
|
||||
import {
|
||||
useGetIOByIdQuery,
|
||||
useGetIOprepopulateDataQuery,
|
||||
} from "../../../Services/io.service";
|
||||
import { useGetIOByIdQuery, useGetIOprepopulateDataQuery } from "../../../Services/io.service";
|
||||
import UnderConstruction from "../../UnderConstruction";
|
||||
import Destribution from "../CreateIO/Destribution";
|
||||
import IOCashDetails from "../CreateIO/IOCashDetails/IOCashDetails";
|
||||
import IONAVDetails from "../CreateIO/IONAVDetails/IONAVDetails";
|
||||
import IOTransaction from "../CreateIO/IOTransaction/IOTransaction";
|
||||
import { GoDotFill } from "react-icons/go";
|
||||
|
||||
const rotate = keyframes`
|
||||
from {
|
||||
@@ -56,6 +69,7 @@ const ViewIOdata = () => {
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [isRefetchLoading, setIsRefetchLoading] = useState(false);
|
||||
const { IODetails, setIODetails } = useContext(GlobalStateContext);
|
||||
console.log(IODetails?.isInvestedAmount);
|
||||
|
||||
const tabs = [
|
||||
{ label: "IO Details", content: <ViewIOdetails data={data?.data} /> },
|
||||
@@ -179,19 +193,13 @@ const ViewIOdata = () => {
|
||||
cursor={"pointer"}
|
||||
/>
|
||||
</Box> */}
|
||||
<Stack
|
||||
position={"absolute"}
|
||||
right={1}
|
||||
bottom={1}
|
||||
direction="row"
|
||||
spacing={4}
|
||||
>
|
||||
<Stack position={"absolute"} right={1} bottom={1} direction="row" spacing={4}>
|
||||
<Button
|
||||
isLoading={isRefetchLoading}
|
||||
loadingText="Refresh"
|
||||
colorScheme="forestGreen"
|
||||
variant="solid"
|
||||
size={"xs"}
|
||||
size={'xs'}
|
||||
onClick={handleRefresh}
|
||||
fontWeight={400}
|
||||
>
|
||||
|
||||
@@ -1,59 +1,60 @@
|
||||
import {
|
||||
Badge,
|
||||
Box,
|
||||
HStack,
|
||||
Icon,
|
||||
Button,
|
||||
Divider,
|
||||
Image,
|
||||
Menu,
|
||||
MenuButton,
|
||||
MenuItem,
|
||||
MenuList,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Portal,
|
||||
Text,
|
||||
useDisclosure,
|
||||
MenuItemOption,
|
||||
MenuGroup,
|
||||
MenuOptionGroup,
|
||||
MenuDivider,
|
||||
Badge,
|
||||
Box,
|
||||
Icon,
|
||||
HStack,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import { useContext, useRef } from "react";
|
||||
import { GrGallery } from "react-icons/gr";
|
||||
import header from "../../../assets/IOheader.png";
|
||||
import { HiDotsVertical } from "react-icons/hi";
|
||||
import { useParams } from "react-router-dom";
|
||||
import Loader01 from "../../../Components/Loaders/Loader01";
|
||||
import ToastBox from "../../../Components/ToastBox";
|
||||
import {
|
||||
decryptString,
|
||||
encryptString,
|
||||
isMaker,
|
||||
} from "../../../Constants/Constants";
|
||||
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||
import { useUpdateTransactionMutation } from "../../../Services/io.service";
|
||||
import { Link, useParams } from "react-router-dom";
|
||||
import AmountInvested from "./HeaderModal/AmountInvested";
|
||||
import Cancle from "./HeaderModal/Cancle";
|
||||
import DistributionInvestor from "./HeaderModal/DistributionInvestor";
|
||||
import DistributionSponsor from "./HeaderModal/DistributionSponsor";
|
||||
import Exit from "./HeaderModal/Exit";
|
||||
import FeesExpenses from "./HeaderModal/FeesExpenses";
|
||||
import DistributionSponsor from "./HeaderModal/DistributionSponsor";
|
||||
import DistributionInvestor from "./HeaderModal/DistributionInvestor";
|
||||
import UpdateIONav from "./HeaderModal/UpdateIONav";
|
||||
import UpdateIOStatus from "./HeaderModal/UpdateIOStatus";
|
||||
import { useAuthProfileQuery } from "../../../Services/token.serivce";
|
||||
import { useContext, useRef } from "react";
|
||||
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||
import Exit from "./HeaderModal/Exit";
|
||||
import Cancle from "./HeaderModal/Cancle";
|
||||
import { AddIcon } from "@chakra-ui/icons";
|
||||
import { GrGallery } from "react-icons/gr";
|
||||
import Loader01 from "../../../Components/Loaders/Loader01";
|
||||
import { useUpdateTransactionMutation } from "../../../Services/io.service";
|
||||
import ToastBox from "../../../Components/ToastBox";
|
||||
// import { formatCurrency } from "../../../Components/CurrencyInput";
|
||||
// import { removeTrailingZeros } from "../../../Constants/Constants";
|
||||
|
||||
const ViewIOdataHeader = ({ data, isLoading }) => {
|
||||
const params = useParams();
|
||||
const toast = useToast();
|
||||
const id = params?.id;
|
||||
const params = useParams()
|
||||
const toast = useToast();
|
||||
const id = params?.id
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const btnRef = useRef();
|
||||
const { IODetails, isIOloading } = useContext(GlobalStateContext);
|
||||
|
||||
const { data: authProfile } = useAuthProfileQuery();
|
||||
if (authProfile?.data?.role) {
|
||||
localStorage.setItem("role", encryptString(authProfile.data.role));
|
||||
} else {
|
||||
console.warn("Role is undefined or null. Skipping localStorage update.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
const {
|
||||
isOpen: isInvestmentOpen,
|
||||
onOpen: onInvestmentOpen,
|
||||
@@ -105,83 +106,95 @@ const ViewIOdataHeader = ({ data, isLoading }) => {
|
||||
fontSize: "0.875rem",
|
||||
fontWeight: "400",
|
||||
};
|
||||
|
||||
const [updateTransaction] = useUpdateTransactionMutation();
|
||||
|
||||
const handleDistributionInvestors = async () => {
|
||||
console.log(
|
||||
import.meta.env.VITE_IMAGE_URL +
|
||||
IODetails?.artifactsImage?.[0]?.artifactPathName
|
||||
);
|
||||
|
||||
const [updateTransaction] = useUpdateTransactionMutation()
|
||||
|
||||
const handleDistributionInvestors = async () =>{
|
||||
|
||||
try {
|
||||
const res = await updateTransaction(id);
|
||||
|
||||
if (res?.data) {
|
||||
const res = await updateTransaction(id)
|
||||
|
||||
if (res?.data) {
|
||||
// toast({
|
||||
// render: () => (
|
||||
// <ToastBox status={"success"} message={res?.data?.message} />
|
||||
// ),
|
||||
// });
|
||||
// setIsLoading(false);
|
||||
onDistInvestorOpen();
|
||||
} else if (res?.error) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox status={"error"} message={res?.error?.data?.message} />
|
||||
),
|
||||
});
|
||||
onDistInvestorOpen()
|
||||
|
||||
} else if (res?.error) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox status={"error"} message={res?.error?.data?.message} />
|
||||
),
|
||||
});
|
||||
// setIsLoading(false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleExit = async () => {
|
||||
const handleExit = async () =>{
|
||||
|
||||
try {
|
||||
const res = await updateTransaction(id);
|
||||
|
||||
if (res?.data) {
|
||||
const res = await updateTransaction(id)
|
||||
|
||||
if (res?.data) {
|
||||
// toast({
|
||||
// render: () => (
|
||||
// <ToastBox status={"success"} message={res?.data?.message} />
|
||||
// ),
|
||||
// });
|
||||
// setIsLoading(false);
|
||||
onExitOpen();
|
||||
} else if (res?.error) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox status={"error"} message={res?.error?.data?.message} />
|
||||
),
|
||||
});
|
||||
onExitOpen()
|
||||
|
||||
} else if (res?.error) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox status={"error"} message={res?.error?.data?.message} />
|
||||
),
|
||||
});
|
||||
// setIsLoading(false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleInvestment = async () => {
|
||||
const handleInvestment = async () =>{
|
||||
|
||||
try {
|
||||
const res = await updateTransaction(id);
|
||||
|
||||
if (res?.data) {
|
||||
const res = await updateTransaction(id)
|
||||
|
||||
if (res?.data) {
|
||||
// toast({
|
||||
// render: () => (
|
||||
// <ToastBox status={"success"} message={res?.data?.message} />
|
||||
// ),
|
||||
// });
|
||||
// setIsLoading(false);
|
||||
onInvestmentOpen();
|
||||
} else if (res?.error) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox status={"error"} message={res?.error?.data?.message} />
|
||||
),
|
||||
});
|
||||
onInvestmentOpen()
|
||||
|
||||
} else if (res?.error) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox status={"error"} message={res?.error?.data?.message} />
|
||||
),
|
||||
});
|
||||
// setIsLoading(false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const menu = [
|
||||
{
|
||||
@@ -203,7 +216,7 @@ const ViewIOdataHeader = ({ data, isLoading }) => {
|
||||
id: 6,
|
||||
title: "Distribution To Investors",
|
||||
onClickFunction: handleDistributionInvestors,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: "Update IO NAV",
|
||||
@@ -237,8 +250,8 @@ const ViewIOdataHeader = ({ data, isLoading }) => {
|
||||
apiTransactionTitles?.includes(item.id)
|
||||
);
|
||||
|
||||
const balanceAmount =
|
||||
IODetails?.goalAmount - IODetails?.totalAmtInvestmentInUSD;
|
||||
|
||||
const balanceAmount = IODetails?.goalAmount - IODetails?.totalAmtInvestmentInUSD
|
||||
|
||||
return IODetails?.investmentNameEnglish ? (
|
||||
<Box
|
||||
@@ -247,19 +260,19 @@ const ViewIOdataHeader = ({ data, isLoading }) => {
|
||||
justifyContent={"space-between"}
|
||||
gap={8}
|
||||
bg={
|
||||
IODetails?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_DRAFT
|
||||
IODetails?.ioStatus?.statusAdmin === "Draft"
|
||||
? "#EDF2F7"
|
||||
: IODetails?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_PROCESSING
|
||||
: IODetails?.ioStatus?.statusAdmin === "Processing"
|
||||
? "#FEFBBF"
|
||||
: IODetails?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_OPEN
|
||||
: IODetails?.ioStatus?.statusAdmin === "Open"
|
||||
? "#BEE2F8"
|
||||
: IODetails?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_CLOSED
|
||||
: IODetails?.ioStatus?.statusAdmin === "Closed"
|
||||
? "#C6F6D5"
|
||||
: IODetails?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_EXITED
|
||||
: IODetails?.ioStatus?.statusAdmin === "Exited"
|
||||
? "#FED7D7"
|
||||
: IODetails?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_CANCELLED
|
||||
: IODetails?.ioStatus?.statusAdmin === "Cancelled"
|
||||
? "#E9D8FD"
|
||||
: IODetails?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_DEACTIVATE
|
||||
: IODetails?.ioStatus?.statusAdmin === "DeActivate"
|
||||
? "#E9D8FD"
|
||||
: null
|
||||
}
|
||||
@@ -304,6 +317,7 @@ const ViewIOdataHeader = ({ data, isLoading }) => {
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
|
||||
<Box display={"flex"} gap={2} pb={1}>
|
||||
<Text
|
||||
as={"span"}
|
||||
@@ -321,7 +335,7 @@ const ViewIOdataHeader = ({ data, isLoading }) => {
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<Box display={"flex"} gap={2} pb={1}>
|
||||
<Box display={"flex"} gap={2} pb={1}>
|
||||
<Text
|
||||
as={"span"}
|
||||
fontSize={"xs"}
|
||||
@@ -338,7 +352,7 @@ const ViewIOdataHeader = ({ data, isLoading }) => {
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<Box display={"flex"} gap={2} pb={1}>
|
||||
<Box display={"flex"} gap={2} pb={1}>
|
||||
<Text
|
||||
as={"span"}
|
||||
fontSize={"xs"}
|
||||
@@ -349,13 +363,18 @@ const ViewIOdataHeader = ({ data, isLoading }) => {
|
||||
IO ID :-
|
||||
</Text>
|
||||
<Text as={"span"} fontSize={"xs"} fontWeight={"500"}>
|
||||
{IODetails?.io_id ? IODetails?.io_id : "---"}
|
||||
{IODetails?.io_id
|
||||
? IODetails?.io_id
|
||||
: "---"}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
</Box>
|
||||
|
||||
</HStack>
|
||||
|
||||
|
||||
<Box gap={8} me={12} w={"220px"}>
|
||||
|
||||
<Box display={"flex"} justifyContent={"space-between"} gap={2} pb={1}>
|
||||
<Text
|
||||
as={"span"}
|
||||
@@ -385,13 +404,10 @@ const ViewIOdataHeader = ({ data, isLoading }) => {
|
||||
</Text>
|
||||
<Text as={"span"} fontSize={"xs"} fontWeight={"500"}>
|
||||
{/* {IODetails?.ioCash ? formatCurrency(removeTrailingZeros(IODetails?.ioCash)) : "00.00"} */}
|
||||
{parseFloat(IODetails?.totalAmtInvestmentInUSD || 0).toLocaleString(
|
||||
undefined,
|
||||
{
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
}
|
||||
)}
|
||||
{parseFloat(IODetails?.totalAmtInvestmentInUSD || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
@@ -432,17 +448,17 @@ const ViewIOdataHeader = ({ data, isLoading }) => {
|
||||
textTransform={"none"}
|
||||
// variant={"solid"}
|
||||
colorScheme={
|
||||
IODetails?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_DRAFT
|
||||
IODetails?.ioStatus?.statusAdmin === "Draft"
|
||||
? "gray"
|
||||
: IODetails?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_PROCESSING
|
||||
: IODetails?.ioStatus?.statusAdmin === "Processing"
|
||||
? "yellow"
|
||||
: IODetails?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_OPEN
|
||||
: IODetails?.ioStatus?.statusAdmin === "Open"
|
||||
? "blue"
|
||||
: IODetails?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_CLOSED
|
||||
: IODetails?.ioStatus?.statusAdmin === "Closed"
|
||||
? "green"
|
||||
: IODetails?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_EXITED
|
||||
: IODetails?.ioStatus?.statusAdmin === "Exited"
|
||||
? "red"
|
||||
: IODetails?.ioStatus?.statusAdmin === import.meta.env.VITE_STATUS_CANCELLED
|
||||
: IODetails?.ioStatus?.statusAdmin === "Cancelled"
|
||||
? "purple"
|
||||
: "purple"
|
||||
}
|
||||
@@ -516,41 +532,39 @@ const ViewIOdataHeader = ({ data, isLoading }) => {
|
||||
alignItems={"start"}
|
||||
height={"95px"}
|
||||
>
|
||||
{isMaker() && (
|
||||
<Menu>
|
||||
<MenuButton
|
||||
className="link p-1 rounded-1 "
|
||||
bg={"#fff"}
|
||||
_hover={{ backgroundColor: "#fff !important" }}
|
||||
onClick={onOpen}
|
||||
ref={btnRef}
|
||||
{localStorage?.getItem("role") === "Maker" && <Menu>
|
||||
<MenuButton
|
||||
className="link p-1 rounded-1 "
|
||||
bg={"#fff"}
|
||||
_hover={{ backgroundColor: "#fff !important" }}
|
||||
onClick={onOpen}
|
||||
ref={btnRef}
|
||||
>
|
||||
<HiDotsVertical className="rubix-text-dark fs-6" />
|
||||
</MenuButton>
|
||||
<MenuList fontSize={"sm"}>
|
||||
<MenuItem
|
||||
_hover={{
|
||||
bg: "#fff",
|
||||
}}
|
||||
as={"span"}
|
||||
fontWeight={600}
|
||||
className="border-bottom"
|
||||
>
|
||||
<HiDotsVertical className="rubix-text-dark fs-6" />
|
||||
</MenuButton>
|
||||
<MenuList fontSize={"sm"}>
|
||||
Tansaction
|
||||
</MenuItem>
|
||||
|
||||
{filteredMenu?.map(({ id, title, onClickFunction }) => (
|
||||
<MenuItem
|
||||
_hover={{
|
||||
bg: "#fff",
|
||||
}}
|
||||
as={"span"}
|
||||
fontWeight={600}
|
||||
key={id}
|
||||
onClick={onClickFunction}
|
||||
className="border-bottom"
|
||||
>
|
||||
Tansaction
|
||||
{title}
|
||||
</MenuItem>
|
||||
|
||||
{filteredMenu?.map(({ id, title, onClickFunction }) => (
|
||||
<MenuItem
|
||||
key={id}
|
||||
onClick={onClickFunction}
|
||||
className="border-bottom"
|
||||
>
|
||||
{title}
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuList>
|
||||
</Menu>
|
||||
)}
|
||||
))}
|
||||
</MenuList>
|
||||
</Menu>}
|
||||
|
||||
{/* Modals */}
|
||||
<AmountInvested isOpen={isInvestmentOpen} onClose={onInvestmentClose} />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ViewIcon } from "@chakra-ui/icons";
|
||||
import {
|
||||
Avatar,
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
@@ -11,21 +11,23 @@ import {
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useContext, useEffect, useRef, useState } from "react";
|
||||
import { LuFileSpreadsheet } from "react-icons/lu";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||
import NormalTable from "../../../Components/DataTable/NormalTable";
|
||||
import Pagination from "../../../Components/Pagination";
|
||||
import {
|
||||
exportToExcelNew,
|
||||
generateSerialNumber,
|
||||
} from "../../../Constants/Constants";
|
||||
import { INVESTOR_TABLE_PAGINATION } from "../../../Constants/Paginations";
|
||||
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||
import React, { useContext, useEffect, useState, useRef } from "react";
|
||||
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||
import { useGetInvestorsQuery } from "../../../Services/investor.details.service";
|
||||
import NormalTable from "../../../Components/DataTable/NormalTable";
|
||||
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
|
||||
import {
|
||||
ViewIcon,
|
||||
} from "@chakra-ui/icons";
|
||||
import Pagination from "../../../Components/Pagination";
|
||||
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||
import ToastBox from "../../../Components/ToastBox";
|
||||
import { debounce } from "../../Master/Sponser/AddSponser";
|
||||
import InvestmentDetailsEdit from "./InvestmentDetailsEdit";
|
||||
import { useGetInvestorsQuery } from "../../../Services/investor.details.service";
|
||||
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
||||
import { exportToExcel, exportToExcelNew, generateSerialNumber } from "../../../Constants/Constants";
|
||||
import { LuFileSpreadsheet } from "react-icons/lu";
|
||||
|
||||
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
||||
|
||||
@@ -47,11 +49,10 @@ const InvestorDetails = () => {
|
||||
} = useDisclosure();
|
||||
const btnRef = React.useRef();
|
||||
|
||||
// =========================== [Use State] =============================
|
||||
const [pageSize, setPageSize] = useState(INVESTOR_TABLE_PAGINATION?.size);
|
||||
const [currentPage, setCurrentPage] = useState(
|
||||
INVESTOR_TABLE_PAGINATION?.page
|
||||
);
|
||||
|
||||
// =========================== [Use State] =============================
|
||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||
|
||||
@@ -72,19 +73,20 @@ const InvestorDetails = () => {
|
||||
data: investorDetails,
|
||||
isLoading: investorDetailsLoading,
|
||||
error,
|
||||
} = useGetInvestorsQuery(
|
||||
{
|
||||
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search userStatus KYCStatus investorType_xid
|
||||
search: debouncedSearchTerm,
|
||||
userStatus: status,
|
||||
KYCStatus: kyc,
|
||||
country_xid: country,
|
||||
},
|
||||
{
|
||||
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 userStatus KYCStatus investorType_xid
|
||||
search: debouncedSearchTerm,
|
||||
userStatus: status,
|
||||
KYCStatus: kyc,
|
||||
country_xid: country
|
||||
|
||||
},
|
||||
{
|
||||
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
// Simulate loading
|
||||
@@ -102,41 +104,43 @@ const InvestorDetails = () => {
|
||||
"Client ID",
|
||||
"First Name",
|
||||
"Last Name",
|
||||
"Country",
|
||||
"Country",
|
||||
"Phone Number",
|
||||
"E-mail ID",
|
||||
"Type",
|
||||
"Type",
|
||||
"KYC Status",
|
||||
"Status",
|
||||
"Action",
|
||||
];
|
||||
|
||||
|
||||
// ====================================================[Table Filter]================================================================
|
||||
const exportInvestor = investorDetails?.data?.rows?.map((item, idx) => ({
|
||||
Id: parseInt(item?.id, 10) || item?.id, // Convert to integer, fallback to string if conversion fails
|
||||
"Id": parseInt(item?.id, 10) || item?.id, // Convert to integer, fallback to string if conversion fails
|
||||
"Client ID": item?.clientReference_id, // This is likely a string
|
||||
"First Name": item?.principal?.firstName,
|
||||
"Last Name": item?.principal?.lastName,
|
||||
Country: item?.country?.countryName,
|
||||
"Country": item?.country?.countryName,
|
||||
"Phone Number": item?.principal?.mobileNumber, // Skipping integer conversion, as this is likely a string
|
||||
"E-mail ID": item?.principal?.emailAddress,
|
||||
Type: item?.investor_type?.investorTypeName,
|
||||
Status: item.ioStatus ? "Ban" : "Unban",
|
||||
"KYC Status": item.KYCStatus ? "Completed" : "Not complete",
|
||||
"Type": item?.investor_type?.investorTypeName,
|
||||
"Status": item.ioStatus ? "Ban" : "Unban",
|
||||
"KYC Status": item.KYCStatus ? "Completed" : "Not complete"
|
||||
}));
|
||||
|
||||
const extractedArray = investorDetails?.data?.rows?.map((item, idx) => ({
|
||||
id: item?.id,
|
||||
"Sr No": (
|
||||
<Text
|
||||
w={"24px"}
|
||||
w={'24px'}
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"gray.600"}
|
||||
className="d-flex align-items-center fw-bold web-text-small"
|
||||
>
|
||||
{/* {item.id} */}
|
||||
{generateSerialNumber(idx, currentPage, pageSize)}
|
||||
{generateSerialNumber(idx,currentPage, pageSize )}
|
||||
|
||||
</Text>
|
||||
),
|
||||
"Client ID": (
|
||||
@@ -144,7 +148,7 @@ const InvestorDetails = () => {
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{item.clientReference_id}
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
),
|
||||
"First Name": (
|
||||
<Box w={"auto"} isTruncated={true}>
|
||||
@@ -181,44 +185,39 @@ const InvestorDetails = () => {
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
Type: (
|
||||
"Type": (
|
||||
<Box w={"auto"} isTruncated={true}>
|
||||
<Text as={"span"}>
|
||||
<Badge
|
||||
color={"forestGreen.500"}
|
||||
variant={"ghost"}
|
||||
fontWeight={"700"}
|
||||
px={2}
|
||||
py={0.5}
|
||||
>
|
||||
<Text as={"span"} >
|
||||
<Badge color={"forestGreen.500"} variant={'ghost'} fontWeight={"700"} px={2} py={0.5}>
|
||||
{item?.investor_type?.investorTypeName}
|
||||
</Badge>
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
Status: (
|
||||
<Box w={"auto"} isTruncated={true}>
|
||||
<Badge
|
||||
fontWeight={"700"}
|
||||
textTransform={"none"}
|
||||
colorScheme={item.ioStatus ? "red" : "green"}
|
||||
px={2}
|
||||
py={0.5}
|
||||
>
|
||||
{item.ioStatus ? "Ban" : "Unban"}
|
||||
</Badge>
|
||||
</Box>
|
||||
<Box w={"auto"} isTruncated={true}>
|
||||
<Badge
|
||||
fontWeight={"700"}
|
||||
textTransform={"none"}
|
||||
colorScheme={item.ioStatus ? "red" : "green"}
|
||||
px={2}
|
||||
py={0.5}
|
||||
>
|
||||
{item.ioStatus ? "Ban" : "Unban"}
|
||||
</Badge>
|
||||
</Box>
|
||||
),
|
||||
"KYC Status": (
|
||||
<Box w={"auto"} display={"flex"} alignItems={"center"} isTruncated={true}>
|
||||
<Box w={"auto"} display={'flex'} alignItems={'center'} isTruncated={true}>
|
||||
<Text
|
||||
as={"span"}
|
||||
as={'span'}
|
||||
fontWeight={"700"}
|
||||
textTransform={"none"}
|
||||
color={item?.KYCStatus === true ? "green" : "yellow.500"}
|
||||
px={2}
|
||||
py={0.5}
|
||||
variant={"solid"}
|
||||
variant={'solid'}
|
||||
|
||||
>
|
||||
{/* {item.KYCStatus ? "Completed" : "Not complete"} */}
|
||||
{item?.KYCStatus === true ? "Completed" : "NotCompleted"}
|
||||
@@ -236,7 +235,7 @@ const InvestorDetails = () => {
|
||||
placement="top"
|
||||
>
|
||||
<Button
|
||||
isDisabled={item.ioStatus}
|
||||
isDisabled={item.ioStatus}
|
||||
onClick={() => {
|
||||
navigate(`/investor-details/profile-view/${item.id}`);
|
||||
}}
|
||||
@@ -267,6 +266,7 @@ const InvestorDetails = () => {
|
||||
setIsLoading(true);
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||
<Box bg="white.500">
|
||||
@@ -346,29 +346,35 @@ const InvestorDetails = () => {
|
||||
</Select>
|
||||
|
||||
<Pagination
|
||||
isLoading={investorDetailsLoading}
|
||||
isLoading={investorDetailsLoading}
|
||||
pageSize={pageSize}
|
||||
setPageSize={setPageSize}
|
||||
currentPage={currentPage}
|
||||
setCurrentPage={setCurrentPage}
|
||||
totalItems={investorDetails?.data?.totalItems}
|
||||
|
||||
/>
|
||||
|
||||
</HStack>
|
||||
|
||||
|
||||
<Button
|
||||
onClick={() => exportToExcelNew(exportInvestor, "Investor Details")}
|
||||
leftIcon={<LuFileSpreadsheet />}
|
||||
colorScheme="forestGreen"
|
||||
size={"sm"}
|
||||
variant={"outline"}
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
w={100}
|
||||
me={2}
|
||||
isDisabled={exportInvestor?.length === 0}
|
||||
>
|
||||
Export xls
|
||||
</Button>
|
||||
onClick={() =>
|
||||
exportToExcelNew(exportInvestor, "Investor Details")
|
||||
}
|
||||
leftIcon={<LuFileSpreadsheet />}
|
||||
colorScheme="forestGreen"
|
||||
size={"sm"}
|
||||
variant={"outline"}
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
w={100}
|
||||
me={2}
|
||||
|
||||
isDisabled={exportInvestor?.length === 0}
|
||||
>
|
||||
Export xls
|
||||
</Button>
|
||||
</HStack>
|
||||
<InvestmentDetailsEdit
|
||||
id={actionId}
|
||||
|
||||
@@ -3,7 +3,7 @@ import Input01 from "../Components/Inputs/Input01";
|
||||
import logo from "../assets/logo2.png";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { loginUser } from "../Redux/Slice/auth";
|
||||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import Button01 from "../Components/Buttons/Button01";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import { useForm } from "react-hook-form";
|
||||
@@ -12,15 +12,12 @@ import Loader01 from "../Components/Loaders/Loader01";
|
||||
import Asset1 from "../assets/asset1.png";
|
||||
import Asset2 from "../assets/asset2.png";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Input,
|
||||
InputGroup,
|
||||
InputRightElement,
|
||||
Text,
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import GlobalStateContext from "../Contexts/GlobalStateContext";
|
||||
@@ -31,7 +28,6 @@ import { useLoginMutation } from "../Services/token.serivce";
|
||||
|
||||
// import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import * as Yup from "yup";
|
||||
import ForgetPassword from "./ForgetPassword";
|
||||
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
@@ -54,8 +50,6 @@ const Login = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [login] = useLoginMutation()
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const firstField = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -211,7 +205,7 @@ const Login = () => {
|
||||
)}
|
||||
</FormControl>
|
||||
|
||||
<FormControl className="mb-2">
|
||||
<FormControl className="mb-4">
|
||||
<FormLabel className="rubix-text-dark ps-1 web-text-medium fw-bold">
|
||||
Password <span className="text-danger">*</span>
|
||||
</FormLabel>
|
||||
@@ -244,9 +238,6 @@ const Login = () => {
|
||||
</span>
|
||||
)}
|
||||
</FormControl>
|
||||
<Box fontSize={"sm"} display={"flex"} justifyContent={"end"} mt={0}>
|
||||
<Text fontWeight={500} cursor={"pointer"} onClick={onOpen}>Forgot Password?</Text>
|
||||
</Box>
|
||||
|
||||
<Button
|
||||
isLoading={isLoading}
|
||||
@@ -256,8 +247,6 @@ const Login = () => {
|
||||
color={"whitesmoke"}
|
||||
colorScheme="green.500"
|
||||
size="lg"
|
||||
fontWeight={500}
|
||||
fontSize={"md"}
|
||||
>
|
||||
Log In
|
||||
</Button>
|
||||
@@ -328,11 +317,6 @@ const Login = () => {
|
||||
src={Asset2}
|
||||
alt="bg-img"
|
||||
/>
|
||||
<ForgetPassword
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
firstField={firstField}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -316,7 +316,7 @@ const AddInvestmentType = () => {
|
||||
|
||||
<Box display={"flex"} justifyContent={"space-between"} alignItems={"center"} mt={5} px={4} mb={5}>
|
||||
<Text fontSize={"sm"} mb={0} onClick={() => navigate(-1)} cursor={"pointer"}>
|
||||
<ArrowBackIcon fontSize={"xl"} me={2} />{params?.id ? "Edit Details" : "Add Details"}
|
||||
<ArrowBackIcon fontSize={"xl"} me={2} />Add Details
|
||||
</Text>
|
||||
<SwitchButton isSwitchOn={isSwitchOn} setIsSwitchOn={setIsSwitchOn} />
|
||||
</Box>
|
||||
|
||||
@@ -301,7 +301,7 @@ const AddSponser = () => {
|
||||
{/* ===================== [Switch Button] ======================== */}
|
||||
<Box display={"flex"} justifyContent={"space-between"} alignItems={"center"} mt={5} px={4}>
|
||||
<Text fontSize={"sm"} mb={0} onClick={() => navigate(-1)} cursor={"pointer"}>
|
||||
<ArrowBackIcon fontSize={"xl"} me={2} />{params?.id ? "Edit Details" : "Add Details"}
|
||||
<ArrowBackIcon fontSize={"xl"} me={2} />Add Details
|
||||
</Text>
|
||||
<SwitchButton isSwitchOn={isSwitchOn} setIsSwitchOn={setIsSwitchOn} />
|
||||
</Box>
|
||||
|
||||
@@ -1,21 +1,26 @@
|
||||
import { CheckIcon, CloseIcon, InfoIcon } from "@chakra-ui/icons";
|
||||
import {
|
||||
Avatar,
|
||||
Box,
|
||||
ButtonGroup,
|
||||
Editable,
|
||||
EditableInput,
|
||||
EditablePreview,
|
||||
EditableTextarea,
|
||||
Flex,
|
||||
HStack,
|
||||
Heading,
|
||||
Icon,
|
||||
IconButton,
|
||||
Input,
|
||||
Text,
|
||||
VStack,
|
||||
useEditableControls
|
||||
useEditableControls,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React from "react";
|
||||
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||
import { CheckIcon, CloseIcon, EditIcon, InfoIcon } from "@chakra-ui/icons";
|
||||
import { FaEarthAmericas } from "react-icons/fa6";
|
||||
import logoMini from "../../assets/propic.png";
|
||||
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||
import { useAuthProfileQuery } from "../../Services/token.serivce";
|
||||
|
||||
const Profile = () => {
|
||||
/* Here's a custom control */
|
||||
@@ -48,56 +53,19 @@ const Profile = () => {
|
||||
)
|
||||
);
|
||||
}
|
||||
const { data } = useAuthProfileQuery();
|
||||
|
||||
const [fields, setFields] = useState([
|
||||
{
|
||||
name: "firstName",
|
||||
label: "First Name",
|
||||
defaultValue: null,
|
||||
},
|
||||
{
|
||||
name: "lastName",
|
||||
label: "Last Name",
|
||||
defaultValue: null,
|
||||
},
|
||||
{
|
||||
name: "email",
|
||||
label: "Email Address",
|
||||
defaultValue: null,
|
||||
},
|
||||
{
|
||||
name: "mobile",
|
||||
label: "Mobile Number",
|
||||
defaultValue: null,
|
||||
},
|
||||
{ name: "role", label: "Role", defaultValue: null },
|
||||
]);
|
||||
useEffect(() => {
|
||||
setFields([
|
||||
{
|
||||
name: "firstName",
|
||||
label: "First Name",
|
||||
defaultValue: data?.data?.firstName || null,
|
||||
},
|
||||
{
|
||||
name: "lastName",
|
||||
label: "Last Name",
|
||||
defaultValue: data?.data?.lastName || null,
|
||||
},
|
||||
{
|
||||
name: "email",
|
||||
label: "Email Address",
|
||||
defaultValue: data?.data?.emailAddress || null,
|
||||
},
|
||||
{
|
||||
name: "mobile",
|
||||
label: "Mobile Number",
|
||||
defaultValue: data?.data?.mobileNumber || null,
|
||||
},
|
||||
{ name: "role", label: "Role", defaultValue: data?.data?.role || null },
|
||||
]);
|
||||
}, [data]);
|
||||
|
||||
// Array of fields to render
|
||||
const fields = [
|
||||
{ name: "firstName", label: "First Name", defaultValue: "Faisal" },
|
||||
{ name: "lastName", label: "Last Name", defaultValue: "Aljalahma" },
|
||||
{ name: "email", label: "Email Address", defaultValue: "f.aljalahma@tanamicapital.com" },
|
||||
{ name: "mobile", label: "Mobile Number", defaultValue: "9898767876" },
|
||||
{ name: "role", label: "Role", defaultValue: "Maker" },
|
||||
];
|
||||
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<VStack
|
||||
@@ -146,7 +114,7 @@ const Profile = () => {
|
||||
color={"gray.700"}
|
||||
fontWeight={500}
|
||||
>
|
||||
{data?.data?.firstName + " " + data?.data?.lastName}
|
||||
Faisal Aljalahma
|
||||
</Text>
|
||||
|
||||
<Text
|
||||
@@ -155,7 +123,7 @@ const Profile = () => {
|
||||
color={"gray.500"}
|
||||
fontWeight={400}
|
||||
>
|
||||
{data?.data?.emailAddress}
|
||||
f.aljalahma@tanamicapital.com
|
||||
</Text>
|
||||
</VStack>
|
||||
</HStack>
|
||||
@@ -182,16 +150,16 @@ const Profile = () => {
|
||||
fontWeight={500}
|
||||
>
|
||||
{" "}
|
||||
<Icon as={FaEarthAmericas} /> {data?.data?.role}
|
||||
<Icon as={FaEarthAmericas} /> Maker
|
||||
</Text>
|
||||
</VStack>
|
||||
</HStack>
|
||||
</Box>
|
||||
|
||||
{/*
|
||||
<Heading as="h3" size="sm">
|
||||
About you
|
||||
</Heading>
|
||||
|
||||
<Box
|
||||
rounded="md"
|
||||
boxShadow="base"
|
||||
@@ -202,56 +170,55 @@ const Profile = () => {
|
||||
alignItems="flex-start"
|
||||
p={6}
|
||||
gap={0}
|
||||
|
||||
pb={6}
|
||||
>
|
||||
{fields?.map((item) => (
|
||||
<VStack
|
||||
alignItems={"flex-start"}
|
||||
w={"100%"}
|
||||
gap={1.5}
|
||||
mb={6}
|
||||
key={item?.label}
|
||||
>
|
||||
<Text
|
||||
as={"span"}
|
||||
fontSize="xs"
|
||||
fontWeight="semibold"
|
||||
color={"gray.500"}
|
||||
>
|
||||
{item?.label}
|
||||
</Text>
|
||||
<Editable
|
||||
position={"relative"}
|
||||
gap={0}
|
||||
defaultValue={item?.defaultValue}
|
||||
w="100%"
|
||||
>
|
||||
<EditablePreview
|
||||
cursor={"pointer"}
|
||||
p={2}
|
||||
rounded={"sm"}
|
||||
w={"100%"}
|
||||
_hover={{
|
||||
bg: "gray.100",
|
||||
}}
|
||||
fontSize="sm"
|
||||
transition={"0.5s"}
|
||||
/>
|
||||
<Input
|
||||
as={EditableInput}
|
||||
ps={2}
|
||||
size={"sm"}
|
||||
fontSize="sm"
|
||||
rounded={"sm"}
|
||||
_focus={{
|
||||
borderColor: "blue.500",
|
||||
}}
|
||||
/>
|
||||
<EditableControls />
|
||||
</Editable>
|
||||
</VStack>
|
||||
))}
|
||||
</Box> */}
|
||||
|
||||
{fields?.map((item) => (
|
||||
<VStack alignItems={"flex-start"} w={"100%"} gap={1.5} mb={6} key={item?.label}>
|
||||
<Text
|
||||
as={"span"}
|
||||
fontSize="xs"
|
||||
fontWeight="semibold"
|
||||
color={"gray.500"}
|
||||
>
|
||||
{item?.label}
|
||||
</Text>
|
||||
<Editable
|
||||
position={"relative"}
|
||||
gap={0}
|
||||
defaultValue={item?.defaultValue}
|
||||
w="100%"
|
||||
>
|
||||
<EditablePreview
|
||||
cursor={'pointer'}
|
||||
p={2}
|
||||
rounded={"sm"}
|
||||
w={"100%"}
|
||||
_hover={{
|
||||
bg: "gray.100",
|
||||
}}
|
||||
fontSize="sm"
|
||||
transition={"0.5s"}
|
||||
/>
|
||||
<Input
|
||||
as={EditableInput}
|
||||
ps={2}
|
||||
size={'sm'}
|
||||
fontSize="sm"
|
||||
rounded={"sm"}
|
||||
_focus={{
|
||||
borderColor:"blue.500"
|
||||
}}
|
||||
/>
|
||||
<EditableControls />
|
||||
</Editable>
|
||||
</VStack>
|
||||
))}
|
||||
|
||||
|
||||
|
||||
</Box>
|
||||
</VStack>
|
||||
</VStack>
|
||||
);
|
||||
|
||||
@@ -1,373 +0,0 @@
|
||||
import { AddIcon, DeleteIcon, EditIcon } from "@chakra-ui/icons";
|
||||
import {
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
HStack,
|
||||
Input,
|
||||
Switch,
|
||||
Text,
|
||||
Tooltip,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useContext, useState } from "react";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
||||
import NormalTable from "../../Components/DataTable/NormalTable";
|
||||
import ToastBox from "../../Components/ToastBox";
|
||||
import {
|
||||
CHECKER_ID,
|
||||
generateSerialNumber,
|
||||
MAKER_ID,
|
||||
SUPER_ADMIN_ID,
|
||||
} from "../../Constants/Constants";
|
||||
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
||||
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||
import {
|
||||
useDeleteUserMutation,
|
||||
useGetSubAdminMasterQuery,
|
||||
useToggleStatusMutation,
|
||||
} from "../../Services/subadmin.service";
|
||||
|
||||
export const formatDate = (date) => {
|
||||
const d = new Date(date);
|
||||
const year = d.getFullYear();
|
||||
const month = String(d.getMonth() + 1).padStart(2, "0"); // Months are 0-indexed
|
||||
const day = String(d.getDate()).padStart(2, "0");
|
||||
|
||||
return `${day}/${month}/${year}`;
|
||||
};
|
||||
|
||||
const SubAdmin = () => {
|
||||
const navigate = useNavigate();
|
||||
const toast = useToast();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||
const [actionId, setActionId] = useState(false);
|
||||
const [mouseEntered, setMouseEntered] = useState(false);
|
||||
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||
// const [deleteSponser] = useDeleteSponserMutation();
|
||||
const { slideFromRight } = useContext(GlobalStateContext);
|
||||
|
||||
// =========================== [Use State] =============================
|
||||
// const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||
// const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
// const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||
|
||||
// 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: subAdmin, isLoading: isSponserLoading } =
|
||||
useGetSubAdminMasterQuery();
|
||||
|
||||
const [deleteUser] = useDeleteUserMutation();
|
||||
|
||||
const [toggleStatus] = useToggleStatusMutation();
|
||||
|
||||
// useEffect(() => {
|
||||
// if (subAdmin?.data) {
|
||||
// setIsSwitchOn(subAdmin?.role?.role);
|
||||
// console.log(subAdmin);
|
||||
// }
|
||||
// }, [subAdmin]);
|
||||
|
||||
// ==============================[Table Filter]========================
|
||||
|
||||
const filteredData = subAdmin?.data?.filter((item) => {
|
||||
const name = item.firstName;
|
||||
const searchLower = searchTerm?.toLowerCase();
|
||||
const nameMatches = name?.toLowerCase().includes(searchLower);
|
||||
return nameMatches;
|
||||
});
|
||||
|
||||
const handleToggleStatus = async (isMaker, id) => {
|
||||
// console.log("hit");
|
||||
const data = {
|
||||
role_xid: isMaker ? CHECKER_ID : MAKER_ID,
|
||||
};
|
||||
console.log("=======================", data);
|
||||
try {
|
||||
const res = await toggleStatus({ id, data });
|
||||
if (res?.error) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox status={"error"} message={res?.error?.data?.message} />
|
||||
),
|
||||
});
|
||||
} else if (res) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox
|
||||
status={"success"}
|
||||
message={res?.message || "Status updated successfully!"}
|
||||
/>
|
||||
),
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox
|
||||
status={"error"}
|
||||
message={error?.data?.message || "Something went wrong"}
|
||||
/>
|
||||
),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// ====================================================[Table Setup]================================================================
|
||||
|
||||
const tableHeadRow = [
|
||||
"Sr No",
|
||||
"First Name",
|
||||
"Last Name",
|
||||
"Email Address",
|
||||
"Role",
|
||||
"Action",
|
||||
];
|
||||
|
||||
const extractedArray = filteredData?.map((item, index) => ({
|
||||
"Sr No": (
|
||||
<Text
|
||||
w={"24px"}
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"gray.600"}
|
||||
className="d-flex align-items-center fw-bold web-text-small"
|
||||
>
|
||||
{/* {item.id} */}
|
||||
{generateSerialNumber(index)}
|
||||
</Text>
|
||||
),
|
||||
"First Name": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item?.firstName}
|
||||
</Text>
|
||||
),
|
||||
"Last Name": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item?.lastName}
|
||||
</Text>
|
||||
),
|
||||
"Email Address": (
|
||||
<Box isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{item?.emailAddress}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
Role: (
|
||||
<Box isTruncated={true}>
|
||||
<Badge
|
||||
py={"2px"}
|
||||
me={2}
|
||||
fontWeight={600}
|
||||
bg={item?.role[0]?.role === "Maker" ? "#00ffcc" : "#b3ff99"}
|
||||
px={item?.role[0]?.role === "Maker" ? "12px" : "5px"}
|
||||
>
|
||||
{item?.role[0]?.role}
|
||||
</Badge>
|
||||
{/* <Switch
|
||||
onChange={() =>
|
||||
handleToggleStatus(item?.role[0]?.role === "Maker", item?.id)
|
||||
}
|
||||
isChecked={item?.role[0]?.role === "Maker"}
|
||||
// colorScheme={item?.role[0]?.role === "Maker" ? "green" : "teal"}
|
||||
sx={{
|
||||
".chakra-switch__track": {
|
||||
bg: item?.role[0]?.role === "Maker" ? "#00ffcc" : "#b3ff99", // "Off" state color
|
||||
},
|
||||
}}
|
||||
/> */}
|
||||
{/* <RoleSwitchButton
|
||||
setIsSwitchOn={setIsSwitchOn}
|
||||
isSwitchOn={item?.role[0]?.role === "Maker"}
|
||||
onClick={() => handleToggleStatus(item?.role[0]?.role=== "Maker")}
|
||||
/> */}
|
||||
</Box>
|
||||
),
|
||||
Action: (
|
||||
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||
<Tooltip
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
label="Edit"
|
||||
bg="#fff"
|
||||
color={"blue.500"}
|
||||
placement="top"
|
||||
>
|
||||
<Button
|
||||
onClick={() => navigate(`/subadmin/subadmin-update/${item.id}`)}
|
||||
// _hover={{ color: "blue.500" }}
|
||||
// color="blue.400"
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
colorScheme="blue"
|
||||
>
|
||||
<EditIcon />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
label="Delete"
|
||||
bg="#fff"
|
||||
color={"red.500"}
|
||||
placement="top"
|
||||
>
|
||||
<Button
|
||||
isDisabled={item?.id === SUPER_ADMIN_ID}
|
||||
onClick={() => {
|
||||
setActionId(item?.id);
|
||||
setDeleteAlert(true);
|
||||
}}
|
||||
// _hover={{ color: "red.500" }}
|
||||
// color="red"
|
||||
// disabled={true}
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
colorScheme="red"
|
||||
variant={"solid"}
|
||||
>
|
||||
<DeleteIcon />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
),
|
||||
}));
|
||||
|
||||
// =========================== [ Delete Function ] =================================
|
||||
|
||||
const handleDelete = async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const response = await deleteUser(actionId);
|
||||
if (response?.error?.data?.code === 400) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox
|
||||
message={response?.error?.data?.message}
|
||||
status={"error"}
|
||||
/>
|
||||
),
|
||||
});
|
||||
setIsLoading(false);
|
||||
setDeleteAlert(false);
|
||||
} else if (
|
||||
response?.data?.statusCode === 201 ||
|
||||
response?.data?.statusCode === 200
|
||||
) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={response?.data?.message} status={"success"} />
|
||||
),
|
||||
});
|
||||
setIsLoading(false);
|
||||
setDeleteAlert(false);
|
||||
}
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
return (
|
||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||
<Box bg="white.500">
|
||||
<HStack
|
||||
display={"flex"}
|
||||
justifyContent={"space-between"}
|
||||
ps={1}
|
||||
pe={1}
|
||||
pb={4}
|
||||
pt={4}
|
||||
spacing="24px"
|
||||
>
|
||||
{/* =======================[Search Input]======================== */}
|
||||
|
||||
<Input
|
||||
type="search"
|
||||
width={300}
|
||||
placeholder="Search..."
|
||||
size="sm"
|
||||
rounded="sm"
|
||||
focusBorderColor="green.500"
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
/>
|
||||
|
||||
<HStack display={"flex"} alignItems={"center"}>
|
||||
{/* ====================[Pagination]===================== */}
|
||||
|
||||
{/* <Pagination
|
||||
isLoading={isSponserLoading}
|
||||
pageSize={pageSize}
|
||||
setPageSize={setPageSize}
|
||||
currentPage={currentPage}
|
||||
setCurrentPage={setCurrentPage}
|
||||
totalItems={subAdmin?.data?.totalItems}
|
||||
/> */}
|
||||
|
||||
{/* =====================[Add Button]===================== */}
|
||||
|
||||
<Link to={"/subadmin/subadmin-update"}>
|
||||
<Button
|
||||
leftIcon={<AddIcon />}
|
||||
colorScheme={"forestGreen"}
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
size={"sm"}
|
||||
>
|
||||
Add
|
||||
</Button>
|
||||
</Link>
|
||||
</HStack>
|
||||
</HStack>
|
||||
</Box>
|
||||
|
||||
{/* =================== [Data Table] ===================== */}
|
||||
|
||||
<NormalTable
|
||||
emptyMessage={`We don't have any Sponers `}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={extractedArray}
|
||||
isLoading={isSponserLoading}
|
||||
viewActionId={actionId}
|
||||
setViewActionId={setActionId}
|
||||
setMouseEnteredId={setMouseEnteredId}
|
||||
setMouseEntered={setMouseEntered}
|
||||
/>
|
||||
|
||||
{/* ======================== [Modal] ======================== */}
|
||||
|
||||
<CustomAlertDialog
|
||||
onClose={() => setDeleteAlert(false)}
|
||||
isOpen={deleteAlert}
|
||||
message={"Are you sure you want to delete sub-admin?"}
|
||||
alertHandler={handleDelete}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default SubAdmin;
|
||||
@@ -1,354 +0,0 @@
|
||||
import { ArrowBackIcon } from "@chakra-ui/icons";
|
||||
import { Box, Text, useToast } from "@chakra-ui/react";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import * as yup from "yup";
|
||||
import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
||||
import FormInputMain from "../../Components/FormInputMain";
|
||||
import FullscreenLoaders from "../../Components/Loaders/FullscreenLoaders";
|
||||
import RoleSwitchButton from "../../Components/RoleSwitchButton";
|
||||
import ToastBox from "../../Components/ToastBox";
|
||||
import {
|
||||
isMaker
|
||||
} from "../../Constants/Constants";
|
||||
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||
import {
|
||||
useCreateSubAdminMutation,
|
||||
useGetSubAdminByIdQuery,
|
||||
useUpdateSubAdminMutation,
|
||||
} from "../../Services/subadmin.service";
|
||||
// ======================= [validation] =========================
|
||||
const addSubAdminSchema = yup.object().shape({
|
||||
firstName: yup
|
||||
.string()
|
||||
.required("First Name is required")
|
||||
.min(3, "First Name must be at least 3 characters long")
|
||||
.max(35, "First Name cannot exceed 35 characters")
|
||||
.matches(/^[^\d]+$/, "First Name cannot contain numbers"),
|
||||
|
||||
lastName: yup.string().required("Last Name is required")
|
||||
.min(3, "Last Name must be at least 3 characters long")
|
||||
.max(35, "Last Name cannot exceed 35 characters")
|
||||
.matches(/^[^\d]+$/, "Last Name cannot contain numbers"),
|
||||
emailAddress:yup.
|
||||
string()
|
||||
.required("Email address is required")
|
||||
.min(6, "Email address must be at least 6 characters long")
|
||||
.max(255, "Email address can be at most 255 characters long"),
|
||||
});
|
||||
|
||||
// ==================== [debounce] ========================
|
||||
|
||||
export function debounce(func, delay) {
|
||||
let debounceTimer;
|
||||
return function (...args) {
|
||||
clearTimeout(debounceTimer);
|
||||
debounceTimer = setTimeout(() => func.apply(this, args), delay);
|
||||
};
|
||||
}
|
||||
|
||||
const SubAdminUpdateCreate = () => {
|
||||
const toast = useToast();
|
||||
const params = useParams();
|
||||
const navigate = useNavigate();
|
||||
const id = params?.id;
|
||||
|
||||
// =====================[useState]=======================
|
||||
|
||||
const [isLoadingBtn, setIsLoadingBtn] = useState(false);
|
||||
const [alert, setAlert] = useState(false);
|
||||
const [form, setForm] = useState();
|
||||
const [isSwitchOn, setIsSwitchOn] = useState(false);
|
||||
|
||||
const [createSubAdmin] = useCreateSubAdminMutation();
|
||||
const [updateSubAdmin] = useUpdateSubAdminMutation();
|
||||
|
||||
// Fetch sponsor data only if id exists
|
||||
const { data: subAdminByIdData, isLoading } = useGetSubAdminByIdQuery(id, {
|
||||
skip: !id,
|
||||
});
|
||||
|
||||
// ======================== [validators] ===========================
|
||||
|
||||
const {
|
||||
control,
|
||||
watch,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
reset,
|
||||
} = useForm({
|
||||
resolver: yupResolver(addSubAdminSchema),
|
||||
mode: "all",
|
||||
});
|
||||
|
||||
// ========================== [useEffect] ================================
|
||||
|
||||
useEffect(() => {
|
||||
if (subAdminByIdData?.data) {
|
||||
reset({
|
||||
firstName: subAdminByIdData?.data?.firstName,
|
||||
lastName: subAdminByIdData?.data?.lastName,
|
||||
emailAddress: subAdminByIdData?.data?.emailAddress,
|
||||
});
|
||||
setIsSwitchOn(isMaker(subAdminByIdData?.data?.role[0]?.role));
|
||||
}
|
||||
}, [subAdminByIdData, reset]);
|
||||
|
||||
if (isLoading) {
|
||||
return <FullscreenLoaders />;
|
||||
}
|
||||
|
||||
// ============================ [API]===============================
|
||||
|
||||
const handleConfirm = async () => {
|
||||
setIsLoadingBtn(true);
|
||||
const id = params?.id;
|
||||
console.log(isSwitchOn);
|
||||
|
||||
if (id) {
|
||||
try {
|
||||
const formData = {
|
||||
...form,
|
||||
role_xid: !isSwitchOn ? 2 : 1,
|
||||
};
|
||||
await updateSubAdmin({ data: formData, id }).then((response) => {
|
||||
if (response?.data?.statusCode) {
|
||||
toast({
|
||||
render: () => <ToastBox message={response?.data?.message} />,
|
||||
});
|
||||
|
||||
setIsLoadingBtn(false);
|
||||
setAlert(false);
|
||||
navigate("/subadmin");
|
||||
} else if (response?.error?.status === 400) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox
|
||||
message={response?.error?.data?.message}
|
||||
status={"error"}
|
||||
/>
|
||||
),
|
||||
});
|
||||
|
||||
setIsLoadingBtn(false);
|
||||
setAlert(false);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
setIsLoadingBtn(false);
|
||||
navigate("/subadmin");
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const formData = {
|
||||
...form,
|
||||
role_xid: isSwitchOn ? 1 : 2,
|
||||
};
|
||||
await createSubAdmin(formData).then((response) => {
|
||||
console.log(response);
|
||||
if (response?.data?.statusCode === 201) {
|
||||
toast({
|
||||
render: () => <ToastBox message={response?.data?.message} />,
|
||||
});
|
||||
|
||||
setIsLoadingBtn(false);
|
||||
navigate("/subadmin");
|
||||
} else if (response?.error?.status === 400) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox
|
||||
message={response?.error?.data?.message}
|
||||
status={"error"}
|
||||
/>
|
||||
),
|
||||
});
|
||||
|
||||
setIsLoadingBtn(false);
|
||||
setAlert(false);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
||||
setIsLoadingBtn(false);
|
||||
navigate("/subadmin");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ====================== [Update Form Object] =========================
|
||||
|
||||
const formFields = [
|
||||
{
|
||||
label: "First Name",
|
||||
placeHolder: " ",
|
||||
name: "firstName",
|
||||
type: "text",
|
||||
isRequired: true,
|
||||
section: "",
|
||||
maxLength: 35,
|
||||
helperText: `Maximum length should be 35 characters. You have entered ${
|
||||
watch()?.firstName?.length || 0
|
||||
} characters.`,
|
||||
},
|
||||
{
|
||||
label: "Last Name",
|
||||
name: "lastName",
|
||||
placeHolder: " ",
|
||||
type: "text",
|
||||
isRequired: true,
|
||||
section: "",
|
||||
maxLength: 35,
|
||||
helperText: `Maximum length should be 35 characters. You have entered ${
|
||||
watch()?.lastName?.length || 0
|
||||
} characters.`,
|
||||
},
|
||||
{
|
||||
label: "Email address",
|
||||
name: "emailAddress",
|
||||
placeHolder: " ",
|
||||
type: "email",
|
||||
isRequired: true,
|
||||
section: "",
|
||||
},
|
||||
];
|
||||
|
||||
// ==================== [Create Form Object] =======================
|
||||
|
||||
const formEditFields = [
|
||||
{
|
||||
label: "First Name",
|
||||
placeHolder: " ",
|
||||
name: "firstName",
|
||||
type: "text",
|
||||
isRequired: true,
|
||||
section: "",
|
||||
maxLength: 35,
|
||||
helperText: `Maximum length should be 35 characters. You have entered ${
|
||||
watch()?.firstName?.length || 0
|
||||
} characters.`,
|
||||
},
|
||||
{
|
||||
label: "Last Name",
|
||||
name: "lastName",
|
||||
placeHolder: " ",
|
||||
type: "text",
|
||||
isRequired: true,
|
||||
section: "",
|
||||
maxLength: 35,
|
||||
helperText: `Maximum length should be 35 characters. You have entered ${
|
||||
watch()?.lastName?.length || 0
|
||||
} characters.`,
|
||||
},
|
||||
{
|
||||
label: "Email Address",
|
||||
name: "emailAddress",
|
||||
placeHolder: " ",
|
||||
type: "email",
|
||||
isRequired: true,
|
||||
section: "",
|
||||
},
|
||||
];
|
||||
|
||||
// ====================== [Group Create Fields] =========================
|
||||
|
||||
const groupedEditFields = formEditFields.reduce((groups, field) => {
|
||||
const { section } = field;
|
||||
if (!groups[section]) {
|
||||
groups[section] = [];
|
||||
}
|
||||
groups[section].push(field);
|
||||
return groups;
|
||||
}, {});
|
||||
|
||||
// ====================== [Group Update Fields] =======================
|
||||
|
||||
const groupedFields = formFields.reduce((groups, field) => {
|
||||
const { section } = field;
|
||||
if (!groups[section]) {
|
||||
groups[section] = [];
|
||||
}
|
||||
groups[section].push(field);
|
||||
return groups;
|
||||
}, {});
|
||||
|
||||
// ==================== [On Submit] ========================
|
||||
// console.log(errors);
|
||||
|
||||
const onSubmit = async (data) => {
|
||||
console.log("Hit");
|
||||
|
||||
if (Object.keys(errors).length === 0) {
|
||||
setForm(data);
|
||||
setAlert(true);
|
||||
}
|
||||
};
|
||||
|
||||
return isLoading ? (
|
||||
<FullscreenLoaders />
|
||||
) : (
|
||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
|
||||
{/* ===================== [Switch Button] ======================== */}
|
||||
<Box
|
||||
display={"flex"}
|
||||
justifyContent={"space-between"}
|
||||
alignItems={"center"}
|
||||
mt={5}
|
||||
px={4}
|
||||
>
|
||||
<Text
|
||||
fontSize={"sm"}
|
||||
mb={0}
|
||||
onClick={() => navigate(-1)}
|
||||
cursor={"pointer"}
|
||||
>
|
||||
<ArrowBackIcon fontSize={"xl"} me={2} />
|
||||
{params?.id ? "Edit Details" : "Add Details"}
|
||||
</Text>
|
||||
{/* {params?.id ? (
|
||||
""
|
||||
) : (
|
||||
<RoleSwitchButton
|
||||
isSwitchOn={isSwitchOn}
|
||||
setIsSwitchOn={setIsSwitchOn}
|
||||
/>
|
||||
)} */}
|
||||
<RoleSwitchButton
|
||||
isSwitchOn={isSwitchOn}
|
||||
setIsSwitchOn={setIsSwitchOn}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* ====================== [Form Input] ====================== */}
|
||||
|
||||
<FormInputMain
|
||||
groupedFields={params?.id ? groupedEditFields : groupedFields}
|
||||
control={control}
|
||||
errors={errors}
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
submitTitle={params?.id ? "Update" : "Submit"}
|
||||
></FormInputMain>
|
||||
|
||||
{/* ======================= [Modal] =========================== */}
|
||||
|
||||
<CustomAlertDialog
|
||||
isOpen={alert}
|
||||
onClose={() => setAlert(false)}
|
||||
alertHandler={handleConfirm}
|
||||
message={
|
||||
id
|
||||
? "Are you sure you want to update this?"
|
||||
: "Are you sure you want to add this?"
|
||||
}
|
||||
isLoading={isLoadingBtn}
|
||||
/>
|
||||
|
||||
{/* <DummyComponent /> */}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default SubAdminUpdateCreate;
|
||||
@@ -104,23 +104,25 @@ export const nav = [
|
||||
title: "INVESTORS REQUEST",
|
||||
type: "title",
|
||||
},
|
||||
{
|
||||
title: "Fawateer Deposit",
|
||||
submenu: [
|
||||
{
|
||||
title: "Aprover Request",
|
||||
path: "/fawateer",
|
||||
icon: RiMoneyDollarBoxLine,
|
||||
},
|
||||
{
|
||||
title: "View History",
|
||||
path: "/fawateer-history",
|
||||
icon: RiExchangeBoxLine,
|
||||
},
|
||||
],
|
||||
type: "accordion",
|
||||
Icon: HiOutlineBanknotes,
|
||||
},
|
||||
{
|
||||
title: "Fawateer Deposit",
|
||||
submenu: [
|
||||
{
|
||||
title: "Aprover Request",
|
||||
path: "/fawateer",
|
||||
icon: RiMoneyDollarBoxLine,
|
||||
},
|
||||
{
|
||||
title: "View History",
|
||||
path: "/fawateer-history",
|
||||
icon: RiExchangeBoxLine,
|
||||
},
|
||||
],
|
||||
type: "accordion",
|
||||
Icon: HiOutlineBanknotes,
|
||||
}
|
||||
,
|
||||
|
||||
{
|
||||
title: "Bank Deposit",
|
||||
submenu: [
|
||||
@@ -231,11 +233,6 @@ export const nav = [
|
||||
path: "/bank-details",
|
||||
icon: RiBankLine,
|
||||
},
|
||||
{
|
||||
title: "Sub Admin",
|
||||
path: "/subadmin",
|
||||
icon: RiFileUserLine,
|
||||
},
|
||||
],
|
||||
type: "accordion",
|
||||
Icon: MdOutlineAdminPanelSettings,
|
||||
|
||||
@@ -46,8 +46,6 @@ import EmailNotification from "../Pages/EmailNotification/EmailNotification";
|
||||
import User from "../Pages/User/User";
|
||||
import AddUser from "../Pages/User/AddUser";
|
||||
import Profile from "../Pages/Profile/Profile";
|
||||
import SubAdmin from "../Pages/SubAdmin/SubAdmin";
|
||||
import SubAdminUpdateCreate from "../Pages/SubAdmin/SubAdminUpdateCreate";
|
||||
|
||||
export const RouteLink = [
|
||||
// =============[ Tanami ]================
|
||||
@@ -125,9 +123,6 @@ export const RouteLink = [
|
||||
// { path: "/bank-details", Component: UnderConstruction },
|
||||
{ path: "/bank-details/edit-bank-details/:id", Component: EditBankDetails },
|
||||
{ path: "/profile", Component: Profile },
|
||||
{ path: "/subadmin", Component: SubAdmin },
|
||||
{ path: "/subadmin/subadmin-update/:id", Component: SubAdminUpdateCreate },
|
||||
{ path: "/subadmin/subadmin-update", Component: SubAdminUpdateCreate },
|
||||
|
||||
|
||||
|
||||
@@ -139,5 +134,8 @@ export const RouteLink = [
|
||||
// { path: "/fawateer-approver", Component: ApproveRequest },
|
||||
// { path: "/approver-history", Component: ApproveHistory },
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
];
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
|
||||
// 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 changePasswordMake = createApi({
|
||||
reducerPath: "changePassword",
|
||||
baseQuery: baseQuery,
|
||||
tagTypes: ["getPassword"],
|
||||
endpoints: (builder) => ({
|
||||
// // ========[ update ]========
|
||||
updatePassword: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `/auth/admin/update-password`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
invalidatesTags: ["getPassword"],
|
||||
}),
|
||||
|
||||
}),
|
||||
});
|
||||
|
||||
// Export hooks for usage in functional components
|
||||
export const {
|
||||
useUpdatePasswordMutation
|
||||
} = changePasswordMake;
|
||||
@@ -1,30 +0,0 @@
|
||||
|
||||
// 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 forgetPasswordMake = createApi({
|
||||
reducerPath: "forgetPassword",
|
||||
baseQuery: baseQuery,
|
||||
tagTypes: ["getPassword"],
|
||||
endpoints: (builder) => ({
|
||||
// // ========[ update ]========
|
||||
forgetPassword: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `/auth/admin/forget-password`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
invalidatesTags: ["getPassword"],
|
||||
}),
|
||||
|
||||
}),
|
||||
});
|
||||
|
||||
// Export hooks for usage in functional components
|
||||
export const {
|
||||
useForgetPasswordMutation
|
||||
} = forgetPasswordMake;
|
||||
@@ -421,7 +421,7 @@ export const ioService = createApi({
|
||||
}),
|
||||
|
||||
profile: builder.query({
|
||||
query: () => `/auth/admin/profile`,
|
||||
query: (id) => `/auth/admin/profile`,
|
||||
}),
|
||||
|
||||
// ========Add Io Details========
|
||||
@@ -435,7 +435,7 @@ export const ioService = createApi({
|
||||
invalidatesTags: ["getIOById"],
|
||||
}),
|
||||
|
||||
|
||||
|
||||
updateTransaction: builder.mutation({
|
||||
query: (id) => ({
|
||||
// url: `/io/admin/maker-transaction/${id}/verify-pending-transaction-for-cash-and-nav`,
|
||||
@@ -448,45 +448,45 @@ export const ioService = createApi({
|
||||
|
||||
|
||||
addNavDetails: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
query: ({id,data}) => ({
|
||||
url: `/io/admin/maker-transaction/${id}/io-nav`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
body:data,
|
||||
}),
|
||||
|
||||
invalidatesTags: ["getIOById"],
|
||||
}),
|
||||
|
||||
addIOTransaction: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
query: ({id,data}) => ({
|
||||
url: `/io/admin/maker-transaction/${id}/io-nav`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
body:data,
|
||||
}),
|
||||
|
||||
invalidatesTags: ["getIOById"],
|
||||
}),
|
||||
|
||||
saveIOTransaction: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
query: ({id,data}) => ({
|
||||
url: `/io/admin/maker-transaction/${id}/io-yeild`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
body:data,
|
||||
}),
|
||||
|
||||
invalidatesTags: ["getIOById"],
|
||||
}),
|
||||
|
||||
exitIOTransaction: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
query: ({id,data}) => ({
|
||||
url: `/io/admin/maker-transaction/${id}/io-exit`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
body:data,
|
||||
}),
|
||||
|
||||
invalidatesTags: ["getIOById"],
|
||||
}),
|
||||
|
||||
|
||||
|
||||
addIoCase: builder.mutation({
|
||||
query: (id) => ({
|
||||
@@ -499,10 +499,10 @@ export const ioService = createApi({
|
||||
|
||||
|
||||
approveIOCase: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
query: ({id,data}) => ({
|
||||
url: `/io/admin/checker-transaction/approved/io-cash/${id}`,
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
body:data,
|
||||
}),
|
||||
|
||||
invalidatesTags: ["getIOById"],
|
||||
@@ -510,71 +510,71 @@ export const ioService = createApi({
|
||||
|
||||
|
||||
approveIONav: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
query: ({id,data}) => ({
|
||||
url: `/io/admin/checker-transaction/approved/io-nav/${id}`,
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
body:data,
|
||||
}),
|
||||
|
||||
invalidatesTags: ["getIOById"],
|
||||
}),
|
||||
|
||||
approveDistribution: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
query: ({id,data}) => ({
|
||||
url: `/io/admin/checker-transaction/approved/distributed-to-investor/${id}`,
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
body:data,
|
||||
}),
|
||||
|
||||
invalidatesTags: ["getIOById"],
|
||||
}),
|
||||
|
||||
|
||||
|
||||
approveExit: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
query: ({id,data}) => ({
|
||||
url: `/io/admin/checker-transaction/approved/exit/${id}`,
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
body:data,
|
||||
}),
|
||||
|
||||
invalidatesTags: ["getIOById"],
|
||||
}),
|
||||
|
||||
approveInvested: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
query: ({id,data}) => ({
|
||||
url: `/io/admin/checker-transaction/approved/amount-invested/${id}`,
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
body:data,
|
||||
}),
|
||||
|
||||
invalidatesTags: ["getIOById"],
|
||||
}),
|
||||
|
||||
|
||||
approveDistributed: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
query: ({id,data}) => ({
|
||||
url: `/io/admin/checker-transaction/approved/distributed-to-investor/${id}`,
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
body:data,
|
||||
}),
|
||||
|
||||
invalidatesTags: ["getIOById"],
|
||||
}),
|
||||
|
||||
approveExitTransaction: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
query: ({id,data}) => ({
|
||||
url: `/io/admin/checker-transaction/approved/exit/${id}`,
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
body:data,
|
||||
}),
|
||||
|
||||
invalidatesTags: ["getIOById"],
|
||||
}),
|
||||
|
||||
approveCancleTransaction: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
query: ({id,data}) => ({
|
||||
url: `/io/admin/checker-transaction/approved/cancel/${id}`,
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
body:data,
|
||||
}),
|
||||
|
||||
invalidatesTags: ["getIOById"],
|
||||
@@ -582,16 +582,16 @@ export const ioService = createApi({
|
||||
|
||||
|
||||
rejectIOCase: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
query: ({id,data}) => ({
|
||||
url: `/io/admin/checker-transaction/reject/${id}`,
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
body:data,
|
||||
}),
|
||||
|
||||
invalidatesTags: ["getIOById"],
|
||||
}),
|
||||
|
||||
|
||||
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
|
||||
// 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 sabAdminMaster = createApi({
|
||||
reducerPath: "sabAdminMaster",
|
||||
baseQuery: baseQuery,
|
||||
tagTypes: ["getSubAdmin", "prePopulate","getSubAdminById"],
|
||||
endpoints: (builder) => ({
|
||||
|
||||
|
||||
|
||||
// ======[Get All]=====
|
||||
|
||||
getSubAdminMaster: builder.query({
|
||||
query: () => `/subadmin/admin/getAll`,
|
||||
providesTags: ["getSubAdmin"],
|
||||
}),
|
||||
|
||||
// // ========[ Create ]========
|
||||
|
||||
createSubAdmin: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `/subadmin/admin/create`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
invalidatesTags: ["getSubAdmin", "prePopulate"],
|
||||
}),
|
||||
|
||||
// // ========[Update Sponser]========
|
||||
|
||||
updateSubAdmin: builder.mutation({
|
||||
query: ({ data, id }) => ({
|
||||
url: `/subadmin/admin/${id}`,
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
}),
|
||||
invalidatesTags: ["getSubAdmin","getSubAdminById"],
|
||||
}),
|
||||
|
||||
getSubAdminById: builder.query({
|
||||
query: (id) => `/subadmin/admin/${id}`,
|
||||
providesTags: ["getSubAdminById"],
|
||||
}),
|
||||
|
||||
// // ========[Toggle Status]========
|
||||
|
||||
toggleStatus: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
url: `/subadmin/admin/toggle-role/${id}`,
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
}),
|
||||
invalidatesTags: ["getSubAdmin"],
|
||||
}),
|
||||
|
||||
|
||||
// ==========[Delete User] ==========
|
||||
deleteUser: builder.mutation({
|
||||
query: (id) => ({
|
||||
url: `/subadmin/admin/${id}`,
|
||||
method: "DELETE",
|
||||
}),
|
||||
invalidatesTags: ["getSubAdmin"],
|
||||
}),
|
||||
|
||||
|
||||
}),
|
||||
});
|
||||
|
||||
// Export hooks for usage in functional components
|
||||
export const {
|
||||
useGetSubAdminMasterQuery,
|
||||
useCreateSubAdminMutation,
|
||||
useUpdateSubAdminMutation,
|
||||
useGetSubAdminByIdQuery,
|
||||
useToggleStatusMutation,
|
||||
useDeleteUserMutation,
|
||||
} = sabAdminMaster;
|
||||
@@ -1,122 +1,131 @@
|
||||
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
|
||||
import { encryptString } from '../Constants/Constants'
|
||||
|
||||
// Define a base query function with token refresh logic, retry mechanism, and AbortController
|
||||
// Define a base query function with RTK Query
|
||||
// export const baseQuery = fetchBaseQuery({
|
||||
// baseUrl: 'https://sprint4.tanami.betadelivery.com/api/v1',
|
||||
// prepareHeaders: (headers) => {
|
||||
// const token = localStorage.getItem('accessToken');
|
||||
// if (token) {
|
||||
// headers.set('x-auth-token', `${token}`);
|
||||
// }
|
||||
// return headers;
|
||||
// },
|
||||
// });
|
||||
|
||||
// Define a base query function with token refresh logic
|
||||
export const baseQuery = async (args, api, extraOptions) => {
|
||||
const fetchBase = fetchBaseQuery({
|
||||
baseUrl: import.meta.env.VITE_BAS_URL,
|
||||
credentials: 'include',
|
||||
prepareHeaders: (headers) => {
|
||||
// headers.set('Content-Type', 'application/json');
|
||||
return headers;
|
||||
},
|
||||
});
|
||||
let result = await fetchBaseQuery({
|
||||
baseUrl: import.meta.env.VITE_BAS_URL,
|
||||
prepareHeaders: (headers) => {
|
||||
const token = localStorage.getItem("accessToken");
|
||||
if (token) {
|
||||
headers.set("x-auth-token", token);
|
||||
}
|
||||
return headers;
|
||||
},
|
||||
})(args, api, extraOptions);
|
||||
|
||||
const abortController = new AbortController();
|
||||
extraOptions = {
|
||||
...extraOptions,
|
||||
signal: abortController.signal,
|
||||
};
|
||||
if (result.error && result.error.status === 403) {
|
||||
// Handle token refresh
|
||||
const refreshToken = localStorage.getItem("refreshToken");
|
||||
console.log(refreshToken);
|
||||
if (refreshToken) {
|
||||
try {
|
||||
const refreshResult = await fetchBaseQuery({
|
||||
baseUrl: import.meta.env.VITE_BAS_URL,
|
||||
})(
|
||||
{
|
||||
url: "/auth/user/regenerate-token",
|
||||
method: "POST",
|
||||
body: { refreshToken },
|
||||
},
|
||||
api,
|
||||
extraOptions
|
||||
);
|
||||
|
||||
let result = await fetchBase(args, api, extraOptions);
|
||||
if (refreshResult.data) {
|
||||
// Save new tokens
|
||||
localStorage.setItem("accessToken", refreshResult?.data?.data?.access?.token);
|
||||
// localStorage.setItem("role", refreshResult?.data?.data?.role);
|
||||
// console.log(refreshResult?.data?.data?.role);
|
||||
|
||||
|
||||
if (result.error) {
|
||||
if (result.error.status === 403) {
|
||||
let retryCount = 0;
|
||||
const maxRetries = import.meta.env.VITE_MAX_TRY_REGENRATE_TOKEN || 2;
|
||||
// Retry the original request with the new token
|
||||
result = await fetchBaseQuery({
|
||||
baseUrl: import.meta.env.VITE_BAS_URL,
|
||||
prepareHeaders: (headers) => {
|
||||
const token = localStorage.getItem("accessToken");
|
||||
if (token) {
|
||||
headers.set("x-auth-token", token);
|
||||
}
|
||||
return headers;
|
||||
},
|
||||
})(args, api, extraOptions);
|
||||
}else{
|
||||
|
||||
while (retryCount < maxRetries) {
|
||||
try {
|
||||
const { data, error } = await fetchBase(
|
||||
{
|
||||
url: "/auth/user/regenerate-token",
|
||||
method: "POST",
|
||||
},
|
||||
api,
|
||||
{ ...extraOptions, signal: abortController.signal }
|
||||
);
|
||||
if (data) {
|
||||
// Retry the original query after successful token regeneration
|
||||
return await fetchBase(args, api, { ...extraOptions, signal: abortController.signal });
|
||||
}
|
||||
console.log('refresh failed');
|
||||
localStorage.clear();
|
||||
window.location.href = '/login'; // Redirect to login page
|
||||
|
||||
throw error;
|
||||
} catch (err) {
|
||||
retryCount++;
|
||||
if (retryCount >= maxRetries) {
|
||||
console.error("Failed to refresh token after retries:", err);
|
||||
abortController.abort();
|
||||
localStorage.clear();
|
||||
window.location.href = '/login'; // Redirect to login page
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (result.error.status === 401) {
|
||||
abortController.abort();
|
||||
localStorage.clear();
|
||||
window.location.href = '/login';
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Failed to refresh token:", err);
|
||||
localStorage.clear();
|
||||
window.location.href = '/login'; // Redirect to login page
|
||||
// Handle refresh failure (e.g., redirect to login)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
};
|
||||
|
||||
// Create an RTK Query API slice
|
||||
export const apiSlice = createApi({
|
||||
reducerPath: "api",
|
||||
baseQuery: baseQuery,
|
||||
tagTypes: ["authProfile"],
|
||||
endpoints: (builder) => ({
|
||||
|
||||
login: builder.mutation({
|
||||
query: (credentials) => ({
|
||||
url: "/auth/admin",
|
||||
method: "POST",
|
||||
body: credentials,
|
||||
}),
|
||||
async onQueryStarted(arg, { queryFulfilled }) {
|
||||
try {
|
||||
const { data } = await queryFulfilled;
|
||||
localStorage.setItem("role", encryptString(data?.data?.role));
|
||||
} catch (error) {
|
||||
console.error("Login failed:", error);
|
||||
}
|
||||
},
|
||||
}),
|
||||
|
||||
refreshToken: builder.mutation({
|
||||
query: (refreshToken) => ({
|
||||
url: "/auth/user/regenerate-token",
|
||||
method: "POST",
|
||||
body: { refreshToken },
|
||||
}),
|
||||
}),
|
||||
|
||||
logout: builder.mutation({
|
||||
query: () => ({
|
||||
url: "/auth/admin/logout",
|
||||
method: "POST",
|
||||
}),
|
||||
}),
|
||||
|
||||
authProfile: builder.query({
|
||||
query: () => `/auth/admin/profile`,
|
||||
providesTags: (result) => result ? [{ type: 'Auth', id: 'profile' }] : [],
|
||||
onQueryStarted: async (args, { queryFulfilled }) => {
|
||||
try {
|
||||
const { data } = await queryFulfilled; // Get the data from the query response
|
||||
if (data?.role) {
|
||||
localStorage.setItem('role', encryptString(data.role));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error setting role in localStorage:', error);
|
||||
}
|
||||
},
|
||||
}),
|
||||
reducerPath: "api",
|
||||
baseQuery: baseQuery,
|
||||
endpoints: (builder) => ({
|
||||
login: builder.mutation({
|
||||
query: (credentials) => ({
|
||||
url: "/auth/admin",
|
||||
method: "POST",
|
||||
body: credentials,
|
||||
}),
|
||||
async onQueryStarted(arg, { dispatch, queryFulfilled }) {
|
||||
try {
|
||||
const { data } = await queryFulfilled;
|
||||
// Store tokens in local storage
|
||||
localStorage.setItem("accessToken", data?.data?.access?.token);
|
||||
|
||||
localStorage.setItem("refreshToken", data?.data?.refresh?.token);
|
||||
// localStorage.setItem('refreshTokenExp', data?.data?.refresh?.expires);
|
||||
localStorage.setItem("accessTokenExp", data?.data?.access?.expires);
|
||||
localStorage.setItem("role", data?.data?.role);
|
||||
} catch (error) {
|
||||
console.error("Login failed:", error);
|
||||
}
|
||||
},
|
||||
}),
|
||||
refreshToken: builder.mutation({
|
||||
query: (refreshToken) => ({
|
||||
url: "/auth/user/regenerate-token",
|
||||
method: "POST",
|
||||
body: { refreshToken },
|
||||
}),
|
||||
}),
|
||||
|
||||
|
||||
}),
|
||||
logout: builder.mutation({
|
||||
query: () => ({
|
||||
url: "/auth/admin/logout",
|
||||
method: "POST",
|
||||
}),
|
||||
}),
|
||||
|
||||
|
||||
|
||||
|
||||
}),
|
||||
});
|
||||
|
||||
export const { useLoginMutation, useRefreshTokenMutation, useLogoutMutation, useAuthProfileQuery } = apiSlice;
|
||||
export const { useLoginMutation, useRefreshTokenMutation, useLogoutMutation } = apiSlice;
|
||||
|
||||
@@ -17,9 +17,6 @@ import { deleteRequest } from "../Services/delete.request.service";
|
||||
import { banInvestorDetails } from "../Services/ban.investor.service";
|
||||
import { fawateerRequest } from "../Services/fawateer.request.service";
|
||||
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";
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
@@ -38,9 +35,6 @@ export const store = configureStore({
|
||||
[banInvestorDetails.reducerPath]: banInvestorDetails.reducer,
|
||||
[fawateerRequest.reducerPath]: fawateerRequest.reducer,
|
||||
[fawateerMaker.reducerPath]: fawateerMaker.reducer,
|
||||
[sabAdminMaster.reducerPath]: sabAdminMaster.reducer,
|
||||
[changePasswordMake.reducerPath]: changePasswordMake.reducer,
|
||||
[forgetPasswordMake.reducerPath]: forgetPasswordMake.reducer,
|
||||
|
||||
// Add other reducers as needed
|
||||
},
|
||||
@@ -65,9 +59,7 @@ export const store = configureStore({
|
||||
banInvestorDetails.middleware,
|
||||
fawateerRequest.middleware,
|
||||
fawateerMaker.middleware,
|
||||
sabAdminMaster.middleware,
|
||||
changePasswordMake.middleware,
|
||||
forgetPasswordMake.middleware,
|
||||
|
||||
),
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user