Compare commits

...

11 Commits

Author SHA1 Message Date
Swapnil Bendal
9eca3ae9fc [update] - pagination on investor details 2024-12-27 15:22:34 +05:30
Swapnil Bendal
212f5d4d37 [fixed] - on IO Transaction 2024-12-24 18:08:15 +05:30
Swapnil Bendal
84298ff453 [update] - IO Transaction bug fix 2024-12-24 16:59:01 +05:30
Swapnil Bendal
8eae4222f4 [fixed] - pending action 2024-12-24 16:36:07 +05:30
52a987b616 Merge pull request '[fixed] - token service' (#28) from dev into main
Reviewed-on: #28
2024-12-23 14:48:38 +00:00
Swapnil Bendal
2a3c211b56 [fixed] - token service 2024-12-23 19:33:08 +05:30
4d6a8bb472 Merge pull request 'dev' (#27) from dev into main
Reviewed-on: #27
2024-12-20 14:49:35 +00:00
Swapnil Bendal
41a60c0892 [fixed] - change password 2024-12-20 20:18:26 +05:30
Swapnil Bendal
5c05a68bb0 [update] - readme 2024-12-20 20:10:43 +05:30
f02f9c8b7d Merge pull request '[update] - readme' (#26) from dev into main
Reviewed-on: #26
2024-12-20 14:39:43 +00:00
Swapnil Bendal
137912aa11 [update] - readme 2024-12-20 20:08:44 +05:30
13 changed files with 1001 additions and 985 deletions

View File

@@ -67,9 +67,25 @@ The project is **live and operational**, catering specifically to the investment
```bash ```bash
npm install pm2 -g npm install pm2 -g
``` ```
2. Start the production server:
2. Build the application (if applicable):
```bash ```bash
npm start 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
``` ```
--- ---
@@ -84,17 +100,14 @@ Create a `.env` file in the root directory based on the structure of [`.env.exam
| Script | Description | | Script | Description |
|---------------------|-------------------------------------------------------------| |---------------------|-------------------------------------------------------------|
| `npm start` | Starts the app in production mode using PM2. | | `npm run dev` | Starts the app in development mode with `Vite` server. |
| `npm run dev` | Starts the app in development mode with `nodemon`. | | `npm run build` | Builds the app for production. |
| `npm run test` | Starts the app in test mode with `nodemon`. |
| `npm run lint` | Runs ESLint to check for code quality issues. | | `npm run lint` | Runs ESLint to check for code quality issues. |
| `npm run lint:fix` | Fixes fixable issues detected by ESLint. | | `npm run preview` | Previews the production build locally. |
| `npm run prettier` | Checks code formatting using Prettier. |
| `npm run prettier:fix` | Formats code files according to Prettier rules. |
| `npm run prepare` | Prepares Husky for managing Git hooks. |
--- ---
## **License** ## **License**
This project is licensed under the [MIT License](LICENSE). This project is licensed under the [MIT License](LICENSE).

View File

@@ -49,7 +49,7 @@ const Pagination = ({
value={pageSize} value={pageSize}
onChange={handlePageSizeChange} onChange={handlePageSizeChange}
> >
{[15, 20, 30]?.map((size) => ( {[15, 20, 30, 500]?.map((size) => (
<option key={size} value={size}> <option key={size} value={size}>
{size} {size}
</option> </option>

View File

@@ -1,2 +1,3 @@
export const TABLE_PAGINATION = { page: 1, size: 20 } export const TABLE_PAGINATION = { page: 1, size: 20 }
export const IMAGE_URI = import.meta.env.VITE_API_IMAGE_URL export const IMAGE_URI = import.meta.env.VITE_API_IMAGE_URL
export const INVESTOR_TABLE_PAGINATION = { page: 1, size: 500 }

View File

@@ -117,7 +117,7 @@ const ChangePassword = ({
return ( return (
<> <>
<Modal isOpen={isOpen} onClose={onClose} initialFocusRef={firstField}> <Modal isOpen={isOpen} onClose={handleClose} initialFocusRef={firstField}>
<ModalOverlay /> <ModalOverlay />
<ModalContent> <ModalContent>
<ModalHeader fontSize="md">Change Password</ModalHeader> <ModalHeader fontSize="md">Change Password</ModalHeader>

View File

@@ -38,7 +38,7 @@ import { useUpdateIOCaseMutation } from "../../../../Services/io.service";
import RequestApproveModal from "./RequestApproveModal"; import RequestApproveModal from "./RequestApproveModal";
import RequestRejectModal from "./RequestRejectModal"; import RequestRejectModal from "./RequestRejectModal";
import AddCaseDetails from "./AddCaseDetails"; import AddCaseDetails from "./AddCaseDetails";
import { encryptString } from "../../../../Constants/Constants"; import { encryptString, isMaker } from "../../../../Constants/Constants";
const formatDate = (date) => new Date(date).toLocaleDateString(); const formatDate = (date) => new Date(date).toLocaleDateString();
@@ -105,8 +105,7 @@ const Pending = () => {
"Comments", "Comments",
"Update By", "Update By",
"Update On", "Update On",
...(localStorage?.getItem('role')!==encryptString(import.meta.env.VITE_VITE_MAKER) ? ["Actions"] : []), ...(!isMaker() ? ["Actions"] : []),
]; ];
const extractedArray = filteredData?.map((item, index) => ({ const extractedArray = filteredData?.map((item, index) => ({
@@ -132,9 +131,9 @@ const Pending = () => {
$ $
</Badge> </Badge>
{parseFloat(item?.transactionAmount || 0).toLocaleString(undefined, { {parseFloat(item?.transactionAmount || 0).toLocaleString(undefined, {
minimumFractionDigits: 2, minimumFractionDigits: 2,
maximumFractionDigits: 2, maximumFractionDigits: 2,
})} })}
</Text> </Text>
), ),
Comments: ( Comments: (
@@ -167,64 +166,69 @@ const Pending = () => {
), ),
Actions: ( Actions: (
<Box display={"flex"} justifyContent={"center"}> <Box display={"flex"} justifyContent={"center"}>
{localStorage?.getItem("role") !== encryptString(import.meta.env.VITE_VITE_MAKER) ? <Box> {!isMaker() ? (
{index===0&&<Box display={"flex"} justifyContent={"center"} gap={2}> <Box>
<Tooltip {index === 0 && (
rounded={"sm"} <Box display={"flex"} justifyContent={"center"} gap={2}>
fontSize={"xs"} <Tooltip
label="Approve" rounded={"sm"}
bg="#fff" fontSize={"xs"}
color={"green.500"} label="Approve"
placement="left-start" 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 <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" colorScheme="green"
rounded={"sm"} rounded={"sm"}
size={"xs"} size={"xs"}
@@ -236,7 +240,8 @@ const Pending = () => {
}} }}
> >
<ViewIcon me={"4px"} /> View <ViewIcon me={"4px"} /> View
</Button>} </Button>
)}
</Box> </Box>
), ),
})); }));
@@ -314,9 +319,9 @@ const Pending = () => {
$ $
</Badge> </Badge>
{parseFloat(IODetails?.ioCash || 0).toLocaleString(undefined, { {parseFloat(IODetails?.ioCash || 0).toLocaleString(undefined, {
minimumFractionDigits: 2, minimumFractionDigits: 2,
maximumFractionDigits: 2, maximumFractionDigits: 2,
})} })}
</Th> </Th>
<Th <Th
textAlign={"center"} textAlign={"center"}

View File

@@ -22,7 +22,7 @@ import ToastBox from "../../../../Components/ToastBox";
import AddNavDetails from "./AddNavDetails"; import AddNavDetails from "./AddNavDetails";
import RequestApproveModal from "./RequestApproveModal"; import RequestApproveModal from "./RequestApproveModal";
import RequestRejectModal from "./RequestRejectModal"; import RequestRejectModal from "./RequestRejectModal";
import { encryptString } from "../../../../Constants/Constants"; import { encryptString, isMaker } from "../../../../Constants/Constants";
const formatDate = (date) => new Date(date).toLocaleDateString(); const formatDate = (date) => new Date(date).toLocaleDateString();
@@ -91,7 +91,7 @@ const Pending = () => {
"Investment Closed", "Investment Closed",
"Comments", "Comments",
"Updated By", "Updated By",
...(localStorage?.getItem("role") !== encryptString(import.meta.env.VITE_VITE_MAKER) ? ["Status"] : []), ...(!isMaker() ? ["Status"] : []),
]; ];
const extractedArray = filteredData?.map((item, index) => ({ const extractedArray = filteredData?.map((item, index) => ({
@@ -112,9 +112,9 @@ const Pending = () => {
$ $
</Badge> </Badge>
{parseFloat(item?.transactionAmount || 0).toLocaleString(undefined, { {parseFloat(item?.transactionAmount || 0).toLocaleString(undefined, {
minimumFractionDigits: 2, minimumFractionDigits: 2,
maximumFractionDigits: 2, maximumFractionDigits: 2,
})} })}
</Text> </Text>
), ),
"Last Nav Update": ( "Last Nav Update": (
@@ -162,66 +162,80 @@ const Pending = () => {
{item?.modifier?.firstName} {item?.modifier?.firstName}
</Text> </Text>
), ),
Status: ( Status: isMaker() ? (
<Button
colorScheme="green"
rounded={"sm"}
size={"xs"}
px={2}
py={1}
fontWeight={500}
onClick={() => {
setActionId(item.id);
}}
>
<ViewIcon me={"4px"} /> View
</Button>
) : (
<Box display={"flex"} justifyContent={"center"}> <Box display={"flex"} justifyContent={"center"}>
<Box> <Box>
<Box display={"flex"} justifyContent={"center"} gap={2}> <Box display={"flex"} justifyContent={"center"} gap={2}>
<Tooltip <Tooltip
rounded={"sm"} rounded={"sm"}
fontSize={"xs"} fontSize={"xs"}
label="Approve" label="Approve"
bg="#fff" bg="#fff"
color={"green.500"} color={"green.500"}
placement="left-start" placement="left-start"
> >
<Button <Button
// colorScheme="forestGreen" // colorScheme="forestGreen"
// color="green.500" // color="green.500"
rounded={"sm"} rounded={"sm"}
size={"xs"} size={"xs"}
textTransform={"inherit"} textTransform={"inherit"}
fontWeight={500} fontWeight={500}
px={2} px={2}
py={1} py={1}
onClick={() => { onClick={() => {
setActionId(item.id); setActionId(item.id);
onConfirmOpen(); onConfirmOpen();
}} }}
colorScheme="green" colorScheme="green"
variant={"solid"} variant={"solid"}
cursor={"pointer"} cursor={"pointer"}
> >
<CheckIcon fontSize={"12px"} /> <CheckIcon fontSize={"12px"} />
</Button> </Button>
</Tooltip> </Tooltip>
<Tooltip <Tooltip
rounded={"sm"} rounded={"sm"}
fontSize={"xs"} fontSize={"xs"}
label="Reject" label="Reject"
bg="#fff" bg="#fff"
color={"red.500"} color={"red.500"}
placement="left-start" placement="left-start"
> >
<Button <Button
colorScheme="red" colorScheme="red"
// color="red.500" // color="red.500"
rounded={"sm"} rounded={"sm"}
size={"xs"} size={"xs"}
textTransform={"inherit"} textTransform={"inherit"}
fontWeight={500} fontWeight={500}
px={2} px={2}
onClick={() => { onClick={() => {
setActionId(item.id); setActionId(item.id);
onRejectOpen(); onRejectOpen();
}} }}
py={1} py={1}
// variant={"solid"} // variant={"solid"}
> >
<CloseIcon fontSize={"10px"} /> <CloseIcon fontSize={"10px"} />
</Button> </Button>
</Tooltip> </Tooltip>
</Box>
</Box> </Box>
</Box>
</Box> </Box>
), ),
})); }));

View File

@@ -1,33 +1,26 @@
import { ViewIcon } from "@chakra-ui/icons";
import { import {
Avatar,
Badge, Badge,
Box, Box,
Button, Button,
HStack, HStack,
Input, Input,
Table,
Tag,
Tbody,
Text, Text,
Th,
Tooltip,
Tr,
useDisclosure, useDisclosure,
useToast, useToast,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import React, { useContext, useEffect, useRef, useState } from "react"; import React, { useContext, useEffect, useRef, useState } from "react";
import { OPACITY_ON_LOAD } from "../../../../Layout/animations";
import NormalTable from "../../../../Components/DataTable/NormalTable";
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
import CustomAlertDialog from "../../../../Components/CustomAlertDialog"; import CustomAlertDialog from "../../../../Components/CustomAlertDialog";
import { CheckIcon, CloseIcon, ViewIcon } from "@chakra-ui/icons"; import NormalTable from "../../../../Components/DataTable/NormalTable";
import { isMaker } from "../../../../Constants/Constants";
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
import { OPACITY_ON_LOAD } from "../../../../Layout/animations";
import RequestApproveModal from "./RequestApproveModal"; import RequestApproveModal from "./RequestApproveModal";
import RequestRejectModal from "./RequestRejectModal"; import RequestRejectModal from "./RequestRejectModal";
import ViewAmountInvested from "./ViewAmountInvested"; import ViewAmountInvested from "./ViewAmountInvested";
import ViewCancel from "./ViewCancel";
import ViewDistributionInvestor from "./ViewDistributionInvestor"; import ViewDistributionInvestor from "./ViewDistributionInvestor";
import ViewExit from "./ViewExit"; import ViewExit from "./ViewExit";
import ViewCancel from "./ViewCancel";
import { encryptString, isMaker } from "../../../../Constants/Constants";
const formatDate = (date) => new Date(date).toLocaleDateString(); const formatDate = (date) => new Date(date).toLocaleDateString();
@@ -43,6 +36,7 @@ const Pending = () => {
const [actionId, setActionId] = useState(false); const [actionId, setActionId] = useState(false);
const [mouseEntered, setMouseEntered] = useState(false); const [mouseEntered, setMouseEntered] = useState(false);
const [mouseEnteredId, setMouseEnteredId] = useState(""); const [mouseEnteredId, setMouseEnteredId] = useState("");
const [distributedAmt, setDistributedAmt] = useState();
const { const {
isOpen: isConfirmOpen, isOpen: isConfirmOpen,
@@ -93,11 +87,6 @@ const Pending = () => {
}); });
}; };
console.log(
"==============panding",
IODetails?.ioTransactionRecords?.Pending
);
// Table filter // Table filter
// const filteredData = IODetails?.ioTransactionRecords?.Pending?.filter((item) => { // const filteredData = IODetails?.ioTransactionRecords?.Pending?.filter((item) => {
// // Filter by name (case insensitive) // // Filter by name (case insensitive)
@@ -195,6 +184,7 @@ const Pending = () => {
onInvestmentOpen(); onInvestmentOpen();
} else if (item?.transactionType === "Distribution To Investor") { } else if (item?.transactionType === "Distribution To Investor") {
onDistInvestorOpen(); onDistInvestorOpen();
setDistributedAmt(item?.transactionAmount);
} else if (item?.transactionType === "Exit") { } else if (item?.transactionType === "Exit") {
onExitOpen(); onExitOpen();
} else if (item?.transactionType === "Cancel") { } else if (item?.transactionType === "Cancel") {
@@ -203,10 +193,7 @@ const Pending = () => {
}} }}
> >
{isMaker() ? <ViewIcon me={"4px"} /> : null}{" "} {isMaker() ? <ViewIcon me={"4px"} /> : null}{" "}
{localStorage?.getItem("role") === {isMaker() ? "View" : "Approve / Reject"}
encryptString(import.meta.env.VITE_VITE_MAKER)
? "View"
: "Approve / Reject"}
</Button> </Button>
</Box> </Box>
), ),
@@ -276,6 +263,7 @@ const Pending = () => {
isOpen={isDistInvestorOpen} isOpen={isDistInvestorOpen}
onClose={onDistInvestorClose} onClose={onDistInvestorClose}
id={actionId} id={actionId}
amount={distributedAmt}
/> />
<ViewExit isOpen={isExitOpen} onClose={onExitClose} id={actionId} /> <ViewExit isOpen={isExitOpen} onClose={onExitClose} id={actionId} />
<ViewCancel isOpen={isCancelOpen} onClose={onCancelClose} id={actionId} /> <ViewCancel isOpen={isCancelOpen} onClose={onCancelClose} id={actionId} />

View File

@@ -27,7 +27,7 @@ import CurrencyInput from "../../../../Components/CurrencyInput";
import RequestRejectModal from "./RequestRejectModal"; import RequestRejectModal from "./RequestRejectModal";
import ApproveInvestedModal from "./ApproveInvestedModal"; import ApproveInvestedModal from "./ApproveInvestedModal";
import { formatDate } from "../../../Master/Sponser/Sponsers"; import { formatDate } from "../../../Master/Sponser/Sponsers";
import { encryptString } from "../../../../Constants/Constants"; import { encryptString, isMaker } from "../../../../Constants/Constants";
// Validation schema // Validation schema
const validationSchema = yup.object().shape({ const validationSchema = yup.object().shape({
@@ -117,7 +117,6 @@ const ViewAmountInvested = ({ isOpen, onClose, id: investorId }) => {
}; };
// const formatDate = (date) => new Date(date).toLocaleDateString(); // const formatDate = (date) => new Date(date).toLocaleDateString();
const handleAmountChange = (e) => { const handleAmountChange = (e) => {
// e might be an object or just a value, handle both cases // e might be an object or just a value, handle both cases
@@ -237,41 +236,43 @@ const ViewAmountInvested = ({ isOpen, onClose, id: investorId }) => {
/> />
</FormControl> </FormControl>
{localStorage?.getItem("role") !== encryptString(import.meta.env.VITE_VITE_MAKER) && <ModalFooter> {!isMaker() && (
<Box display={"flex"} justifyContent={"center"} gap={2}> <ModalFooter>
<Button <Box display={"flex"} justifyContent={"center"} gap={2}>
rounded={"sm"} <Button
size={"xs"} rounded={"sm"}
textTransform={"inherit"} size={"xs"}
fontWeight={500} textTransform={"inherit"}
px={3} fontWeight={500}
py={2} px={3}
onClick={() => { py={2}
setActionId(id); // Use the `id` variable from params onClick={() => {
onConfirmOpen(); setActionId(id); // Use the `id` variable from params
}} onConfirmOpen();
colorScheme="forestGreen" }}
variant={"solid"} colorScheme="forestGreen"
cursor={"pointer"} variant={"solid"}
> cursor={"pointer"}
Approve >
</Button> Approve
<Button </Button>
rounded={"sm"} <Button
size={"xs"} rounded={"sm"}
textTransform={"inherit"} size={"xs"}
fontWeight={500} textTransform={"inherit"}
px={3} fontWeight={500}
py={2} px={3}
onClick={() => { py={2}
setActionId(id); // Use the `id` variable from params onClick={() => {
onRejectOpen(); setActionId(id); // Use the `id` variable from params
}} onRejectOpen();
> }}
Reject >
</Button> Reject
</Box> </Button>
</ModalFooter>} </Box>
</ModalFooter>
)}
</form> </form>
</ModalBody> </ModalBody>
</ModalContent> </ModalContent>

View File

@@ -1,128 +1,128 @@
import { import {
Badge, Badge,
Box, Box,
Button, Button,
HStack, HStack,
Modal, Modal,
ModalBody, ModalBody,
ModalCloseButton, ModalCloseButton,
ModalContent, ModalContent,
ModalFooter, ModalFooter,
ModalHeader, ModalHeader,
ModalOverlay, ModalOverlay,
Table, Table,
Tbody, Tbody,
Text, Text,
Th, Th,
Tr, Tr,
useDisclosure, useDisclosure,
useToast, useToast,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import NormalData from "../../../../Components/DataTable/NormalTable"; import NormalData from "../../../../Components/DataTable/NormalTable";
import { useContext, useState } from "react"; import { useContext, useState } from "react";
import { import {
useExitIOTransactionMutation, useExitIOTransactionMutation,
useGetDistributedToInvestorMutation, useGetDistributedToInvestorMutation,
useGetDistributionInvestorMutation, useGetDistributionInvestorMutation,
useGetIOByIdQuery, useGetIOByIdQuery,
} from "../../../../Services/io.service"; } from "../../../../Services/io.service";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { useEffect } from "react"; import { useEffect } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import * as yup from "yup"; import * as yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup"; import { yupResolver } from "@hookform/resolvers/yup";
import ToastBox from "../../../../Components/ToastBox"; import ToastBox from "../../../../Components/ToastBox";
import GlobalStateContext from "../../../../Contexts/GlobalStateContext"; import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
import ApprovedCancelTransaction from "./ApprovedCancelTransaction"; import ApprovedCancelTransaction from "./ApprovedCancelTransaction";
import RequestRejectModal from "./RequestRejectModal"; import RequestRejectModal from "./RequestRejectModal";
import { encryptString } from "../../../../Constants/Constants"; import { encryptString, isMaker } from "../../../../Constants/Constants";
const ViewCancel = ({ isOpen, onClose,id:cancleId }) => { const ViewCancel = ({ isOpen, onClose, id: cancleId }) => {
const params = useParams(); const params = useParams();
const toast = useToast(); const toast = useToast();
const id = params?.id; const id = params?.id;
const [isCalculateLoading, setIsCalculateLoading] = useState(false); const [isCalculateLoading, setIsCalculateLoading] = useState(false);
const [isFinalCalculateLoading, setIsFinalCalculateLoading] = useState(false); const [isFinalCalculateLoading, setIsFinalCalculateLoading] = useState(false);
const [calcualtedData, setCalculatedDate] = useState(null); const [calcualtedData, setCalculatedDate] = useState(null);
const [isCalcualtedData, setIsCalcualtedData] = useState(false); const [isCalcualtedData, setIsCalcualtedData] = useState(false);
const { investors, setInvestors, slideFromRight, IODetails } = const { investors, setInvestors, slideFromRight, IODetails } =
useContext(GlobalStateContext); useContext(GlobalStateContext);
const [actionId, setActionId] = useState(false); const [actionId, setActionId] = useState(false);
const { const {
isOpen: isConfirmOpen, isOpen: isConfirmOpen,
onOpen: onConfirmOpen, onOpen: onConfirmOpen,
onClose: onConfirmClose, onClose: onConfirmClose,
} = useDisclosure(); } = useDisclosure();
const { const {
isOpen: isRejectOpen, isOpen: isRejectOpen,
onOpen: onRejectOpen, onOpen: onRejectOpen,
onClose: onRejectClose, onClose: onRejectClose,
} = useDisclosure(); } = useDisclosure();
const investorExit = yup.object().shape({ const investorExit = yup.object().shape({
amount: yup amount: yup
.string() .string()
.required("Amount is required") .required("Amount is required")
.test( .test(
"max", "max",
`Distribution amount should not be greater than IO cash amount ${IODetails?.ioCash}`, `Distribution amount should not be greater than IO cash amount ${IODetails?.ioCash}`,
function (value) { function (value) {
const { ioCash } = IODetails || {}; // Safely get ioCash const { ioCash } = IODetails || {}; // Safely get ioCash
if (value && ioCash) { if (value && ioCash) {
return parseFloat(value) <= parseFloat(ioCash); // Ensure both are compared as numbers 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, const {
formState: { errors }, control,
reset, handleSubmit,
} = useForm({ formState: { errors },
resolver: yupResolver(investorExit), reset,
}); } = useForm({
resolver: yupResolver(investorExit),
useEffect(() => { });
console.log("hiit useEffectc");
if (id && IODetails) { useEffect(() => {
handleCalculate(id, { console.log("hiit useEffectc");
amount: IODetails?.ioMVNAV, if (id && IODetails) {
}); handleCalculate(id, {
}
reset({
amount: IODetails?.ioMVNAV, amount: IODetails?.ioMVNAV,
}); });
}, [IODetails, id]); }
reset({
const handleCalculate = async (id, data) => { amount: IODetails?.ioMVNAV,
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 = [ 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 = [
"Client ID", "Client ID",
"First name", "First name",
"Last name", "Last name",
@@ -134,221 +134,223 @@ import { encryptString } from "../../../../Constants/Constants";
"Distribution Percent", "Distribution Percent",
"Total Return", "Total Return",
"Total return on Investment", "Total return on Investment",
]; ];
const extractedArray = IODetails?.investors?.map((item, index) => ({ const extractedArray = IODetails?.investors?.map((item, index) => ({
id: item?.id, id: item?.id,
"Client ID": ( "Client ID": (
<Text <Text
justifyContent={slideFromRight ? "right" : "center"} justifyContent={slideFromRight ? "right" : "center"}
as={"span"} as={"span"}
color={"teal.900"} color={"teal.900"}
fontWeight={"500"} fontWeight={"500"}
className="d-flex align-items-center web-text-small" className="d-flex align-items-center web-text-small"
> >
{item?.clientReference_id} {item?.clientReference_id}
</Text> </Text>
), ),
"First name": ( "First name": (
<Text <Text
justifyContent={slideFromRight ? "right" : "center"} justifyContent={slideFromRight ? "right" : "center"}
as={"span"} as={"span"}
color={"teal.900"} color={"teal.900"}
fontWeight={"500"} fontWeight={"500"}
className="d-flex align-items-center web-text-small" className="d-flex align-items-center web-text-small"
> >
{item.firstName} {item.firstName}
</Text> </Text>
), ),
"Last name": ( "Last name": (
<Text <Text
justifyContent={slideFromRight ? "right" : "center"} justifyContent={slideFromRight ? "right" : "center"}
as={"span"} as={"span"}
color={"teal.900"} color={"teal.900"}
fontWeight={"500"} fontWeight={"500"}
className="d-flex align-items-center web-text-small" className="d-flex align-items-center web-text-small"
> >
{item.lastName} {item.lastName}
</Text> </Text>
), ),
"Investment amount": ( "Investment amount": (
<Text <Text
justifyContent={slideFromRight ? "right" : "left"} justifyContent={slideFromRight ? "right" : "left"}
as={"span"} as={"span"}
color={"teal.900"} color={"teal.900"}
fontWeight={"500"} fontWeight={"500"}
className="d-flex align-items-center web-text-small" className="d-flex align-items-center web-text-small"
> >
<Badge ms={1} colorScheme="green" me={1}> <Badge ms={1} colorScheme="green" me={1}>
$ $
</Badge> </Badge>
{/* {`$${formatCurrency(item.InvestedAmount_USD)}`} */} {/* {`$${formatCurrency(item.InvestedAmount_USD)}`} */}
{`${parseFloat(item.InvestedAmount_USD || 0).toLocaleString(undefined, { {`${parseFloat(item.InvestedAmount_USD || 0).toLocaleString(undefined, {
minimumFractionDigits: 2, minimumFractionDigits: 2,
maximumFractionDigits: 2, maximumFractionDigits: 2,
})}`} })}`}
</Text> </Text>
), ),
Percentage: ( Percentage: (
<Text <Text
justifyContent={slideFromRight ? "right" : "center"} justifyContent={slideFromRight ? "right" : "center"}
as={"span"} as={"span"}
color={"teal.900"} color={"teal.900"}
fontWeight={"500"} fontWeight={"500"}
className="d-flex align-items-center web-text-small" className="d-flex align-items-center web-text-small"
> >
{item.Investor_Holidings} % {item.Investor_Holidings} %
</Text> </Text>
), ),
"Market Value": ( "Market Value": (
<Text <Text
justifyContent={slideFromRight ? "right" : "left"} justifyContent={slideFromRight ? "right" : "left"}
as={"span"} as={"span"}
color={"teal.900"} color={"teal.900"}
fontWeight={"500"} fontWeight={"500"}
className="d-flex align-items-center web-text-small" className="d-flex align-items-center web-text-small"
> >
<Badge ms={1} colorScheme="green" me={1}> <Badge ms={1} colorScheme="green" me={1}>
$ $
</Badge> </Badge>
{`${parseFloat(item.Market_Value || 0).toLocaleString(undefined, { {`${parseFloat(item.Market_Value || 0).toLocaleString(undefined, {
minimumFractionDigits: 2, minimumFractionDigits: 2,
maximumFractionDigits: 2, maximumFractionDigits: 2,
})}`} })}`}
</Text> </Text>
), ),
"Return on Investment": ( "Return on Investment": (
<Text <Text
justifyContent={slideFromRight ? "right" : "center"} justifyContent={slideFromRight ? "right" : "center"}
as={"span"} as={"span"}
color={"teal.900"} color={"teal.900"}
fontWeight={"500"} fontWeight={"500"}
h={6} h={6}
className="d-flex align-items-center web-text-small" className="d-flex align-items-center web-text-small"
> >
{item.Return_On_Investment || 0} % {item.Return_On_Investment || 0} %
</Text> </Text>
), ),
Distribution: ( Distribution: (
<Text <Text
justifyContent={slideFromRight ? "right" : "left"} justifyContent={slideFromRight ? "right" : "left"}
as={"span"} as={"span"}
color={"teal.900"} color={"teal.900"}
fontWeight={"500"} fontWeight={"500"}
className="d-flex align-items-center web-text-small" className="d-flex align-items-center web-text-small"
> >
<Badge ms={1} colorScheme="green" me={1}> <Badge ms={1} colorScheme="green" me={1}>
$ $
</Badge> </Badge>
{/* {`$${item.Distribution_Amt}`} */} {/* {`$${item.Distribution_Amt}`} */}
{`${parseFloat(item.Distribution_Amt || 0).toLocaleString(undefined, { {`${parseFloat(item.Distribution_Amt || 0).toLocaleString(undefined, {
minimumFractionDigits: 2, minimumFractionDigits: 2,
maximumFractionDigits: 2, maximumFractionDigits: 2,
})}`} })}`}
</Text> </Text>
), ),
"Distribution Percent": ( "Distribution Percent": (
<Text <Text
justifyContent={slideFromRight ? "right" : "center"} justifyContent={slideFromRight ? "right" : "center"}
as={"span"} as={"span"}
color={"teal.900"} color={"teal.900"}
fontWeight={"500"} fontWeight={"500"}
className="d-flex align-items-center web-text-small" className="d-flex align-items-center web-text-small"
> >
{/* {`$${item.Distribution_Amt}`} */} {/* {`$${item.Distribution_Amt}`} */}
{`${parseFloat(item.Distribution_Per || 0).toLocaleString(undefined, { {`${parseFloat(item.Distribution_Per || 0).toLocaleString(undefined, {
minimumFractionDigits: 2, minimumFractionDigits: 2,
maximumFractionDigits: 2, maximumFractionDigits: 2,
})} %`} })} %`}
</Text> </Text>
), ),
"Total Return": ( "Total Return": (
<Text <Text
justifyContent={slideFromRight ? "right" : "left"} justifyContent={slideFromRight ? "right" : "left"}
as={"span"} as={"span"}
color={"teal.900"} color={"teal.900"}
fontWeight={"500"} fontWeight={"500"}
className="d-flex align-items-center web-text-small" className="d-flex align-items-center web-text-small"
> >
<Badge ms={1} colorScheme="green" me={1}> <Badge ms={1} colorScheme="green" me={1}>
$ $
</Badge> </Badge>
{/* {`$${formatCurrency(item.Total_Return) || 0}`} */} {/* {`$${formatCurrency(item.Total_Return) || 0}`} */}
{`${parseFloat(item.Total_Return || 0).toLocaleString(undefined, { {`${parseFloat(item.Total_Return || 0).toLocaleString(undefined, {
minimumFractionDigits: 2, minimumFractionDigits: 2,
maximumFractionDigits: 2, maximumFractionDigits: 2,
})}`} })}`}
</Text> </Text>
), ),
"Total return on Investment": ( "Total return on Investment": (
<Text <Text
justifyContent={slideFromRight ? "right" : "center"} justifyContent={slideFromRight ? "right" : "center"}
as={"span"} as={"span"}
color={"teal.900"} color={"teal.900"}
fontWeight={"500"} fontWeight={"500"}
className="d-flex align-items-center web-text-small" className="d-flex align-items-center web-text-small"
> >
{item.Total_Return_On_Investment || 0} % {item.Total_Return_On_Investment || 0} %
</Text> </Text>
), ),
})); }));
const handleClose = () => { const handleClose = () => {
onClose(); onClose();
setIsFinalCalculateLoading(false); setIsFinalCalculateLoading(false);
setIsCalcualtedData(false); setIsCalcualtedData(false);
}; };
return ( return (
<Modal size={"xl"} isOpen={isOpen} onClose={handleClose} > <Modal size={"xl"} isOpen={isOpen} onClose={handleClose}>
<ModalOverlay /> <ModalOverlay />
<ModalContent maxW={1000}> <ModalContent maxW={1000}>
<ModalHeader fontSize={"md"}>Cancel Transaction</ModalHeader> <ModalHeader fontSize={"md"}>Cancel Transaction</ModalHeader>
<ModalCloseButton /> <ModalCloseButton />
<ModalBody> <ModalBody>
<NormalData <NormalData
emptyMessage={`We don't have any Sponers `} emptyMessage={`We don't have any Sponers `}
tableHeadRow={tableHeadRow} tableHeadRow={tableHeadRow}
data={extractedArray} data={extractedArray}
/> />
</ModalBody> </ModalBody>
{localStorage?.getItem("role") !== encryptString(import.meta.env.VITE_VITE_MAKER) && <ModalFooter pt={0}> {!isMaker() && (
<ModalFooter pt={0}>
<Box display={"flex"} justifyContent={"center"} gap={2}> <Box display={"flex"} justifyContent={"center"} gap={2}>
<Button <Button
rounded={"sm"} rounded={"sm"}
size={"xs"} size={"xs"}
textTransform={"inherit"} textTransform={"inherit"}
fontWeight={500} fontWeight={500}
px={3} px={3}
py={2} py={2}
onClick={() => { onClick={() => {
setActionId(id); // Use the `id` variable from params setActionId(id); // Use the `id` variable from params
onConfirmOpen(); onConfirmOpen();
}} }}
colorScheme="forestGreen" colorScheme="forestGreen"
variant={"solid"} variant={"solid"}
cursor={"pointer"} cursor={"pointer"}
> >
Approve Approve
</Button> </Button>
<Button <Button
rounded={"sm"} rounded={"sm"}
size={"xs"} size={"xs"}
textTransform={"inherit"} textTransform={"inherit"}
fontWeight={500} fontWeight={500}
px={3} px={3}
py={2} py={2}
onClick={() => { onClick={() => {
setActionId(id); // Use the `id` variable from params setActionId(id); // Use the `id` variable from params
onRejectOpen(); onRejectOpen();
}} }}
> >
Reject Reject
</Button> </Button>
</Box> </Box>
</ModalFooter>} </ModalFooter>
</ModalContent> )}
<ApprovedCancelTransaction </ModalContent>
<ApprovedCancelTransaction
isOpen={isConfirmOpen} isOpen={isConfirmOpen}
onClose={onConfirmClose} onClose={onConfirmClose}
onBigModalClose={onClose} onBigModalClose={onClose}
@@ -360,9 +362,8 @@ import { encryptString } from "../../../../Constants/Constants";
onBigModalClose={onClose} onBigModalClose={onClose}
id={cancleId} id={cancleId}
/> />
</Modal> </Modal>
); );
}; };
export default ViewCancel; export default ViewCancel;

View File

@@ -23,9 +23,9 @@ import { yupResolver } from "@hookform/resolvers/yup";
import GlobalStateContext from "../../../../Contexts/GlobalStateContext"; import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
import ApproveDistrubationModal from "./ApproveDistrubationModal"; import ApproveDistrubationModal from "./ApproveDistrubationModal";
import RequestRejectModal from "./RequestRejectModal"; import RequestRejectModal from "./RequestRejectModal";
import { encryptString } from "../../../../Constants/Constants"; import { encryptString, isMaker } from "../../../../Constants/Constants";
const ViewDistributionInvestor = ({ isOpen, onClose,id:exitId }) => { const ViewDistributionInvestor = ({ isOpen, onClose, id: exitId, amount }) => {
const params = useParams(); const params = useParams();
const toast = useToast(); const toast = useToast();
const id = params?.id; const id = params?.id;
@@ -72,19 +72,15 @@ const ViewDistributionInvestor = ({ isOpen, onClose,id:exitId }) => {
}); });
useEffect(() => { useEffect(() => {
console.log("hiit useEffectc");
// handleCalculate(id, {
// amount: IODetails?.ioMVNAV,
// });
if (id && IODetails) { if (id && IODetails) {
handleCalculate(id, { handleCalculate(id, {
amount: IODetails?.ioMVNAV, amount: Math.abs(amount),
}); });
} }
reset({ reset({
amount: IODetails?.ioMVNAV, amount: amount,
}); });
}, [IODetails, id]); }, [IODetails, id, amount]);
const handleCalculate = async (id, data) => { const handleCalculate = async (id, data) => {
try { try {
@@ -201,7 +197,6 @@ const ViewDistributionInvestor = ({ isOpen, onClose,id:exitId }) => {
setIsFinalCalculateLoading(false); setIsFinalCalculateLoading(false);
setIsCalcualtedData(false); setIsCalcualtedData(false);
}; };
return ( return (
<Modal size={"xl"} isOpen={isOpen} onClose={handleClose}> <Modal size={"xl"} isOpen={isOpen} onClose={handleClose}>
@@ -219,41 +214,43 @@ const ViewDistributionInvestor = ({ isOpen, onClose,id:exitId }) => {
/> />
</ModalBody> </ModalBody>
{/* ...(localStorage?.getItem("role") !== "Maker" ? ["Status"] : []), */} {/* ...(localStorage?.getItem("role") !== "Maker" ? ["Status"] : []), */}
{localStorage?.getItem("role") !== encryptString(import.meta.env.VITE_VITE_MAKER) &&<ModalFooter pt={0}> {!isMaker() && (
<Box display={"flex"} justifyContent={"center"} gap={2}> <ModalFooter pt={0}>
<Button <Box display={"flex"} justifyContent={"center"} gap={2}>
rounded={"sm"} <Button
size={"xs"} rounded={"sm"}
textTransform={"inherit"} size={"xs"}
fontWeight={500} textTransform={"inherit"}
px={3} fontWeight={500}
py={2} px={3}
onClick={() => { py={2}
setActionId(id); // Use the `id` variable from params onClick={() => {
onConfirmOpen(); setActionId(id); // Use the `id` variable from params
}} onConfirmOpen();
colorScheme="forestGreen" }}
variant={"solid"} colorScheme="forestGreen"
cursor={"pointer"} variant={"solid"}
> cursor={"pointer"}
Approve >
</Button> Approve
<Button </Button>
rounded={"sm"} <Button
size={"xs"} rounded={"sm"}
textTransform={"inherit"} size={"xs"}
fontWeight={500} textTransform={"inherit"}
px={3} fontWeight={500}
py={2} px={3}
onClick={() => { py={2}
setActionId(id); // Use the `id` variable from params onClick={() => {
onRejectOpen(); setActionId(id); // Use the `id` variable from params
}} onRejectOpen();
> }}
Reject >
</Button> Reject
</Box> </Button>
</ModalFooter>} </Box>
</ModalFooter>
)}
</ModalContent> </ModalContent>
<ApproveDistrubationModal <ApproveDistrubationModal
isOpen={isConfirmOpen} isOpen={isConfirmOpen}

View File

@@ -1,330 +1,332 @@
import { import {
Alert, Alert,
AlertIcon, AlertIcon,
Box, Box,
Button, Button,
FormControl, FormControl,
FormErrorMessage, FormErrorMessage,
FormLabel, FormLabel,
HStack, HStack,
Input, Input,
Modal, Modal,
ModalBody, ModalBody,
ModalCloseButton, ModalCloseButton,
ModalContent, ModalContent,
ModalFooter, ModalFooter,
ModalHeader, ModalHeader,
ModalOverlay, ModalOverlay,
Switch, Switch,
Table, Table,
Tbody, Tbody,
Text, Text,
Textarea, Textarea,
Th, Th,
Tr, Tr,
useDisclosure, useDisclosure,
useToast, useToast,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import NormalData from "../../../../Components/DataTable/NormalTable"; import NormalData from "../../../../Components/DataTable/NormalTable";
import { useContext, useState } from "react"; import { useContext, useState } from "react";
import { AddIcon } from "@chakra-ui/icons"; import { AddIcon } from "@chakra-ui/icons";
import { import {
useExitIOTransactionMutation, useExitIOTransactionMutation,
useGetDistributedToInvestorMutation, useGetDistributedToInvestorMutation,
useGetDistributionInvestorMutation, useGetDistributionInvestorMutation,
useUpdateExitToInvestorMutation, useUpdateExitToInvestorMutation,
} from "../../../../Services/io.service"; } from "../../../../Services/io.service";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { useEffect } from "react"; import { useEffect } from "react";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import * as yup from "yup"; import * as yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup"; import { yupResolver } from "@hookform/resolvers/yup";
import ToastBox from "../../../../Components/ToastBox"; import ToastBox from "../../../../Components/ToastBox";
import GlobalStateContext from "../../../../Contexts/GlobalStateContext"; import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
import ApprovedExit from "./ApprovedExit"; import ApprovedExit from "./ApprovedExit";
import RequestRejectModal from "./RequestRejectModal"; import RequestRejectModal from "./RequestRejectModal";
import { encryptString } from "../../../../Constants/Constants"; 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 { const ViewExit = ({ isOpen, onClose, id: investerId }) => {
isOpen: isConfirmOpen, const params = useParams();
onOpen: onConfirmOpen, const toast = useToast();
onClose: onConfirmClose, const id = params?.id;
} = useDisclosure(); const [isCalculateLoading, setIsCalculateLoading] = useState(false);
const { const [isFinalCalculateLoading, setIsFinalCalculateLoading] = useState(false);
isOpen: isRejectOpen, const [calcualtedData, setCalculatedDate] = useState(null);
onOpen: onRejectOpen, const [isCalcualtedData, setIsCalcualtedData] = useState(false);
onClose: onRejectClose, const { IODetails } = useContext(GlobalStateContext);
} = useDisclosure(); const [actionId, setActionId] = useState(false);
const {
const { isOpen: isConfirmOpen,
control, onOpen: onConfirmOpen,
handleSubmit, onClose: onConfirmClose,
formState: { errors }, } = useDisclosure();
reset, const {
} = useForm({ isOpen: isRejectOpen,
resolver: yupResolver(), onOpen: onRejectOpen,
}); onClose: onRejectClose,
} = useDisclosure();
useEffect(() => {
console.log("hiit useEffectc"); const {
if (id && IODetails) { control,
handleSubmit,
formState: { errors },
reset,
} = useForm({
resolver: yupResolver(),
});
useEffect(() => {
console.log("hiit useEffectc");
if (id && IODetails) {
handleCalculate(id, { handleCalculate(id, {
amount: IODetails?.ioMVNAV, amount: IODetails?.ioMVNAV,
}); });
} }
reset({ reset({
amount: IODetails?.ioMVNAV, 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 extractedArray = calcualtedData?.data?.map((item, index) => ({ const res = await getDistributionInvestment({ id, data });
id: item?.id, console.log(res?.data?.data);
"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 ( if (res?.error?.status === 401) {
<Modal size={"xl"} isOpen={isOpen} onClose={handleClose} > setIsCalculateLoading(false);
<ModalOverlay /> setIsCalcualtedData(false);
<ModalContent maxW={1000}> } else if (res?.data?.statusCode === 200) {
<ModalHeader fontSize={"md"}>Exit Transaction</ModalHeader> setCalculatedDate(res?.data?.data);
<ModalCloseButton /> setIsCalculateLoading(false);
<ModalBody> setIsCalcualtedData(true);
{/* <Text as="label" mb="5px" fontSize="sm" fontWeight={500}> }
} 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}>
Amount to Distribute Amount to Distribute
</Text> */} </Text> */}
<HStack onSubmit={handleSubmit(onSubmit)} as={"form"} mb={4} alignItems={'center'}> <HStack
{/* <Input placeholder="$00.00" size={"sm"} className="col" /> */} onSubmit={handleSubmit(onSubmit)}
{/* <FormControl isInvalid={errors.amount} isRequired>*/} as={"form"}
<Text textAlign={"right"} fontSize={"sm"}> mb={4}
Exit Amount : alignItems={"center"}
</Text> >
<Text {/* <Input placeholder="$00.00" size={"sm"} className="col" /> */}
textAlign={"start"} {/* <FormControl isInvalid={errors.amount} isRequired>*/}
bg={"green.100"} <Text textAlign={"right"} fontSize={"sm"}>
p={2} Exit Amount :
rounded={"md"} </Text>
fontSize={"sm"} <Text
pt={1} textAlign={"start"}
pb={1} bg={"green.100"}
fontWeight={600} p={2}
> rounded={"md"}
${" "} fontSize={"sm"}
{parseFloat(IODetails?.ioMVNAV || 0).toLocaleString(undefined, { pt={1}
minimumFractionDigits: 2, pb={1}
maximumFractionDigits: 2, fontWeight={600}
})} >
</Text> ${" "}
{parseFloat(IODetails?.ioMVNAV || 0).toLocaleString(undefined, {
{/* </FormControl> */} minimumFractionDigits: 2,
</HStack> maximumFractionDigits: 2,
})}
{/* {calcualtedData && ( */} </Text>
<NormalData
emptyMessage={`We don't have any Sponers `} {/* </FormControl> */}
tableHeadRow={tableHeadRow} </HStack>
data={extractedArray}
// total={<Total />} {/* {calcualtedData && ( */}
// isLoading={isLoading} <NormalData
/> emptyMessage={`We don't have any Sponers `}
{/* ) } */} tableHeadRow={tableHeadRow}
</ModalBody> data={extractedArray}
{localStorage?.getItem("role") !== encryptString(import.meta.env.VITE_VITE_MAKER) && <ModalFooter pt={0}> // total={<Total />}
// isLoading={isLoading}
/>
{/* ) } */}
</ModalBody>
{!isMaker() && (
<ModalFooter pt={0}>
<Box display={"flex"} justifyContent={"center"} gap={2}> <Box display={"flex"} justifyContent={"center"} gap={2}>
<Button <Button
rounded={"sm"} rounded={"sm"}
size={"xs"} size={"xs"}
textTransform={"inherit"} textTransform={"inherit"}
fontWeight={500} fontWeight={500}
px={3} px={3}
py={2} py={2}
onClick={() => { onClick={() => {
setActionId(id); // Use the `id` variable from params setActionId(id); // Use the `id` variable from params
onConfirmOpen(); onConfirmOpen();
}} }}
colorScheme="forestGreen" colorScheme="forestGreen"
variant={"solid"} variant={"solid"}
cursor={"pointer"} cursor={"pointer"}
> >
Approve Approve
</Button> </Button>
<Button <Button
rounded={"sm"} rounded={"sm"}
size={"xs"} size={"xs"}
textTransform={"inherit"} textTransform={"inherit"}
fontWeight={500} fontWeight={500}
px={3} px={3}
py={2} py={2}
onClick={() => { onClick={() => {
setActionId(id); // Use the `id` variable from params setActionId(id); // Use the `id` variable from params
onRejectOpen(); onRejectOpen();
}} }}
> >
Reject Reject
</Button> </Button>
</Box> </Box>
</ModalFooter>} </ModalFooter>
</ModalContent> )}
<ApprovedExit </ModalContent>
isOpen={isConfirmOpen} <ApprovedExit
onClose={onConfirmClose} isOpen={isConfirmOpen}
onBigModalClose={onClose} onClose={onConfirmClose}
id={investerId} onBigModalClose={onClose}
/> id={investerId}
<RequestRejectModal />
isOpen={isRejectOpen} <RequestRejectModal
onClose={onRejectClose} isOpen={isRejectOpen}
onBigModalClose={onClose} onClose={onRejectClose}
id={investerId} onBigModalClose={onClose}
/> id={investerId}
</Modal> />
); </Modal>
}; );
};
export default ViewExit;
export default ViewExit;

