admin pages Working👷‍♂️

This commit is contained in:
YasinShaikh123
2024-09-17 15:33:27 +05:30
parent ab175b4c76
commit a126d6515d
16 changed files with 968 additions and 194 deletions

View File

@@ -1368,6 +1368,28 @@ const GlobalStateProvider = ({ children }) => {
mailId: "john@gmail.com",
status: "Incompleted",
},
{
id: 10,
date: "02-Jan-2024",
clientId: "SA00000001",
firstName: "John",
lastName: "David",
country: "Saudi Arabia",
phoneNumber: "8940035906",
mailId: "john@gmail.com",
status: "Incompleted",
},
{
id: 10,
date: "02-Jan-2024",
clientId: "SA00000001",
firstName: "John",
lastName: "David",
country: "Saudi Arabia",
phoneNumber: "8940035906",
mailId: "john@gmail.com",
status: "Incompleted",
},
]);
const [manageAcademy, setManageAcademy] = useState([

View File

@@ -5,14 +5,6 @@ import {
Button,
HStack,
Input,
Menu,
MenuButton,
MenuItem,
MenuList,
Portal,
Select,
Switch,
Tag,
Text,
Tooltip,
useDisclosure,
@@ -22,11 +14,7 @@ import React, { useContext, useEffect, useState, useRef } from "react";
import { HiDotsVertical } from "react-icons/hi";
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
import {
AddIcon,
DeleteIcon,
EditIcon,
EmailIcon,
ViewIcon,
} from "@chakra-ui/icons";
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
import DataTable from "../../../Components/DataTable/DataTable";
@@ -77,7 +65,7 @@ const BankDetails = () => {
// ====================================================[Table Setup]================================================================
const tableHeadRow = [
// "Sr N/O",
"Sr N/O",
"Country name",
"Account Name",
"Account No",
@@ -131,7 +119,7 @@ const BankDetails = () => {
"Country name": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{item.country_xid}
{/* {item.country_xid} */}
</Text>
</Box>
),
@@ -161,7 +149,7 @@ const BankDetails = () => {
<Tooltip
rounded={"sm"}
fontSize={"xs"}
label="View"
label="Edit"
bg="#fff"
color={"green.500"}
placement="top"
@@ -228,7 +216,7 @@ const BankDetails = () => {
</Box>
<DataTable
emptyMessage={`We don't have any Sponers `}
emptyMessage={`We don't have any Details`}
tableHeadRow={tableHeadRow}
data={extractedArray}
isLoading={isLoading}

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React, { useContext, useEffect, useState } from "react";
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
import { Box, useToast } from "@chakra-ui/react";
import { useForm } from "react-hook-form";
@@ -11,6 +11,7 @@ import CustomAlertDialog from "../../../Components/CustomAlertDialog";
import SwitchButton from "../../../Components/SwitchButton";
import * as yup from "yup";
import { useGetBankQuery, useUpdateBankDetailsMutation } from "../../../Services/bank.details.service";
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
// import { useUpdateBankDetailsMutation, useGetBankQuery } from "../../../Services/investorDetails.service";
const editBankSchema = yup.object().shape({
@@ -28,6 +29,8 @@ const EditBankDetails = () => {
const id = params?.id;
const [isLoadingBtn, setIsLoadingBtn] = useState(false);
const { InvestorDetails, setInvestorDetails, slideFromRight } =
useContext(GlobalStateContext);
const [alert, setAlert] = useState(false);
const [form, setForm] = useState({});
const [isSwitchOn, setIsSwitchOn] = useState(false);
@@ -45,16 +48,19 @@ const EditBankDetails = () => {
});
useEffect(() => {
if (bankDetails) {
setInvestorDetails({
...bankDetails?.data,
});
if (bankDetails?.data) {
reset({
accountNumber: bankDetails.accountNumber,
swiftCode: bankDetails.swiftCode,
bankName: bankDetails.bankName,
bankAddress: bankDetails.bankAddress,
IBANnumber: bankDetails.IBANnumber,
accountNumber: bankDetails?.accountNumber,
swiftCode: bankDetails?.swiftCode,
bankName: bankDetails?.bankName,
bankAddress: bankDetails?.bankAddress,
IBANnumber: bankDetails?.IBANnumber,
});
}
}, [bankDetails, reset]);
}, [bankDetails, reset,id]);
if (isLoading) {
return <FullscreenLoaders />;
@@ -62,7 +68,6 @@ const EditBankDetails = () => {
const handleConfirm = async () => {
setIsLoadingBtn(true);
try {
const formData = {
...form,
@@ -91,6 +96,9 @@ const EditBankDetails = () => {
}
};
console.log(bankDetails?.accountNumber);
const formEditFields = [
{
label: "Country Name",
@@ -104,9 +112,10 @@ const EditBankDetails = () => {
},
{
label: "Account Name",
value:bankDetails?.accountNumber,
name: "accountName",
placeHolder: "Enter account name",
type: "text",
type: "number",
isRequired: true,
section: "Add Details",
maxLength: 255,
@@ -116,7 +125,7 @@ const EditBankDetails = () => {
label: "Account Number *",
name: "accountNumber",
placeHolder: "Enter account number",
type: "text",
type: "number",
section: "Add Details",
width: "32%",
},
@@ -130,6 +139,7 @@ const EditBankDetails = () => {
},
{
label: "SWIFT Code",
value: bankDetails?.data?.swiftCode,
name: "swiftCode",
placeHolder: "Enter SWIFT code",
type: "text",

View File

@@ -2,39 +2,25 @@ import {
Avatar,
Badge,
Box,
Button,
HStack,
Input,
Menu,
MenuButton,
MenuItem,
MenuList,
Portal,
Select,
Switch,
Tag,
Text,
Tooltip,
useDisclosure,
useToast,
} from "@chakra-ui/react";
import React, { useContext, useEffect, useState,useRef } from "react";
import { HiDotsVertical } from "react-icons/hi";
import { Link, Link as RouterLink,useNavigate } from "react-router-dom";
import {
AddIcon,
DeleteIcon,
EditIcon,
EmailIcon,
ViewIcon,
} from "@chakra-ui/icons";
import GlobalStateContext from "../../Contexts/GlobalStateContext";
import { debounce } from "../Master/Sponser/AddSponser";
import { OPACITY_ON_LOAD } from "../../Layout/animations";
import DataTable from "../../Components/DataTable/DataTable";
import CustomAlertDialog from "../../Components/CustomAlertDialog";
import Pagination from "../../Components/Pagination";
import ToastBox from "../../Components/ToastBox";
import React, { useContext, useEffect, useState, useRef } from "react";
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
import { debounce } from "../../../Master/Sponser/AddSponser";
import { OPACITY_ON_LOAD } from "../../../../Layout/animations";
import DataTable from "../../../../Components/DataTable/DataTable";
import CustomAlertDialog from "../../../../Components/CustomAlertDialog";
import Pagination from "../../../../Components/Pagination";
import ToastBox from "../../../../Components/ToastBox";
import ReasonBanModal from "./ReasonBanModal";
import { useGetbanInvestorQuery } from "../../../../Services/ban.investor.service";
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
@@ -50,8 +36,28 @@ const BankInvestor = () => {
const [actionId, setActionId] = useState(false);
const [mouseEntered, setMouseEntered] = useState(false);
const [mouseEnteredId, setMouseEnteredId] = useState("");
const {isOpen: isEditOpen,onOpen: onEditOpen,onClose: onEditClose,} = useDisclosure();
const btnRef = React.useRef()
const {
isOpen: isOpen,
onOpen: onOpen,
onClose: onClose,
} = useDisclosure();
const formatDate = (date) => {
return new Date(date).toLocaleDateString("en-GB", {
day: "2-digit",
month: "2-digit",
year: "numeric",
});
};
const {
data,
isLoading: unbanLoading,
error,
refetch
} = useGetbanInvestorQuery();
useEffect(() => {
// Simulate loading
@@ -66,6 +72,7 @@ const BankInvestor = () => {
// ====================================================[Table Setup]================================================================
const tableHeadRow = [
"Sr N/O",
"Date",
"Client ID",
"First Name",
"Last Name",
@@ -88,9 +95,9 @@ const BankInvestor = () => {
}, 300);
// ====================================================[Table Filter]================================================================
const filteredData = bankInvestor?.filter((item) => {
const filteredData = data?.data?.rows?.filter((item) => {
// Filter by name (case insensitive)
const name = item.firstName;
const name = item?.clientReference_id;
const searchLower = searchTerm.toLowerCase();
const nameMatches = name?.toLowerCase().includes(searchLower);
@@ -118,62 +125,82 @@ const BankInvestor = () => {
{item.id}
</Text>
),
"Date": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{formatDate(item?.principal?.createdAt)}
</Text>
</Box>
),
"Client ID": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{item.clientId}
{item?.clientReference_id}
</Text>
</Box>
),
"First Name": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{item.firstName}
{item?.principal?.firstName}
</Text>
</Box>
),
"Last Name": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{item.lastName}
{item?.principal?.lastName}
</Text>
</Box>
),
Country: (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{item.country}
{item?.country_xid}
</Text>
</Box>
),
"Phone Number": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{item.phoneNumber}
{item?.principal?.mobileNumber}
</Text>
</Box>
),
"E-mail ID": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{item.mailId}
{item?.principal?.emailAddress}
</Text>
</Box>
),
"KYC Status": (
<Box w={"auto"} isTruncated={true}>
<Badge fontWeight={'500'} textTransform={'none'} color={item.status === "Completed" ? "blue" : "red"} px={2} py={0.5}>
{item.status}
<Badge
fontWeight={"500"}
textTransform={"none"}
color={item.status === "Completed" ? "blue" : "red"}
px={2}
py={0.5}
>
{item?.KYCStatus}
</Badge>
</Box>
),
Action: (
<Switch
size={"sm"}
colorScheme="forestGreen"
onChange={() => handleUpdateStatus(item.id)}
isChecked={item.status}
/>
<Box w={"auto"} isTruncated={true}>
<Badge
cursor={"pointer"}
fontWeight={"500"}
textTransform={"none"}
colorScheme={"red"}
px={2}
py={0.5}
onClick={onOpen}
>
Ban Investor
</Badge>
</Box>
),
}));
@@ -196,7 +223,7 @@ const BankInvestor = () => {
};
return (
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
<Box {...OPACITY_ON_LOAD}>
<Box bg="white.500">
<HStack
display={"flex"}
@@ -208,7 +235,7 @@ const BankInvestor = () => {
spacing="24px"
>
<Input
mt={1}
mt={1}
type="search"
width={300}
placeholder="Search..."
@@ -219,7 +246,32 @@ const BankInvestor = () => {
onChange={(e) => setSearchTerm(e.target.value)}
/>
<HStack display={"flex"} alignItems={"center"}>
<Pagination totalItems={10} />
<Select
focusBorderColor="green.500"
size={"sm"}
fontSize={"xs"}
cursor={"pointer"}
placeholder='KYC Status'
w={180}
rounded={"md"}
>
<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"}
placeholder='Country'
w={180}
rounded={"md"}
>
<option value="all">All</option>
<option value="ban">Ban</option>
<option value="unban">UnBan</option>
</Select>
</HStack>
</HStack>
</Box>
@@ -242,6 +294,11 @@ const BankInvestor = () => {
alertHandler={handleDelete}
isLoading={isLoading}
/>
<ReasonBanModal
isOpen={isOpen}
onClose={onClose}
id={actionId}
/>
</Box>
);
};

View File

@@ -0,0 +1,27 @@
import { Box, Tab, TabList, TabPanel, TabPanels, Tabs } from "@chakra-ui/react";
import React from "react";
import BankInvestor from "./BankInvestor";
import UnbanInvestor from "../UnbanInvestor/UnbanInvestor";
const Investor = () => {
return (
<Box overflowY={"scroll"} height={"100vh"}>
<Tabs colorScheme="green" mt={3}>
<TabList>
<Tab fontSize={"sm"}>Unban Investor</Tab>
<Tab fontSize={"sm"}>Ban Investor</Tab>
</TabList>
<TabPanels>
<TabPanel>
<UnbanInvestor />
</TabPanel>
<TabPanel>
<BankInvestor />
</TabPanel>
</TabPanels>
</Tabs>
</Box>
);
};
export default Investor;

View File

@@ -0,0 +1,141 @@
import {
Box,
Button,
FormControl,
FormLabel,
Input,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
Text,
Textarea,
useDisclosure,
useToast,
} from "@chakra-ui/react";
import React, { useEffect, useState } from "react";
import * as yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";
import { useForm } from "react-hook-form";
import ToastBox from "../../../../Components/ToastBox";
import { useDepositRejectMutation } from "../../../../Services/drawal.request.service";
export const conformModalSchema = yup.object().shape({
comments: yup.string().required("Comment is required"),
});
const ReasonBanModal = ({ isOpen, onClose, firstField ,id}) => {
const [isBtnLoading , setIsBtnLoading] = useState(false)
const toast = useToast()
const {
register,
reset,
handleSubmit,
formState: { errors },
} = useForm({
resolver: yupResolver(conformModalSchema),
});
// const [ depositReject ] = useDepositRejectMutation()
const onSubmit = async(data) => {
setIsBtnLoading(true)
try {
const res = await depositReject({ id ,data})
if (res?.error) {
toast({
render: () => (
<ToastBox message={res?.error?.data?.message} status={"error"} />
),
});
heandleOnClose()
}else if(res?.data?.statusCode === 200) {
toast({
render: () => (
<ToastBox message={res?.data?.message} />
),
});
heandleOnClose()
}
} catch (error) {
console.log(error);
}
};
const heandleOnClose = () =>{
reset()
onClose()
setIsBtnLoading(false)
}
return (
<Modal isOpen={isOpen} onClose={heandleOnClose} initialFocusRef={firstField}>
<ModalOverlay />
<ModalContent pb={4}>
<ModalHeader fontSize={"md"}>Reason for Ban</ModalHeader>
<ModalCloseButton />
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
<ModalBody>
<FormControl mb={4} isRequired>
<FormLabel fontSize="sm">Comment</FormLabel>
<Textarea
rows={6}
focusBorderColor="green.400"
name="comments"
{...register("comments")}
fontSize="sm"
type="textarea"
size="md"
placeholder={"Enter your comments...."}
rounded={"md"}
resize={"none"}
/>
{errors.comments && (
<Text fontSize="xs" color="red">
{errors.comments.message}
</Text>
)}
</FormControl>
</ModalBody>
<ModalFooter>
<Button
colorScheme="gray"
mr={3}
onClick={onClose}
size={"sm"}
rounded={"sm"}
>
Cancel
</Button>
<Button
colorScheme="forestGreen"
variant="solid"
size={"sm"}
rounded={"sm"}
isLoading={isBtnLoading}
type="submit"
fontWeight={400}
>
Save
</Button>
</ModalFooter>
</Box>
</ModalContent>
</Modal>
);
};
export default ReasonBanModal;

View File

@@ -0,0 +1,145 @@
import {
Box,
Button,
FormControl,
FormLabel,
Input,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
Text,
Textarea,
useDisclosure,
useToast,
} from "@chakra-ui/react";
import React, { useEffect, useState } from "react";
import * as yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";
import { useForm } from "react-hook-form";
import ToastBox from "../../../../Components/ToastBox";
import { useDepositRejectMutation } from "../../../../Services/drawal.request.service";
import { useUpdateUnbanMutation } from "../../../../Services/ban.investor.service";
export const conformModalSchema = yup.object().shape({
comments: yup.string().required("Comment is required"),
});
const ReasonBanModal = ({ isOpen, onClose, firstField ,id}) => {
const [isBtnLoading , setIsBtnLoading] = useState(false)
const toast = useToast()
const {
register,
reset,
handleSubmit,
formState: { errors },
} = useForm({
resolver: yupResolver(conformModalSchema),
});
const [ updateUnban ] = useUpdateUnbanMutation()
console.log(updateUnban);
const onSubmit = async(data) => {
setIsBtnLoading(true)
try {
const res = await updateUnban({ id ,data})
if (res?.error) {
toast({
render: () => (
<ToastBox message={res?.error?.data?.message} status={"error"} />
),
});
heandleOnClose()
}else if(res?.data?.statusCode === 200) {
toast({
render: () => (
<ToastBox message={res?.data?.message} />
),
});
heandleOnClose()
}
} catch (error) {
console.log(error);
}
};
const heandleOnClose = () =>{
reset()
onClose()
setIsBtnLoading(false)
}
return (
<Modal isOpen={isOpen} onClose={heandleOnClose} initialFocusRef={firstField}>
<ModalOverlay />
<ModalContent pb={4}>
<ModalHeader fontSize={"md"}>Reason for Unban</ModalHeader>
<ModalCloseButton />
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
<ModalBody>
<FormControl mb={4} isRequired>
<FormLabel fontSize="sm">Comment</FormLabel>
<Textarea
rows={6}
focusBorderColor="green.400"
name="comments"
{...register("comments")}
fontSize="sm"
type="textarea"
size="md"
placeholder={"Enter your comments...."}
rounded={"md"}
resize={"none"}
/>
{errors.comments && (
<Text fontSize="xs" color="red">
{errors.comments.message}
</Text>
)}
</FormControl>
</ModalBody>
<ModalFooter>
<Button
colorScheme="gray"
mr={3}
onClick={onClose}
size={"sm"}
rounded={"sm"}
>
Cancel
</Button>
<Button
colorScheme="forestGreen"
variant="solid"
size={"sm"}
rounded={"sm"}
isLoading={isBtnLoading}
type="submit"
fontWeight={400}
>
Save
</Button>
</ModalFooter>
</Box>
</ModalContent>
</Modal>
);
};
export default ReasonBanModal;

View File

@@ -0,0 +1,294 @@
import {
Avatar,
Badge,
Box,
HStack,
Input,
Select,
Switch,
Text,
useDisclosure,
useToast,
} from "@chakra-ui/react";
import React, { useContext, useEffect, useState, useRef } from "react";
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
import GlobalStateContext from "../../../../Contexts/GlobalStateContext";
import { debounce } from "../../../Master/Sponser/AddSponser";
import { OPACITY_ON_LOAD } from "../../../../Layout/animations";
import DataTable from "../../../../Components/DataTable/DataTable";
import CustomAlertDialog from "../../../../Components/CustomAlertDialog";
import Pagination from "../../../../Components/Pagination";
import ToastBox from "../../../../Components/ToastBox";
import ReasonBanModal from "./ReasonBanModal";
import { useGetInvestorQuery, useGetUnbanInvestorQuery } from "../../../../Services/ban.investor.service";
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
const UnbanInvestor = () => {
const navigate = useNavigate();
const toast = useToast();
const thirdField = useRef();
const { bankInvestor, setBankInvestor, slideFromRight } =
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("");
const {
isOpen: isOpen,
onOpen: onOpen,
onClose: onClose,
} = useDisclosure();
const formatDate = (date) => {
return new Date(date).toLocaleDateString("en-GB", {
day: "2-digit",
month: "2-digit",
year: "numeric",
});
};
const {
data,isLoading: unbanLoading,error,refetch} = useGetUnbanInvestorQuery();
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",
"Date",
"Client ID",
"First Name",
"Last Name",
"Country",
"Phone Number",
"E-mail ID",
"KYC Status",
"Action",
];
const handleUpdateStatus = debounce((id) => {
setBankInvestor((prevData) =>
prevData.map((bankInvestor) =>
bankInvestor.id === id ? { ...bankInvestor } : bankInvestor
)
);
toast({
render: () => <ToastBox message={"Status changed succesfully.!"} />,
});
}, 300);
// ====================================================[Table Filter]================================================================
const filteredData = data?.data?.rows?.filter((item) => {
// Filter by name (case insensitive)
const name = item?.clientReference_id;
const searchLower = searchTerm.toLowerCase();
const nameMatches = name?.toLowerCase().includes(searchLower);
return nameMatches;
});
const extractedArray = filteredData?.map((item) => ({
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}
</Text>
),
"Date": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{formatDate(item?.principal?.createdAt)}
</Text>
</Box>
),
"Client ID": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{item?.clientReference_id}
</Text>
</Box>
),
"First Name": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{item?.principal?.firstName}
</Text>
</Box>
),
"Last Name": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{item?.principal?.lastName}
</Text>
</Box>
),
Country: (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{item?.country_xid}
</Text>
</Box>
),
"Phone Number": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{item?.principal?.mobileNumber}
</Text>
</Box>
),
"E-mail ID": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{item?.principal?.emailAddress}
</Text>
</Box>
),
"KYC Status": (
<Box w={"auto"} isTruncated={true}>
<Badge
fontWeight={"500"}
textTransform={"none"}
color={item?.KYCStatus === "Completed" ? "blue" : "red"}
px={2}
py={0.5}
>
{item?.KYCStatus}
</Badge>
</Box>
),
Action: (
<Box w={"auto"} isTruncated={true}>
<Badge
cursor={"pointer"}
fontWeight={"500"}
textTransform={"none"}
colorScheme={"red"}
px={2}
py={0.5}
onClick={onOpen}
>
Unban Investor
</Badge>
</Box>
),
}));
const handleDelete = () => {
const updatedInvestorDetails = InvestorDetails.filter(
(sponsor) => sponsor.id !== actionId
);
setTimeout(() => {
setInvestorDetails(updatedInvestorDetails);
setDeleteAlert(false);
setIsLoading(false);
}, 100);
setIsLoading(true);
};
const handleEdit = (id) => {
setActionId(id);
onEditOpen();
};
return (
<Box {...OPACITY_ON_LOAD}>
<Box bg="white.500">
<HStack
display={"flex"}
justifyContent={"space-between"}
ps={1}
pe={1}
pb={4}
pt={4}
spacing="24px"
>
<Input
mt={1}
type="search"
width={300}
placeholder="Search..."
size="sm"
rounded="sm"
focusBorderColor="green.500"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
<HStack display={"flex"} alignItems={"center"}>
<Select
focusBorderColor="green.500"
size={"sm"}
fontSize={"xs"}
cursor={"pointer"}
placeholder='KYC Status'
w={180}
rounded={"md"}
>
<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"}
placeholder='Country'
w={180}
rounded={"md"}
>
<option value="all">All</option>
<option value="ban">Ban</option>
<option value="unban">UnBan</option>
</Select>
</HStack>
</HStack>
</Box>
<DataTable
emptyMessage={`We don't have any Sponers `}
tableHeadRow={tableHeadRow}
data={extractedArray}
isLoading={isLoading}
viewActionId={actionId}
setViewActionId={setActionId}
setMouseEnteredId={setMouseEnteredId}
setMouseEntered={setMouseEntered}
/>
<CustomAlertDialog
onClose={() => setDeleteAlert(false)}
isOpen={deleteAlert}
message={"Are you sure you want to delete sponers?"}
alertHandler={handleDelete}
isLoading={isLoading}
/>
<ReasonBanModal
isOpen={isOpen}
onClose={onClose}
id={actionId}
/>
</Box>
);
};
export default UnbanInvestor;

View File

@@ -96,16 +96,8 @@ const schema = yup.object().shape({
.required("Expected return is required"),
});
const IODetails = ({ enableNextTab, index, data }) => {
const params = useParams();
const navigate = useNavigate();
const toast = useToast();
@@ -393,7 +385,7 @@ const IODetails = ({ enableNextTab, index, data }) => {
{
label: "Expected Return (Arabic)",
name: "expectedReturnArabic",
name: "expectedReturnArabic",
type: "text",
isRequired: true,
arabic: true,
@@ -685,7 +677,7 @@ const IODetails = ({ enableNextTab, index, data }) => {
setIsLoading(false);
toast({
render: () => <ToastBox message={res?.error?.data?.message } status={"error"} />,
});
});
} else if(res?.error?.status === 500){
setIsLoading(false);
toast({

View File

@@ -293,7 +293,7 @@ const EditViewIO = () => {
isRequired: true,
section: " ",
width: "32.3%",
},
},
{
label: "Name (Arabic)",
placeHolder: " ",

View File

@@ -19,13 +19,14 @@ import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
// ======================= [validation] =========================
export const addInvestmentType = yup.object().shape({
investmentTypeName: yup.string()
.required('Investment type is required')
.max(50, 'Investment name cannot be more than 50 characters'),
note: yup.string()
.optional()
.max(255, 'Note cannot exceed 255 characters'),
investmentTypeNameArabic: yup.string().required("Investment type in required"),
investmentTypeName: yup
.string()
.required("Investment type is required")
.max(50, "Investment name cannot be more than 50 characters"),
note: yup.string().optional().max(255, "Note cannot exceed 255 characters"),
investmentTypeNameArabic: yup
.string()
.required("Investment type in required"),
noteArabic: yup.string().notRequired(),
});
@@ -40,12 +41,11 @@ export function debounce(func, delay) {
}
const AddInvestmentType = () => {
const navigate = useNavigate();
const toast = useToast();
const params = useParams();
const id = params?.id;
console.log('hit');
console.log("hit");
// =====================[useState]=======================
@@ -54,8 +54,6 @@ const AddInvestmentType = () => {
const [alert, setAlert] = useState(false);
const [form, setForm] = useState();
const [createInvestmentType] = useCreateInvestmentTypeMutation();
const [updateInvestmentType] = useUpdateInvestmentTypeMutation();
@@ -71,9 +69,11 @@ const AddInvestmentType = () => {
resolver: yupResolver(addInvestmentType),
});
const { data: investmentTypeByIdData, error, isLoading, } = useGetInvestmentTypeByIdQuery(id, { skip: !id });
const {
data: investmentTypeByIdData,
error,
isLoading,
} = useGetInvestmentTypeByIdQuery(id, { skip: !id });
// ========================== [useEffect] ================================
@@ -86,7 +86,7 @@ const AddInvestmentType = () => {
note: investmentTypeByIdData?.data?.note,
noteArabic: investmentTypeByIdData?.data?.noteArabic,
});
setIsSwitchOn(investmentTypeByIdData?.data?.isActive)
setIsSwitchOn(investmentTypeByIdData?.data?.isActive);
}
}, [investmentTypeByIdData, reset]);
@@ -176,7 +176,9 @@ const AddInvestmentType = () => {
isRequired: true,
section: "Add Details",
maxLength: 50,
helperText:`Maximum length should be 50 characters. You have entered ${watch()?.investmentTypeName?.length || 0} characters.`
helperText: `Maximum length should be 50 characters. You have entered ${
watch()?.investmentTypeName?.length || 0
} characters.`,
},
{
label: "Investment Type (Arabic) ",
@@ -187,7 +189,9 @@ const AddInvestmentType = () => {
section: "Add Details",
arabic: true,
maxLength: 255,
helperText:`Maximum length should be 255 characters. You have entered ${watch()?.investmentTypeNameArabic?.length || 0} characters.`
helperText: `Maximum length should be 255 characters. You have entered ${
watch()?.investmentTypeNameArabic?.length || 0
} characters.`,
},
{
label: "Description (English)",
@@ -197,7 +201,9 @@ const AddInvestmentType = () => {
// isRequired: true,
section: "Add Details",
maxLength: 255,
helperText:`Maximum length should be 255 characters. You have entered ${watch()?.note?.length || 0} characters.`
helperText: `Maximum length should be 255 characters. You have entered ${
watch()?.note?.length || 0
} characters.`,
},
{
label: "Description (Arabic)",
@@ -208,7 +214,9 @@ const AddInvestmentType = () => {
arabic: true,
section: "Add Details",
maxLength: 255,
helperText:`Maximum length should be 255 characters. You have entered ${watch()?.noteArabic?.length || 0} characters.`
helperText: `Maximum length should be 255 characters. You have entered ${
watch()?.noteArabic?.length || 0
} characters.`,
},
];
@@ -223,7 +231,9 @@ const AddInvestmentType = () => {
isRequired: true,
section: "Add Details",
maxLength: 50,
helperText:`Maximum length should be 50 characters. You have entered ${watch()?.investmentTypeName?.length || 0} characters.`
helperText: `Maximum length should be 50 characters. You have entered ${
watch()?.investmentTypeName?.length || 0
} characters.`,
},
{
label: "Investment Type (Arabic)",
@@ -234,7 +244,9 @@ const AddInvestmentType = () => {
section: "Add Details",
arabic: true,
maxLength: 255,
helperText:`Maximum length should be 255 characters. You have entered ${watch()?.investmentTypeNameArabic?.length || 0} characters.`
helperText: `Maximum length should be 255 characters. You have entered ${
watch()?.investmentTypeNameArabic?.length || 0
} characters.`,
},
{
label: "Description (English)",
@@ -244,7 +256,9 @@ const AddInvestmentType = () => {
// isRequired: true,
section: "Add Details",
maxLength: 255,
helperText:`Maximum length should be 255 characters. You have entered ${watch()?.note?.length || 0} characters.`
helperText: `Maximum length should be 255 characters. You have entered ${
watch()?.note?.length || 0
} characters.`,
},
{
label: "Description (Arabic)",
@@ -255,7 +269,9 @@ const AddInvestmentType = () => {
arabic: true,
section: "Add Details",
maxLength: 255,
helperText:`Maximum length should be 255 characters. You have entered ${watch()?.noteArabic?.length || 0} characters.`
helperText: `Maximum length should be 255 characters. You have entered ${
watch()?.noteArabic?.length || 0
} characters.`,
},
];
@@ -281,7 +297,6 @@ const AddInvestmentType = () => {
return groups;
}, {});
// ==================== [On Submit] ========================
const onSubmit = async (data) => {
@@ -292,39 +307,37 @@ const AddInvestmentType = () => {
}
};
return (
isLoading ? <FullscreenLoaders /> :
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
{/* ===================== [Switch Button] ======================== */}
<Box mt={5} display={"flex"} justifyContent={"right"} mr={5}>
<SwitchButton isSwitchOn={isSwitchOn} setIsSwitchOn={setIsSwitchOn} />
</Box>
{/* ====================== [Form Input] ====================== */}
<FormInputMain
groupedFields={params?.id ? groupedEditFields : groupedFields}
control={control}
errors={errors}
onSubmit={handleSubmit(onSubmit)}
submitTitle={params?.id ? "Update" : "Submit"}
// btnLoading={isLoadingBtn}
>
</FormInputMain>
{/* ======================= [Modal] =========================== */}
<CustomAlertDialog
isOpen={alert}
onClose={() => setAlert(false)}
alertHandler={handleConfirm}
message={"Are you sure you want to add this?"}
isLoading={isLoadingBtn}
/>
return isLoading ? (
<FullscreenLoaders />
) : (
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
{/* ===================== [Switch Button] ======================== */}
<Box mt={5} display={"flex"} justifyContent={"right"} mr={5}>
<SwitchButton isSwitchOn={isSwitchOn} setIsSwitchOn={setIsSwitchOn} />
</Box>
{/* ====================== [Form Input] ====================== */}
<FormInputMain
groupedFields={params?.id ? groupedEditFields : groupedFields}
control={control}
errors={errors}
onSubmit={handleSubmit(onSubmit)}
submitTitle={params?.id ? "Update" : "Submit"}
// btnLoading={isLoadingBtn}
></FormInputMain>
{/* ======================= [Modal] =========================== */}
<CustomAlertDialog
isOpen={alert}
onClose={() => setAlert(false)}
alertHandler={handleConfirm}
message={"Are you sure you want to add this?"}
isLoading={isLoadingBtn}
/>
</Box>
);
};

View File

@@ -12,23 +12,29 @@ import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
import SwitchButton from "../../../Components/SwitchButton";
import DummyComponent from "../../../Components/DummyComponent";
import { useCreateSponserMutation, useGetSponserByIdQuery, useUpdateSponserMutation } from "../../../Services/io.service";
import {
useCreateSponserMutation,
useGetSponserByIdQuery,
useUpdateSponserMutation,
} from "../../../Services/io.service";
// ======================= [validation] =========================
export const addSponser = yup.object().shape({
sponsorName: yup.
string()
.required('Sponsor Name is required')
.min(3, 'Sponsor Name must be at least 3 characters long')
.max(50, 'Investment Type Name cannot exceed 50 characters'),
sponsorNameArabic: yup.string().required("Sponser name in arabic is required"),
sponsorName: yup
.string()
.required("Sponsor Name is required")
.min(3, "Sponsor Name must be at least 3 characters long")
.max(50, "Investment Type Name cannot exceed 50 characters"),
sponsorNameArabic: yup
.string()
.required("Sponser name in arabic is required"),
email: yup.string().email("Invalid email address").notRequired(),
// .test("emailValidity", "Email address is invalid", async function (value) {
// if (!value) {
// return true; // Allow if the field is empty
// }
// return await checkEmailValidity(value);
// }),
// .test("emailValidity", "Email address is invalid", async function (value) {
// if (!value) {
// return true; // Allow if the field is empty
// }
// return await checkEmailValidity(value);
// }),
});
// ==================== [debounce] ========================
@@ -42,13 +48,12 @@ export function debounce(func, delay) {
}
const AddSponser = () => {
const toast = useToast();
const params = useParams();
const navigate = useNavigate();
const id = params?.id;
// =====================[useState]=======================
// =====================[useState]=======================
const [isLoadingBtn, setIsLoadingBtn] = useState(false);
const [alert, setAlert] = useState(false);
@@ -59,7 +64,11 @@ const AddSponser = () => {
const [updateSponser] = useUpdateSponserMutation();
// Fetch sponsor data only if id exists
const {data: sponserByIdData,error,isLoading,} = useGetSponserByIdQuery(id, {skip: !id,});
const {
data: sponserByIdData,
error,
isLoading,
} = useGetSponserByIdQuery(id, { skip: !id });
// ======================== [validators] ===========================
@@ -71,10 +80,9 @@ const AddSponser = () => {
reset,
} = useForm({
resolver: yupResolver(addSponser),
});
// ========================== [useEffect] ================================
// ========================== [useEffect] ================================
useEffect(() => {
if (sponserByIdData?.data) {
@@ -83,14 +91,12 @@ const AddSponser = () => {
sponsorNameArabic: sponserByIdData?.data?.sponsorNameArabic,
email: sponserByIdData?.data?.email,
});
setIsSwitchOn(sponserByIdData?.data?.isActive)
setIsSwitchOn(sponserByIdData?.data?.isActive);
console.log(sponserByIdData?.data?.isActive);
}
}, [sponserByIdData, reset]);
// console.log(isSwitchOn);
if (false) {
return <FullscreenLoaders />;
@@ -106,11 +112,11 @@ const AddSponser = () => {
const formData = {
...form,
isActive: isSwitchOn,
};
// Remove email field if it's an empty string
if (formData.email === '') {
delete formData.email;
}
};
// Remove email field if it's an empty string
if (formData.email === "") {
delete formData.email;
}
await updateSponser({ data: formData, id }).then((response) => {
if (response?.data?.statusCode) {
toast({
@@ -120,15 +126,18 @@ const AddSponser = () => {
setIsLoadingBtn(false);
setAlert(false);
navigate("/sponser");
} else if(response?.error?.status === 400) {
} else if (response?.error?.status === 400) {
toast({
render: () => (
<ToastBox message={response?.error?.data?.message} status={"error"} />
<ToastBox
message={response?.error?.data?.message}
status={"error"}
/>
),
});
setIsLoadingBtn(false);
setAlert(false)
setAlert(false);
}
});
} catch (error) {
@@ -144,22 +153,25 @@ const AddSponser = () => {
};
await createSponser(formData).then((response) => {
console.log(response);
if (response?.data?.statusCode === 201 ) {
if (response?.data?.statusCode === 201) {
toast({
render: () => <ToastBox message={response?.data?.message} />,
});
setIsLoadingBtn(false);
navigate("/sponser");
} else if(response?.error?.status === 400) {
} else if (response?.error?.status === 400) {
toast({
render: () => (
<ToastBox message={response?.error?.data?.message} status={"error"} />
<ToastBox
message={response?.error?.data?.message}
status={"error"}
/>
),
});
setIsLoadingBtn(false);
setAlert(false)
setAlert(false);
}
});
} catch (error) {
@@ -171,7 +183,7 @@ const AddSponser = () => {
}
};
// ====================== [Update Form Object] =========================
// ====================== [Update Form Object] =========================
const formFields = [
{
@@ -181,8 +193,10 @@ const AddSponser = () => {
type: "text",
isRequired: true,
section: "",
maxLength:50,
helperText:`Maximum length should be 50 characters. You have entered ${watch()?.sponsorName?.length || 0} characters.`
maxLength: 50,
helperText: `Maximum length should be 50 characters. You have entered ${
watch()?.sponsorName?.length || 0
} characters.`,
},
{
label: "Sponsor name (Arabic)",
@@ -193,8 +207,10 @@ const AddSponser = () => {
section: "",
arabic: true,
right: true,
maxLength:55,
helperText:`Maximum length should be 55 characters. You have entered ${watch()?.sponsorNameArabic?.length || 0} characters.`
maxLength: 55,
helperText: `Maximum length should be 55 characters. You have entered ${
watch()?.sponsorNameArabic?.length || 0
} characters.`,
},
{
label: "Email address",
@@ -216,8 +232,10 @@ const AddSponser = () => {
type: "text",
isRequired: true,
section: "",
maxLength:55,
helperText:`Maximum length should be 55 characters. You have entered ${watch()?.sponsorName?.length || 0} characters.`
maxLength: 55,
helperText: `Maximum length should be 55 characters. You have entered ${
watch()?.sponsorName?.length || 0
} characters.`,
},
{
label: "Sponsor name (Arabic)",
@@ -227,8 +245,10 @@ const AddSponser = () => {
isRequired: true,
section: "",
arabic: true,
maxLength:55,
helperText:`Maximum length should be 55 characters. You have entered ${watch()?.sponsorNameArabic?.length || 0} characters.`
maxLength: 55,
helperText: `Maximum length should be 55 characters. You have entered ${
watch()?.sponsorNameArabic?.length || 0
} characters.`,
},
{
label: "Email adress",
@@ -240,7 +260,7 @@ const AddSponser = () => {
},
];
// ====================== [Group Create Fields] =========================
// ====================== [Group Create Fields] =========================
const groupedEditFields = formEditFields.reduce((groups, field) => {
const { section } = field;
@@ -271,17 +291,16 @@ const AddSponser = () => {
}
};
return (
isLoading?<FullscreenLoaders/>:
return isLoading ? (
<FullscreenLoaders />
) : (
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
{/* ===================== [Switch Button] ======================== */}
{/* ===================== [Switch Button] ======================== */}
<Box mt={5} display={"flex"} justifyContent={"right"} mr={5}>
<SwitchButton isSwitchOn={isSwitchOn} setIsSwitchOn={setIsSwitchOn} />
</Box>
{/* ====================== [Form Input] ====================== */}
<FormInputMain
@@ -291,7 +310,7 @@ const AddSponser = () => {
onSubmit={handleSubmit(onSubmit)}
submitTitle={params?.id ? "Update" : "Submit"}
></FormInputMain>
{/* ======================= [Modal] =========================== */}
<CustomAlertDialog
@@ -302,7 +321,7 @@ const AddSponser = () => {
isLoading={isLoadingBtn}
/>
{/* <DummyComponent /> */}
{/* <DummyComponent /> */}
</Box>
);
};

View File

@@ -113,6 +113,7 @@ const PendingRequest = () => {
"Last Name",
"Country",
// "Phone Number",
"Wallet Balance",
"Withdrawal Amount",
// "Currency",
// "Withdrawal Amount",
@@ -205,6 +206,17 @@ const PendingRequest = () => {
// </Text>
// </Box>
// ),
"Wallet Balance": (
<Box w={"100px"} isTruncated={true} display={'flex'} justifyContent={'end'}>
<Text as={"span"} color={"teal.900"}>
{/* {item.investorAmount} */}
{parseFloat(item?.wallet_balance || 0).toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})}<Badge ms={1} colorScheme="green">{item?.currencyCode}</Badge>
</Text>
</Box>
),
"Withdrawal Amount": (
<Box w={"100px"} isTruncated={true} display={'flex'} justifyContent={'end'}>
<Text as={"span"} color={"teal.900"}>

View File

@@ -2,7 +2,6 @@
import DeletionHistory from "../Pages/AccountDeletion/DeletionHistory";
import DeletionRequest from "../Pages/AccountDeletion/DeletionRequest";
import BankDetails from "../Pages/Admin/BankDetails/BankDetails";
import BankInvestor from "../Pages/Admin/BankInvestor";
import Contact from "../Pages/Admin/Contact";
import Notification from "../Pages/Admin/Notification";
import Users from "../Pages/Admin/Users";
@@ -35,6 +34,9 @@ import Welcome from "../Pages/PaymentSuccess";
import Dashbaord from "../Pages/Dashbaord";
import UnderConstruction from "../Pages/UnderConstruction";
import PendingRequest from "../Pages/WithDrawal/DrawalRequest/PendingRequest";
import BankInvestor from "../Pages/Admin/Investor/BankInvestor/BankInvestor";
import Investor from "../Pages/Admin/Investor/BankInvestor/Investor";
import UnbanInvestor from "../Pages/Admin/Investor/UnbanInvestor/UnbanInvestor";
export const RouteLink = [
// =============[ Tanami ]================
@@ -92,14 +94,16 @@ export const RouteLink = [
{ path: "/deletion-history", Component: DeletionHistory },
// ===============[ Admin]===============
// { path: "/bank-investor", Component: BankInvestor },
{ path: "/bank-investor", Component: UnderConstruction },
{ path: "/bank-investor", Component: Investor },
{ path: "/ban-investor", Component: BankInvestor },
{ path: "/unban-investor", Component: UnbanInvestor },
// { path: "/bank-investor", Component: UnderConstruction },
// { path: "/academy", Component: Academy },
{ path: "/academy", Component: UnderConstruction },
// { path: "/notification", Component: Notification },
{ path: "/notification", Component: UnderConstruction },
// { path: "/contact", Component: Contact },
{ path: "/contact", Component: UnderConstruction },
{ path: "/contact", Component: Contact },
// { path: "/contact", Component: UnderConstruction },
{ path: "/users", Component: Users },
// { path: "/users", Component: UnderConstruction },
{ path: "/bank-details", Component: BankDetails },

View File

@@ -0,0 +1,47 @@
// investorDetails.service.js
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
// import { api } from "./api.service";
import { baseQuery } from "./token.serivce";
// const baseUrl = api?.defaults.baseURL;
// Define a service using a base URL and expected endpoints
export const banInvestorDetails = createApi({
reducerPath: "banInvestorDetails",
baseQuery: baseQuery,
tagTypes: ["getBanInvestor", "getUnbanInvestor"],
endpoints: (builder) => ({
getInvestor: builder.query({
query: () => `/investorDetails/admin`,
providesTags: ["getBanInvestor"],
}),
getUnbanInvestor: builder.query({
query: () => `/investorDetails/admin/getAllUnbanned`,
providesTags: ["getBanInvestor"],
}),
getbanInvestor: builder.query({
query: () => `/investorDetails/admin/getAllBanned`,
providesTags: ["getBanInvestor"],
}),
updateUnban: builder.mutation({
query: ({ id, data }) => ({
url: `/investorDetails/admin/unBanById/${id}`,
method: "PATCH",
body: data,
}),
invalidatesTags: ["getBanInvestor"],
}),
}),
});
// Export hooks for usage in functional components
export const {
useGetUnbanInvestorQuery,
useGetInvestorQuery,
useGetbanInvestorQuery,
useUpdateUnbanMutation,
} = banInvestorDetails;

View File

@@ -14,6 +14,7 @@ import { depositRequest } from "../Services/deposit.request.service";
import { apiSlice, baseQuery } from "../Services/token.serivce";
import { drawalRequest } from "../Services/drawal.request.service";
import { deleteRequest } from "../Services/delete.request.service";
import { banInvestorDetails } from "../Services/ban.investor.service";
export const store = configureStore({
reducer: {
@@ -29,6 +30,7 @@ export const store = configureStore({
[depositRequest.reducerPath]: depositRequest.reducer,
[drawalRequest.reducerPath]: drawalRequest.reducer,
[deleteRequest.reducerPath]: deleteRequest.reducer,
[banInvestorDetails.reducerPath]: banInvestorDetails.reducer,
// Add other reducers as needed
},
middleware: (getDefaultMiddleware) =>
@@ -49,6 +51,7 @@ export const store = configureStore({
depositRequest.middleware,
drawalRequest.middleware,
deleteRequest.middleware,
banInvestorDetails.middleware,
),
});