diff --git a/src/Components/CurrencyInput.jsx b/src/Components/CurrencyInput.jsx
index c972aee..573c341 100644
--- a/src/Components/CurrencyInput.jsx
+++ b/src/Components/CurrencyInput.jsx
@@ -1,36 +1,32 @@
import React, { forwardRef } from 'react';
import { Input } from "@chakra-ui/react";
-// export const formatCurrency = (value) => {
-// if (!value) return '';
-// const [integer, decimal] = value.split('.');
-// const formattedInteger = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
-// return decimal ? `${formattedInteger}.${decimal}` : formattedInteger;
-// };
-
export const formatCurrency = (value) => {
- if (value === undefined || value === null) return ''; // Handle undefined or null values
- const [integer, decimal] = String(value).split('.'); // Convert value to string before splitting
+ if (value === undefined || value === null) return '';
+ const [integer, decimal] = String(value).split('.');
const formattedInteger = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
- return decimal ? `${formattedInteger}.${decimal}` : formattedInteger;
+ return decimal !== undefined ? `${formattedInteger}.${decimal}` : formattedInteger;
};
const CurrencyInput = forwardRef(({ value, onChange, ...props }, ref) => {
-
-
const handleChange = (event) => {
let { value } = event?.target;
// Remove non-numeric characters except decimal point
- value = value?.replace(/[^0-9.]/g, '');
+ value = value.replace(/[^0-9.]/g, '');
// Ensure only one decimal point
- const parts = value?.split('.');
+ const parts = value.split('.');
if (parts.length > 2) {
- value = parts[0] + '.' + parts?.slice(1)?.join('');
+ value = parts[0] + '.' + parts.slice(1).join('');
}
- onChange(value); // Pass the raw value to parent or use it directly
+ // Restrict to two decimal places
+ if (parts[1]?.length > 2) {
+ value = parts[0] + '.' + parts[1].slice(0, 2);
+ }
+
+ onChange(value); // Pass the raw value to parent
};
return (
@@ -45,3 +41,50 @@ const CurrencyInput = forwardRef(({ value, onChange, ...props }, ref) => {
});
export default CurrencyInput;
+
+
+
+
+// import React, { forwardRef } from 'react';
+// import { Input } from "@chakra-ui/react";
+
+// export const formatCurrency = (value) => {
+// if (value === undefined || value === null) return ''; // Handle undefined or null values
+// const [integer, decimal] = String(value).split('.'); // Convert value to string before splitting
+// const formattedInteger = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
+// return decimal ? `${formattedInteger}.${decimal}` : formattedInteger;
+// };
+
+// const CurrencyInput = forwardRef(({ value, onChange, ...props }, ref) => {
+
+// const handleChange = (event) => {
+// let { value } = event?.target;
+
+// // Remove non-numeric characters except decimal point
+// value = value?.replace(/[^0-9.]/g, '');
+
+// // Ensure only one decimal point and restrict to two decimal places
+// const parts = value?.split('.');
+// if (parts.length > 2) {
+// value = parts[0] + '.' + parts?.slice(1)?.join('');
+// }
+
+// if (parts[1]?.length > 2) {
+// value = parts[0] + '.' + parts[1]?.slice(0, 2);
+// }
+
+// onChange(value); // Pass the raw value to parent or use it directly
+// };
+
+// return (
+//
+// );
+// });
+
+// export default CurrencyInput;
diff --git a/src/Components/FormField.jsx b/src/Components/FormField.jsx
index abf6817..c18c14f 100644
--- a/src/Components/FormField.jsx
+++ b/src/Components/FormField.jsx
@@ -477,8 +477,8 @@ const FormField = ({
placeholder={placeHolder ? placeHolder : label}
textAlign={arabic ? "right" : align ? align : "left"}
_placeholder={{ fontSize: "sm" }}
- min={type === "date" ? today : undefined}
- maxLength={maxLength}
+ // min={type === "date" ? today : undefined}
+ // maxLength={maxLength}
// defaultValue={type === "date" && "2023-07-26" : undefined}
// defaultValue={value}
// value={dateValue}
diff --git a/src/Constants/Constants.js b/src/Constants/Constants.js
index 6031b55..9d4b34a 100644
--- a/src/Constants/Constants.js
+++ b/src/Constants/Constants.js
@@ -1,5 +1,6 @@
import dns from "node:dns"
+import * as XLSX from 'xlsx';
export const generateSerialNumber = (index, currentPage, pageSize) => {
@@ -145,4 +146,53 @@ export function calculatePercentage(part, total) {
return 0; // To avoid division by zero
}
return (part / total) * 100;
-}
\ No newline at end of file
+}
+
+export const exportToExcel = (data, customHeaders, fileName = 'exported-data.xlsx') => {
+ // Map your data to include only the fields that match your custom headers
+ const mappedData = data.map(item =>
+ customHeaders.map(header => item[header.key] || '')
+ );
+
+ // Prepend the headers row
+ const sheetData = [customHeaders.map(header => header.label), ...mappedData];
+
+ // Create a worksheet from the data array
+ const worksheet = XLSX.utils.aoa_to_sheet(sheetData);
+
+ // Apply styles to header cells
+ customHeaders.forEach((header, index) => {
+ const cellAddress = XLSX.utils.encode_cell({ r: 0, c: index }); // r: row, c: column
+ if (!worksheet[cellAddress]) return; // Skip if cell doesn't exist
+
+ worksheet[cellAddress].s = {
+ fill: {
+ fgColor: { rgb: "FFFF00" } // Set header background color (Yellow in this case)
+ },
+ font: {
+ bold: true, // Make header text bold
+ color: { rgb: "000000" } // Set header text color (Black in this case)
+ }
+ };
+ });
+
+ // Create a new workbook and append the worksheet
+ const workbook = XLSX.utils.book_new();
+ XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
+
+ // Generate a buffer from the workbook
+ const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
+
+ // Create a Blob object from the buffer
+ const dataBlob = new Blob([excelBuffer], { type: 'application/octet-stream' });
+
+ // Create a link element to trigger the download
+ const link = document.createElement('a');
+ link.href = URL.createObjectURL(dataBlob);
+ link.download = fileName;
+
+ // Append the link to the document body, trigger the download, and remove the link
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+};
diff --git a/src/Pages/Deposit/DepositRequest/DepositRequest.jsx b/src/Pages/Deposit/DepositRequest/DepositRequest.jsx
index 25f144a..750a6f8 100644
--- a/src/Pages/Deposit/DepositRequest/DepositRequest.jsx
+++ b/src/Pages/Deposit/DepositRequest/DepositRequest.jsx
@@ -161,7 +161,7 @@ const DepositRequest = () => {
),
"First Name": (
-
+
{item?.firstName}
diff --git a/src/Pages/IO_Management/CreateIO/AddIONav.jsx b/src/Pages/IO_Management/CreateIO/AddIONav.jsx
index 98acdf5..84d91c0 100644
--- a/src/Pages/IO_Management/CreateIO/AddIONav.jsx
+++ b/src/Pages/IO_Management/CreateIO/AddIONav.jsx
@@ -11,10 +11,13 @@ import {
FormControl,
FormErrorMessage,
FormLabel,
+ HStack,
Input,
Select,
Stack,
+ Text,
Textarea,
+ VStack,
useToast,
} from "@chakra-ui/react";
import * as yup from "yup";
@@ -123,7 +126,15 @@ import { formatDatee } from "../../../Components/FormField";
-const today = formatDatee(new Date(), 'yyyy-MM-dd');
+const today = formatDatee(new Date(), 'yyyy-MM-dd');
+
+function calculatePercentage(newNav, currNav) {
+ const per = (newNav - currNav) / currNav * 100
+ return per.toFixed(2)
+}
+
+
+console.log(calculatePercentage(1092500, 976070));
@@ -162,7 +173,7 @@ const today = formatDatee(new Date(), 'yyyy-MM-dd');
- Transaction Amount
+ New NAV
-
+
+
+
+
+ Current nav
+ {parseFloat(IODetails?.ioNAV || 0).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}
+
+
+
+
+ Live return %
+ {calculatePercentage(watch()?.transactionAmount||IODetails?.ioNAV,IODetails?.ioNAV)}
+
+
+
diff --git a/src/Pages/IO_Management/CreateIO/Destribution.jsx b/src/Pages/IO_Management/CreateIO/Destribution.jsx
index c53d1e2..4b031a3 100644
--- a/src/Pages/IO_Management/CreateIO/Destribution.jsx
+++ b/src/Pages/IO_Management/CreateIO/Destribution.jsx
@@ -1,6 +1,6 @@
import React, { useContext, useEffect, useRef, useState } from 'react'
import GlobalStateContext from '../../../Contexts/GlobalStateContext';
-import { Box, HStack, Input,Text, Table, Tbody, Th, Tr, Avatar, useDisclosure,Button } from '@chakra-ui/react';
+import { Box, HStack, Input,Text, Table, Tbody, Th, Tr, Avatar, useDisclosure,Button, Badge } from '@chakra-ui/react';
import { OPACITY_ON_LOAD } from '../../../Layout/animations';
import Pagination from '../../../Components/Pagination';
import NormalTable from '../../../Components/DataTable/NormalTable';
@@ -86,9 +86,7 @@ const Destribution = () => {
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
- {/* {`${item.transactionAmount}`} */}
-
- {/* {`$${parseFloat(item.transactionAmount||0).toLocaleString()}`} */}
+ $
{`${parseFloat(item.transactionAmount || 0).toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
diff --git a/src/Pages/IO_Management/CreateIO/IOCashDetails.jsx b/src/Pages/IO_Management/CreateIO/IOCashDetails.jsx
index 6f471c4..a1423fc 100644
--- a/src/Pages/IO_Management/CreateIO/IOCashDetails.jsx
+++ b/src/Pages/IO_Management/CreateIO/IOCashDetails.jsx
@@ -121,7 +121,7 @@ const IOCashDetails = () => {
),
Amount: (
{
@@ -166,21 +168,90 @@ const IODetails = ({ enableNextTab, index, data }) => {
}
);
+ console.log(IObyID?.data?.minInvestmentAmt);
- const minInvestmentById = IObyID?.data?.minInvestmentAmt?.map(({minInvestmentAmt, country, country_xid,id })=>{
+
+ 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: country?.countryCode,
+ curr: currencyCode,
}
})
+
+ const schemaEdit = yup.object().shape({
+ investmentNameEnglish: yup
+ .string()
+ .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")
+ .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"),
+
+ // 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.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"),
+ });
+
+
+
const [values, setValues] = useState(id?minInvestmentById:miniValue);
+
+ console.log(values);
const formatNumber = (num) => {
// Remove non-numeric characters and format with commas
@@ -198,7 +269,7 @@ const IODetails = ({ enableNextTab, index, data }) => {
handleSubmit,
formState: { errors },
} = useForm({
- resolver: yupResolver(schema),
+ resolver: yupResolver(id ? schemaEdit : schema),
});
useEffect(() => {
diff --git a/src/Pages/IO_Management/CreateIO/IONAVDetails.jsx b/src/Pages/IO_Management/CreateIO/IONAVDetails.jsx
index b518724..7ba16cf 100644
--- a/src/Pages/IO_Management/CreateIO/IONAVDetails.jsx
+++ b/src/Pages/IO_Management/CreateIO/IONAVDetails.jsx
@@ -22,6 +22,8 @@ import { formatDatee } from "../../../Components/FormField";
import { AddIcon } from "@chakra-ui/icons";
import AddIONav from "./AddIONav";
import { formatDate } from "../../Master/Sponser/Sponsers";
+import { LuFileSpreadsheet } from "react-icons/lu";
+import { exportToExcel } from "../../../Constants/Constants";
const IONAVDetails = () => {
const { navDetails, setNavDetails, IODetails } =
@@ -80,7 +82,7 @@ const IONAVDetails = () => {
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
- {/* {formatDatee(item.transactionDate)} */}
+ {/* {/ {formatDatee(item.transactionDate)} /} */}
{formatDate(item?.transactionDate)}
),
@@ -90,17 +92,11 @@ const IONAVDetails = () => {
as={"span"}
color={"teal.900"}
fontWeight={"500"}
- className="d-flex align-items-left web-text-small"
+ className="d-flex align-items-center web-text-small"
>
- {/* {`${item.transactionAmount}`} */}
-
-
- $
-
- {parseFloat(item.transactionAmount || 0).toLocaleString(undefined, {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- })}
+ {/* {/ {`${item.transactionAmount}`} /} */}
+ $
+ {`${parseFloat(item.transactionAmount || 0).toLocaleString()}`}
),
"Last NAV update": (
@@ -162,6 +158,23 @@ const IONAVDetails = () => {
),
}));
+ const customHeaders = [
+ { label: "ID", key: "id" },
+ { label: "Valuation Date", key: "transactionDate" },
+ { label: "NAV", key: "transactionAmount" },
+ { label: "Last NAV update", key: "previousNAVvalue" },
+
+ { label: "Investment Closed", key: "initialNAVvalue" },
+ { label: "Comments", key: "comments" },
+
+ { label: "Update by", key: "creator" },
+ { label: "Transaction Type", key: "transactionType" },
+ { label: "Comments", key: "comments" },
+ // Add more headers as needed
+ ];
+
+ console.log(IODetails?.ioNAVHistory);
+
const handleDelete = () => {
const updatedNav = navDetails.filter((sponsor) => sponsor.id !== actionId);
@@ -173,6 +186,8 @@ const IONAVDetails = () => {
setIsLoading(true);
};
+ const handleExport = () => {};
+
return (
@@ -193,24 +208,34 @@ const IONAVDetails = () => {
onChange={(e) => setSearchTerm(e.target.value)}
/>
- {/*
-
- */}
-
- {/* {IODetails?.isInvestedAmount ? :null} */}
-
- {IODetails?.isInvestedAmount ? (
+
}
+ onClick={() =>
+ exportToExcel(IODetails?.ioNAVHistory, customHeaders)
+ }
+ leftIcon={}
colorScheme="forestGreen"
size={"sm"}
+ variant={"outline"}
rounded={"sm"}
fontSize={"xs"}
>
- Add IO Nav
+ Export xls
- ) : null}
+
+ {IODetails?.isInvestedAmount ? (
+ }
+ colorScheme="forestGreen"
+ size={"sm"}
+ rounded={"sm"}
+ fontSize={"xs"}
+ >
+ Add IO Nav
+
+ ) : null}
+
diff --git a/src/Pages/IO_Management/CreateIO/Investors.jsx b/src/Pages/IO_Management/CreateIO/Investors.jsx
index fedf87e..6bf12e7 100644
--- a/src/Pages/IO_Management/CreateIO/Investors.jsx
+++ b/src/Pages/IO_Management/CreateIO/Investors.jsx
@@ -39,8 +39,6 @@ import { FiRefreshCw } from "react-icons/fi";
import { useGetIOByIdQuery } from "../../../Services/io.service";
import { RepeatIcon } from "@chakra-ui/icons";
-
-
const rotate = keyframes`
from {
transform: rotate(0deg);
@@ -52,21 +50,18 @@ const rotate = keyframes`
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
-const Investors = ({data}) => {
- const params = useParams()
- const id = params?.id
+const Investors = ({ data }) => {
+ const params = useParams();
+ const id = params?.id;
const toast = useToast();
const { investors, setInvestors, slideFromRight, IODetails } =
useContext(GlobalStateContext);
-
- const [ isRefetchLoading, setIsRefetchLoading ] = useState(false)
-
- const {
- isLoading: IObyIDisLoading,
- refetch
- } = useGetIOByIdQuery(id, { skip: !id });
-
+ const [isRefetchLoading, setIsRefetchLoading] = useState(false);
+
+ const { isLoading: IObyIDisLoading, refetch } = useGetIOByIdQuery(id, {
+ skip: !id,
+ });
const [searchTerm, setSearchTerm] = useState("");
const [isLoading, setIsLoading] = useState(true);
@@ -137,9 +132,6 @@ const Investors = ({data}) => {
return nameMatches;
});
-
-
-
const extractedArray = filteredData?.map((item, index) => ({
id: item?.id,
"Client ID": (
@@ -177,17 +169,23 @@ const Investors = ({data}) => {
),
"Investment amount": (
+
+ $
+
{/* {`$${formatCurrency(item.InvestedAmount_USD)}`} */}
- {`$${parseFloat(item.InvestedAmount_USD||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`}
+ {`${parseFloat(item.InvestedAmount_USD || 0).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}`}
),
- "Percentage": (
+ Percentage: (
{
),
"Market Value": (
- {`$${parseFloat(item.Market_Value ||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`}
+
+ $
+
+ {`${parseFloat(item.Market_Value || 0).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}`}
),
"Return on Investment": (
@@ -221,16 +225,20 @@ const Investors = ({data}) => {
{item.Return_On_Investment || 0} %
),
- "Distribution": (
+ Distribution: (
+ $
{/* {`$${item.Distribution_Amt}`} */}
- {`$${parseFloat(item.Distribution_Amt||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`}
+ {`$${parseFloat(item.Distribution_Amt || 0).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}`}
),
"Distribution Percent": (
@@ -242,19 +250,26 @@ const Investors = ({data}) => {
className="d-flex align-items-center web-text-small"
>
{/* {`$${item.Distribution_Amt}`} */}
- {`${parseFloat(item.Distribution_Per||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} %`}
+ {`${parseFloat(item.Distribution_Per || 0).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })} %`}
),
"Total Return": (
+ $
{/* {`$${formatCurrency(item.Total_Return) || 0}`} */}
- {`$${parseFloat(item.Total_Return||0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`}
+ {`${parseFloat(item.Total_Return || 0).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}`}
),
"Total return on Investment": (
@@ -265,7 +280,7 @@ const Investors = ({data}) => {
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
- {item.Total_Return_On_Investment||0} %
+ {item.Total_Return_On_Investment || 0} %
),
}));
@@ -287,7 +302,7 @@ const Investors = ({data}) => {
return (
-
+
{
);
};
-
- const handleRefresh = async() =>{
- setIsRefetchLoading(true)
- await refetch()
- setIsRefetchLoading(false)
- }
+ const handleRefresh = async () => {
+ setIsRefetchLoading(true);
+ await refetch();
+ setIsRefetchLoading(false);
+ };
return (
@@ -419,27 +433,60 @@ const Investors = ({data}) => {
justifyContent={"space-between"}
pb={3}
spacing="24px"
-
>
- setSearchTerm(e.target.value)}
- />
-
+ setSearchTerm(e.target.value)}
+ />
+
-
- $ {parseFloat(IODetails?.totalAmtInvestmentInUSD).toLocaleString()}
- Total Investment Amount ( USD )
-
+
+
+ Total Investment Amount ( USD )
+
+ $
+
+ {parseFloat(IODetails?.totalAmtInvestmentInUSD).toLocaleString()}
+
@@ -448,7 +495,7 @@ const Investors = ({data}) => {
centered={true}
emptyMessage={`We don't have any Sponers `}
tableHeadRow={tableHeadRow}
- data={extractedArray}
+ data={extractedArray}
isLoading={isLoading}
viewActionId={actionId}
setViewActionId={setActionId}
diff --git a/src/Pages/IO_Management/ViewIO/HeaderModal/DistributionInvestor.jsx b/src/Pages/IO_Management/ViewIO/HeaderModal/DistributionInvestor.jsx
index 7444c44..483fd2f 100644
--- a/src/Pages/IO_Management/ViewIO/HeaderModal/DistributionInvestor.jsx
+++ b/src/Pages/IO_Management/ViewIO/HeaderModal/DistributionInvestor.jsx
@@ -25,7 +25,7 @@ import {
useToast,
} from "@chakra-ui/react";
import NormalData from "../../../../Components/DataTable/NormalTable";
-import { useState } from "react";
+import { useContext, useState } from "react";
import { AddIcon } from "@chakra-ui/icons";
import {
useGetDistributedToInvestorMutation,
@@ -41,19 +41,19 @@ import ToastBox from "../../../../Components/ToastBox";
import CurrencyInput from "../../../../Components/CurrencyInput";
import { IoCalculator } from "react-icons/io5";
import { debounce } from "../../../Master/Sponser/AddSponser";
+import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
+
-export const investor = yup.object().shape({
- amount: yup.string().required("Amount is required"),
-});
const DistributionInvestor = ({ isOpen, onClose, exit }) => {
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 [ isCalculateLoading, setIsCalculateLoading ] = useState(false)
+ const [ isFinalCalculateLoading, setIsFinalCalculateLoading ] = useState(false)
+ const [ calcualtedData, setCalculatedDate ] = useState(null)
+ const [ isCalcualtedData, setIsCalcualtedData ] = useState(false)
+ const { IODetails } = useContext(GlobalStateContext);
// const {
// data:IObyID,
@@ -66,13 +66,35 @@ const DistributionInvestor = ({ isOpen, onClose, exit }) => {
useGetDistributedToInvestorMutation();
const [updateExitToInvestor] = useUpdateExitToInvestorMutation();
+ 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
+ }
+ ),
+ });
+
+ const investor = yup.object().shape({
+ amount: yup.string().required("Amount is required"),
+ });
+
+
const {
control,
handleSubmit,
formState: { errors },
reset,
} = useForm({
- resolver: yupResolver(investor),
+ resolver: yupResolver(!exit? investorExit: investor),
});
// useEffect(()=>{
@@ -391,13 +413,7 @@ const DistributionInvestor = ({ isOpen, onClose, exit }) => {
Calculate
*/}
-
+
{errors.amount?.message}
diff --git a/src/Pages/IO_Management/ViewIO/ViewIOdetails.jsx b/src/Pages/IO_Management/ViewIO/ViewIOdetails.jsx
index dfbdaa8..7a40dd9 100644
--- a/src/Pages/IO_Management/ViewIO/ViewIOdetails.jsx
+++ b/src/Pages/IO_Management/ViewIO/ViewIOdetails.jsx
@@ -125,7 +125,7 @@ const ViewIOdetails = () => {
country: country?.countryName,
value: removeTrailingZeros(minInvestmentAmt),
logo: country?.flagIcon,
- curr: country?.countryCode,
+ curr: currencyCode,
}
})
diff --git a/src/Pages/Investor_Management/InvestorDetails/Transaction.jsx b/src/Pages/Investor_Management/InvestorDetails/Transaction.jsx
index 813e450..b177f4a 100644
--- a/src/Pages/Investor_Management/InvestorDetails/Transaction.jsx
+++ b/src/Pages/Investor_Management/InvestorDetails/Transaction.jsx
@@ -1,365 +1,308 @@
import {
- Avatar,
- Badge,
- Box,
- Button,
- HStack,
- Input,
- Menu,
- MenuButton,
- MenuItem,
- MenuList,
- Portal,
- Select,
- Switch,
- Table,
- Tag,
- Tbody,
- Text,
- Th,
- Tooltip,
- Tr,
- useToast,
- } from "@chakra-ui/react";
- import React, { useContext, useEffect, useState } from "react";
- import { OPACITY_ON_LOAD } from "../../../Layout/animations";
- import DataTable from "../../../Components/DataTable/DataTable";
- 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";
-
- const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
-
- const Transaction = () => {
- const toast = useToast();
- const { transaction, setTransaction, slideFromRight, InvestorWallet, } =
- useContext(GlobalStateContext);
- const [searchTerm, setSearchTerm] = useState("");
- const [isLoading, setIsLoading] = useState(true);
- const [deleteAlert, setDeleteAlert] = useState(false);
- const [actionId, setActionId] = useState(false);
- const [mouseEntered, setMouseEntered] = useState(false);
- const [mouseEnteredId, setMouseEnteredId] = useState("");
-
- useEffect(() => {
- // Simulate loading
- const timer = setTimeout(() => {
- setIsLoading(false);
- }, 1500);
-
- // Cleanup the timer on component unmount
- return () => clearTimeout(timer);
- }, []);
-
- const formatDate = (date) => {
- return new Date(date).toLocaleDateString('en-GB', {
- day: '2-digit',
- month: '2-digit',
- year: 'numeric',
- });
- };
-
- // ====================================================[Table Setup]================================================================
- const tableHeadRow = [
- // "Sr N/O",
- "Date",
- "Transaction",
- "Amount in investors currency",
- // "Currency",
- "TO USD",
- "From USD",
- "USD amount",
- "IO Name",
- "Payment Method",
- ];
-
-console.log(transaction);
+ Avatar,
+ Badge,
+ Box,
+ Button,
+ HStack,
+ Input,
+ Menu,
+ MenuButton,
+ MenuItem,
+ MenuList,
+ Portal,
+ Select,
+ Switch,
+ Table,
+ Tag,
+ Tbody,
+ Text,
+ Th,
+ Tooltip,
+ Tr,
+ useToast,
+} from "@chakra-ui/react";
+import React, { useContext, useEffect, useState } from "react";
+import { OPACITY_ON_LOAD } from "../../../Layout/animations";
+import NormalTable from "../../../Components/DataTable/NormalTable";
+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";
- // ====================================================[Table Filter]================================================================
- const filteredData = transaction?.filter((item) => {
- // Filter by name (case insensitive)
- console.log(item?.investorTransaction?.transactionName);
-
- const name = item?.investorTransaction?.transactionName;
- const searchLower = searchTerm?.toLowerCase();
- const nameMatches = name?.toLowerCase().includes(searchLower);
-
- // Filter by status
- // const status = item.status;
- // const statusLower = status ? "active" : "inactive";
-
- // const statusMatches =
- // statusFilter === "all" ||
- // (statusFilter === "active" && status === true) ||
- // (statusFilter === "inactive" && status === false);
-
- return nameMatches;
+const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
+
+const Transaction = () => {
+ const toast = useToast();
+ const { transaction, setTransaction, slideFromRight, InvestorWallet } =
+ useContext(GlobalStateContext);
+ const [searchTerm, setSearchTerm] = useState("");
+ const [isLoading, setIsLoading] = useState(true);
+ const [deleteAlert, setDeleteAlert] = useState(false);
+ const [actionId, setActionId] = useState(false);
+ const [mouseEntered, setMouseEntered] = useState(false);
+ const [mouseEnteredId, setMouseEnteredId] = useState("");
+
+ useEffect(() => {
+ // Simulate loading
+ const timer = setTimeout(() => {
+ setIsLoading(false);
+ }, 1500);
+
+ // Cleanup the timer on component unmount
+ return () => clearTimeout(timer);
+ }, []);
+
+ const formatDate = (date) => {
+ return new Date(date).toLocaleDateString("en-GB", {
+ day: "2-digit",
+ month: "2-digit",
+ year: "numeric",
});
+ };
- console.log(filteredData);
-
-
- const extractedArray = filteredData?.map((item) => ({
- id: item?.id,
- "Sr N/O": (
-
- {item.id}
+ console.log(transaction);
+
+ // ====================================================[Table Filter]================================================================
+ const filteredData = transaction?.filter((item) => {
+ // Filter by name (case insensitive)
+ console.log(item?.investorTransaction?.transactionName);
+
+ const name = item?.investorTransaction?.transactionName;
+ const searchLower = searchTerm?.toLowerCase();
+ const nameMatches = name?.toLowerCase().includes(searchLower);
+
+ // Filter by status
+ // const status = item.status;
+ // const statusLower = status ? "active" : "inactive";
+
+ // const statusMatches =
+ // statusFilter === "all" ||
+ // (statusFilter === "active" && status === true) ||
+ // (statusFilter === "inactive" && status === false);
+
+ return nameMatches;
+ });
+
+ console.log(filteredData);
+
+ // ====================================================[Table Setup]================================================================
+ const tableHeadRow = [
+ // "Sr N/O",
+ "Date",
+ "Transaction",
+ "Amount in investors currency",
+ // "Currency",
+ "TO USD",
+ "From USD",
+ "USD amount",
+ "IO Name",
+ "Payment Method",
+ ];
+ const extractedArray = filteredData?.map((item) => ({
+ id: item?.id,
+ "Sr N/O": (
+
+ {item.id}
+
+ ),
+ Date: (
+
+
+ {formatDate(item.transactionDate)}
- ),
- "Date": (
-
-
- {formatDate(item.transactionDate)}
-
-
- ),
- "Transaction": (
-
-
- {item.investorTransaction?.transactionName}
-
-
- ),
- "Currency": (
-
-
- {item.investorCurrency}
-
-
- ),
- "Amount in investors currency": (
-
-
- {/* {item.investorAmount} */}
- {parseFloat(item?.investorAmount || 0).toLocaleString(undefined, {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- })}
- {item?.investorCurrency}
-
-
- ),
- "From USD": (
-
-
- {item.USDToInvCur_Rate}
-
-
- ),
- "TO USD": (
-
-
- {item.invCurToUSD_Rate}
-
-
- ),
- "USD amount": (
-
-
- {/* {item.USDAmount} */}
- {parseFloat(item?.USDAmount || 0).toLocaleString(undefined, {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- })}
- {/* $ */}
- USD
-
-
- ),
- "IO Name": (
-
-
- {item.io && item.io?.investmentNameEnglish}
-
-
- ),
- "Payment Method": (
-
-
- {item.paymentMethod && item.paymentMethod?.paymentMethodName}
-
-
- ),
- }));
-
- const handleDelete = () => {
- const updatedInvestorDetails = InvestorDetails.filter(
- (sponsor) => sponsor.id !== actionId
- );
-
- setTimeout(() => {
- setInvestorDetails(updatedInvestorDetails);
- setDeleteAlert(false);
- setIsLoading(false);
- }, 100);
- setIsLoading(true);
- };
+
+ ),
+ Transaction: (
+
+
+ {item.investorTransaction?.transactionName}
+
+
+ ),
+ Currency: (
+
+
+ {item.investorCurrency}
+
+
+ ),
+ "Amount in investors currency": (
+
+
+ {/* {item.investorAmount} */}
+ {parseFloat(item?.investorAmount || 0).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}
+
+ {item?.investorCurrency}
+
+
+
+ ),
+ "From USD": (
+
+ {item.USDToInvCur_Rate}
+
+ ),
+ "TO USD": (
+
+ {item.invCurToUSD_Rate}
+
+ ),
+ "USD amount": (
+
+
+ {/* {item.USDAmount} */}
+ {parseFloat(item?.USDAmount || 0).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}
+
+ $
+
+
+
+ ),
+ "IO Name": (
+
+
+ {item.io && item.io?.investmentNameEnglish}
+
+
+ ),
+ "Payment Method": (
+
+
+ {item.paymentMethod && item.paymentMethod?.paymentMethodName}
+
+
+ ),
+ }));
- const Total = () => {
- return (
-
-
-
- |
- Balance:
- |
-
- {" "}
- |
-
-
- {parseFloat(InvestorWallet?.WalletBalance_InInvCur).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- {InvestorWallet?.currencyCode_InCur}
-
- |
-
- {" "}
- |
-
- {" "}
- |
-
-
- {parseFloat(InvestorWallet?.WalletBalance_InUSD).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- USD
-
- |
-
- {" "}
- |
-
- {" "}
- |
-
-
-
- );
- };
-
- return (
-
-
-
- setSearchTerm(e.target.value)}
- />
-
- {/*
+ const totalRow = {
+ // id: "total", // or any unique ID
+ // "Sr N/O": (
+ // Total
+ // ),
+ Date: (
+
+
+ Total
+
+
+ ),
+ Transaction: null,
+ // "Currency": null,
+ "Amount in investors currency": (
+
+
+ {parseFloat(InvestorWallet?.WalletBalance_InInvCur).toLocaleString(
+ undefined,
+ { minimumFractionDigits: 2, maximumFractionDigits: 2 }
+ )}
+
+ {InvestorWallet?.currencyCode_InCur}
+
+
+
+ ),
+ "TO USD": null,
+ "From USD": null,
+ "USD amount": (
+
+
+ {parseFloat(InvestorWallet?.WalletBalance_InUSD).toLocaleString(
+ undefined,
+ { minimumFractionDigits: 2, maximumFractionDigits: 2 }
+ )}
+
+ $
+
+
+
+ ),
+ "IO Name": null,
+ "Payment Method": null,
+ };
+
+ extractedArray?.push(totalRow);
+
+ const handleDelete = () => {
+ const updatedInvestorDetails = InvestorDetails.filter(
+ (sponsor) => sponsor.id !== actionId
+ );
+
+ setTimeout(() => {
+ setInvestorDetails(updatedInvestorDetails);
+ setDeleteAlert(false);
+ setIsLoading(false);
+ }, 100);
+ setIsLoading(true);
+ };
+
+ return (
+
+
+
+ setSearchTerm(e.target.value)}
+ />
+
+ {/*
*/}
-
-
-
- }
- setMouseEntered={setMouseEntered}
- />
-
- setDeleteAlert(false)}
- isOpen={deleteAlert}
- message={"Are you sure you want to delete sponers?"}
- alertHandler={handleDelete}
- isLoading={isLoading}
- />
-
+
- );
- };
-
- export default Transaction;
-
\ No newline at end of file
+
+
+
+ setDeleteAlert(false)}
+ isOpen={deleteAlert}
+ message={"Are you sure you want to delete sponers?"}
+ alertHandler={handleDelete}
+ isLoading={isLoading}
+ />
+
+ );
+};
+
+export default Transaction;
diff --git a/src/Pages/Investor_Management/InvestorDetails/ViewInvestorDetails.jsx b/src/Pages/Investor_Management/InvestorDetails/ViewInvestorDetails.jsx
index f871af0..7e0f0d3 100644
--- a/src/Pages/Investor_Management/InvestorDetails/ViewInvestorDetails.jsx
+++ b/src/Pages/Investor_Management/InvestorDetails/ViewInvestorDetails.jsx
@@ -19,7 +19,7 @@ import {
} from "@chakra-ui/react";
import React, { useContext, useEffect, useState } from "react";
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
-import DataTable from "../../../Components/DataTable/DataTable";
+import NormalTable from "../../../Components/DataTable/NormalTable";
import { HiDotsVertical } from "react-icons/hi";
import { Link, Navigate, Link as RouterLink } from "react-router-dom";
import {
@@ -47,7 +47,7 @@ const ViewInvestorDetails = () => {
const [actionId, setActionId] = useState(false);
const [mouseEntered, setMouseEntered] = useState(false);
const [mouseEnteredId, setMouseEnteredId] = useState("");
-
+
useEffect(() => {
// Simulate loading
const timer = setTimeout(() => {
@@ -75,8 +75,7 @@ const ViewInvestorDetails = () => {
// "Action",
];
-console.log(viewInvestor);
-
+ console.log(viewInvestor);
// ====================================================[Table Filter]================================================================
const filteredData = viewInvestor?.filter((item) => {
@@ -99,10 +98,11 @@ console.log(viewInvestor);
console.log(filteredData);
- const extractedArray = filteredData?.map((item,index) => ({
+ const extractedArray = filteredData?.map((item, index) => ({
id: item?.id,
"Sr N/O": (
-
),
"Sponsor Name": (
-
+
{item.sponsorName}
@@ -128,15 +128,15 @@ console.log(viewInvestor);
"Investment Amount": (
- {/* {item.investedAmount} */}
- $ {parseFloat(item?.investedAmount || 0).toLocaleString(undefined, {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- })}
+ $
+ {parseFloat(item?.investedAmount || 0).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}
),
- "Percentage": (
+ Percentage: (
{item?.Investor_Holidings} %
@@ -145,11 +145,12 @@ console.log(viewInvestor);
),
"Market Value": (
-
- $ {parseFloat(item?.MarketValue || 0).toLocaleString(undefined, {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- })}
+
+ $
+ {parseFloat(item?.MarketValue || 0).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}
),
@@ -160,13 +161,17 @@ console.log(viewInvestor);
),
- "Distribution": (
+ Distribution: (
- $ {parseFloat(item?.DistributionAmountReceived || 0).toLocaleString(undefined, {
+ $
+ {parseFloat(item?.DistributionAmountReceived || 0).toLocaleString(
+ undefined,
+ {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
- })}
+ }
+ )}
),
@@ -180,10 +185,11 @@ console.log(viewInvestor);
"Total return": (
- $ {parseFloat(item?.TotalReturn || 0).toLocaleString(undefined, {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- })}
+ $
+ {parseFloat(item?.TotalReturn || 0).toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}
),
@@ -195,23 +201,35 @@ console.log(viewInvestor);
),
Status: (
-
-
- {item.statusAdmin}
-
-
+
+ {item?.statusAdmin}
+
),
Action: (
@@ -279,7 +297,7 @@ console.log(viewInvestor);
-
-
);
};
diff --git a/src/Services/api.service.js b/src/Services/api.service.js
index 0cbd46d..e69de29 100644
--- a/src/Services/api.service.js
+++ b/src/Services/api.service.js
@@ -1,66 +0,0 @@
-import axios from "axios";
-
-// Create an Axios instance for API calls
-export const api = axios.create({
- // baseURL: `https://tanami.betadelivery.com/api/v1`,
- baseURL: import.meta.env.VITE_BAS_URL, // Replace with your API base URL
- timeout: 10000, // Adjust timeout as needed
- headers: {
- "Content-Type": "application/json",
- },
-});
-
-// Add Axios request interceptor to refresh token if expired
-api.interceptors.request.use(
- (config) => {
- console.log(config);
- // Modify headers or add tokens as needed
- // const token = localStorage.getItem("accessToken");
- // if (token) {
- // config.headers.Authorization = `Bearer ${token}`;
- // }
- return config;
- },
- (error) => {
- return Promise.reject(error);
- }
-);
-
-// // Add Axios response interceptor to handle token refreshing
-api.interceptors.response.use(
- (response) => {
- return response;
- },
- async (error) => {
- const originalRequest = error.config;
-
- // Example logic for handling token expiration and refreshing
- if (
- error.response.status === 401 &&
- !originalRequest._retry &&
- localStorage.getItem("refreshToken")
- ) {
- originalRequest._retry = true;
-
- try {
- const response = await api.post("/refresh_token", {
- refreshToken: localStorage.getItem("refreshToken"),
- });
-
- if (response.status === 200) {
- // Update tokens in local storage
- localStorage.setItem("accessTokenn", response.data.accessToken);
- localStorage.setItem("refreshTokenn", response.data.refreshToken);
-
- // Retry the original request with the new tokens
- return api(originalRequest);
- }
- } catch (error) {
- console.error("Failed to refresh token:", error);
- // Handle token refresh failure (e.g., redirect to login)
- }
- }
-
- return Promise.reject(error);
- }
-);
|