View File

@@ -1,5 +1,5 @@
import { ViewIcon } from "@chakra-ui/icons";
import { import {
Avatar,
Badge, Badge,
Box, Box,
Button, Button,
@@ -11,23 +11,21 @@ import {
useDisclosure, useDisclosure,
useToast, useToast,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import React, { useContext, useEffect, useState, useRef } from "react"; import React, { useContext, useEffect, useRef, useState } from "react";
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
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"; 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 { OPACITY_ON_LOAD } from "../../../Layout/animations";
import { useGetInvestorsQuery } from "../../../Services/investor.details.service";
import InvestmentDetailsEdit from "./InvestmentDetailsEdit";
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
@@ -49,10 +47,11 @@ const InvestorDetails = () => {
} = useDisclosure(); } = useDisclosure();
const btnRef = React.useRef(); const btnRef = React.useRef();
// =========================== [Use State] =============================
// =========================== [Use State] ============================= const [pageSize, setPageSize] = useState(INVESTOR_TABLE_PAGINATION?.size);
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size); const [currentPage, setCurrentPage] = useState(
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page); INVESTOR_TABLE_PAGINATION?.page
);
const [searchTerm, setSearchTerm] = useState(""); const [searchTerm, setSearchTerm] = useState("");
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState(""); const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
@@ -73,20 +72,19 @@ const InvestorDetails = () => {
data: investorDetails, data: investorDetails,
isLoading: investorDetailsLoading, isLoading: investorDetailsLoading,
error, error,
} = useGetInvestorsQuery({ } = useGetInvestorsQuery(
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search {
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search userStatus KYCStatus investorType_xid page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
search: debouncedSearchTerm, size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search userStatus KYCStatus investorType_xid
userStatus: status, search: debouncedSearchTerm,
KYCStatus: kyc, userStatus: status,
country_xid: country KYCStatus: kyc,
country_xid: country,
}, },
{ {
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
} }
); );
useEffect(() => { useEffect(() => {
// Simulate loading // Simulate loading
@@ -104,43 +102,41 @@ const InvestorDetails = () => {
"Client ID", "Client ID",
"First Name", "First Name",
"Last Name", "Last Name",
"Country", "Country",
"Phone Number", "Phone Number",
"E-mail ID", "E-mail ID",
"Type", "Type",
"KYC Status", "KYC Status",
"Status", "Status",
"Action", "Action",
]; ];
// ====================================================[Table Filter]================================================================ // ====================================================[Table Filter]================================================================
const exportInvestor = investorDetails?.data?.rows?.map((item, idx) => ({ 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 "Client ID": item?.clientReference_id, // This is likely a string
"First Name": item?.principal?.firstName, "First Name": item?.principal?.firstName,
"Last Name": item?.principal?.lastName, "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 "Phone Number": item?.principal?.mobileNumber, // Skipping integer conversion, as this is likely a string
"E-mail ID": item?.principal?.emailAddress, "E-mail ID": item?.principal?.emailAddress,
"Type": item?.investor_type?.investorTypeName, Type: item?.investor_type?.investorTypeName,
"Status": item.ioStatus ? "Ban" : "Unban", Status: item.ioStatus ? "Ban" : "Unban",
"KYC Status": item.KYCStatus ? "Completed" : "Not complete" "KYC Status": item.KYCStatus ? "Completed" : "Not complete",
})); }));
const extractedArray = investorDetails?.data?.rows?.map((item, idx) => ({ const extractedArray = investorDetails?.data?.rows?.map((item, idx) => ({
id: item?.id, id: item?.id,
"Sr No": ( "Sr No": (
<Text <Text
w={'24px'} w={"24px"}
justifyContent={slideFromRight ? "right" : "left"} justifyContent={slideFromRight ? "right" : "left"}
as={"span"} as={"span"}
color={"gray.600"} color={"gray.600"}
className="d-flex align-items-center fw-bold web-text-small" className="d-flex align-items-center fw-bold web-text-small"
> >
{/* {item.id} */} {/* {item.id} */}
{generateSerialNumber(idx,currentPage, pageSize )} {generateSerialNumber(idx, currentPage, pageSize)}
</Text> </Text>
), ),
"Client ID": ( "Client ID": (
@@ -148,7 +144,7 @@ const InvestorDetails = () => {
<Text as={"span"} color={"teal.900"}> <Text as={"span"} color={"teal.900"}>
{item.clientReference_id} {item.clientReference_id}
</Text> </Text>
</Box> </Box>
), ),
"First Name": ( "First Name": (
<Box w={"auto"} isTruncated={true}> <Box w={"auto"} isTruncated={true}>
@@ -185,39 +181,44 @@ const InvestorDetails = () => {
</Text> </Text>
</Box> </Box>
), ),
"Type": ( Type: (
<Box w={"auto"} isTruncated={true}> <Box w={"auto"} isTruncated={true}>
<Text as={"span"} > <Text as={"span"}>
<Badge color={"forestGreen.500"} variant={'ghost'} fontWeight={"700"} px={2} py={0.5}> <Badge
color={"forestGreen.500"}
variant={"ghost"}
fontWeight={"700"}
px={2}
py={0.5}
>
{item?.investor_type?.investorTypeName} {item?.investor_type?.investorTypeName}
</Badge> </Badge>
</Text> </Text>
</Box> </Box>
), ),
Status: ( Status: (
<Box w={"auto"} isTruncated={true}> <Box w={"auto"} isTruncated={true}>
<Badge <Badge
fontWeight={"700"} fontWeight={"700"}
textTransform={"none"} textTransform={"none"}
colorScheme={item.ioStatus ? "red" : "green"} colorScheme={item.ioStatus ? "red" : "green"}
px={2} px={2}
py={0.5} py={0.5}
> >
{item.ioStatus ? "Ban" : "Unban"} {item.ioStatus ? "Ban" : "Unban"}
</Badge> </Badge>
</Box> </Box>
), ),
"KYC Status": ( "KYC Status": (
<Box w={"auto"} display={'flex'} alignItems={'center'} isTruncated={true}> <Box w={"auto"} display={"flex"} alignItems={"center"} isTruncated={true}>
<Text <Text
as={'span'} as={"span"}
fontWeight={"700"} fontWeight={"700"}
textTransform={"none"} textTransform={"none"}
color={item?.KYCStatus === true ? "green" : "yellow.500"} color={item?.KYCStatus === true ? "green" : "yellow.500"}
px={2} px={2}
py={0.5} py={0.5}
variant={'solid'} variant={"solid"}
> >
{/* {item.KYCStatus ? "Completed" : "Not complete"} */} {/* {item.KYCStatus ? "Completed" : "Not complete"} */}
{item?.KYCStatus === true ? "Completed" : "NotCompleted"} {item?.KYCStatus === true ? "Completed" : "NotCompleted"}
@@ -235,7 +236,7 @@ const InvestorDetails = () => {
placement="top" placement="top"
> >
<Button <Button
isDisabled={item.ioStatus} isDisabled={item.ioStatus}
onClick={() => { onClick={() => {
navigate(`/investor-details/profile-view/${item.id}`); navigate(`/investor-details/profile-view/${item.id}`);
}} }}
@@ -266,7 +267,6 @@ const InvestorDetails = () => {
setIsLoading(true); setIsLoading(true);
}; };
return ( return (
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}> <Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
<Box bg="white.500"> <Box bg="white.500">
@@ -346,35 +346,29 @@ const InvestorDetails = () => {
</Select> </Select>
<Pagination <Pagination
isLoading={investorDetailsLoading} isLoading={investorDetailsLoading}
pageSize={pageSize} pageSize={pageSize}
setPageSize={setPageSize} setPageSize={setPageSize}
currentPage={currentPage} currentPage={currentPage}
setCurrentPage={setCurrentPage} setCurrentPage={setCurrentPage}
totalItems={investorDetails?.data?.totalItems} totalItems={investorDetails?.data?.totalItems}
/> />
</HStack> </HStack>
<Button <Button
onClick={() => onClick={() => exportToExcelNew(exportInvestor, "Investor Details")}
exportToExcelNew(exportInvestor, "Investor Details") leftIcon={<LuFileSpreadsheet />}
} colorScheme="forestGreen"
leftIcon={<LuFileSpreadsheet />} size={"sm"}
colorScheme="forestGreen" variant={"outline"}
size={"sm"} rounded={"sm"}
variant={"outline"} fontSize={"xs"}
rounded={"sm"} w={100}
fontSize={"xs"} me={2}
w={100} isDisabled={exportInvestor?.length === 0}
me={2} >
Export xls
isDisabled={exportInvestor?.length === 0} </Button>
>
Export xls
</Button>
</HStack> </HStack>
<InvestmentDetailsEdit <InvestmentDetailsEdit
id={actionId} id={actionId}

View File

@@ -7,7 +7,7 @@ export const baseQuery = async (args, api, extraOptions) => {
baseUrl: import.meta.env.VITE_BAS_URL, baseUrl: import.meta.env.VITE_BAS_URL,
credentials: 'include', credentials: 'include',
prepareHeaders: (headers) => { prepareHeaders: (headers) => {
headers.set('Content-Type', 'application/json'); // headers.set('Content-Type', 'application/json');
return headers; return headers;
}, },
}); });