updated
This commit is contained in:
104
src/Components/CutomBreadcrumb.jsx
Normal file
104
src/Components/CutomBreadcrumb.jsx
Normal file
@@ -0,0 +1,104 @@
|
||||
import React from "react";
|
||||
import {
|
||||
Box,
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
Text,
|
||||
Button,
|
||||
} from "@chakra-ui/react";
|
||||
import { Link, useLocation } from "react-router-dom";
|
||||
import { nav } from "../Routes/Nav";
|
||||
|
||||
const CustomBreadcrumb = () => {
|
||||
const { pathname } = useLocation();
|
||||
|
||||
// Remove leading slash and split path into parts
|
||||
const pathParts = pathname.replace(/^\//, "").split("/");
|
||||
|
||||
// Find the current menu item based on the provided path
|
||||
const findMenuItem = (path) => {
|
||||
let menuItem = null;
|
||||
nav.forEach((menu) => {
|
||||
if (menu.submenu) {
|
||||
menu.submenu.forEach((item) => {
|
||||
if (item.path === path) {
|
||||
menuItem = item;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return menuItem;
|
||||
};
|
||||
|
||||
// Generate breadcrumb items based on the current path
|
||||
const generateBreadcrumbs = (pathParts) => {
|
||||
const breadcrumbs = [];
|
||||
let currentPath = "";
|
||||
pathParts.forEach((part, index) => {
|
||||
currentPath += `/${part}`;
|
||||
const menuItem = findMenuItem(currentPath);
|
||||
if (menuItem) {
|
||||
breadcrumbs.push({ path: currentPath, title: menuItem.title });
|
||||
} else {
|
||||
// For nested paths without direct match, create a custom breadcrumb title
|
||||
const customTitle = part.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
||||
breadcrumbs.push({ path: currentPath, title: customTitle });
|
||||
}
|
||||
});
|
||||
return breadcrumbs;
|
||||
};
|
||||
|
||||
const breadcrumbs = generateBreadcrumbs(pathParts);
|
||||
console.log(breadcrumbs);
|
||||
|
||||
return (
|
||||
<Box
|
||||
fontWeight="medium"
|
||||
fontSize="xs"
|
||||
color={"blue.700"}
|
||||
display={"flex"}
|
||||
alignItems={"center"}
|
||||
p={1}
|
||||
mt={2}
|
||||
>
|
||||
<Button
|
||||
cursor={"pointer"}
|
||||
variant="ghost"
|
||||
pt={1.5}
|
||||
pb={1.5}
|
||||
ps={2}
|
||||
pe={2}
|
||||
rounded={"full"}
|
||||
size={"xs"}
|
||||
as={"span"}
|
||||
>
|
||||
Master
|
||||
</Button>{" "}
|
||||
{breadcrumbs.map((item, index) => (
|
||||
<React.Fragment key={index}>
|
||||
|
||||
<Text size={"xs"} ps={1} pe={1} as={"span"}>
|
||||
/
|
||||
</Text>
|
||||
<Link to={item.path}>
|
||||
<Button
|
||||
cursor={"pointer"}
|
||||
variant="ghost"
|
||||
pt={0.5}
|
||||
pb={0.5}
|
||||
ps={2}
|
||||
pe={2}
|
||||
rounded={"full"}
|
||||
size={"xs"}
|
||||
as={"span"}
|
||||
>
|
||||
{item.title}
|
||||
</Button></Link>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default CustomBreadcrumb;
|
||||
@@ -8,9 +8,9 @@ const FullscreenLoaders = () => {
|
||||
justifyContent={"center"}
|
||||
alignItems={"center"}
|
||||
w={"100%"}
|
||||
h={"90%"}
|
||||
h={"70vh"}
|
||||
>
|
||||
<Spinner color='teal.700' />
|
||||
<Spinner color='green.700' />
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
40
src/Components/NavBreadCrumbs.jsx
Normal file
40
src/Components/NavBreadCrumbs.jsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import React from "react";
|
||||
import { Link } from "react-router-dom"; // Adjust this based on your routing setup
|
||||
import CustomBreadcrumb from "./CutomBreadcrumb";
|
||||
|
||||
const NavBreadcrumbs = ({ nav }) => {
|
||||
// Function to recursively flatten submenu items and add parent titles
|
||||
const flattenNav = (items, parentTitle = "") => {
|
||||
let breadcrumbs = [];
|
||||
items.forEach((item) => {
|
||||
if (item.submenu) {
|
||||
// Add parent title if present
|
||||
breadcrumbs.push({
|
||||
label: parentTitle ? `${parentTitle} / ${item.title}` : item.title,
|
||||
link: null, // Adjust link as per your routing setup
|
||||
});
|
||||
// Recursively flatten submenu items
|
||||
breadcrumbs = [
|
||||
...breadcrumbs,
|
||||
...flattenNav(item.submenu, `${parentTitle} / ${item.title}`),
|
||||
];
|
||||
} else {
|
||||
// If no submenu, add current item as breadcrumb
|
||||
breadcrumbs.push({
|
||||
label: parentTitle ? `${parentTitle} / ${item.title}` : item.title,
|
||||
link: item.path, // Adjust link as per your routing setup
|
||||
});
|
||||
}
|
||||
});
|
||||
return breadcrumbs;
|
||||
};
|
||||
|
||||
// Flatten nav array into breadcrumbs
|
||||
const flattenedNav = flattenNav(nav);
|
||||
|
||||
console.log(nav);
|
||||
|
||||
return <CustomBreadcrumb items={flattenedNav} />;
|
||||
};
|
||||
|
||||
export default NavBreadcrumbs;
|
||||
@@ -49,6 +49,7 @@ import {
|
||||
Image,
|
||||
Alert,
|
||||
AlertIcon,
|
||||
Breadcrumb,
|
||||
} from "@chakra-ui/react";
|
||||
import GlobalStateContext from "../Contexts/GlobalStateContext";
|
||||
import Cookies from "js-cookie"; // Import the Cookies library
|
||||
@@ -68,6 +69,8 @@ import { GrManual } from "react-icons/gr";
|
||||
import { LuContact } from "react-icons/lu";
|
||||
import shield from "../assets/shield.png";
|
||||
import SplashScreen from "../Pages/SplashScreen";
|
||||
import CutomBreadcrumb from "../Components/CutomBreadcrumb";
|
||||
import CustomBreadcrumb from "../Components/CutomBreadcrumb";
|
||||
|
||||
const DashboardLayout = ({ isOnline }) => {
|
||||
const navigate = useNavigate();
|
||||
@@ -120,8 +123,6 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
navigate("/login");
|
||||
};
|
||||
|
||||
console.log();
|
||||
|
||||
// // Function to get the title based on the route
|
||||
const getTitle = () => {
|
||||
switch (true) {
|
||||
@@ -623,10 +624,11 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
)}
|
||||
|
||||
<main
|
||||
className={`h-100 ${slideFromRight ? "pe-3" : "ps-3"} `}
|
||||
className={`h-100 ${slideFromRight ? "pe-3" : "ps-3"} d-flex flex-column gap-0`}
|
||||
style={{
|
||||
width: `calc(100% - ${isDrawerOpen || openDrawerClick ? 232 : 74}px)`,
|
||||
transition: "width 0.3s ease-in-out",
|
||||
|
||||
}}
|
||||
>
|
||||
{/* <header className="p-2 ps-0 pt-3 fw-400 border-bottom">
|
||||
@@ -639,6 +641,8 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
icon
|
||||
title={getTitle()}
|
||||
/>
|
||||
|
||||
<CustomBreadcrumb />
|
||||
|
||||
<AppContent />
|
||||
</main>
|
||||
|
||||
@@ -97,12 +97,7 @@ const schema = yup.object().shape({
|
||||
.min(new Date(), "Closing date cannot be in the past"),
|
||||
|
||||
ioStatus: yup
|
||||
.string()
|
||||
.required("Investment Object status is required")
|
||||
.oneOf(
|
||||
["open", "pending", "closed"],
|
||||
"Investment Object status must be one of 'open', 'pending', or 'closed'"
|
||||
),
|
||||
.string(),
|
||||
});
|
||||
|
||||
const IODetails = ({ enableNextTab, index, isLoading, setIsLoading }) => {
|
||||
@@ -153,6 +148,8 @@ const IODetails = ({ enableNextTab, index, isLoading, setIsLoading }) => {
|
||||
resolver: yupResolver(schema),
|
||||
});
|
||||
|
||||
console.log(errors);
|
||||
|
||||
useEffect(() => {
|
||||
const found = IODetails?.find(
|
||||
(item) => item?.id.toString() === id?.toString()
|
||||
@@ -515,8 +512,10 @@ const IODetails = ({ enableNextTab, index, isLoading, setIsLoading }) => {
|
||||
return enableNextTab(index);
|
||||
}
|
||||
const id = generateUniqueId();
|
||||
setValue("id", id)
|
||||
const updatedData = { ...data, id };
|
||||
const status = "Draft"
|
||||
// setValue("id", id)
|
||||
console.log(data);
|
||||
const updatedData = { ...data, id, ioStatus : status };
|
||||
|
||||
console.log(data);
|
||||
// Add the updated data to the IODetails array
|
||||
|
||||
@@ -43,19 +43,32 @@ const AmountInvested = ({ isOpen, onClose }) => {
|
||||
size="sm"
|
||||
rounded={'sm'}
|
||||
textAlign={'end'}
|
||||
readOnly
|
||||
value={"$ 100000"}
|
||||
focusBorderColor="forestGreen.300"
|
||||
fontSize={"sm"} placeholder="$00.00" />
|
||||
</FormControl>
|
||||
|
||||
<FormControl mb={"15px"} >
|
||||
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>Amount to invest</FormLabel>
|
||||
<Input
|
||||
size="sm"
|
||||
rounded={'sm'}
|
||||
textAlign={'end'}
|
||||
focusBorderColor="forestGreen.300"
|
||||
fontSize={"sm"} placeholder="$00.00" />
|
||||
</FormControl>
|
||||
|
||||
<FormControl mb={"15px"}>
|
||||
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>
|
||||
Comments
|
||||
IO Cash
|
||||
</FormLabel>
|
||||
<Textarea
|
||||
<Input
|
||||
size="sm"
|
||||
rounded={'sm'}
|
||||
placeholder="$00.00"
|
||||
focusBorderColor="forestGreen.300"
|
||||
fontSize={"sm"} placeholder="Write Comments" />
|
||||
fontSize={"sm"} />
|
||||
</FormControl>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
|
||||
63
src/Pages/IO_Management/ViewIO/HeaderModal/Cancle.jsx
Normal file
63
src/Pages/IO_Management/ViewIO/HeaderModal/Cancle.jsx
Normal file
@@ -0,0 +1,63 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Input,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Text,
|
||||
Textarea,
|
||||
} from "@chakra-ui/react";
|
||||
|
||||
const Cancle = ({ isOpen, onClose }) => {
|
||||
return (
|
||||
<Modal isCentered isOpen={isOpen} onClose={onClose}>
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader fontSize={'md'}>Cancel</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<FormControl mb={"15px"} >
|
||||
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>Comment</FormLabel>
|
||||
<Textarea
|
||||
size="sm"
|
||||
rounded={'sm'}
|
||||
textAlign={'start'}
|
||||
rows={3}
|
||||
focusBorderColor="forestGreen.300"
|
||||
fontSize={"sm"} placeholder="Enter comments here..." />
|
||||
</FormControl>
|
||||
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button
|
||||
bg={"hsla(139, 100%, 14%, 1)"}
|
||||
mr={3}
|
||||
color={"#fff"}
|
||||
_hover={{
|
||||
bg: "hsl(139deg 98.99% 26.59%)",
|
||||
}}
|
||||
size={'sm'}
|
||||
rounded={"sm"}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
size={'sm'}
|
||||
rounded={"sm"} mr={3} onClick={onClose}>
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default Cancle;
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
Button,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
HStack,
|
||||
Input,
|
||||
Modal,
|
||||
ModalBody,
|
||||
@@ -11,54 +12,218 @@ import {
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Switch,
|
||||
Table,
|
||||
Tbody,
|
||||
Text,
|
||||
Textarea,
|
||||
Th,
|
||||
Tr,
|
||||
} from "@chakra-ui/react";
|
||||
import DataTable from "../../../../Components/DataTable/DataTable";
|
||||
import { useState } from "react";
|
||||
import { AddIcon } from "@chakra-ui/icons";
|
||||
|
||||
const DistributionInvestor = ({ isOpen, onClose }) => {
|
||||
|
||||
// ====================================================[Table Setup]================================================================
|
||||
const tableHeadRow = [
|
||||
"Sr No.",
|
||||
"Client Id",
|
||||
"First name",
|
||||
"Last Name",
|
||||
"Amount",
|
||||
"%",
|
||||
"($)",
|
||||
];
|
||||
|
||||
const filteredData = [
|
||||
{
|
||||
id: 1,
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
},]
|
||||
|
||||
const [extractedArray, setExtractedArray] = useState(
|
||||
filteredData?.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"}>
|
||||
BH00000001
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"First name": (
|
||||
<Box minW={24} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
Faisal
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Last Name": (
|
||||
<Box minW={24} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
Aljalahma
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Amount": (
|
||||
<Box minW={24} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
$100,000 /-
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"%": (
|
||||
<Box minW={19} isTruncated={true}>
|
||||
<Text textAlign={'right'} as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
26.0 %
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"($)": (
|
||||
<Box minW={24} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
$100,000 /-
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
}))
|
||||
);
|
||||
|
||||
|
||||
const Total = () => {
|
||||
return (
|
||||
<Table size="sm">
|
||||
<Tbody backgroundColor="gray.50">
|
||||
<Tr >
|
||||
<Th
|
||||
textAlign={"left"}
|
||||
p={3}
|
||||
width="90px"
|
||||
color={"#004118"}
|
||||
whiteSpace="normal"
|
||||
wordBreak="normal"
|
||||
overflowWrap="normal"
|
||||
>
|
||||
Total
|
||||
</Th>
|
||||
<Th
|
||||
textAlign={"center"}
|
||||
p={3}
|
||||
width="110px"
|
||||
color={"#004118"}
|
||||
whiteSpace="normal"
|
||||
wordBreak="normal"
|
||||
overflowWrap="normal"
|
||||
>
|
||||
{" "}
|
||||
</Th>
|
||||
<Th
|
||||
textAlign={"center"}
|
||||
p={3}
|
||||
width="110px"
|
||||
color={"#004118"}
|
||||
whiteSpace="normal"
|
||||
wordBreak="normal"
|
||||
overflowWrap="normal"
|
||||
>
|
||||
{" "}
|
||||
</Th>
|
||||
<Th
|
||||
textAlign={"center"}
|
||||
p={3}
|
||||
width="110px"
|
||||
color={"#004118"}
|
||||
whiteSpace="normal"
|
||||
wordBreak="normal"
|
||||
overflowWrap="normal"
|
||||
>
|
||||
{" "}
|
||||
</Th>
|
||||
<Th
|
||||
textAlign={"left"}
|
||||
p={3}
|
||||
width="110px"
|
||||
color={"#004118"}
|
||||
whiteSpace="normal"
|
||||
wordBreak="normal"
|
||||
overflowWrap="normal"
|
||||
>
|
||||
$100200
|
||||
</Th>
|
||||
<Th
|
||||
textAlign={"left"}
|
||||
p={3}
|
||||
width="90px"
|
||||
color={"#004118"}
|
||||
whiteSpace="normal"
|
||||
wordBreak="normal"
|
||||
overflowWrap="normal"
|
||||
>
|
||||
{" "}
|
||||
</Th>
|
||||
<Th
|
||||
textAlign={"center"}
|
||||
p={3}
|
||||
width="100px"
|
||||
color={"#004118"}
|
||||
whiteSpace="normal"
|
||||
wordBreak="normal"
|
||||
overflowWrap="normal"
|
||||
>
|
||||
|
||||
$100230
|
||||
</Th>
|
||||
</Tr>
|
||||
</Tbody>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose}>
|
||||
<Modal size={'xl'} isOpen={isOpen} onClose={onClose}>
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalContent maxW={1000} >
|
||||
<ModalHeader fontSize={"md"}>Distribution To investors</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<FormControl mb={"15px"}>
|
||||
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>
|
||||
Date
|
||||
</FormLabel>
|
||||
<Input
|
||||
placeholder="Select Date"
|
||||
size="sm"
|
||||
rounded={'sm'}
|
||||
focusBorderColor="forestGreen.300"
|
||||
fontSize={"sm"}
|
||||
type="date"
|
||||
/>
|
||||
</FormControl>
|
||||
<ModalBody >
|
||||
|
||||
<FormControl mb={"15px"} >
|
||||
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>Amount</FormLabel>
|
||||
<Input
|
||||
size="sm"
|
||||
rounded={'sm'}
|
||||
focusBorderColor="forestGreen.300"
|
||||
textAlign={'end'}
|
||||
fontSize={"sm"} placeholder="$00.00" />
|
||||
</FormControl>
|
||||
<HStack mb={4} >
|
||||
<Input placeholder="$00.00" size={'sm'} className="col" />
|
||||
<Input placeholder="$00.00" size={'sm'} className="col" />
|
||||
<Button leftIcon={<AddIcon />} size={'sm'} rounded={'sm'} colorScheme="green">Add</Button>
|
||||
</HStack>
|
||||
|
||||
<FormControl mb={"15px"}>
|
||||
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>
|
||||
Comments
|
||||
</FormLabel>
|
||||
<Textarea
|
||||
size="sm"
|
||||
rounded={'sm'}
|
||||
focusBorderColor="forestGreen.300"
|
||||
fontSize={"sm"} placeholder="Write Comments" />
|
||||
</FormControl>
|
||||
<DataTable
|
||||
emptyMessage={`We don't have any Sponers `}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={extractedArray}
|
||||
setData={setExtractedArray}
|
||||
caption={<Total/>}
|
||||
// isLoading={isLoading}
|
||||
/>
|
||||
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
{/* <ModalFooter>
|
||||
<Button
|
||||
bg={"hsla(139, 100%, 14%, 1)"}
|
||||
mr={3}
|
||||
@@ -76,7 +241,10 @@ const DistributionInvestor = ({ isOpen, onClose }) => {
|
||||
rounded={"sm"} mr={3} onClick={onClose}>
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalFooter> */}
|
||||
|
||||
|
||||
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
86
src/Pages/IO_Management/ViewIO/HeaderModal/Exit.jsx
Normal file
86
src/Pages/IO_Management/ViewIO/HeaderModal/Exit.jsx
Normal file
@@ -0,0 +1,86 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Input,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Text,
|
||||
Textarea,
|
||||
} from "@chakra-ui/react";
|
||||
|
||||
const Exit = ({ isOpen, onClose }) => {
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose}>
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader fontSize={'md'}>Amount Invested</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<FormControl mb={"15px"}>
|
||||
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>
|
||||
Date
|
||||
</FormLabel>
|
||||
<Input
|
||||
placeholder="Select Date"
|
||||
size="sm"
|
||||
rounded={'sm'}
|
||||
fontSize={"sm"}
|
||||
focusBorderColor="forestGreen.300"
|
||||
type="date"
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
<FormControl mb={"15px"} >
|
||||
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>IO NAV</FormLabel>
|
||||
<Input
|
||||
size="sm"
|
||||
rounded={'sm'}
|
||||
textAlign={'end'}
|
||||
focusBorderColor="forestGreen.300"
|
||||
fontSize={"sm"} placeholder="$00.00" />
|
||||
</FormControl>
|
||||
|
||||
<FormControl mb={"15px"} >
|
||||
<FormLabel as={"label"} fontSize={"sm"} fontWeight={500}>Distribution</FormLabel>
|
||||
<Input
|
||||
size="sm"
|
||||
rounded={'sm'}
|
||||
textAlign={'end'}
|
||||
focusBorderColor="forestGreen.300"
|
||||
fontSize={"sm"} placeholder="$00.00" />
|
||||
</FormControl>
|
||||
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button
|
||||
bg={"hsla(139, 100%, 14%, 1)"}
|
||||
mr={3}
|
||||
color={"#fff"}
|
||||
_hover={{
|
||||
bg: "hsl(139deg 98.99% 26.59%)",
|
||||
}}
|
||||
size={'sm'}
|
||||
rounded={"sm"}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
size={'sm'}
|
||||
rounded={"sm"} mr={3} onClick={onClose}>
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default Exit;
|
||||
|
||||
@@ -54,7 +54,7 @@ const UpdateIOStatus = ({ isOpen, onClose }) => {
|
||||
<Textarea
|
||||
size="sm"
|
||||
rounded={'sm'}
|
||||
colorScheme={'green'}
|
||||
focusBorderColor="forestGreen.300"
|
||||
fontSize={"sm"} placeholder="Write Comments" />
|
||||
</FormControl>
|
||||
</ModalBody>
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
MenuDivider,
|
||||
Badge,
|
||||
Box,
|
||||
Icon,
|
||||
} from "@chakra-ui/react";
|
||||
import header from "../../../assets/IOheader.png";
|
||||
import { HiDotsVertical } from "react-icons/hi";
|
||||
@@ -34,9 +35,13 @@ import UpdateIONav from "./HeaderModal/UpdateIONav";
|
||||
import UpdateIOStatus from "./HeaderModal/UpdateIOStatus";
|
||||
import { useContext, useRef } from "react";
|
||||
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||
import Exit from "./HeaderModal/Exit";
|
||||
import Cancle from "./HeaderModal/Cancle";
|
||||
import { AddIcon } from "@chakra-ui/icons";
|
||||
import { GrGallery } from "react-icons/gr";
|
||||
|
||||
const ViewIOdataHeader = () => {
|
||||
const params = useParams()
|
||||
const params = useParams();
|
||||
const id = params?.id;
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const btnRef = useRef();
|
||||
@@ -45,7 +50,6 @@ const ViewIOdataHeader = () => {
|
||||
(item) => item?.id.toString() === id?.toString()
|
||||
);
|
||||
|
||||
|
||||
const {
|
||||
isOpen: isInvestmentOpen,
|
||||
onOpen: onInvestmentOpen,
|
||||
@@ -76,6 +80,17 @@ const ViewIOdataHeader = () => {
|
||||
onOpen: onUpdateStatusOpen,
|
||||
onClose: onUpdateStatusClose,
|
||||
} = useDisclosure();
|
||||
const {
|
||||
isOpen: isExitOpen,
|
||||
onOpen: onExitOpen,
|
||||
onClose: onExitClose,
|
||||
} = useDisclosure();
|
||||
const {
|
||||
isOpen: isCancleOpen,
|
||||
onOpen: onCancleOpen,
|
||||
onClose: onCancleClose,
|
||||
} = useDisclosure();
|
||||
|
||||
|
||||
const bg = {
|
||||
bg: "#fff",
|
||||
@@ -109,8 +124,11 @@ const ViewIOdataHeader = () => {
|
||||
borderRadius={"10px"}
|
||||
position={"relative"}
|
||||
>
|
||||
<Box p={1}>
|
||||
<Image h={82} src={header} />
|
||||
<Box h={100} w={200} p={1.5} >
|
||||
{/* <Image rounded={'md'} h={"100%"} src={foundObject?.ioName} alt={foundObject?.ioName}/> */}
|
||||
<Box w={'100%'} h={'100%'} display={'flex'} justifyContent={'center'} alignItems={'center'} bg={"#fff"} rounded={'md'}>
|
||||
<Icon color={'gray.700'} as={GrGallery} />
|
||||
</Box>
|
||||
</Box>
|
||||
{/* <Box display={"flex"} flexDirection={"column"} gap={2}>
|
||||
<Text as={"span"} fontSize={"sm"} fontWeight={"500"}>
|
||||
@@ -121,37 +139,35 @@ const ViewIOdataHeader = () => {
|
||||
</Text>
|
||||
</Box> */}
|
||||
|
||||
<Box display={"flex"} flexDirection={"column"} gap={2}>
|
||||
<Box display={"flex"} flexDirection={"column"} gap={2}>
|
||||
<Text as={"span"} fontSize={"xs"} color={"gray.500"} fontWeight={"500"}>
|
||||
IO Name
|
||||
</Text>
|
||||
<Text as={"span"} fontSize={"sm"} fontWeight={"500"}>
|
||||
{id ? foundObject?.ioName : "N/A"}
|
||||
{id ? foundObject?.ioName : "---"}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
|
||||
<Box display={"flex"} flexDirection={"column"} gap={2}>
|
||||
<Text as={"span"} fontSize={"xs"} color={"gray.500"} fontWeight={"500"}>
|
||||
Sponsorer Name
|
||||
</Text>
|
||||
<Text as={"span"} fontSize={"sm"} fontWeight={"500"}>
|
||||
{id ? foundObject?.sponserName : "N/A"}
|
||||
{id ? foundObject?.sponserName : "---"}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
|
||||
<Box display={"flex"} flexDirection={"column"} gap={2}>
|
||||
<Text as={"span"} fontSize={"xs"} color={"gray.500"} fontWeight={"500"}>
|
||||
IO Status
|
||||
</Text>
|
||||
<Badge
|
||||
rounded={'md'}
|
||||
rounded={"md"}
|
||||
pt={0.5}
|
||||
pb={0.5}
|
||||
ps={4}
|
||||
pe={4}
|
||||
textTransform={'none'}
|
||||
textTransform={"none"}
|
||||
color={
|
||||
foundObject?.ioStatus === "Open"
|
||||
? "#00B69B"
|
||||
@@ -167,7 +183,7 @@ const ViewIOdataHeader = () => {
|
||||
: "red"
|
||||
}
|
||||
>
|
||||
{id ? foundObject?.ioStatus : "N/A"}
|
||||
{id ? foundObject?.ioStatus : "---"}
|
||||
</Badge>
|
||||
</Box>
|
||||
<Box display={"flex"} flexDirection={"column"} gap={2}>
|
||||
@@ -175,8 +191,7 @@ const ViewIOdataHeader = () => {
|
||||
IO MV NAV
|
||||
</Text>
|
||||
<Text as={"span"} fontSize={"sm"} fontWeight={"500"}>
|
||||
{id? "$42012.00" : "N/A"}
|
||||
|
||||
{id ? "$42012.00" : "---"}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box display={"flex"} flexDirection={"column"} gap={2}>
|
||||
@@ -184,7 +199,7 @@ const ViewIOdataHeader = () => {
|
||||
IO cash
|
||||
</Text>
|
||||
<Text as={"span"} fontSize={"sm"} fontWeight={"500"}>
|
||||
{id ?"$48,000" : "N/A"}
|
||||
{id ? "$48,000" : "---"}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box display={"flex"} flexDirection={"column"} gap={2}>
|
||||
@@ -192,7 +207,7 @@ const ViewIOdataHeader = () => {
|
||||
IO NAV
|
||||
</Text>
|
||||
<Text as={"span"} fontSize={"sm"} fontWeight={"500"}>
|
||||
{id ? "$1,140,500" : "N/A"}
|
||||
{id ? "$1,140,500" : "---"}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
@@ -215,24 +230,34 @@ const ViewIOdataHeader = () => {
|
||||
<HiDotsVertical className="rubix-text-dark fs-6" />
|
||||
</MenuButton>
|
||||
<MenuList fontSize={"sm"}>
|
||||
<MenuItem _hover={{
|
||||
bg:"#fff"
|
||||
}} as={'span'} fontWeight={600} className="border-bottom">
|
||||
<MenuItem
|
||||
_hover={{
|
||||
bg: "#fff",
|
||||
}}
|
||||
as={"span"}
|
||||
fontWeight={600}
|
||||
className="border-bottom"
|
||||
>
|
||||
Tansaction
|
||||
</MenuItem>
|
||||
<MenuItem onClick={onInvestmentOpen} className="border-bottom">Amount Invested</MenuItem>
|
||||
<MenuItem onClick={onFeesOpen} className="border-bottom">Fees & Expenses</MenuItem>
|
||||
<MenuItem onClick={onInvestmentOpen} className="border-bottom">
|
||||
Amount Invested
|
||||
</MenuItem>
|
||||
<MenuItem onClick={onFeesOpen} className="border-bottom">
|
||||
Fees & Expenses
|
||||
</MenuItem>
|
||||
<MenuItem onClick={onDistSponsorOpen} className="border-bottom">
|
||||
Distribution from Sponsors
|
||||
</MenuItem>
|
||||
<MenuItem onClick={onDistInvestorOpen}
|
||||
className="border-bottom">
|
||||
<MenuItem onClick={onDistInvestorOpen} className="border-bottom">
|
||||
Distribution To investors
|
||||
</MenuItem>
|
||||
<MenuItem onClick={onUpdateNavOpen} className="border-bottom">Update iO NAV</MenuItem>
|
||||
<MenuItem className="border-bottom">Exit</MenuItem>
|
||||
<MenuItem className="border-bottom">Cancel</MenuItem>
|
||||
<MenuItem onClick={onUpdateStatusOpen}>Update iO status</MenuItem>
|
||||
<MenuItem onClick={onUpdateNavOpen} className="border-bottom">
|
||||
Update iO NAV
|
||||
</MenuItem>
|
||||
<MenuItem onClick={onExitOpen} className="border-bottom">Exit</MenuItem>
|
||||
<MenuItem onClick={onCancleOpen} className="border-bottom">Cancel</MenuItem>
|
||||
<MenuItem onClick={onUpdateStatusOpen}>Update iO status</MenuItem>
|
||||
</MenuList>
|
||||
</Menu>
|
||||
|
||||
@@ -322,6 +347,8 @@ const ViewIOdataHeader = () => {
|
||||
{/* Modals */}
|
||||
<AmountInvested isOpen={isInvestmentOpen} onClose={onInvestmentClose} />
|
||||
<FeesExpenses isOpen={isFeesOpen} onClose={onFeesClose} />
|
||||
<Exit isOpen={isExitOpen} onClose={onExitClose} />
|
||||
<Cancle isOpen={isCancleOpen} onClose={onCancleClose} />
|
||||
<DistributionSponsor
|
||||
isOpen={isDistSponsorOpen}
|
||||
onClose={onDistSponsorClose}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useForm } from "react-hook-form";
|
||||
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||
import DataTable from "../../../Components/DataTable/DataTable";
|
||||
import FormInputView from "../../../Components/FormInputView";
|
||||
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
||||
|
||||
const ViewIOdetails = () => {
|
||||
const navigate = useNavigate()
|
||||
@@ -117,7 +118,7 @@ const ViewIOdetails = () => {
|
||||
}, {});
|
||||
|
||||
if (!foundObject) {
|
||||
return <Box>Loading...</Box>;
|
||||
return <FullscreenLoaders/>;
|
||||
}
|
||||
|
||||
return <Box position={'relative'}>
|
||||
|
||||
@@ -296,6 +296,20 @@ const InvestorDetails = () => {
|
||||
<Select focusBorderColor="green.500" size={'sm'} fontSize={'xs'} cursor={'pointer'}>
|
||||
<option value="" selected disabled hidden>Status</option>
|
||||
|
||||
<option value="all">All</option>
|
||||
<option value="ban">Ban</option>
|
||||
<option value="unban">UnBan</option>
|
||||
</Select>
|
||||
<Select focusBorderColor="green.500" size={'sm'} fontSize={'xs'} cursor={'pointer'}>
|
||||
<option value="" selected disabled hidden>Status</option>
|
||||
|
||||
<option value="all">All</option>
|
||||
<option value="ban">Ban</option>
|
||||
<option value="unban">UnBan</option>
|
||||
</Select>
|
||||
<Select focusBorderColor="green.500" size={'sm'} fontSize={'xs'} cursor={'pointer'}>
|
||||
<option value="" selected disabled hidden>Status</option>
|
||||
|
||||
<option value="all">All</option>
|
||||
<option value="ban">Ban</option>
|
||||
<option value="unban">UnBan</option>
|
||||
|
||||
@@ -143,7 +143,7 @@ const Login = () => {
|
||||
type="text"
|
||||
name="name"
|
||||
variant="filled"
|
||||
placeholder="Owner name"
|
||||
placeholder="Email"
|
||||
size="lg"
|
||||
className="web-text-medium"
|
||||
/>
|
||||
|
||||
@@ -294,7 +294,7 @@ const InvestmentType = () => {
|
||||
};
|
||||
|
||||
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">
|
||||
<HStack
|
||||
display={"flex"}
|
||||
|
||||
@@ -28,11 +28,16 @@ import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||
import ToastBox from "../../../Components/ToastBox";
|
||||
import { debounce } from "./AddSponser";
|
||||
import { useGetSponserMasterQuery } from "../../../Services/sponser.service";
|
||||
|
||||
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
|
||||
|
||||
const Sponser = () => {
|
||||
const toast = useToast();
|
||||
const { data: sponsors, error, isLoading: isSponserLoading } = useGetSponserMasterQuery();
|
||||
console.log(isSponserLoading);
|
||||
console.log(sponsors);
|
||||
|
||||
const { sponser, setSponser, slideFromRight } =
|
||||
useContext(GlobalStateContext);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
|
||||
68
src/Services/api.service.js
Normal file
68
src/Services/api.service.js
Normal file
@@ -0,0 +1,68 @@
|
||||
import axios from "axios";
|
||||
|
||||
// Create an Axios instance for API calls
|
||||
export const api = axios.create({
|
||||
baseURL: "https://fakestoreapi.com", // 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("accessToken", response.data.accessToken);
|
||||
localStorage.setItem(
|
||||
"refreshToken",
|
||||
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);
|
||||
}
|
||||
);
|
||||
@@ -1,23 +1,25 @@
|
||||
//sponser.service
|
||||
// Need to use the React-specific entry point to import createApi
|
||||
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
|
||||
import { api } from "./api.service";
|
||||
|
||||
const baseUrl = import.meta.env.VITE_API_BASE_URL + "/api";
|
||||
const baseUrl = api?.defaults.baseURL;
|
||||
|
||||
// Define a service using a base URL and expected endpoints
|
||||
export const sponserMaster = createApi({
|
||||
reducerPath: "sponserMaster",
|
||||
baseQuery: fetchBaseQuery({ baseUrl }),
|
||||
baseQuery: fetchBaseQuery({ baseUrl: baseUrl }),
|
||||
tagTypes: [],
|
||||
endpoints: (builder) => ({
|
||||
getSponserMaster: builder.query({
|
||||
query: () => '/getUsers',
|
||||
query: () => '/products/1',
|
||||
}),
|
||||
getsponserMasterById: builder.query({
|
||||
getSponserMasterById: builder.query({
|
||||
query: (id) => `/getUser/${id}`,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
// Export hooks for usage in functional components
|
||||
export const { useSponserMasterQuery, useGetsponserMasterByIdQuery } = sponserMaster;
|
||||
export const { useGetSponserMasterQuery, useGetSponserMasterByIdQuery } = sponserMaster;
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import axios from "axios";
|
||||
import { configureStore } from "@reduxjs/toolkit";
|
||||
import { setupListeners } from "@reduxjs/toolkit/query";
|
||||
import { sponserMaster } from "../Services/sponser.service";
|
||||
@@ -7,72 +6,7 @@ import { exchangeRate } from "../Services/exchange.rate.service";
|
||||
import { ioService } from "../Services/io.service";
|
||||
import { investorDetails } from "../Services/investor.details.service";
|
||||
import { investorTransaction } from "../Services/investor.transaction.service";
|
||||
|
||||
// Create an Axios instance for API calls
|
||||
const api = axios.create({
|
||||
baseURL: "https://api.example.com", // 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) => {
|
||||
// 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("accessToken", response.data.accessToken);
|
||||
localStorage.setItem(
|
||||
"refreshToken",
|
||||
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);
|
||||
}
|
||||
);
|
||||
import { api } from "../Services/api.service";
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
@@ -89,7 +23,14 @@ export const store = configureStore({
|
||||
thunk: {
|
||||
extraArgument: api, // Pass Axios instance as extra argument
|
||||
},
|
||||
}),
|
||||
}).concat(
|
||||
sponserMaster.middleware,
|
||||
investmentType.middleware,
|
||||
exchangeRate.middleware,
|
||||
ioService.middleware,
|
||||
investorDetails.middleware,
|
||||
investorTransaction.middleware
|
||||
),
|
||||
});
|
||||
|
||||
setupListeners(store.dispatch);
|
||||
|
||||
BIN
src/assets/pro1.jpg
Normal file
BIN
src/assets/pro1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 532 KiB |
@@ -7,8 +7,9 @@ import { Provider } from "react-redux";
|
||||
import { PersistGate } from "redux-persist/integration/react";
|
||||
import { ChakraProvider } from "@chakra-ui/react";
|
||||
import GlobalStateProvider from "./Contexts/GlobalStateProvider";
|
||||
import { store } from "./Store/Store.js";
|
||||
// import { store } from "./Store/Store.js";
|
||||
import customTheme from "./Theme/Theme.js";
|
||||
import store from "./Store/Store.js";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")).render(
|
||||
<ChakraProvider theme={customTheme} >
|
||||
|
||||
Reference in New Issue
Block a user