This commit is contained in:
2024-08-14 12:19:27 +05:30
parent 83aa170c60
commit 2d641a9748
13 changed files with 215 additions and 190 deletions

View File

@@ -13,15 +13,15 @@ const CurrencyInput = forwardRef(({ value, onChange, ...props }, ref) => {
const handleChange = (event) => {
let { value } = event.target;
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

View File

@@ -109,7 +109,7 @@ const DepositRequest = () => {
// ====================================================[Table Filter]================================================================
const filteredData = data?.data?.rows.filter((item) => {
// Filter by name (case insensitive)
const name = item?.createdAt;
const name = [item.firstName, item.lastName, item.countryName].filter(Boolean).join(' ');
const searchLower = searchTerm.toLowerCase();
const nameMatches = name.toLowerCase().includes(searchLower);

View File

@@ -101,15 +101,15 @@ const DepositHistory = () => {
});
}, 300);
// ====================================================[Table Filter]================================================================
const filteredData = data?.data?.rows.filter((item) => {
// Filter by name (case insensitive)
const name = item.createdAt;
const searchLower = searchTerm.toLowerCase();
const nameMatches = name.toLowerCase().includes(searchLower);
// ====================================================[Table Filter]================================================================
const filteredData = data?.data?.rows.filter((item) => {
// Combine firstName, lastName, and countryName for filtering
const name = [item.firstName, item.lastName, item.countryName].filter(Boolean).join(' ');
const searchLower = searchTerm.toLowerCase();
const nameMatches = name.toLowerCase().includes(searchLower);
return nameMatches;
});
return nameMatches;
});
// const handleView = (id) => {
// setActionId(id);
@@ -139,34 +139,34 @@ const DepositHistory = () => {
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
{item?.principal?.investor_details?.clientReference_id}
{item?.clientReference_id}
</Text>
),
"First Name": (
<Box isTruncated={true} w={"60px"}>
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
{item?.principal?.firstName}
{item?.firstName}
</Text>
</Box>
),
"Last Name": (
<Box w={"70px"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{item?.principal?.lastName}
{item?.lastName}
</Text>
</Box>
),
Country: (
<Box w={"80px"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{item?.principal?.investor_details?.country?.countryName}
{item?.countryName}
</Text>
</Box>
),
"Phone Number": (
<Box w={"80px"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{item?.principal?.mobileNumber}
{item?.mobileNumber}
</Text>
</Box>
),

View File

@@ -15,6 +15,7 @@ import ViewIOdataHeader from "../ViewIO/ViewIOdataHeader";
import { useParams } from "react-router-dom";
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
import { useGetIOprepopulateDataQuery } from "../../../Services/io.service";
import UnderConstruction from "../../UnderConstruction";
const CreateIO = () => {
const id = useParams()?.id;
@@ -57,7 +58,8 @@ const CreateIO = () => {
},
{
label: "Investors",
Content: Investors,
// Content: Investors,
Content: UnderConstruction,
isDisabled: id ? false : true,
},
{

View File

@@ -86,10 +86,7 @@ const KeyMeritsAdd = ({ isOpen, onClose, firstField, id, icons }) => {
toast({
render: () => <ToastBox message={res?.data?.message} />,
});
setAlert(false);
onClose();
setIsLoading(false);
reset();
handleClose()
return;
}
@@ -115,12 +112,7 @@ const KeyMeritsAdd = ({ isOpen, onClose, firstField, id, icons }) => {
});
}
setIsLoading(false);
onClose();
setAlert(false);
reset();
setFile(null);
setSelectedImageIcon(null);
setSelectedIcon("Select Icon");
handleClose()
}
reset();
};

View File

@@ -59,6 +59,8 @@ const KeyMeritsEdit = ({
const [selectedImageIcon, setSelectedImageIcon] = useState(null);
const found = data?.find((item) => item?.id === actionId);
console.log(found);
const {
control,
@@ -71,6 +73,9 @@ const KeyMeritsEdit = ({
});
// useEffect to reset the form when `found` changes
useEffect(() => {
setValue("icon_xid", found?.icon?.id);
setSelectedIcon(found?.icon?.iconName); // Update selected icon name
setSelectedImageIcon(found?.icon?.iconFilePath);
if (found) {
reset({
meritsHeader: found?.meritsHeader,
@@ -91,10 +96,7 @@ const KeyMeritsEdit = ({
toast({
render: () => <ToastBox message={res?.data?.message} />,
});
setAlert(false);
onClose();
setIsLoading(false);
reset();
handleClose()
return;
}
if (res?.error?.data?.code === 400) {
@@ -103,10 +105,7 @@ const KeyMeritsEdit = ({
<ToastBox message={res?.error?.data?.message} status={"error"} />
),
});
setAlert(false);
onClose();
setIsLoading(false);
reset();
handleClose()
return;
}
} catch (error) {
@@ -121,10 +120,7 @@ const KeyMeritsEdit = ({
),
});
}
setIsLoading(false);
setAlert(false);
onClose();
reset();
handleClose()
}
reset();
};
@@ -140,6 +136,14 @@ const KeyMeritsEdit = ({
setSelectedImageIcon(iconFilePath);
};
const handleClose = () => {
setIsLoading(false);
setAlert(false);
onClose();
reset();
}
return (
<>
<Drawer

View File

@@ -26,70 +26,77 @@ import ToastBox from '../../../../Components/ToastBox';
// Validation schema
const validationSchema = yup.object().shape({
transactionDate: yup.date().required('Date is required'),
Total_Amount: yup.number().positive('Amount must be positive').required('Amount is required'),
amountInvested: yup.number().positive('Amount to invest must be positive').required('Amount to invest is required'),
Total_Amount: yup.number().required('Amount is required'),
amountInvested: yup.number().required('Amount to invest is required'),
IoCash: yup.number().positive('IO Cash must be positive').required('IO Cash is required'),
});
// Function to format currency
const formatCurrency = (value) => {
if (isNaN(value)) return '';
const formatted = parseFloat(value).toFixed(2).toString();
const [integer, decimal] = formatted.split('.');
const formattedInteger = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return decimal ? `${formattedInteger}.${decimal}` : formattedInteger;
};
const AmountInvested = ({ isOpen, onClose }) => {
const params = useParams()
const toast = useToast()
const id = params?.id
const { register, handleSubmit, reset, watch, formState: { errors } } = useForm({
const params = useParams();
const toast = useToast();
const id = params?.id;
const { control, register, handleSubmit, reset, watch, formState: { errors } } = useForm({
resolver: yupResolver(validationSchema),
});
const [ isLoading, setIsLoading ] = useState(false)
const [isLoading, setIsLoading] = useState(false);
const { IODetails } = useContext(GlobalStateContext);
const [ amountInvested ] = useAmountIvestmentMutation()
const [amountInvested] = useAmountIvestmentMutation();
useEffect(() => {
reset({
Total_Amount: IODetails?.goalAmount,
IoCash: IODetails?.goalAmount
})
}, [IODetails])
if (IODetails?.goalAmount) {
const totalAmount = parseFloat(IODetails.goalAmount);
const ioCashUpdate = parseFloat(IODetails.goalAmount)
reset({
Total_Amount: totalAmount,
IoCash: ioCashUpdate,
});
}
}, [IODetails, reset]);
const onSubmit = async (data) => {
console.log(data);
setIsLoading(true)
setIsLoading(true);
try {
const res = await amountInvested({data, id})
const res = await amountInvested({ data, id });
console.log(res);
if (res?.data?.statusCode === 200 ) {
if (res?.data?.statusCode === 200) {
toast({
render: () => <ToastBox message={res?.data?.message} />,
});
setIsLoading(false)
onClose()
}else if(response?.error?.status === 400) {
setIsLoading(false);
onClose();
} else if (res?.error?.status === 400) {
toast({
render: () => (
<ToastBox message={response?.error?.data?.message} status={"error"} />
<ToastBox message={res?.error?.data?.message} status={"error"} />
),
});
setIsLoading(false)
setIsLoading(false);
}
} catch (error) {
setIsLoading(false);
}
// Handle form submission
};
const handleAmountChange = (e) => {
const amount = parseFloat(e.target.value) || 0;
const totalAmount = parseFloat(IODetails?.goalAmount) || 0;
const ioCash = (totalAmount - amount).toFixed(2); // Ensure precision with toFixed
const ioCash = (totalAmount - amount).toFixed(2);
reset({
amountInvested: amount,
IoCash: parseFloat(ioCash), // Convert to number for consistent formatting
amountInvested: parseFloat(amount),
IoCash: parseFloat(ioCash),
Total_Amount: IODetails?.goalAmount
});
};
@@ -119,8 +126,8 @@ const AmountInvested = ({ isOpen, onClose }) => {
<FormControl mb={"15px"} isInvalid={!!errors.Total_Amount} isReadOnly>
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>Amount</FormLabel>
<Input
type="number"
{...register('Total_Amount')}
type="text"
value={formatCurrency(watch('Total_Amount'))}
size="sm"
rounded={'sm'}
textAlign={'end'}
@@ -142,7 +149,6 @@ const AmountInvested = ({ isOpen, onClose }) => {
focusBorderColor="forestGreen.300"
fontSize={"sm"}
onChange={handleAmountChange}
/>
{errors.amountInvested && <Text color="red.500">{errors.amountInvested.message}</Text>}
</FormControl>
@@ -152,8 +158,8 @@ const AmountInvested = ({ isOpen, onClose }) => {
IO Cash
</FormLabel>
<Input
type="number"
{...register('IoCash')}
type="text"
value={formatCurrency(watch('IoCash'))}
size="sm"
rounded={'sm'}
focusBorderColor="forestGreen.300"

View File

@@ -1,9 +1,9 @@
import { ChevronDownIcon } from "@chakra-ui/icons";
import React, { useEffect, useState } from "react";
import {
Badge,
Button,
FormControl,
FormLabel,
Menu,
MenuButton,
@@ -16,39 +16,41 @@ import {
ModalFooter,
ModalHeader,
ModalOverlay,
FormErrorMessage
} from "@chakra-ui/react";
import {
useGetIOByIdQuery,
useGetIOprepopulateDataQuery,
useUpdateStatusIoMutation,
} from "../../../../Services/io.service";
import { useParams } from "react-router-dom";
const UpdateIOStatus = ({ isOpen, onClose , status}) => {
const UpdateIOStatus = ({ isOpen, onClose, status }) => {
const params = useParams();
const id = params?.id;
const [selectedItem, setSelectedItem] = useState(status?.[0]?.statusAdmin);
const [selectedItem, setSelectedItem] = useState();
const [isLoadingg, setIsLoading] = useState(false);
const { data, error, isLoading } = useGetIOprepopulateDataQuery();
const [error, setError] = useState("");
const [selectedStatusId, setSelectedStatusId] = useState(status?.[0]?.id);
useEffect(() => {
setSelectedItem(status?.[0]?.statusAdmin)
setSelectedStatusId(status?.[0]?.id)
}, [status])
const { data } = useGetIOprepopulateDataQuery();
const [updateStatusIo] = useUpdateStatusIoMutation();
useEffect(() => {
setSelectedStatusId(status?.[0]?.id);
}, [status]);
const handleMenuItemClick = (item, id) => {
setSelectedItem(item);
setSelectedStatusId(id);
};
const handleSubmit = async () => {
setIsLoading(true)
if (!selectedStatusId) {
setError("Status is required.");
return;
}
setError("");
setIsLoading(true);
try {
const res = await updateStatusIo({
data: {
@@ -57,109 +59,117 @@ const UpdateIOStatus = ({ isOpen, onClose , status}) => {
id,
});
console.log(res);
setIsLoading(false)
onClose()
} catch (error) {}
setIsLoading(false);
handleClose();
} catch (error) {
setIsLoading(false);
}
};
const handleClose = () => {
setSelectedItem("")
onClose()
}
return (
<Modal isOpen={isOpen} onClose={onClose}>
<Modal isOpen={isOpen} onClose={handleClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader fontSize={"md"}>Update IO Status Transaction</ModalHeader>
<ModalCloseButton />
<ModalBody>
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>
Status
</FormLabel>
<Menu>
<MenuButton
as={Button}
rightIcon={<ChevronDownIcon />}
fontSize={"sm"}
fontWeight={500}
w={"100%"}
textAlign={"left"}
>
<Badge
rounded={"full"}
pt={1.5}
pb={1.5}
ps={4}
pe={4}
mt={1.5}
mb={1.5}
textTransform={"none"}
colorScheme={
selectedItem === "Draft"
? "gray"
: selectedItem === "Processing"
? "yellow"
: selectedItem === "Open"
? "blue"
: selectedItem === "Closed"
? "green"
: selectedItem === "Exited"
? "red"
: selectedItem === "Canclled"
? "orange"
: "purple"
}
py={"3px"} px={"8px"}>
{selectedItem ? selectedItem: "No action"}
</Badge>
</MenuButton>
<MenuList w={"400px"}>
{status?.map(({ id, statusAdmin }) => (
<MenuItem
key={id}
fontSize={"sm"}
onClick={() => handleMenuItemClick(statusAdmin, id)}
>
<FormControl isInvalid={!!error}>
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>
Status
</FormLabel>
<Menu>
<MenuButton
as={Button}
rightIcon={<ChevronDownIcon />}
fontSize={"sm"}
fontWeight={500}
w={"100%"}
textAlign={"left"}
>
{selectedItem ? (
<Badge
rounded={"full"}
pt={1.5}
pb={1.5}
ps={4}
pe={4}
mt={1.5}
mb={1.5}
textTransform={"none"}
// variant={"solid"}
colorScheme={
statusAdmin === "Draft"
? "gray"
: statusAdmin === "Processing"
? "yellow"
: statusAdmin === "Open"
? "blue"
: statusAdmin === "Closed"
? "green"
: statusAdmin === "Exited"
? "red"
: statusAdmin === "Canclled"
? "orange"
: "purple"
}
py={"1px"} px={"8px"}>
{statusAdmin}
rounded={"full"}
pt={1.5}
pb={1.5}
ps={4}
pe={4}
mt={1.5}
mb={1.5}
textTransform={"none"}
colorScheme={
selectedItem === "Draft"
? "gray"
: selectedItem === "Processing"
? "yellow"
: selectedItem === "Open"
? "blue"
: selectedItem === "Closed"
? "green"
: selectedItem === "Exited"
? "red"
: selectedItem === "Canclled"
? "orange"
: "purple"
}
py={"3px"} px={"8px"}
>
{selectedItem}
</Badge>
</MenuItem>
))}
</MenuList>
</Menu>
) : "Select Item"}
</MenuButton>
{status?.length > 0 ?<MenuList w={"400px"}>
{status?.map(({ id, statusAdmin }) => (
<MenuItem
key={id}
fontSize={"sm"}
onClick={() => handleMenuItemClick(statusAdmin, id)}
>
<Badge
rounded={"full"}
pt={1.5}
pb={1.5}
ps={4}
pe={4}
mt={1.5}
mb={1.5}
textTransform={"none"}
colorScheme={
statusAdmin === "Draft"
? "gray"
: statusAdmin === "Processing"
? "yellow"
: statusAdmin === "Open"
? "blue"
: statusAdmin === "Closed"
? "green"
: statusAdmin === "Exited"
? "red"
: statusAdmin === "Canclled"
? "orange"
: "purple"
}
py={"1px"} px={"8px"}
>
{statusAdmin}
</Badge>
</MenuItem>
))}
</MenuList>:""}
</Menu>
<FormErrorMessage fontSize={'xs'} fontWeight={600} >{error}</FormErrorMessage>
</FormControl>
</ModalBody>
<ModalFooter>
<Button
// bg={"hsla(139, 100%, 14%, 1)"}
colorScheme="forestGreen"
mr={3}
color={"#fff"}
// _hover={{
// bg: "hsl(139deg 98.99% 26.59%)",
// }}
size={"sm"}
rounded={"sm"}
onClick={handleSubmit}
@@ -167,7 +177,7 @@ const UpdateIOStatus = ({ isOpen, onClose , status}) => {
>
Save
</Button>
<Button size={"sm"} rounded={"sm"} mr={3} onClick={onClose}>
<Button size={"sm"} rounded={"sm"} mr={3} onClick={handleClose}>
Close
</Button>
</ModalFooter>

View File

@@ -35,6 +35,7 @@ import IOArtifacts from "../CreateIO/IOArtifacts";
import IOCashDetails from "../CreateIO/IOCashDetails";
import IONAVDetails from "../CreateIO/IONAVDetails";
import { useGetIOprepopulateDataQuery } from "../../../Services/io.service";
import UnderConstruction from "../../UnderConstruction";
const ViewIOdata = () => {
@@ -51,10 +52,12 @@ const ViewIOdata = () => {
{ label: "Investment documents", content: <InvestmentDocument data={data?.data} /> },
{ label: "Key merits", content: <KeyMerits data={data?.data} /> },
{ label: "IO artifacts", content: <IOArtifacts data={data?.data} /> },
{ label: "Investors", content: <Investors data={data?.data} /> },
// { label: "Investors", content: <Investors data={data?.data} /> },
{ label: "Investors", content: <UnderConstruction h={'75vh'} /> },
{ label: "IO Cash Details", content: <IOCashDetails data={data?.data} /> },
{ label: "IO NAV Details", content: <IONAVDetails data={data?.data} /> },
{ label: "Distribution to Investors", content: <IONAVDetails data={data?.data} /> },
// { label: "Distribution to Investors", content: <IONAVDetails data={data?.data} /> },
{ label: "Distribution to Investors", content: <UnderConstruction h={'75vh'} /> },
];
return (

View File

@@ -23,6 +23,7 @@ import {
Badge,
Box,
Icon,
HStack,
} from "@chakra-ui/react";
import header from "../../../assets/IOheader.png";
import { HiDotsVertical } from "react-icons/hi";
@@ -40,6 +41,7 @@ import Cancle from "./HeaderModal/Cancle";
import { AddIcon } from "@chakra-ui/icons";
import { GrGallery } from "react-icons/gr";
import Loader01 from "../../../Components/Loaders/Loader01";
import { formatCurrency } from "../../../Components/CurrencyInput";
const ViewIOdataHeader = ({data, isLoading}) => {
const params = useParams();
@@ -166,7 +168,7 @@ console.log(isLoading);
<Box
display={"flex"}
alignItems={"center"}
justifyContent={"start"}
justifyContent={"space-between"}
gap={8}
bg={
IODetails?.ioStatus?.statusAdmin === "Draft"
@@ -198,7 +200,7 @@ console.log(isLoading);
<HStack gap={8}>
<Box h={100} w={200} p={1.5}>
{/* <Image rounded={'md'} h={"100%"} src={ " https://tanami.betadelivery.com/" + IODetails?.ioName} alt={IODetails?.ioName}/> */}
{IODetails?.artifactsImage?.[0]?.artifactPathName ? (
@@ -249,6 +251,10 @@ console.log(isLoading);
: "---"}
</Text>
</Box>
</HStack>
<HStack gap={8} me={20}>
<Box display={"flex"} flexDirection={"column"} gap={2}>
<Text as={"span"} textAlign={'center'} fontSize={"xs"} color={"gray.500"} fontWeight={"500"}>
@@ -290,7 +296,7 @@ console.log(isLoading);
IO NAV
</Text>
<Text as={"span"} fontSize={"sm"} fontWeight={"500"}>
{IODetails?.ioNAV ? IODetails?.ioNAV : "00.00"}
{IODetails?.ioNAV ? formatCurrency(IODetails?.ioNAV) : "00.00"}
</Text>
</Box>
@@ -299,7 +305,7 @@ console.log(isLoading);
IO cash
</Text>
<Text as={"span"} fontSize={"sm"} fontWeight={"500"}>
{IODetails?.ioCash ? IODetails?.ioCash : "00.00"}
{IODetails?.ioCash ? formatCurrency(IODetails?.ioCash) : "00.00"}
</Text>
</Box>
@@ -308,10 +314,12 @@ console.log(isLoading);
IO MV NAV
</Text>
<Text as={"span"} fontSize={"sm"} fontWeight={"500"}>
{IODetails?.ioMVNAV ? IODetails?.ioMVNAV : "00.00"}
{IODetails?.ioMVNAV ? formatCurrency(IODetails?.ioMVNAV) : "00.00"}
</Text>
</Box>
</HStack>
<Box
position={"absolute"}
right={3}

View File

@@ -108,7 +108,7 @@ const InvestorDetails = () => {
// ====================================================[Table Filter]================================================================
const filteredData = investorDetails?.data?.rows?.filter((item) => {
// Filter by name (case insensitive)
const name = item.clientReference_id;
const name = [item?.principal?.firstName, item?.principal?.lastName, item?.country?.countryName, item?.principal?.mobileNumber, item?.principal?.emailAddress].filter(Boolean).join(' ');
const searchLower = searchTerm.toLowerCase();
const nameMatches = name?.toLowerCase().includes(searchLower);

View File

@@ -3,10 +3,10 @@ import React from 'react'
// import noInternet from "../assets/Error.svg"
import robot from "../assets/under-construction.png"
const UnderConstruction = ({title}) => {
const UnderConstruction = ({title, h}) => {
return (
<Box
h={'100vh'}
h={h?h:'100vh'}
display={'flex'}
justifyContent={'center'}
alignItems={'center'}

View File

@@ -39,7 +39,7 @@ export const RouteLink = [
// =============[ Tanami ]================
// ===============[ Management]===============
// { path: "/", Component: Dashbaord },
{ path: "/", Component: Sponser },
{ path: "/sponser", Component: Sponser },
{ path: "/sponser/add-sponser/:id", Component: AddSponser },
{ path: "/sponser/add-sponser", Component: AddSponser },