[update] - dashboard ❤️✅😒
This commit is contained in:
@@ -58,7 +58,6 @@ const NormalTable = ({
|
||||
};
|
||||
|
||||
|
||||
|
||||
const handleCheckboxChange = (value) => {
|
||||
if (radio) {
|
||||
// If radio is true, select only one option
|
||||
|
||||
@@ -140,6 +140,14 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
switch (true) {
|
||||
case "/":
|
||||
return "👋🏻 Hi, Admin";
|
||||
|
||||
case path.startsWith("/"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<TbLayoutDashboard className="h4 m-0" />Dashboard
|
||||
</span>
|
||||
);
|
||||
|
||||
case path.startsWith("/investment-opportunities"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
|
||||
@@ -1,201 +1,455 @@
|
||||
import { Box, Divider, Flex, Grid, GridItem, Heading, HStack, Select, SimpleGrid, Stack, Text } from '@chakra-ui/react'
|
||||
import React from 'react'
|
||||
import { BsArrowsAngleContract, BsBoxArrowDown, BsBoxArrowUp } from "react-icons/bs";
|
||||
import {
|
||||
Box,
|
||||
Divider,
|
||||
Flex,
|
||||
Heading,
|
||||
HStack,
|
||||
Select,
|
||||
SimpleGrid,
|
||||
Text,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
BsArrowsAngleContract,
|
||||
BsBoxArrowDown,
|
||||
BsBoxArrowUp,
|
||||
} from "react-icons/bs";
|
||||
import { FaRegPenToSquare } from "react-icons/fa6";
|
||||
import { LuContact } from "react-icons/lu";
|
||||
import { FaRegPenToSquare } from "react-icons/fa6";
|
||||
import InvestmentOpportunities from './InvestmentOpportunities';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Link } from "react-router-dom";
|
||||
import { useGetDashboardMasterQuery } from "../../Services/dashboard.service";
|
||||
import InvestmentOpportunities from "./InvestmentOpportunities";
|
||||
|
||||
const panddingReguest = [
|
||||
{
|
||||
icon: <BsBoxArrowUp />,
|
||||
label: "Pending deposit requests",
|
||||
count: 27,
|
||||
},
|
||||
{
|
||||
icon: <BsBoxArrowDown />,
|
||||
label: "Pending withdrawal requests",
|
||||
count: 27,
|
||||
},
|
||||
{
|
||||
icon: <LuContact />,
|
||||
label: "Pending KYC review request",
|
||||
count: 27,
|
||||
},
|
||||
{
|
||||
icon: <FaRegPenToSquare />,
|
||||
label: "Pending Acc modification request",
|
||||
count: 27,
|
||||
},
|
||||
];
|
||||
|
||||
const userActivity = [
|
||||
{
|
||||
icon: <BsBoxArrowUp />,
|
||||
label: "Total number of users",
|
||||
count: 1500,
|
||||
},
|
||||
{
|
||||
icon: <BsBoxArrowDown />,
|
||||
label: "Total number of users with completed KYC (%)",
|
||||
count: '320',
|
||||
percentage:'(50%)',
|
||||
},
|
||||
{
|
||||
icon: <LuContact />,
|
||||
label: "Total number of Active users",
|
||||
count: '3,298',
|
||||
},
|
||||
];
|
||||
|
||||
const closedOpportunities = [
|
||||
{
|
||||
icon: <BsBoxArrowUp />,
|
||||
label: "Closed Opportunities",
|
||||
count: 27,
|
||||
},
|
||||
{
|
||||
icon: <BsBoxArrowUp />,
|
||||
label: "Total assets under managemnet",
|
||||
count: 27,
|
||||
},
|
||||
{
|
||||
icon: <BsBoxArrowUp />,
|
||||
label: "Total number of investors",
|
||||
count: 27,
|
||||
},
|
||||
{
|
||||
icon: <BsBoxArrowUp />,
|
||||
label: "Total number of unique investors",
|
||||
count: 27,
|
||||
},
|
||||
];
|
||||
|
||||
const walletCase = [
|
||||
{ amount: "$ د. ب. 50,000", currency: "USD" },
|
||||
{ amount: "$ د. ب. 50,000", currency: "BHD" },
|
||||
{ amount: "$ ﷼. 50,000", currency: "SAR" },
|
||||
{ amount: "$ د.ك 50,0000", currency: "KWD" },
|
||||
{ amount: "$ د.إ 50,000", currency: "AED" },
|
||||
{ amount: "$ ﷼ 50,000", currency: "OMR" },
|
||||
{ amount: "$ ر. ق 50,000" , currency: "QAR" },
|
||||
];
|
||||
// const panddingReguest = [
|
||||
// {
|
||||
// icon: <BsBoxArrowUp />,
|
||||
// label: "Pending deposit requests",
|
||||
// count: 27,
|
||||
// },
|
||||
// {
|
||||
// icon: <BsBoxArrowDown />,
|
||||
// label: "Pending withdrawal requests",
|
||||
// count: 27,
|
||||
// },
|
||||
// {
|
||||
// icon: <LuContact />,
|
||||
// label: "Pending KYC review request",
|
||||
// count: 27,
|
||||
// },
|
||||
// {
|
||||
// icon: <FaRegPenToSquare />,
|
||||
// label: "Pending Acc modification request",
|
||||
// count: 27,
|
||||
// },
|
||||
// ];
|
||||
|
||||
const Dashbaord = ({ showSearch = false }) => {
|
||||
const [filter, setFilter] = useState("today");
|
||||
const { data, error, isLoading } = useGetDashboardMasterQuery();
|
||||
console.log(data);
|
||||
|
||||
const panddingReguest = [
|
||||
{
|
||||
icon: <BsBoxArrowUp />,
|
||||
label: "Pending deposit requests",
|
||||
count: parseFloat(
|
||||
data?.data?.pendingRequests?.pendingDepositReq?.totalDepositReq || 0
|
||||
).toLocaleString(),
|
||||
},
|
||||
{
|
||||
icon: <BsBoxArrowDown />,
|
||||
label: "Pending withdrawal requests",
|
||||
count: parseFloat(
|
||||
data?.data?.pendingRequests?.pendingWithdrawalReq || 0
|
||||
).toLocaleString(),
|
||||
},
|
||||
{
|
||||
icon: <LuContact />,
|
||||
label: "Pending KYC review request",
|
||||
count: parseFloat(
|
||||
data?.data?.pendingRequests?.pendingKYCReviewReq || 0
|
||||
).toLocaleString(),
|
||||
},
|
||||
{
|
||||
icon: <FaRegPenToSquare />,
|
||||
label: "Pending Acc modification request",
|
||||
count: parseFloat(
|
||||
data?.data?.pendingRequests?.pendingAccModReq?.totalAccModReq || 0
|
||||
).toLocaleString(),
|
||||
},
|
||||
];
|
||||
|
||||
const userActivity = [
|
||||
{
|
||||
icon: <BsBoxArrowUp />,
|
||||
label: "Total number of users",
|
||||
count: data?.data?.userActivity?.totalCount, //totalCount
|
||||
},
|
||||
{
|
||||
icon: <BsBoxArrowDown />,
|
||||
label: "Total number of users with completed KYC (%)",
|
||||
count: data?.data?.userActivity?.KYCCompletedCount, //KYCCompletedCount
|
||||
percentage: data?.data?.userActivity?.completedKYCPer, //completedKYCPer
|
||||
},
|
||||
{
|
||||
icon: <LuContact />,
|
||||
label: "Total number of Active users",
|
||||
count: data?.data?.userActivity?.ActiveUsers, //ActiveUsers
|
||||
},
|
||||
];
|
||||
|
||||
const closedOpportunities = [
|
||||
{
|
||||
icon: <BsBoxArrowUp />,
|
||||
label: "Closed Opportunities",
|
||||
count: parseFloat(
|
||||
data?.data?.investmentOpportunity?.closedOpportunityDetails
|
||||
?.numberOfClosedOpportunities || 0
|
||||
).toLocaleString(),
|
||||
},
|
||||
{
|
||||
icon: <BsBoxArrowUp />,
|
||||
label: "Total assets under managemnet",
|
||||
count: `$ ${parseFloat(
|
||||
data?.data?.investmentOpportunity?.closedOpportunityDetails?.totalAUM ||
|
||||
0
|
||||
).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`,
|
||||
},
|
||||
{
|
||||
icon: <BsBoxArrowUp />,
|
||||
label: "Total number of investors",
|
||||
count: parseFloat(
|
||||
data?.data?.investmentOpportunity?.closedOpportunityDetails
|
||||
?.totalNumberOfInvestors || 0
|
||||
).toLocaleString(),
|
||||
},
|
||||
{
|
||||
icon: <BsBoxArrowUp />,
|
||||
label: "Total number of unique investors",
|
||||
count: parseFloat(
|
||||
data?.data?.investmentOpportunity?.closedOpportunityDetails
|
||||
?.numberOfUniqueInvestors || 0
|
||||
).toLocaleString(),
|
||||
},
|
||||
];
|
||||
|
||||
const walletCase = [
|
||||
{
|
||||
amount: `$ ${parseFloat(
|
||||
data?.data?.walletBalance?.usersWalletCashInUSD || 0
|
||||
).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`,
|
||||
currency: "USD",
|
||||
},
|
||||
{
|
||||
amount: ` د. ب. ${parseFloat(
|
||||
data?.data?.walletBalance?.usersWalletCashInBHD || 0
|
||||
).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`,
|
||||
currency: "BHD",
|
||||
},
|
||||
{
|
||||
amount: ` ﷼. ${parseFloat(
|
||||
data?.data?.walletBalance?.usersWalletCashInSAR || 0
|
||||
).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`,
|
||||
currency: "SAR",
|
||||
},
|
||||
{
|
||||
amount: ` د.ك ${parseFloat(
|
||||
data?.data?.walletBalance?.usersWalletCashInKWD || 0
|
||||
).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`,
|
||||
currency: "KWD",
|
||||
},
|
||||
{
|
||||
amount: ` د.إ ${parseFloat(
|
||||
data?.data?.walletBalance?.usersWalletCashInAED || 0
|
||||
).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`,
|
||||
currency: "AED",
|
||||
},
|
||||
{
|
||||
amount: ` ﷼. ${parseFloat(
|
||||
data?.data?.walletBalance?.usersWalletCashInOMR || 0
|
||||
).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`,
|
||||
currency: "OMR",
|
||||
},
|
||||
{
|
||||
amount: ` ر. ق. ${parseFloat(
|
||||
data?.data?.walletBalance?.usersWalletCashInQAR || 0
|
||||
).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`,
|
||||
currency: "QAR",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Box height={'100vh'} bg={'#fff'} roundedTop={0} pt={5} pr={4} overflowX={"hidden"} mb={5}>
|
||||
<Box display={'flex'} gap={5} mb={5}>
|
||||
<Box w={'40%'} bg={'#0047170F'} p={4} rounded={5}>
|
||||
<Heading fontSize={'md'} fontWeight={500}>Pending Request</Heading>
|
||||
<Box
|
||||
height={"100vh"}
|
||||
bg={"#fff"}
|
||||
roundedTop={0}
|
||||
pt={5}
|
||||
pr={4}
|
||||
overflowX={"hidden"}
|
||||
mb={5}
|
||||
>
|
||||
<Box display={"flex"} gap={5} mb={5}>
|
||||
<Box w={"40%"} bg={"#0047170F"} p={4} rounded={5}>
|
||||
<Heading fontSize={"md"} fontWeight={500}>
|
||||
Pending Request
|
||||
</Heading>
|
||||
<Divider />
|
||||
<SimpleGrid columns={2} spacing={3}>
|
||||
{panddingReguest.map((item, index) => (
|
||||
<Box key={index} bg="white" p={4} rounded={10}>
|
||||
<Text fontSize={'18px'} mb={2}>{item.icon}</Text>
|
||||
<Text mb={0} mt={0} fontSize={'11px'} fontWeight={500}>
|
||||
<Text fontSize={"18px"} mb={2}>
|
||||
{item.icon}
|
||||
</Text>
|
||||
<Text mb={0} mt={0} fontSize={"11px"} fontWeight={500}>
|
||||
{item.label}
|
||||
</Text>
|
||||
<Text as="span" fontSize={'md'} fontWeight={700} mb={0}>
|
||||
<Text as="span" fontSize={"md"} fontWeight={700} mb={0}>
|
||||
{item.count}
|
||||
</Text>
|
||||
</Box>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
<Box bg={'#0047170F'} w={'65%'} p={4} rounded={5}>
|
||||
<Heading fontSize={'md'} fontWeight={500}>User Activity</Heading>
|
||||
<Box bg={"#0047170F"} w={"65%"} p={4} rounded={5}>
|
||||
<Heading fontSize={"md"} fontWeight={500}>
|
||||
User Activity
|
||||
</Heading>
|
||||
<Divider />
|
||||
<SimpleGrid columns={3} spacing={3}>
|
||||
{userActivity.map((item, index) => (
|
||||
<Box key={index} bg="white" p={4} rounded={10}>
|
||||
<Flex alignContent={'center'}>
|
||||
<Text fontSize={'18px'}>{item.icon}</Text>
|
||||
<Text fontSize={'11px'} fontWeight={500} mb={2} minH={'38px'} ml={1} mt={0}>
|
||||
{item.label}
|
||||
</Text>
|
||||
<Flex alignContent={"center"}>
|
||||
<Text fontSize={"18px"}>{item.icon}</Text>
|
||||
<Text
|
||||
fontSize={"11px"}
|
||||
fontWeight={500}
|
||||
mb={2}
|
||||
minH={"38px"}
|
||||
ml={1}
|
||||
mt={0}
|
||||
>
|
||||
{item.label}
|
||||
</Text>
|
||||
</Flex>
|
||||
<Text as="span" fontSize={'md'} fontWeight={700} mb={0}>
|
||||
{item.count} <Text as={'span'} fontSize={'sm'} color={'#666'}>{item.percentage}</Text>
|
||||
<Text as="span" fontSize={"md"} fontWeight={700} mb={0}>
|
||||
{item?.count}
|
||||
{item?.percentage && (
|
||||
<Text
|
||||
as={"span"}
|
||||
fontSize={"12px"}
|
||||
color={"#666"}
|
||||
fontWeight={400}
|
||||
>
|
||||
{` (${item?.percentage}) %`}
|
||||
</Text>
|
||||
)}
|
||||
</Text>
|
||||
</Box>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
<Box display={'flex'} gap={3} mt={4}>
|
||||
<Box w={'50%'} bg={'#fff'} p={4} rounded={10}>
|
||||
<Box h={'25px'}></Box>
|
||||
<HStack justifyContent={'space-between'}>
|
||||
<Box textAlign={'center'}>
|
||||
<Text as={'span'} color={'#066123'} fontSize={'md'} fontWeight={500}>80%</Text>
|
||||
<Text fontSize={'11px'} fontWeight={500}>Users that opened the app today</Text>
|
||||
<Box display={"flex"} gap={3} mt={4}>
|
||||
<Box w={"50%"} bg={"#fff"} p={4} rounded={10}>
|
||||
<Box h={"25px"}></Box>
|
||||
<HStack justifyContent={"space-between"}>
|
||||
<Box textAlign={"center"}>
|
||||
<Text
|
||||
as={"span"}
|
||||
color={"#066123"}
|
||||
fontSize={"md"}
|
||||
fontWeight={500}
|
||||
>
|
||||
{data?.data?.userActivity?.openedAppToday?.percentage} %
|
||||
</Text>
|
||||
<Text fontSize={"11px"} fontWeight={500}>
|
||||
Users that opened the app today
|
||||
</Text>
|
||||
</Box>
|
||||
<Divider orientation='vertical' />
|
||||
<Box textAlign={'center'}>
|
||||
<Text as={'span'} color={'#066123'} fontSize={'md'} fontWeight={500}>3,298</Text>
|
||||
<Text fontSize={'11px'} fontWeight={500}>New sign-ups </Text>
|
||||
<Divider orientation="vertical" />
|
||||
<Box textAlign={"center"}>
|
||||
<Text
|
||||
as={"span"}
|
||||
color={"#066123"}
|
||||
fontSize={"md"}
|
||||
fontWeight={500}
|
||||
>
|
||||
{parseFloat(
|
||||
data?.data?.userActivity?.loggedInWithInLastMonth
|
||||
?.number || 0
|
||||
).toLocaleString()}
|
||||
</Text>
|
||||
<Text fontSize={"11px"} fontWeight={500}>
|
||||
Users who logged in during the last month
|
||||
</Text>
|
||||
</Box>
|
||||
</HStack>
|
||||
</Box>
|
||||
<Box w={'50%'} bg={'#fff'} p={4} rounded={10} alignItems={'inherit'}>
|
||||
<Box display={'flex'} justifyContent={'end'}>
|
||||
<Select bg={'#0047170F'} w={'90px'} display={'flex'} alignItems={'center'} placeholder='Select' size='xs' rounded={5}>
|
||||
<option value='option1'>Option 1</option>
|
||||
<option value='option2'>Option 2</option>
|
||||
<option value='option3'>Option 3</option>
|
||||
<Box
|
||||
w={"50%"}
|
||||
bg={"#fff"}
|
||||
p={4}
|
||||
rounded={10}
|
||||
alignItems={"inherit"}
|
||||
>
|
||||
<Box display={"flex"} justifyContent={"end"}>
|
||||
<Select
|
||||
bg={"#0047170F"}
|
||||
w={"110px"}
|
||||
display={"flex"}
|
||||
alignItems={"center"}
|
||||
// placeholder="Select"
|
||||
size="xs"
|
||||
rounded={5}
|
||||
onChange={(e) => setFilter(e.target.value)}
|
||||
>
|
||||
<option value="today" selected>
|
||||
Today
|
||||
</option>
|
||||
<option value="last7days">Last 7 day's</option>
|
||||
<option value="last30days">Last 30 day's</option>
|
||||
</Select>
|
||||
</Box>
|
||||
<HStack justifyContent={'space-between'}>
|
||||
<Box textAlign={'center'}>
|
||||
<Text as={'span'} color={'#066123'} fontSize={'md'} fontWeight={500}>80%</Text>
|
||||
<Text fontSize={'11px'} fontWeight={500}>New KYC verification</Text>
|
||||
<HStack justifyContent={"space-between"}>
|
||||
<Box textAlign={"center"}>
|
||||
<Text
|
||||
as={"span"}
|
||||
color={"#066123"}
|
||||
fontSize={"md"}
|
||||
fontWeight={500}
|
||||
>
|
||||
{filter === "today"
|
||||
? data?.data?.userActivity?.newSignUps?.today
|
||||
: filter === "last7days"
|
||||
? data?.data?.userActivity?.newSignUps?.last7days
|
||||
: data?.data?.userActivity?.newSignUps?.last30days}
|
||||
</Text>
|
||||
<Text fontSize={"11px"} fontWeight={500}>
|
||||
New sign-ups{" "}
|
||||
</Text>
|
||||
</Box>
|
||||
<Divider orientation='vertical' />
|
||||
<Box textAlign={'center'}>
|
||||
<Text as={'span'} color={'#066123'} fontSize={'md'} fontWeight={500}>3,298</Text>
|
||||
<Text fontSize={'11px'} fontWeight={500}>Users who logged in </Text>
|
||||
<Divider orientation="vertical" />
|
||||
<Box textAlign={"center"}>
|
||||
<Text
|
||||
as={"span"}
|
||||
color={"#066123"}
|
||||
fontSize={"md"}
|
||||
fontWeight={500}
|
||||
>
|
||||
{filter === "today"
|
||||
? data?.data?.userActivity?.newKYCVerifications?.today
|
||||
: filter === "last7days"
|
||||
? data?.data?.userActivity?.newKYCVerifications?.last7days
|
||||
: data?.data?.userActivity?.newKYCVerifications
|
||||
?.last30days}
|
||||
</Text>
|
||||
<Text fontSize={"11px"} fontWeight={500}>
|
||||
New KYC verification
|
||||
</Text>
|
||||
</Box>
|
||||
</HStack>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box display={'flex'} gap={5}>
|
||||
<Box w={'50%'} bg={'#0047170F'} p={4} rounded={5}>
|
||||
<Heading fontSize={'md'} fontWeight={500}>Investment Opportunities</Heading>
|
||||
<Box display={"flex"} gap={5}>
|
||||
<Box w={"50%"} bg={"#0047170F"} p={4} rounded={5}>
|
||||
<Heading fontSize={"md"} fontWeight={500}>
|
||||
Investment Opportunities
|
||||
</Heading>
|
||||
<Divider />
|
||||
<Box mb={5} bg={'#fff'} py={2} rounded={4}>
|
||||
<HStack justifyContent={'space-between'} px={3} alignItems={'center'}>
|
||||
<Heading fontSize={'sm'} fontWeight={500} py={2} >Open Opportunities</Heading>
|
||||
<Link to={'/investment-opportunities'}><BsArrowsAngleContract fontSize={'18px'} /></Link>
|
||||
<Box mb={5} bg={"#fff"} py={2} rounded={4}>
|
||||
<HStack
|
||||
justifyContent={"space-between"}
|
||||
px={3}
|
||||
alignItems={"center"}
|
||||
mb={1}
|
||||
>
|
||||
<Heading fontSize={"sm"} fontWeight={500} py={1} mb={0}>
|
||||
Open Opportunities
|
||||
</Heading>
|
||||
<Link to={"/investment-opportunities"}>
|
||||
<BsArrowsAngleContract fontSize={"18px"} />
|
||||
</Link>
|
||||
</HStack>
|
||||
<Box h={'130px'} overflowY={'scroll'}>
|
||||
<InvestmentOpportunities showSearch={false} />
|
||||
<Box h={"150px"} overflowY={"scroll"} position={"relative"}>
|
||||
<InvestmentOpportunities
|
||||
showSearch={false}
|
||||
selectStyle={{
|
||||
right: "5px",
|
||||
marginBottom: "5px",
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<SimpleGrid columns={2} spacing={4}>
|
||||
{closedOpportunities.map((item, index) => (
|
||||
<Box key={index} bg="white" p={4} rounded={10}>
|
||||
<HStack alignItems={'center'}>
|
||||
<Text fontSize={'17px'} mb={0}>{item.icon}</Text>
|
||||
<Text mb={0} mt={0} fontSize={'11px'} fontWeight={500}>
|
||||
<HStack alignItems={"center"}>
|
||||
<Text fontSize={"17px"} mb={0}>
|
||||
{item.icon}
|
||||
</Text>
|
||||
<Text mb={0} mt={0} fontSize={"11px"} fontWeight={500}>
|
||||
{item.label}
|
||||
</Text>
|
||||
</HStack>
|
||||
<Text as="span" fontSize={'md'} fontWeight={700} mb={0}>
|
||||
<Text as="span" fontSize={"md"} fontWeight={700} mb={0}>
|
||||
{/* {parseFloat(item?.count || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})} */}
|
||||
{item.count}
|
||||
</Text>
|
||||
</Box>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
<Box w={'50%'} bg={'#0047170F'} p={4} rounded={5}>
|
||||
<Heading fontSize={'md'} fontWeight={500}>Wallet Balances</Heading>
|
||||
<Box w={"50%"} bg={"#0047170F"} p={4} rounded={5}>
|
||||
<Heading fontSize={"md"} fontWeight={500}>
|
||||
Wallet Balances
|
||||
</Heading>
|
||||
<Divider />
|
||||
<Box bg={'#fff'} p={4} rounded={4} mb={5}>
|
||||
<Text fontSize={'xxl'} fontWeight={600}>$ 50,000</Text>
|
||||
<Text fontSize={'md'} mb={0}>TOTAL CASH AVAILABLE ACROSS ALL WALLETS USD</Text>
|
||||
<Box bg={"#fff"} p={4} rounded={4} mb={5}>
|
||||
<Text fontSize={"xxl"} fontWeight={600} mb={2}>
|
||||
${" "}
|
||||
{parseFloat(
|
||||
data?.data?.walletBalance?.totalCashAvailAcrossAllUSD || 0
|
||||
).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
{/* {data?.data?.walletBalance?.totalCashAvailAcrossAllUSD} */}
|
||||
</Text>
|
||||
<Text fontSize={"md"} mb={0}>
|
||||
TOTAL CASH AVAILABLE ACROSS ALL WALLETS USD
|
||||
</Text>
|
||||
</Box>
|
||||
<Text fontSize={'sm'} mb={2}>Sum of users available wallet cash in</Text>
|
||||
<SimpleGrid columns={4} spacing={2} mb={4}>
|
||||
<Text fontSize={"sm"} mb={2}>
|
||||
Sum of users available wallet cash in
|
||||
</Text>
|
||||
<SimpleGrid columns={2} spacing={2} mb={4}>
|
||||
{walletCase.slice(0, 4).map((item, index) => (
|
||||
<Box key={index} bg={"#fff"} p={3} rounded={4}>
|
||||
<Text mb={1} fontSize={"md"} fontWeight={500}>
|
||||
@@ -223,7 +477,7 @@ const Dashbaord = ({ showSearch = false }) => {
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default Dashbaord
|
||||
export default Dashbaord;
|
||||
|
||||
@@ -1,122 +1,102 @@
|
||||
import {
|
||||
Box,
|
||||
HStack,
|
||||
Input,
|
||||
Select,
|
||||
Text,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useContext, useEffect, useState, useRef } from "react";
|
||||
import { Box, HStack, Input, Select, Text, useToast } from "@chakra-ui/react";
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
||||
import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
||||
import NormalTable from "../../Components/DataTable/NormalTable";
|
||||
|
||||
const formatDate = (date) => new Date(date).toLocaleDateString();
|
||||
|
||||
const InvestmentOpportunities = ({ showSearch = true }) => {
|
||||
const toast = useToast();
|
||||
const { opportunities, setOpportunities, slideFromRight } =
|
||||
useContext(GlobalStateContext);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||
const [actionId, setActionId] = useState(false);
|
||||
|
||||
// const {
|
||||
// data: bankDetails,
|
||||
// isLoading: bankDetailsLoading,
|
||||
// error,
|
||||
// } = useGetBankQuery({ page: 1, size: 10 });
|
||||
|
||||
useEffect(() => {
|
||||
// Simulate loading
|
||||
const timer = setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
}, 1500);
|
||||
|
||||
// Cleanup the timer on component unmount
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
// ====================================================[Table Setup]================================================================
|
||||
const tableHeadRow = [
|
||||
"Sr N/O",
|
||||
"Investors",
|
||||
"Amount remaining %",
|
||||
"Total deal size",
|
||||
// <Box display="flex" alignItems="center">
|
||||
// Total deal size
|
||||
// <Select ml={1} bg={"#fff"} w={"100px"} placeholder="Select" size="xs" rounded={5}
|
||||
// >
|
||||
// <option value="option1">1</option>
|
||||
// <option value="option2">2</option>
|
||||
// <option value="option3">3</option>
|
||||
// </Select>
|
||||
// </Box>,
|
||||
"No of views",
|
||||
];
|
||||
|
||||
// ====================================================[Table Filter]================================================================
|
||||
const filteredData = opportunities?.filter((item) => {
|
||||
// Filter by name (case insensitive)
|
||||
const name = item.Investors;
|
||||
const searchLower = searchTerm.toLowerCase();
|
||||
const nameMatches = name?.toLowerCase().includes(searchLower);
|
||||
|
||||
return nameMatches;
|
||||
});
|
||||
|
||||
|
||||
const extractedArray = filteredData?.map((item,index) => ({
|
||||
id: item?.id,
|
||||
"Sr N/O": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"gray.600"}
|
||||
className="d-flex align-items-center fw-bold web-text-small"
|
||||
>
|
||||
{item.id}
|
||||
import { useGetDashboardMasterQuery } from "../../Services/dashboard.service";
|
||||
import { generateSerialNumber } from "../../Constants/Constants";
|
||||
|
||||
const formatDate = (date) => new Date(date).toLocaleDateString();
|
||||
|
||||
const InvestmentOpportunities = ({ showSearch = true, selectStyle = {} }) => {
|
||||
const toast = useToast();
|
||||
const { opportunities, setOpportunities, slideFromRight } =
|
||||
useContext(GlobalStateContext);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||
const [actionId, setActionId] = useState(null);
|
||||
const [filter, setFilter] = useState(null);
|
||||
|
||||
const { data, error } = useGetDashboardMasterQuery();
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setIsLoading(false), 1500);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
const tableHeadRow = [
|
||||
"Sr No",
|
||||
"Investors",
|
||||
"Amount Remaining %",
|
||||
"Total Deal Size",
|
||||
"No of Views",
|
||||
];
|
||||
|
||||
const filteredData =
|
||||
data?.data?.investmentOpportunity?.openOpportunityDetails?.filter((item) =>
|
||||
item?.Investment_name?.toLowerCase().includes(searchTerm.toLowerCase())
|
||||
);
|
||||
|
||||
const extractedArray = filteredData?.map((item, index) => ({
|
||||
id: item?.id,
|
||||
"Sr No": (
|
||||
<Text
|
||||
w={"24px"}
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"gray.600"}
|
||||
className="d-flex align-items-center fw-bold web-text-small"
|
||||
>
|
||||
{index + 1}
|
||||
</Text>
|
||||
),
|
||||
Investors: (
|
||||
<Box w={"auto"} isTruncated>
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{item?.Investment_name}
|
||||
</Text>
|
||||
),
|
||||
"Investors": (
|
||||
<Box w={"auto"} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{item?.Investors}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Amount remaining %": (
|
||||
<Box w={"auto"} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{item?.amountRemaining}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Total deal size": (
|
||||
<Box w={"auto"} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{item?.totalDealsize}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"No of views": (
|
||||
<Box w={"auto"} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{item.noViews}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
}));
|
||||
|
||||
return (
|
||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"}>
|
||||
<Box bg="white.500">
|
||||
</Box>
|
||||
),
|
||||
"Amount Remaining %": (
|
||||
<Box w={"auto"} isTruncated>
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{`${parseFloat(item?.Amount_remaining_per || 0).toLocaleString()} %`}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Total Deal Size": (
|
||||
<Box w={"auto"} isTruncated>
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{`$ ${parseFloat(item?.Deal_size || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"No of Views": (
|
||||
<Box w={"auto"} isTruncated>
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{item?.Views_today}
|
||||
{filter === "today"
|
||||
? item?.Views_today
|
||||
: filter === "last7days"
|
||||
? item?.Views_last_7_days
|
||||
: item?.Views_mtd}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
}));
|
||||
|
||||
return (
|
||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"}>
|
||||
<Box bg="white.500" display="flex" justifyContent="space-between">
|
||||
{showSearch && (
|
||||
<HStack
|
||||
display={"flex"}
|
||||
justifyContent={"space-between"}
|
||||
display="flex"
|
||||
justifyContent="space-between"
|
||||
ps={1}
|
||||
pe={1}
|
||||
pb={4}
|
||||
@@ -136,26 +116,49 @@ import NormalTable from "../../Components/DataTable/NormalTable";
|
||||
/>
|
||||
</HStack>
|
||||
)}
|
||||
<Box display="flex" alignItems="center" justifyContent="end" w="100%">
|
||||
<Select
|
||||
{...selectStyle}
|
||||
// placeholder="Select"
|
||||
size="xs"
|
||||
rounded={2}
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
w={120}
|
||||
h="25px"
|
||||
_focus={{
|
||||
outline: "none",
|
||||
border: "1px solid #ccc",
|
||||
boxShadow: "none",
|
||||
}}
|
||||
onChange={(e) => setFilter(e.target.value)}
|
||||
>
|
||||
<option value="today" selected>
|
||||
Today
|
||||
</option>
|
||||
<option value="last7days">Last 7 day's</option>
|
||||
<option value="last30days">Last 30 day's</option>
|
||||
</Select>
|
||||
</Box>
|
||||
|
||||
<NormalTable
|
||||
emptyMessage={`We don't have any Details`}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={extractedArray}
|
||||
isLoading={isLoading}
|
||||
viewActionId={actionId}
|
||||
setViewActionId={setActionId}
|
||||
/>
|
||||
|
||||
<CustomAlertDialog
|
||||
onClose={() => setDeleteAlert(false)}
|
||||
isOpen={deleteAlert}
|
||||
message={"Are you sure you want to delete sponers?"}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default InvestmentOpportunities;
|
||||
|
||||
|
||||
<NormalTable
|
||||
emptyMessage={"We don't have any details"}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={extractedArray}
|
||||
isLoading={isLoading}
|
||||
viewActionId={actionId}
|
||||
setViewActionId={setActionId}
|
||||
/>
|
||||
|
||||
<CustomAlertDialog
|
||||
onClose={() => setDeleteAlert(false)}
|
||||
isOpen={deleteAlert}
|
||||
message={"Are you sure you want to delete this opportunity?"}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default InvestmentOpportunities;
|
||||
|
||||
@@ -37,7 +37,7 @@ export const nav = [
|
||||
{
|
||||
title: "Dashboard",
|
||||
type: "single",
|
||||
path: "/dashboard",
|
||||
path: "/",
|
||||
Icon: TbLayoutDashboard,
|
||||
},
|
||||
{
|
||||
|
||||
20
src/Services/dashboard.service.js
Normal file
20
src/Services/dashboard.service.js
Normal file
@@ -0,0 +1,20 @@
|
||||
// Need to use the React-specific entry point to import createApi
|
||||
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
|
||||
import { baseQuery } from "./token.serivce";
|
||||
|
||||
// Define a service using a base URL and expected endpoints
|
||||
export const dashboardMaster = createApi({
|
||||
reducerPath: "Dashboard",
|
||||
baseQuery: baseQuery,
|
||||
tagTypes: ["getDashboard"],
|
||||
endpoints: (builder) => ({
|
||||
// ======[Get All]=====
|
||||
|
||||
getDashboardMaster: builder.query({
|
||||
query: () => `/dashboard/admin/`,
|
||||
providesTags: ["getDashboard"],
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export const { useGetDashboardMasterQuery } = dashboardMaster;
|
||||
@@ -20,6 +20,7 @@ import { fawateerMaker } from "../Services/fawateer.maker.service";
|
||||
import { sabAdminMaster } from "../Services/subadmin.service";
|
||||
import { changePasswordMake } from "../Services/change.password.service";
|
||||
import { forgetPasswordMake } from "../Services/forget.password.service";
|
||||
import { dashboardMaster } from "../Services/dashboard.service";
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
@@ -41,6 +42,7 @@ export const store = configureStore({
|
||||
[sabAdminMaster.reducerPath]: sabAdminMaster.reducer,
|
||||
[changePasswordMake.reducerPath]: changePasswordMake.reducer,
|
||||
[forgetPasswordMake.reducerPath]: forgetPasswordMake.reducer,
|
||||
[dashboardMaster.reducerPath]: dashboardMaster.reducer,
|
||||
|
||||
// Add other reducers as needed
|
||||
},
|
||||
@@ -68,6 +70,7 @@ export const store = configureStore({
|
||||
sabAdminMaster.middleware,
|
||||
changePasswordMake.middleware,
|
||||
forgetPasswordMake.middleware,
|
||||
dashboardMaster.middleware,
|
||||
),
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user