update
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
Skeleton,
|
||||
TableCaption,
|
||||
Checkbox,
|
||||
Radio,
|
||||
} from "@chakra-ui/react";
|
||||
import EmptySearchList from "../EmptySearchList";
|
||||
import { TABLE_PAGINATION } from "../../Constants/Paginations";
|
||||
@@ -24,6 +25,11 @@ const NormalTable = ({
|
||||
showRadioButton, // Prop for showing the checkboxes
|
||||
selectedRadio,
|
||||
setSelectedRadio, // State for managing selected checkboxes
|
||||
|
||||
handleCheckboxChange: radioChange,
|
||||
|
||||
|
||||
radio
|
||||
}) => {
|
||||
const columnWidth =
|
||||
data && data[0]
|
||||
@@ -31,17 +37,17 @@ const NormalTable = ({
|
||||
: "auto";
|
||||
|
||||
// Toggle checkbox selection for individual rows
|
||||
const handleCheckboxChange = (value) => {
|
||||
setSelectedRadio((prev) => {
|
||||
if (prev.includes(value)) {
|
||||
// Remove if already selected
|
||||
return prev.filter((id) => id !== value);
|
||||
} else {
|
||||
// Add to selected
|
||||
return [...prev, value];
|
||||
}
|
||||
});
|
||||
};
|
||||
// const handleCheckboxChange = (value) => {
|
||||
// setSelectedRadio((prev) => {
|
||||
// if (prev.includes(value)) {
|
||||
// // Remove if already selected
|
||||
// return prev.filter((id) => id !== value);
|
||||
// } else {
|
||||
// // Add to selected
|
||||
// return [...prev, value];
|
||||
// }
|
||||
// });
|
||||
// };
|
||||
|
||||
// Handle "Check All" checkbox
|
||||
const handleCheckAllChange = () => {
|
||||
@@ -53,6 +59,26 @@ const NormalTable = ({
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
const handleCheckboxChange = (value) => {
|
||||
if (radio) {
|
||||
// If radio is true, select only one option
|
||||
setSelectedRadio([value]); // Set the selected radio to this value only
|
||||
} else {
|
||||
// Handle multiple selection for checkboxes
|
||||
setSelectedRadio((prev) => {
|
||||
if (prev.includes(value)) {
|
||||
// Remove if already selected
|
||||
return prev.filter((id) => id !== value);
|
||||
} else {
|
||||
// Add to selected
|
||||
return [...prev, value];
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<TableContainer overflowX={"auto"} className="h-auto w-100 table-scroll">
|
||||
{data?.length === 0 ? (
|
||||
@@ -64,7 +90,7 @@ const NormalTable = ({
|
||||
</TableCaption>
|
||||
<Thead bg="forestGreen.100">
|
||||
<Tr>
|
||||
{showRadioButton && (
|
||||
{showRadioButton &&(
|
||||
<Th
|
||||
color={"purple.900"}
|
||||
textAlign={"center"}
|
||||
@@ -74,12 +100,12 @@ const NormalTable = ({
|
||||
overflowWrap="normal"
|
||||
textTransform={"none"}
|
||||
>
|
||||
<Checkbox
|
||||
isChecked={selectedRadio?.length === data?.length}
|
||||
onChange={handleCheckAllChange}
|
||||
colorScheme="forestGreen"
|
||||
{radio? "Select":<Checkbox
|
||||
isChecked={selectedRadio?.length === data?.length}
|
||||
onChange={handleCheckAllChange}
|
||||
colorScheme="forestGreen"
|
||||
|
||||
/>
|
||||
/>}
|
||||
</Th>
|
||||
)}
|
||||
{tableHeadRow.map((heading, index) => (
|
||||
@@ -135,13 +161,19 @@ const NormalTable = ({
|
||||
>
|
||||
{showRadioButton && (
|
||||
<Td textAlign={"center"}>
|
||||
<Checkbox
|
||||
{radio ? <Radio
|
||||
bg={"#fff"}
|
||||
colorScheme="forestGreen"
|
||||
value={item.id}
|
||||
isChecked={selectedRadio.includes(item.id)}
|
||||
onChange={() => radioChange(item.id, item)}
|
||||
/>:<Checkbox
|
||||
bg={"#fff"}
|
||||
colorScheme="forestGreen"
|
||||
value={item.id}
|
||||
isChecked={selectedRadio.includes(item.id)}
|
||||
onChange={() => handleCheckboxChange(item.id)}
|
||||
/>
|
||||
/>}
|
||||
</Td>
|
||||
)}
|
||||
{tableHeadRow.map((heading, i) => (
|
||||
|
||||
216
src/Pages/Fawateer/CreateRequest.jsx
Normal file
216
src/Pages/Fawateer/CreateRequest.jsx
Normal file
@@ -0,0 +1,216 @@
|
||||
import React, { useState } from "react";
|
||||
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||
import { Box, Button, HStack, Input, InputGroup, InputRightAddon, InputRightElement, Textarea, useDisclosure } from "@chakra-ui/react";
|
||||
import {
|
||||
FormControl,
|
||||
FormLabel,
|
||||
FormErrorMessage,
|
||||
FormHelperText,
|
||||
} from "@chakra-ui/react";
|
||||
import { ArrowForwardIcon, Search2Icon } from "@chakra-ui/icons";
|
||||
import SelectInvestorModal from "./SelectInvestorModal";
|
||||
import { useForm } from "react-hook-form"; // Import useForm
|
||||
import { yupResolver } from "@hookform/resolvers/yup"; // Import resolver for Yup
|
||||
import * as Yup from "yup"; // Import Yup for validation
|
||||
|
||||
|
||||
|
||||
// Validation schema using Yup
|
||||
const validationSchema = Yup.object().shape({
|
||||
investorName: Yup.string().required("Investor name is required"),
|
||||
clientId: Yup.string().required("Client ID is required"),
|
||||
date: Yup.date().required("Date is required").max(new Date(), "Date cannot be in the future"),
|
||||
amount: Yup.number().required("Amount is required").positive("Amount must be positive"),
|
||||
supportFile: Yup.mixed().required("Support file is required"),
|
||||
description: Yup.string().required("Description is required"),
|
||||
});
|
||||
|
||||
const CreateRequest = () => {
|
||||
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||
const [ selectedInvestor, setSelectorInvestor] = useState({})
|
||||
|
||||
// Initialize useForm with the resolver for Yup validation
|
||||
const { register, handleSubmit, setValue, formState: { errors } } = useForm({
|
||||
resolver: yupResolver(validationSchema),
|
||||
});
|
||||
|
||||
|
||||
// Handle form submission
|
||||
const onSubmit = (data) => {
|
||||
console.log(data); // Form data
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||
{/* <HStack ps={1} mb={2} pe={4} w={'100%'} justifyContent={'space-between'}>
|
||||
<Button
|
||||
rightIcon={<Search2Icon />}
|
||||
colorScheme="forestGreen"
|
||||
size={"sm"}
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
variant={'ghost'}
|
||||
mt={3}
|
||||
onClick={()=>onOpen()}
|
||||
>Search Investor</Button>
|
||||
</HStack> */}
|
||||
<Box
|
||||
display={"flex"}
|
||||
justifyContent={"space-between"}
|
||||
flexWrap={'wrap'}
|
||||
alignItems={"center"}
|
||||
mt={5}
|
||||
px={4}
|
||||
as="form"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
>
|
||||
<FormControl w={"49%"} mb={2}>
|
||||
<FormLabel isInvalid={errors.investorName} textAlign={"left"} fontSize={"xs"} color={"gray.600"}>
|
||||
Investor name
|
||||
</FormLabel>
|
||||
<InputGroup size='sm'>
|
||||
<Input
|
||||
bg={"#F5F8F6"}
|
||||
focusBorderColor="forestGreen.300"
|
||||
size={"sm"}
|
||||
fontSize={"sm"}
|
||||
rounded={"sm"}
|
||||
type={"text"}
|
||||
readOnly={true}
|
||||
placeholder={"Investor name"}
|
||||
|
||||
{...register("investorName")} // Register the field
|
||||
_placeholder={{ fontSize: "sm" }}
|
||||
// value={`${selectedInvestor?.principal?.firstName} ${selectedInvestor?.principal?.lastName}`}
|
||||
/>
|
||||
<InputRightAddon gap={2} color={'forestgreen.400'} onClick={onOpen} cursor={'pointer'} fontWeight={600} fontSize={'xs'}><Search2Icon /> Search</InputRightAddon>
|
||||
</InputGroup>
|
||||
|
||||
<FormHelperText as={'span'} fontSize={'xs'} fontWeight={500} style={{ color: "red" }} >{errors.investorName?.message}</FormHelperText>
|
||||
</FormControl>
|
||||
|
||||
|
||||
|
||||
|
||||
<FormControl isInvalid={errors.clientId} w={"49%"} mb={2}>
|
||||
<FormLabel textAlign={"left"} fontSize={"xs"} color={"gray.600"}>
|
||||
Client Id
|
||||
</FormLabel>
|
||||
<Input
|
||||
bg={"#F5F8F6"}
|
||||
focusBorderColor="forestGreen.300"
|
||||
size={"sm"}
|
||||
fontSize={"sm"}
|
||||
rounded={"sm"}
|
||||
type={"text"}
|
||||
readOnly={true}
|
||||
placeholder={"Client ID"}
|
||||
_placeholder={{ fontSize: "sm" }}
|
||||
|
||||
{...register("clientId")} // Register the field
|
||||
// value={selectedInvestor?.clientReference_id}
|
||||
/>
|
||||
|
||||
<FormHelperText as={'span'} fontSize={'xs'} fontWeight={500} style={{ color: "red" }} >{errors.clientId?.message}</FormHelperText>
|
||||
</FormControl>
|
||||
|
||||
|
||||
{/* Date */}
|
||||
<FormControl w={"49%"} mb={2} isInvalid={errors.date}>
|
||||
<FormLabel textAlign={"left"} fontSize={"xs"} color={"gray.600"}>
|
||||
Date
|
||||
</FormLabel>
|
||||
<Input
|
||||
bg={"#F5F8F6"}
|
||||
focusBorderColor="forestGreen.300"
|
||||
size={"sm"}
|
||||
fontSize={"sm"}
|
||||
rounded={"sm"}
|
||||
type={"date"}
|
||||
placeholder={"Date"}
|
||||
{...register("date")} // Register the field
|
||||
max={new Date().toISOString().split("T")[0]} // Disable future dates
|
||||
/>
|
||||
|
||||
<FormHelperText as={'span'} fontSize={'xs'} fontWeight={500} style={{ color: "red" }} >{errors.date?.message}</FormHelperText>
|
||||
</FormControl>
|
||||
|
||||
|
||||
{/* Amount */}
|
||||
<FormControl w={"49%"} mb={2} isInvalid={errors.amount}>
|
||||
<FormLabel textAlign={"left"} fontSize={"xs"} color={"gray.600"}>
|
||||
Amount
|
||||
</FormLabel>
|
||||
<Input
|
||||
bg={"#F5F8F6"}
|
||||
focusBorderColor="forestGreen.300"
|
||||
size={"sm"}
|
||||
fontSize={"sm"}
|
||||
rounded={"sm"}
|
||||
type={'number'}
|
||||
placeholder={"Amount"}
|
||||
{...register("amount")} // Register the field
|
||||
/>
|
||||
|
||||
<FormHelperText as={'span'} fontSize={'xs'} fontWeight={500} style={{ color: "red" }} >{errors.amount?.message}</FormHelperText>
|
||||
</FormControl>
|
||||
{/* Support file */}
|
||||
<FormControl w={"49%"} mb={2} isInvalid={errors.supportFile}>
|
||||
<FormLabel textAlign={"left"} fontSize={"xs"} color={"gray.600"}>
|
||||
Support file
|
||||
</FormLabel>
|
||||
<Input
|
||||
bg={"#F5F8F6"}
|
||||
focusBorderColor="forestGreen.300"
|
||||
size={"sm"}
|
||||
fontSize={"sm"}
|
||||
rounded={"sm"}
|
||||
type={"file"}
|
||||
className="form-control"
|
||||
placeholder={"Support file"}
|
||||
{...register("supportFile")} // Register the field
|
||||
onChange={(e) => setValue("supportFile", e.target.files[0])}
|
||||
/>
|
||||
<FormHelperText as={'span'} fontSize={'xs'} fontWeight={500} style={{ color: "red" }} >{errors.supportFile?.message}</FormHelperText>
|
||||
</FormControl>
|
||||
|
||||
{/* Description */}
|
||||
<FormControl w={"100%"} mb={2} isInvalid={errors.description}>
|
||||
<FormLabel textAlign={"left"} fontSize={"xs"} color={"gray.600"}>
|
||||
Description
|
||||
</FormLabel>
|
||||
<Textarea
|
||||
bg={"#F5F8F6"}
|
||||
focusBorderColor="forestGreen.300"
|
||||
size={"sm"}
|
||||
fontSize={"sm"}
|
||||
rounded={"sm"}
|
||||
placeholder={"Description"}
|
||||
{...register("description")} // Register the field
|
||||
/>
|
||||
<FormHelperText as={'span'} fontSize={'xs'} fontWeight={500} style={{ color: "red" }} >{errors.description?.message}</FormHelperText>
|
||||
</FormControl>
|
||||
|
||||
|
||||
<HStack mt={2} w={'100%'} justifyContent={'flex-end'}>
|
||||
<Button
|
||||
colorScheme="forestGreen"
|
||||
size={"sm"}
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
type="submit"
|
||||
>Create request</Button>
|
||||
</HStack>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</Box>
|
||||
<SelectInvestorModal setValue={setValue} onClose={onClose} isOpen={isOpen} onOpen={onOpen}/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateRequest;
|
||||
350
src/Pages/Fawateer/FawateerRequest.jsx
Normal file
350
src/Pages/Fawateer/FawateerRequest.jsx
Normal file
@@ -0,0 +1,350 @@
|
||||
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 { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||
import NormalTable from "../../Components/DataTable/NormalTable";
|
||||
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 Pagination from "../../Components/Pagination";
|
||||
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
||||
import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
||||
import ToastBox from "../../Components/ToastBox";
|
||||
import { debounce } from "../Master/Sponser/AddSponser";
|
||||
// import InvestmentDetailsEdit from "./InvestmentDetailsEdit";
|
||||
import { useGetInvestorsQuery } from "../../Services/investor.details.service";
|
||||
import { TABLE_PAGINATION } from "../../Constants/Paginations";
|
||||
import { exportToExcel, generateSerialNumber } from "../../Constants/Constants";
|
||||
import { LuFileSpreadsheet } from "react-icons/lu";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const FawateerRequest = () => {
|
||||
const navigate = useNavigate();
|
||||
const toast = useToast();
|
||||
const thirdField = useRef();
|
||||
const { InvestorDetails, setInvestorDetails, slideFromRight } =
|
||||
useContext(GlobalStateContext);
|
||||
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: isEditOpen,
|
||||
onOpen: onEditOpen,
|
||||
onClose: onEditClose,
|
||||
} = useDisclosure();
|
||||
const btnRef = React.useRef();
|
||||
|
||||
|
||||
// =========================== [Use State] =============================
|
||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||
|
||||
// Debounce the search term to avoid making a request on every keystroke
|
||||
useEffect(() => {
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedSearchTerm(searchTerm);
|
||||
}, 500); // Adjust delay as needed
|
||||
return () => {
|
||||
clearTimeout(handler);
|
||||
};
|
||||
}, [searchTerm]);
|
||||
const {
|
||||
data: investorDetails,
|
||||
isLoading: investorDetailsLoading,
|
||||
error,
|
||||
} = useGetInvestorsQuery({
|
||||
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||
search: debouncedSearchTerm,
|
||||
},
|
||||
{
|
||||
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
// Simulate loading
|
||||
const timer = setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
}, 1500);
|
||||
|
||||
// Cleanup the timer on component unmount
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
// ====================================================[Table Setup]================================================================
|
||||
const tableHeadRow = [
|
||||
"Sr No",
|
||||
|
||||
"Client ID",
|
||||
"First Name",
|
||||
"Last Name",
|
||||
"Country",
|
||||
"Phone Number",
|
||||
"E-mail ID",
|
||||
// "Type",
|
||||
// "KYC Status",
|
||||
"Approval Status",
|
||||
];
|
||||
|
||||
const handleUpdateStatus = debounce((id) => {
|
||||
setInvestorDetails((prevData) =>
|
||||
prevData.map((InvestorDetails) =>
|
||||
InvestorDetails.id === id ? { ...InvestorDetails } : InvestorDetails
|
||||
)
|
||||
);
|
||||
toast({
|
||||
render: () => <ToastBox message={"Status changed succesfully.!"} />,
|
||||
});
|
||||
}, 300);
|
||||
|
||||
// ====================================================[Table Filter]================================================================
|
||||
const filteredData = investorDetails?.data?.rows?.filter((item) => {
|
||||
// Filter by name (case insensitive)
|
||||
const name = [item?.principal?.firstName, item?.principal?.lastName, item?.country?.countryName, item?.principal?.mobileNumber, item?.principal?.emailAddress].filter(Boolean).join(' ');
|
||||
const searchLower = searchTerm.toLowerCase();
|
||||
const nameMatches = name?.toLowerCase().includes(searchLower);
|
||||
|
||||
// Filter by status
|
||||
// const status = item.status;
|
||||
// const statusLower = status ? "active" : "inactive";
|
||||
|
||||
// const statusMatches =
|
||||
// statusFilter === "all" ||
|
||||
// (statusFilter === "active" && status === true) ||
|
||||
// (statusFilter === "inactive" && status === false);
|
||||
|
||||
return nameMatches;
|
||||
});
|
||||
|
||||
|
||||
|
||||
const customHeaders = [
|
||||
{ label: "ID", key: "id" },
|
||||
{ label: "Client ID", key: "clientReference_id" },
|
||||
{ label: "First Name", key: "principal.firstName" }, // Nested property
|
||||
{ label: "Last Name", key: "principal.lastName" }, // Nested property
|
||||
{ label: "Country", key: "country.countryName" }, // Nested property
|
||||
{ label: "Phone Number", key: "principal.mobileNumber" }, // Nested property
|
||||
{ label: "E-mail ID", key: "principal.emailAddress" }, // Nested property
|
||||
{ label: "Type", key: "investor_type.investorTypeName" }, // Nested property
|
||||
{ label: "Status", key: "ioStatus" }, // Simple property
|
||||
{ label: "KYC Status", key: "KYCStatus" }, // Simple property
|
||||
];
|
||||
|
||||
|
||||
const extractedArray = investorDetails?.data?.rows?.map((item, idx) => ({
|
||||
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"
|
||||
>
|
||||
{/* {item.id} */}
|
||||
{generateSerialNumber(idx,currentPage, pageSize )}
|
||||
|
||||
</Text>
|
||||
),
|
||||
"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={"70px"} 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?.countryName}
|
||||
</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>
|
||||
),
|
||||
"Type": (
|
||||
<Box w={"auto"} isTruncated={true}>
|
||||
<Text as={"span"} >
|
||||
<Badge color={"forestGreen.500"} variant={'ghost'} fontWeight={"700"} px={2} py={0.5}>
|
||||
{item?.investor_type?.investorTypeName}
|
||||
</Badge>
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Approval Status": (
|
||||
<Box w={"auto"} isTruncated={true}>
|
||||
<Badge
|
||||
fontWeight={"700"}
|
||||
textTransform={"none"}
|
||||
colorScheme={item.ioStatus ? "red" : "purple"}
|
||||
px={2}
|
||||
py={0.5}
|
||||
>
|
||||
Approved
|
||||
</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();
|
||||
};
|
||||
|
||||
console.log(investorDetails?.data?.totalItems);
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||
<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"}>
|
||||
|
||||
|
||||
<Pagination
|
||||
isLoading={investorDetailsLoading}
|
||||
pageSize={pageSize}
|
||||
setPageSize={setPageSize}
|
||||
currentPage={currentPage}
|
||||
setCurrentPage={setCurrentPage}
|
||||
totalItems={investorDetails?.data?.totalItems}
|
||||
|
||||
/>
|
||||
|
||||
|
||||
{/*
|
||||
<Button
|
||||
leftIcon={<AddIcon />}
|
||||
colorScheme="forestGreen"
|
||||
size={"sm"}
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
onClick={()=> navigate('create-request')}
|
||||
>
|
||||
Create request
|
||||
</Button> */}
|
||||
|
||||
</HStack>
|
||||
</HStack>
|
||||
</Box>
|
||||
|
||||
<NormalTable
|
||||
// centered={true}
|
||||
emptyMessage={`We don't have any Sponers `}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={extractedArray}
|
||||
isLoading={investorDetailsLoading}
|
||||
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}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default FawateerRequest
|
||||
238
src/Pages/Fawateer/SelectInvestorModal.jsx
Normal file
238
src/Pages/Fawateer/SelectInvestorModal.jsx
Normal file
@@ -0,0 +1,238 @@
|
||||
import {
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalFooter,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
Button,
|
||||
Text,
|
||||
Box,
|
||||
Badge,
|
||||
Select,
|
||||
HStack,
|
||||
Input,
|
||||
} from '@chakra-ui/react'
|
||||
import NormalTable from '../../Components/DataTable/NormalTable'
|
||||
import { generateSerialNumber } from '../../Constants/Constants';
|
||||
import { useGetInvestorsQuery } from '../../Services/investor.details.service';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { TABLE_PAGINATION } from '../../Constants/Paginations';
|
||||
import Pagination from '../../Components/Pagination';
|
||||
import { AddIcon } from '@chakra-ui/icons';
|
||||
|
||||
const SelectInvestorModal = ({ isOpen, setValue, onClose}) => {
|
||||
|
||||
|
||||
|
||||
// =========================== [Use State] =============================
|
||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||
|
||||
// Debounce the search term to avoid making a request on every keystroke
|
||||
useEffect(() => {
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedSearchTerm(searchTerm);
|
||||
}, 500); // Adjust delay as needed
|
||||
return () => {
|
||||
clearTimeout(handler);
|
||||
};
|
||||
}, [searchTerm]);
|
||||
|
||||
const {
|
||||
data: investorDetails,
|
||||
isLoading: investorDetailsLoading,
|
||||
error,
|
||||
} = useGetInvestorsQuery({
|
||||
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||
search: debouncedSearchTerm,
|
||||
},
|
||||
{
|
||||
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||
}
|
||||
);
|
||||
|
||||
const [ selectedRadio, setSelectedRadio] = useState([])
|
||||
const [ selectedInvestor, setSelectorInvestor] = useState(null)
|
||||
|
||||
const handleCheckboxChange = (id) => {
|
||||
setSelectedRadio([id]);
|
||||
const investor = investorDetails?.data?.rows?.find((item)=> item?.id === id)
|
||||
setSelectorInvestor(investor)
|
||||
// setValue("investorName",`${selectedInvestor?.principal?.firstName} ${selectedInvestor?.principal?.lastName}`)
|
||||
// setValue("clientId",selectedInvestor?.clientReference_id)
|
||||
return
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
console.log(selectedInvestor);
|
||||
setValue("investorName",`${selectedInvestor?.principal?.firstName} ${selectedInvestor?.principal?.lastName}`)
|
||||
setValue("clientId",selectedInvestor?.clientReference_id)
|
||||
return onClose()
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ====================================================[Table Setup]================================================================
|
||||
const tableHeadRow = [
|
||||
|
||||
"Sr No",
|
||||
"Client ID",
|
||||
"First Name",
|
||||
"Last Name",
|
||||
"Country",
|
||||
"Phone Number",
|
||||
"E-mail ID",
|
||||
// "Type",
|
||||
// "KYC Status",
|
||||
"Approval Status",
|
||||
];
|
||||
|
||||
|
||||
const extractedArray = investorDetails?.data?.rows?.map((item, idx) => ({
|
||||
id: item?.id,
|
||||
"Sr No": (
|
||||
<Text
|
||||
w={'24px'}
|
||||
as={"span"}
|
||||
color={"gray.600"}
|
||||
className="d-flex align-items-center fw-bold web-text-small"
|
||||
>
|
||||
{/* {item.id} */}
|
||||
{generateSerialNumber(idx,currentPage, pageSize )}
|
||||
|
||||
</Text>
|
||||
),
|
||||
"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={"70px"} 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?.countryName}
|
||||
</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>
|
||||
),
|
||||
"Type": (
|
||||
<Box w={"auto"} isTruncated={true}>
|
||||
<Text as={"span"} >
|
||||
<Badge color={"forestGreen.500"} variant={'ghost'} fontWeight={"700"} px={2} py={0.5}>
|
||||
{item?.investor_type?.investorTypeName}
|
||||
</Badge>
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Approval Status": (
|
||||
<Box w={"auto"} isTruncated={true}>
|
||||
<Badge
|
||||
fontWeight={"700"}
|
||||
textTransform={"none"}
|
||||
colorScheme={item.ioStatus ? "red" : "purple"}
|
||||
px={2}
|
||||
py={0.5}
|
||||
>
|
||||
Approved
|
||||
</Badge>
|
||||
</Box>
|
||||
),
|
||||
}));
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isCentered
|
||||
onClose={onClose}
|
||||
isOpen={isOpen}
|
||||
motionPreset='scale'
|
||||
>
|
||||
<ModalOverlay />
|
||||
<ModalContent maxW={1200}>
|
||||
<ModalHeader fontSize={'md'}>Select Investor</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
{/* <Lorem count={2} /> */}
|
||||
|
||||
<HStack
|
||||
display={"flex"}
|
||||
justifyContent={"space-between"}
|
||||
ps={1}
|
||||
pe={1}
|
||||
pb={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)}
|
||||
/>
|
||||
<Button leftIcon={<AddIcon/>} fontSize={'xs'} colorScheme='forestGreen' size={'sm'} rounded={'sm'} onClick={handleAdd}>
|
||||
Add Invvestor
|
||||
</Button>
|
||||
|
||||
</HStack>
|
||||
|
||||
|
||||
<NormalTable
|
||||
// centered={true}
|
||||
emptyMessage={`We don't have any Sponers `}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={extractedArray}
|
||||
isLoading={investorDetailsLoading}
|
||||
|
||||
|
||||
|
||||
handleCheckboxChange={handleCheckboxChange}
|
||||
setSelectedRadio={setSelectedRadio}
|
||||
selectedRadio={selectedRadio}
|
||||
showRadioButton={true}
|
||||
radio={true}
|
||||
/>
|
||||
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
export default SelectInvestorModal
|
||||
@@ -1,5 +1,5 @@
|
||||
import { HiOutlineNewspaper } from "react-icons/hi";
|
||||
import { TbBrandMedium, TbChartHistogram, TbLayoutDashboard, TbReportMoney } from "react-icons/tb";
|
||||
import { TbBrandMedium, TbBuildingBank, TbChartHistogram, TbLayoutDashboard, TbReportMoney } from "react-icons/tb";
|
||||
import {
|
||||
RiBankLine,
|
||||
RiFileUserLine,
|
||||
@@ -24,6 +24,7 @@ import { SiAcademia } from "react-icons/si";
|
||||
import { LuContact } from "react-icons/lu";
|
||||
import { LiaCrownSolid } from "react-icons/lia";
|
||||
import { PiCrownDuotone } from "react-icons/pi";
|
||||
import { HiOutlineBanknotes } from "react-icons/hi2";
|
||||
|
||||
export const nav = [
|
||||
// {
|
||||
@@ -97,7 +98,46 @@ export const nav = [
|
||||
type: "title",
|
||||
},
|
||||
{
|
||||
title: "Deposit",
|
||||
title: "Fawateer Deposit",
|
||||
submenu: [
|
||||
{
|
||||
title: "Create Request",
|
||||
path: "/fawateer-request",
|
||||
icon: RiMoneyDollarBoxLine,
|
||||
},
|
||||
{
|
||||
title: "View History",
|
||||
path: "/fawateer-history",
|
||||
icon: RiExchangeBoxLine,
|
||||
},
|
||||
],
|
||||
type: "accordion",
|
||||
Icon: HiOutlineBanknotes,
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
title: "Fawateer Deposit",
|
||||
submenu: [
|
||||
{
|
||||
title: "Pending Request",
|
||||
path: "/fawateer-approver",
|
||||
icon: RiMoneyDollarBoxLine,
|
||||
},
|
||||
{
|
||||
title: "View History",
|
||||
path: "/approver-history",
|
||||
icon: RiExchangeBoxLine,
|
||||
},
|
||||
],
|
||||
type: "accordion",
|
||||
Icon: HiOutlineBanknotes,
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
title: "Bank Deposit",
|
||||
submenu: [
|
||||
{
|
||||
title: "Pending Request",
|
||||
@@ -111,7 +151,7 @@ export const nav = [
|
||||
},
|
||||
],
|
||||
type: "accordion",
|
||||
Icon: BiMoneyWithdraw,
|
||||
Icon: TbBuildingBank,
|
||||
},
|
||||
{
|
||||
title: "Withdrawal",
|
||||
|
||||
@@ -37,6 +37,8 @@ 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";
|
||||
import FawateerRequest from "../Pages/Fawateer/FawateerRequest";
|
||||
import CreateRequest from "../Pages/Fawateer/CreateRequest";
|
||||
|
||||
export const RouteLink = [
|
||||
// =============[ Tanami ]================
|
||||
@@ -71,6 +73,8 @@ export const RouteLink = [
|
||||
// { path: "/investor-transactions", Component: InvestorTransactions },
|
||||
// { path: "/investor-transactions", Component: UnderConstruction },
|
||||
|
||||
|
||||
|
||||
// ===============[ Deposit ]===============
|
||||
{ path: "/deposit-request", Component: DepositRequest },
|
||||
{ path: "/deposit-history", Component: DepositHistory },
|
||||
@@ -109,4 +113,26 @@ export const RouteLink = [
|
||||
{ path: "/bank-details", Component: BankDetails },
|
||||
// { path: "/bank-details", Component: UnderConstruction },
|
||||
{ path: "/bank-details/edit-bank-details/:id", Component: EditBankDetails },
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ===============[ fawateer ]===============
|
||||
{ path: "/fawateer-history", Component: FawateerRequest },
|
||||
{ path: "/fawateer-request", Component: CreateRequest },
|
||||
|
||||
|
||||
{ path: "/fawateer-approver", Component: PendingRequest },
|
||||
{ path: "/approver-history", Component: FawateerRequest },
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user