Compare commits
91 Commits
bug-fix/9.
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b141743190 | ||
|
|
f9d0b3ce6c | ||
|
|
965263a3f2 | ||
|
|
04a5d1280f | ||
|
|
d40eadb35e | ||
|
|
f4a2fd2889 | ||
|
|
96f813f632 | ||
|
|
8587b91a33 | ||
|
|
49b06e81a6 | ||
|
|
79ec8d92ae | ||
|
|
f2d8aee6a9 | ||
|
|
a108dcdb17 | ||
|
|
41a1bde62b | ||
|
|
efddfe6d7a | ||
|
|
abe9b14436 | ||
|
|
f31b67f676 | ||
|
|
066e2fc169 | ||
|
|
2892334e41 | ||
|
|
103959b40b | ||
|
|
714804fdd6 | ||
|
|
af2485ba58 | ||
|
|
2b89e52e58 | ||
|
|
05f1d4055e | ||
|
|
efbb72ca4c | ||
|
|
fba6a7ad45 | ||
|
|
0ccfba1238 | ||
|
|
5e86a72700 | ||
|
|
9f93993938 | ||
|
|
79c822bb4d | ||
|
|
7523fd48f2 | ||
|
|
7e8f5e1115 | ||
|
|
ccd27b7840 | ||
|
|
27b7e31930 | ||
|
|
27d243ee30 | ||
|
|
ba06bf28c0 | ||
|
|
cbfeff4710 | ||
|
|
c82ef27958 | ||
|
|
067edfb4a5 | ||
|
|
92977c4bed | ||
|
|
c7856baf45 | ||
|
|
27d3167acc | ||
|
|
9b5dd51660 | ||
|
|
7f3dd5aa79 | ||
|
|
584df9b140 | ||
|
|
31d237b675 | ||
|
|
3f5e154e23 | ||
|
|
bb9513fcfe | ||
|
|
d196dffd12 | ||
|
|
f9b1f820c2 | ||
|
|
6d2964036a | ||
|
|
21eb9e41ff | ||
|
|
87f8977c73 | ||
|
|
390ec27e35 | ||
|
|
5ff437970e | ||
|
|
1beeeed8d3 | ||
|
|
401c9daf75 | ||
|
|
d23bf5d7e9 | ||
|
|
20213408c4 | ||
|
|
3d456c3c48 | ||
|
|
4e4de8caf5 | ||
|
|
150194cc26 | ||
|
|
5928af4283 | ||
|
|
55a397594e | ||
|
|
874940ae7c | ||
|
|
96a302d262 | ||
| 35d3e07224 | |||
|
|
651c775c2a | ||
|
|
18035047d4 | ||
|
|
a51585089c | ||
|
|
ebcb06bf5e | ||
|
|
84dc47b447 | ||
|
|
aeb0f25663 | ||
|
|
a07d011c85 | ||
|
|
0ed01bf94f | ||
|
|
96f8c32483 | ||
|
|
45f69fe2b7 | ||
|
|
57c6923784 | ||
|
|
974d1501b2 | ||
|
|
c33e358e8e | ||
|
|
1434088c1b | ||
|
|
3c6f083432 | ||
|
|
f81b210b0a | ||
|
|
5743cadf5e | ||
|
|
4579573f23 | ||
|
|
625f721325 | ||
|
|
01aece9bf6 | ||
|
|
d9692c3890 | ||
|
|
6e42bc0adb | ||
|
|
c9e5223989 | ||
| 6c2a38becb | |||
| bddf7381a6 |
@@ -58,7 +58,6 @@ const NormalTable = ({
|
||||
};
|
||||
|
||||
|
||||
|
||||
const handleCheckboxChange = (value) => {
|
||||
if (radio) {
|
||||
// If radio is true, select only one option
|
||||
|
||||
@@ -520,7 +520,7 @@ const FormField = ({
|
||||
ps={1}
|
||||
{...field}
|
||||
{...props} size='md' colorScheme='forestGreen'>
|
||||
<Text as={"span"} fontSize={"sm"}>Is This Sharia Compliant</Text>
|
||||
<Text as={"span"} fontSize={"sm"}>Is This Shariah Compliant</Text>
|
||||
</Checkbox>
|
||||
</HStack>
|
||||
);} else{
|
||||
|
||||
202
src/Components/Popups/ConfirmReversalPopups.jsx
Normal file
@@ -0,0 +1,202 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Checkbox,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Input,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Text,
|
||||
Textarea,
|
||||
useBoolean,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import * as yup from "yup";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import { useForm } from "react-hook-form";
|
||||
import ReactQuill from "react-quill";
|
||||
|
||||
export const conformModalSchema = yup.object().shape({
|
||||
comment: yup
|
||||
.string()
|
||||
.min(2, "Minimum length should be 2 characters.")
|
||||
.max(150, "Maximum length should be 150 characters.")
|
||||
// .matches(/^[^\d]+$/, "Sponsor Name cannot contain numbers")
|
||||
.required("Comment is required"),
|
||||
subject: yup.string().notRequired(),
|
||||
emailTemplate: yup.string().notRequired(),
|
||||
});
|
||||
|
||||
const ConfirmReversalPopups = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
handleConfirm,
|
||||
isLoading,
|
||||
}) => {
|
||||
const {
|
||||
watch,
|
||||
register,
|
||||
reset,
|
||||
handleSubmit,
|
||||
setValue,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: yupResolver(conformModalSchema),
|
||||
mode: "all",
|
||||
});
|
||||
|
||||
const [richTextValue, setRichTextValue] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
setValue("emailTemplate", richTextValue);
|
||||
}, [richTextValue]);
|
||||
|
||||
// Reset the form when the modal closes
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
reset(); // Clear the form state
|
||||
}
|
||||
}, [isOpen, reset]);
|
||||
|
||||
const [emailApproval, setEmailApproval] = useBoolean(false);
|
||||
|
||||
const modules = {
|
||||
toolbar: [
|
||||
// [{ header: "1" }, { header: "2" },
|
||||
// // { font: [] }
|
||||
// ],
|
||||
// [{ size: [] }],
|
||||
["bold", "italic", "underline", "strike", "blockquote"],
|
||||
[{ list: "ordered" }, { list: "bullet" }],
|
||||
["clean"],
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose}>
|
||||
<ModalOverlay />
|
||||
<ModalContent pb={4}>
|
||||
<ModalHeader fontSize={"md"}>Approve</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<Box
|
||||
as="form"
|
||||
onSubmit={handleSubmit((data) => {
|
||||
handleConfirm(data);
|
||||
reset();
|
||||
onClose();
|
||||
})}
|
||||
>
|
||||
<ModalBody>
|
||||
<FormControl mb={4} isRequired>
|
||||
<FormLabel fontSize="sm">Comment</FormLabel>
|
||||
<Textarea
|
||||
rows={6}
|
||||
focusBorderColor="green.400"
|
||||
name="comment"
|
||||
{...register("comment")}
|
||||
fontSize="sm"
|
||||
type="textarea"
|
||||
size="md"
|
||||
placeholder={"Enter your comment...."}
|
||||
rounded={"md"}
|
||||
resize={"none"}
|
||||
mb={2}
|
||||
/>
|
||||
{errors.comment ? (
|
||||
<Text fontSize="xs" color="red">
|
||||
{errors.comment.message}
|
||||
</Text>
|
||||
) : (
|
||||
<Text fontSize="xs" color="gray.500">
|
||||
Maximum length should be 150 characters. You have entered{" "}
|
||||
{watch()?.comment?.length || 0} characters.
|
||||
</Text>
|
||||
)}
|
||||
</FormControl>
|
||||
<Checkbox
|
||||
colorScheme="forestGreen"
|
||||
onChange={setEmailApproval.toggle}
|
||||
defaultChecked={emailApproval}
|
||||
>
|
||||
<Text mb={0} fontSize={"sm"}>
|
||||
Send an email to the user upon approval
|
||||
</Text>
|
||||
</Checkbox>
|
||||
{emailApproval && (
|
||||
<Box className="messageBox">
|
||||
<FormControl mb={4}>
|
||||
<FormLabel fontSize="sm" mb={1}>
|
||||
Subject
|
||||
</FormLabel>
|
||||
<Input
|
||||
focusBorderColor="green.400"
|
||||
name="fileName"
|
||||
{...register("subject")}
|
||||
fontSize="sm"
|
||||
type="text"
|
||||
size="sm"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl mb={12}>
|
||||
<FormLabel fontSize="sm" mb={1}>
|
||||
Message
|
||||
</FormLabel>
|
||||
<ReactQuill
|
||||
theme="snow"
|
||||
style={{
|
||||
height: 150,
|
||||
}}
|
||||
value={richTextValue}
|
||||
onChange={setRichTextValue}
|
||||
modules={modules}
|
||||
placeholder="Start typing here..."
|
||||
/>
|
||||
</FormControl>
|
||||
</Box>
|
||||
)}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button
|
||||
colorScheme="gray"
|
||||
mr={3}
|
||||
onClick={onClose}
|
||||
size={"sm"}
|
||||
rounded={"sm"}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
colorScheme="forestGreen"
|
||||
variant="solid"
|
||||
size={"sm"}
|
||||
rounded={"sm"}
|
||||
type="submit"
|
||||
fontWeight={400}
|
||||
>
|
||||
Send
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Box>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
ConfirmReversalPopups.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
handelApproved: PropTypes.func.isRequired,
|
||||
isLoading: PropTypes.func.isRequired,
|
||||
richTextValue: PropTypes.any.isRequired,
|
||||
setRichTextValue: PropTypes.any.isRequired,
|
||||
};
|
||||
|
||||
export default ConfirmReversalPopups;
|
||||
133
src/Components/Popups/InitiateReversalPopups.jsx
Normal file
@@ -0,0 +1,133 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Text,
|
||||
Textarea,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useEffect } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import * as yup from "yup";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
export const conformModalSchema = yup.object().shape({
|
||||
comment: yup
|
||||
.string()
|
||||
.min(2, "Minimum length should be 2 characters.")
|
||||
.max(150, "Maximum length should be 150 characters.")
|
||||
// .matches(/^[^\d]+$/, "Sponsor Name cannot contain numbers")
|
||||
.required("Comment is required"),
|
||||
});
|
||||
|
||||
const InitiateReversalPopup = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
handelApproved,
|
||||
isLoading,
|
||||
}) => {
|
||||
const {
|
||||
watch,
|
||||
register,
|
||||
reset,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: yupResolver(conformModalSchema),
|
||||
mode: "all",
|
||||
});
|
||||
|
||||
// Reset the form when the modal closes
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
reset(); // Clear the form state
|
||||
}
|
||||
}, [isOpen, reset]);
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose}>
|
||||
<ModalOverlay />
|
||||
<ModalContent pb={4}>
|
||||
<ModalHeader fontSize={"md"}>Reversal Reason</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<Box
|
||||
as="form"
|
||||
onSubmit={handleSubmit((data) => {
|
||||
handelApproved(data);
|
||||
reset();
|
||||
onClose();
|
||||
})}
|
||||
>
|
||||
<ModalBody>
|
||||
<FormControl mb={4} isRequired>
|
||||
<FormLabel fontSize="sm">Comment</FormLabel>
|
||||
<Textarea
|
||||
rows={6}
|
||||
focusBorderColor="green.400"
|
||||
name="fileName"
|
||||
{...register("comment")}
|
||||
fontSize="sm"
|
||||
type="textarea"
|
||||
size="md"
|
||||
placeholder={"Enter your comment...."}
|
||||
rounded={"md"}
|
||||
resize={"none"}
|
||||
mb={2}
|
||||
/>
|
||||
|
||||
{errors.comment ? (
|
||||
<Text fontSize="xs" color="red">
|
||||
{errors.comment.message}
|
||||
</Text>
|
||||
) : (
|
||||
<Text fontSize="xs" color="gray.500">
|
||||
Maximum length should be 150 characters. You have entered{" "}
|
||||
{watch()?.comment?.length || 0} characters.
|
||||
</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"}
|
||||
type={"submit"}
|
||||
isDisabled={isLoading}
|
||||
>
|
||||
Send
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Box>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
InitiateReversalPopup.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
isLoading: PropTypes.bool.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
handelApproved: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default InitiateReversalPopup;
|
||||
132
src/Components/Popups/RejectReversalPopups.jsx
Normal file
@@ -0,0 +1,132 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Text,
|
||||
Textarea,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useEffect } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import * as yup from "yup";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
export const conformModalSchema = yup.object().shape({
|
||||
comment: yup
|
||||
.string()
|
||||
.min(2, "Minimum length should be 2 characters.")
|
||||
.max(150, "Maximum length should be 150 characters.")
|
||||
// .matches(/^[^\d]+$/, "Sponsor Name cannot contain numbers")
|
||||
.required("Comment is required"),
|
||||
});
|
||||
|
||||
const RejectReversalPopups = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
handelApproved,
|
||||
isLoading,
|
||||
}) => {
|
||||
const {
|
||||
watch,
|
||||
register,
|
||||
reset,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: yupResolver(conformModalSchema),
|
||||
mode: "all",
|
||||
});
|
||||
|
||||
// Reset the form when the modal closes
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
reset(); // Clear the form state
|
||||
}
|
||||
}, [isOpen, reset]);
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose}>
|
||||
<ModalOverlay />
|
||||
<ModalContent pb={4}>
|
||||
<ModalHeader fontSize={"md"}>Reject</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<Box
|
||||
as="form"
|
||||
onSubmit={handleSubmit((data) => {
|
||||
handelApproved(data);
|
||||
reset();
|
||||
onClose();
|
||||
})}
|
||||
>
|
||||
<ModalBody>
|
||||
<FormControl mb={4} isRequired>
|
||||
<FormLabel fontSize="sm">Comment</FormLabel>
|
||||
<Textarea
|
||||
rows={6}
|
||||
focusBorderColor="green.400"
|
||||
name="comment"
|
||||
{...register("comment")}
|
||||
fontSize="sm"
|
||||
type="textarea"
|
||||
size="md"
|
||||
placeholder={"Enter your comment...."}
|
||||
rounded={"md"}
|
||||
resize={"none"}
|
||||
mb={2}
|
||||
/>
|
||||
{errors.comment ? (
|
||||
<Text fontSize="xs" color="red">
|
||||
{errors.comment.message}
|
||||
</Text>
|
||||
) : (
|
||||
<Text fontSize="xs" color="gray.500">
|
||||
Maximum length should be 150 characters. You have entered{" "}
|
||||
{watch()?.comment?.length || 0} characters.
|
||||
</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"}
|
||||
type="submit"
|
||||
fontWeight={400}
|
||||
>
|
||||
Send
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Box>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
RejectReversalPopups.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
handelApproved: PropTypes.func.isRequired,
|
||||
isLoading: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default RejectReversalPopups;
|
||||
@@ -1674,6 +1674,79 @@ const GlobalStateProvider = ({ children }) => {
|
||||
},
|
||||
]);
|
||||
|
||||
const [opportunities, setOpportunities] = useState([
|
||||
{
|
||||
id: 1,
|
||||
Investors: "Blackstone",
|
||||
amountRemaining: "10 %",
|
||||
totalDealsize: "$ 520",
|
||||
noViews: "50",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
Investors: "Blackstone",
|
||||
amountRemaining: "10 %",
|
||||
totalDealsize: "$ 520",
|
||||
noViews: "50",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
Investors: "Blackstone",
|
||||
amountRemaining: "10 %",
|
||||
totalDealsize: "$ 520",
|
||||
noViews: "50",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
Investors: "Blackstone",
|
||||
amountRemaining: "10 %",
|
||||
totalDealsize: "$ 520",
|
||||
noViews: "50",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
Investors: "Blackstone",
|
||||
amountRemaining: "10 %",
|
||||
totalDealsize: "$ 520",
|
||||
noViews: "50",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
Investors: "Blackstone",
|
||||
amountRemaining: "10 %",
|
||||
totalDealsize: "$ 520",
|
||||
noViews: "50",
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
Investors: "Blackstone",
|
||||
amountRemaining: "10 %",
|
||||
totalDealsize: "$ 520",
|
||||
noViews: "50",
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
Investors: "Blackstone",
|
||||
amountRemaining: "10 %",
|
||||
totalDealsize: "$ 520",
|
||||
noViews: "50",
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
Investors: "Blackstone",
|
||||
amountRemaining: "10 %",
|
||||
totalDealsize: "$ 520",
|
||||
noViews: "50",
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
Investors: "Blackstone",
|
||||
amountRemaining: "10 %",
|
||||
totalDealsize: "$ 520",
|
||||
noViews: "50",
|
||||
},
|
||||
]);
|
||||
|
||||
const [InvestorWallet, setInvestorWallet] = useState(null);
|
||||
|
||||
// ==============[ prod state ]===============================
|
||||
@@ -1767,6 +1840,8 @@ const GlobalStateProvider = ({ children }) => {
|
||||
setIONAVDetail,
|
||||
iOTransaction,
|
||||
setIOTransaction,
|
||||
opportunities,
|
||||
setOpportunities,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
4
src/Images/dash_icon_1.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="25" height="22" viewBox="0 0 25 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.21972 0.088562C3.15668 0.321268 2.26287 0.834278 1.46427 1.66461C-0.111786 3.31471 -0.450268 5.80044 0.618065 7.85248C1.32676 9.20112 2.53789 10.1637 4.01346 10.5498L4.53705 10.6873V15.0293C4.53705 19.8104 4.52647 19.6306 4.86495 20.334C5.20872 21.0427 6.02848 21.6985 6.84295 21.91C7.29779 22.0264 16.9974 22.0317 17.4575 21.91C18.5417 21.6297 19.4091 20.7624 19.6894 19.6782C19.7581 19.4243 19.7687 18.6998 19.7687 15.0241V10.6714L19.9168 10.6397C21.6832 10.2483 22.9684 9.28045 23.7353 7.76257C24.7349 5.77928 24.3911 3.32 22.8891 1.7175C22.6722 1.4848 22.3391 1.17805 22.1487 1.03525C21.715 0.702057 20.8741 0.289536 20.324 0.13616L19.9009 0.0145187L12.2851 0.00394058C5.08708 -0.00663567 4.64282 -0.0013485 4.21972 0.088562ZM19.7687 1.80212C19.9591 1.85501 20.3135 1.99252 20.562 2.11416C20.9217 2.28869 21.0962 2.41562 21.4664 2.78584C21.8525 3.1772 21.9636 3.32529 22.1645 3.7431C22.466 4.38304 22.5453 4.70037 22.54 5.35618C22.54 6.77357 21.7732 7.98999 20.4827 8.61406C20.25 8.72513 19.9961 8.8309 19.9168 8.85206L19.7687 8.88379V6.96925C19.7687 5.11289 19.7634 5.04414 19.6576 4.86961C19.5942 4.77441 19.4567 4.64748 19.3403 4.58931C19.1446 4.48353 18.9966 4.48353 12.1529 4.48353C5.30921 4.48353 5.16112 4.48353 4.96544 4.58931C4.84908 4.64748 4.71158 4.77441 4.64811 4.86961C4.54233 5.04414 4.53705 5.11289 4.53705 6.96925V8.88379L4.39425 8.85206C4.12981 8.78859 3.40525 8.4078 3.10379 8.16452C2.56433 7.73613 2.13594 7.11734 1.90853 6.41393C1.79746 6.07016 1.77102 5.87977 1.76573 5.40907C1.76044 4.70566 1.82919 4.39891 2.14123 3.74839C2.33692 3.34116 2.45327 3.1772 2.80762 2.81757C3.44227 2.18291 4.12981 1.83914 4.97601 1.73866C5.18756 1.71221 8.52478 1.69635 12.3909 1.70164C18.9014 1.71221 19.4514 1.7175 19.7687 1.80212ZM18.0657 12.6917L18.0499 19.1599L17.9018 19.4613C17.7378 19.7998 17.5316 19.9955 17.1772 20.1595C16.9392 20.2705 16.8969 20.2705 12.1529 20.2705C7.40885 20.2705 7.36654 20.2705 7.12854 20.1595C6.7742 19.9955 6.56793 19.7998 6.40398 19.4613L6.2559 19.1599L6.24003 12.6917L6.22416 6.22883H12.1529H18.0816L18.0657 12.6917Z" fill="#004717"/>
|
||||
<path d="M11.6239 9.05782C11.1585 9.19004 10.9576 9.34341 10.0003 10.3113C9.23342 11.0834 9.09062 11.2579 9.05889 11.4272C8.95312 11.9984 9.27044 12.4585 9.81519 12.5114C10.1642 12.5431 10.3388 12.4479 10.8729 11.9243L11.3066 11.4907V13.9817V16.4727L11.4283 16.6472C11.7615 17.1391 12.5442 17.1391 12.8827 16.6472L12.999 16.4727V13.9817V11.4907L13.438 11.9243C13.9669 12.4479 14.1414 12.5431 14.4905 12.5114C14.9136 12.4691 15.215 12.1782 15.2573 11.7657C15.3049 11.3426 15.2309 11.2315 14.1996 10.2108C13.3375 9.35928 13.2053 9.24821 12.9197 9.14244C12.5072 8.98906 11.9994 8.95733 11.6239 9.05782Z" fill="#004717"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
4
src/Images/dash_icon_2.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="25" height="22" viewBox="0 0 25 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.21995 0.0885715C3.15685 0.321289 2.263 0.834328 1.46435 1.66471C-0.111792 3.3149 -0.450292 5.80076 0.618099 7.85292C1.32683 9.20163 2.53803 10.1642 4.01368 10.5503L4.5373 10.6879V15.0302C4.5373 19.8115 4.52672 19.6317 4.86522 20.3351C5.20901 21.0438 6.02881 21.6997 6.84333 21.9113C7.29819 22.0276 16.9983 22.0329 17.4585 21.9113C18.5427 21.6309 19.4102 20.7635 19.6905 19.6793C19.7592 19.4254 19.7698 18.7008 19.7698 15.0249V10.672L19.9179 10.6403C21.6845 10.2489 22.9697 9.28097 23.7366 7.763C24.7362 5.7796 24.3925 3.32019 22.8904 1.7176C22.6735 1.48488 22.3403 1.17812 22.1499 1.03531C21.7162 0.702101 20.8752 0.289555 20.3252 0.136171L19.902 0.0145245L12.2858 0.0039463C5.08736 -0.00663185 4.64308 -0.00134277 4.21995 0.0885715ZM19.7698 1.80223C19.9602 1.85512 20.3146 1.99263 20.5632 2.11428C20.9228 2.28882 21.0974 2.41576 21.4676 2.78599C21.8537 3.17738 21.9648 3.32548 22.1658 3.74331C22.4672 4.38329 22.5466 4.70063 22.5413 5.35648C22.5413 6.77395 21.7744 7.99043 20.4838 8.61454C20.2511 8.72561 19.9972 8.8314 19.9179 8.85255L19.7698 8.88429V6.96964C19.7698 5.11318 19.7645 5.04442 19.6587 4.86988C19.5953 4.77468 19.4578 4.64774 19.3414 4.58956C19.1457 4.48378 18.9976 4.48378 12.1536 4.48378C5.3095 4.48378 5.16141 4.48378 4.96571 4.58956C4.84935 4.64774 4.71184 4.77468 4.64837 4.86988C4.54259 5.04442 4.5373 5.11318 4.5373 6.96964V8.88429L4.39449 8.85255C4.13004 8.78908 3.40544 8.40827 3.10396 8.16497C2.56448 7.73656 2.13606 7.11774 1.90863 6.41429C1.79756 6.0705 1.77112 5.8801 1.76583 5.40937C1.76054 4.70592 1.8293 4.39916 2.14135 3.7486C2.33705 3.34134 2.4534 3.17738 2.80777 2.81773C3.44246 2.18304 4.13004 1.83925 4.97629 1.73876C5.18785 1.71231 8.52525 1.69645 12.3916 1.70173C18.9024 1.71231 19.4525 1.7176 19.7698 1.80223ZM18.0667 12.6924L18.0509 19.1609L17.9028 19.4624C17.7388 19.8009 17.5325 19.9966 17.1782 20.1606C16.9402 20.2716 16.8978 20.2716 12.1536 20.2716C7.40926 20.2716 7.36695 20.2716 7.12894 20.1606C6.77457 19.9966 6.5683 19.8009 6.40434 19.4624L6.25624 19.1609L6.24038 12.6924L6.22451 6.22917H12.1536H18.0826L18.0667 12.6924Z" fill="#004717"/>
|
||||
<path d="M11.8362 9.03725C11.7621 9.06369 11.6458 9.14303 11.5823 9.2065C11.302 9.46566 11.3073 9.42864 11.3073 12.0838V14.559L10.8471 14.0989C10.588 13.8503 10.3288 13.6176 10.2653 13.5858C10.0538 13.4801 9.60421 13.5118 9.39793 13.6546C9.04357 13.8926 8.9325 14.3898 9.13348 14.7865C9.19166 14.8922 9.62536 15.363 10.1014 15.8337C11.1909 16.9074 11.339 16.992 12.1535 16.992C12.9628 16.992 13.1109 16.9074 14.211 15.8337C14.6817 15.363 15.1207 14.8922 15.1736 14.7865C15.3746 14.3898 15.2424 13.8609 14.888 13.6387C14.687 13.5171 14.2374 13.4854 14.0417 13.5858C13.9783 13.6176 13.7191 13.8503 13.4652 14.0989L12.9998 14.559V12.0679V9.57673L12.8834 9.40219C12.8147 9.30699 12.6983 9.18005 12.619 9.12187C12.455 9.00023 12.0319 8.95262 11.8362 9.03725Z" fill="#004717"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
7
src/Images/dash_icon_3.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg width="27" height="27" viewBox="0 0 27 27" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0.85 4.90458V4.91276C0.85 6.01672 0.856512 6.94052 0.867926 7.59765C0.873631 7.92606 0.880574 8.18879 0.888592 8.37443C0.892591 8.46702 0.89692 8.54198 0.901643 8.5969C0.903985 8.62414 0.906596 8.64852 0.909645 8.66854C0.911156 8.67847 0.913075 8.68934 0.915626 8.69997C0.917334 8.70708 0.921735 8.72497 0.931566 8.7441M0.85 4.90458L8.67578 1.97656M0.85 4.90458C0.85 3.12796 0.85 2.21329 0.866361 1.72737C0.874474 1.48641 0.886798 1.33911 0.908538 1.24176C0.919918 1.1908 0.935053 1.14765 0.957087 1.1092C0.979442 1.0702 1.00475 1.04353 1.02414 1.02414C1.04354 1.00474 1.0702 0.979438 1.10921 0.957083C1.14765 0.935049 1.19081 0.919914 1.24176 0.908534C1.33911 0.886794 1.48641 0.874471 1.72737 0.866357C2.21328 0.849997 3.1279 0.849997 4.90439 0.849997H4.91276C6.01672 0.849997 6.94052 0.856508 7.59766 0.867923C7.92606 0.873627 8.18879 0.88057 8.37443 0.888588C8.46702 0.892587 8.54198 0.896916 8.5969 0.901639C8.62414 0.903981 8.64852 0.906592 8.66855 0.909641C8.67847 0.911153 8.68935 0.913072 8.69997 0.915623C8.70708 0.91733 8.72499 0.921734 8.74413 0.931574M0.85 4.90458L8.67578 1.0651M0.931566 8.7441C0.932164 8.74527 0.932781 8.74643 0.93342 8.7476L1.0651 8.67578M0.931566 8.7441C0.931356 8.74369 0.931148 8.74327 0.93094 8.74286L1.0651 8.67578M0.931566 8.7441C0.963258 8.80668 1.02187 8.86203 1.07407 8.90253C1.13034 8.94619 1.19851 8.9874 1.26743 9.0159C1.41953 9.08075 1.59317 9.07817 1.74168 9.03232C1.88916 8.98679 2.03374 8.89141 2.10946 8.74534C2.11906 8.72705 2.12362 8.70995 2.12556 8.70234C2.1282 8.69195 2.13019 8.68143 2.13175 8.67193C2.13489 8.65279 2.13755 8.62989 2.13992 8.60472C2.14469 8.55396 2.14904 8.48537 2.15304 8.40135C2.16108 8.23282 2.16803 7.99558 2.17374 7.70049C2.18515 7.10996 2.19167 6.2837 2.19167 5.30338V2.19166H5.30339C6.28371 2.19166 7.10996 2.18515 7.70049 2.17373C7.99558 2.16803 8.23282 2.16108 8.40135 2.15304C8.48538 2.14903 8.55396 2.14468 8.60472 2.13991C8.62989 2.13755 8.6528 2.13489 8.67193 2.13175C8.68144 2.13019 8.69195 2.1282 8.70234 2.12555C8.70994 2.12362 8.72702 2.11907 8.74528 2.10949M1.0651 8.67578C1.02604 8.60416 1 7.11979 1 4.91276C1 1.34505 1 1.26041 1.13021 1.1302C1.26042 0.999996 1.34505 0.999996 4.91276 0.999996C7.11979 0.999996 8.60417 1.02604 8.67578 1.0651M1.0651 8.67578C1.09766 8.74088 1.21484 8.83203 1.32552 8.8776L8.67578 1.0651M8.74528 2.10949C8.74606 2.10908 8.74683 2.10867 8.74761 2.10824L8.67578 1.97656M8.74528 2.10949C8.74505 2.10961 8.74481 2.10973 8.74458 2.10985L8.67578 1.97656M8.74528 2.10949C8.89139 2.03377 8.98678 1.88918 9.03232 1.74167C9.07817 1.59316 9.08075 1.41951 9.0159 1.26741C8.9874 1.1985 8.94619 1.13034 8.90253 1.07406C8.86204 1.02187 8.80669 0.963269 8.74413 0.931574M8.67578 1.97656C8.8776 1.87239 8.97526 1.55338 8.8776 1.32552C8.83203 1.21484 8.74089 1.09765 8.67578 1.0651M8.74413 0.931574C8.74529 0.932168 8.74645 0.932782 8.74761 0.933416L8.67578 1.0651M8.74413 0.931574C8.74371 0.93136 8.74329 0.931148 8.74286 0.930936L8.67578 1.0651" fill="#004717" stroke="#004717" stroke-width="0.3"/>
|
||||
<path d="M17.9845 1.22324C17.9499 1.311 17.9398 1.4096 17.9398 1.52083C17.9398 1.63206 17.9499 1.73066 17.9845 1.81842C18.0208 1.91027 18.0788 1.9776 18.1526 2.03525C18.2078 2.08018 18.2679 2.11228 18.3744 2.13377C18.4723 2.15351 18.6152 2.16551 18.8404 2.17366C19.2939 2.19006 20.1195 2.19166 21.6771 2.19166H24.8083V5.30338C24.8083 6.2837 24.8148 7.10996 24.8263 7.70049C24.832 7.99558 24.8389 8.23282 24.847 8.40135C24.851 8.48537 24.8553 8.55396 24.8601 8.60472C24.8624 8.62989 24.8651 8.65279 24.8682 8.67193C24.8698 8.68143 24.8718 8.69195 24.8744 8.70234C24.8764 8.70994 24.8809 8.72703 24.8905 8.7453M17.9845 1.22324L25.0234 8.67578M17.9845 1.22324C18.0208 1.13139 18.0788 1.06406 18.1526 1.0064L17.9845 1.22324ZM24.8905 8.7453C24.8909 8.74607 24.8913 8.74684 24.8918 8.7476L25.0234 8.67578M24.8905 8.7453C24.8904 8.74506 24.8903 8.74482 24.8901 8.74457L25.0234 8.67578M24.8905 8.7453C24.9662 8.89139 25.1108 8.98678 25.2583 9.03232C25.4068 9.07817 25.5805 9.08075 25.7326 9.01589M25.0234 8.67578C25.1276 8.8776 25.4466 8.97526 25.6745 8.8776M25.7326 9.01589C25.7323 9.01603 25.7319 9.01617 25.7316 9.0163L25.6745 8.8776M25.7326 9.01589C25.7329 9.01575 25.7332 9.01561 25.7336 9.01547L25.6745 8.8776M25.7326 9.01589L25.6745 8.8776M26.0684 8.74412C26.0678 8.74528 26.0672 8.74644 26.0666 8.7476L25.9349 8.67578L26.0691 8.74286C26.0688 8.74328 26.0686 8.7437 26.0684 8.74412Z" fill="#004717" stroke="#004717" stroke-width="0.3"/>
|
||||
<path d="M19.7169 20.2555C19.7561 20.1886 19.7914 20.1261 19.8187 20.0545C19.8467 19.9812 19.8645 19.9036 19.8762 19.8046C19.8986 19.6137 19.9 19.3226 19.9 18.7934C19.9 17.9063 19.8742 17.5712 19.7651 17.1482C19.3751 15.6152 18.154 14.2862 16.66 13.7815L16.6594 13.7813L16.3409 13.6752L16.6146 13.3975C17.1158 12.8895 17.5323 12.1429 17.7144 11.4214C17.7808 11.1594 17.8118 10.769 17.8118 10.3836C17.8118 9.99752 17.7807 9.59879 17.715 9.31905L17.715 9.319C17.2151 7.19077 15.1037 5.77026 12.9072 6.06661C11.167 6.29605 9.73096 7.57041 9.29241 9.27619C9.22583 9.52546 9.19154 9.90933 9.18579 10.2877C9.18002 10.6675 9.20276 11.0608 9.25801 11.3301L9.25806 11.3303C9.30092 11.5375 9.47027 11.9741 9.6273 12.3078L9.62808 12.3095L9.62809 12.3095C9.85584 12.7784 10.0341 13.0394 10.3851 13.3972L10.3853 13.3974L10.6591 13.6752L10.3406 13.7813L10.34 13.7815C8.84605 14.2862 7.62497 15.6151 7.2349 17.1481C7.12575 17.5711 7.1 17.9063 7.1 18.7934C7.1 19.3226 7.10136 19.6137 7.12381 19.8046C7.13547 19.9036 7.15326 19.9812 7.18129 20.0545C7.20864 20.1261 7.24394 20.1886 7.28308 20.2555C7.39392 20.4474 7.5949 20.6484 7.78679 20.7591C7.78687 20.7592 7.78694 20.7592 7.78702 20.7593L8.06653 20.9218L8.10149 20.9421H8.14193H13.5H18.8581H18.8985L18.9335 20.9218L19.213 20.7593C19.213 20.7593 19.2131 20.7592 19.2131 20.7592C19.4051 20.6484 19.6061 20.4474 19.7169 20.2555ZM19.7169 20.2555C19.717 20.2554 19.7171 20.2552 19.7172 20.2551L19.5872 20.1801L19.7167 20.2559C19.7168 20.2558 19.7169 20.2556 19.7169 20.2555ZM14.3606 7.58254L14.3599 7.58233C13.5947 7.34167 12.6188 7.47247 11.9597 7.89114C11.0841 8.45651 10.5901 9.35333 10.5901 10.382C10.5901 11.2305 10.8905 11.9143 11.5456 12.5319L11.5456 12.5319C12.0893 13.0448 12.703 13.2853 13.5 13.2853C14.3197 13.2853 14.9335 13.0341 15.531 12.4552L15.5316 12.4546C16.1264 11.8846 16.4099 11.2079 16.4099 10.3754C16.4099 9.55444 16.1707 8.96017 15.6117 8.37632L15.6109 8.37543C15.2047 7.94423 14.8817 7.74382 14.3606 7.58254ZM15.7673 15.0129L15.7663 15.0126C15.3468 14.9016 15.0954 14.8874 13.4746 14.8939H13.474C11.8987 14.8939 11.5948 14.9145 11.2203 15.0127L11.22 15.0128C9.94165 15.3449 8.96771 16.2766 8.60518 17.4999C8.55776 17.6733 8.49341 18.1916 8.46746 18.6457L8.46746 18.6458C8.44432 19.0491 8.43591 19.244 8.4474 19.3568C8.45269 19.4087 8.46135 19.4314 8.46841 19.4446C8.4763 19.4595 8.48841 19.4746 8.52143 19.5077L8.61422 19.6004H13.5H18.3858L18.4786 19.5077C18.5116 19.4746 18.5237 19.4595 18.5316 19.4446C18.5387 19.4314 18.5473 19.4087 18.5526 19.3568C18.5641 19.244 18.5557 19.0491 18.5325 18.6458L18.5325 18.6457C18.5066 18.1917 18.4423 17.6736 18.3949 17.5001C18.0259 16.264 17.0587 15.3452 15.7673 15.0129ZM8.41536 19.6137C8.27865 19.477 8.27214 19.4314 8.31771 18.6372L8.55208 19.7504L8.41536 19.6137Z" fill="#004717" stroke="#004717" stroke-width="0.3"/>
|
||||
<path d="M1.22097 17.9849C1.36074 17.9241 1.52242 17.921 1.66423 17.9519C1.80571 17.9827 1.9487 18.052 2.04388 18.1608L2.04399 18.1607L2.04812 18.1659C2.09512 18.2246 2.12219 18.292 2.14012 18.3978C2.15724 18.4988 2.16798 18.6471 2.17531 18.8773C2.19006 19.3402 2.19167 20.1652 2.19167 21.6775V24.8088H5.30339C6.28371 24.8088 7.10996 24.8153 7.70049 24.8267C7.99558 24.8324 8.23282 24.8394 8.40135 24.8474C8.48538 24.8514 8.55396 24.8558 8.60472 24.8605C8.62989 24.8629 8.6528 24.8656 8.67193 24.8687C8.68144 24.8703 8.69195 24.8722 8.70234 24.8749C8.70995 24.8768 8.72705 24.8814 8.74534 24.891C8.89141 24.9667 8.98679 25.1113 9.03232 25.2588C9.07817 25.4073 9.08075 25.5809 9.01589 25.733M1.22097 17.9849C1.16165 18.0099 1.10541 18.0503 1.05999 18.0918C1.01471 18.1332 0.970638 18.1842 0.940974 18.2379C0.924837 18.2663 0.918305 18.2965 0.915428 18.3102C0.911126 18.3307 0.907629 18.3544 0.90462 18.3799C0.898557 18.4312 0.893319 18.4997 0.888679 18.5839C0.879369 18.753 0.872006 18.9945 0.866301 19.3083C0.854881 19.9363 0.85 20.8604 0.85 22.0877V22.0959C0.85 23.8725 0.85 24.7871 0.866361 25.2731C0.874474 25.514 0.886798 25.6613 0.908538 25.7587C0.919918 25.8096 0.935053 25.8528 0.957087 25.8912C0.979442 25.9302 1.00475 25.9569 1.02414 25.9763C1.04354 25.9957 1.0702 26.021 1.10921 26.0434C1.14765 26.0654 1.19081 26.0805 1.24176 26.0919C1.33911 26.1136 1.48641 26.126 1.72737 26.1341C2.2133 26.1504 3.12797 26.1504 4.90458 26.1504H4.91276C6.01672 26.1504 6.94052 26.1439 7.59766 26.1325C7.92606 26.1268 8.18879 26.1199 8.37443 26.1119C8.46702 26.1079 8.54198 26.1035 8.5969 26.0988C8.62414 26.0965 8.64852 26.0938 8.66855 26.0908C8.67847 26.0893 8.68935 26.0874 8.69997 26.0848C8.70711 26.0831 8.72509 26.0787 8.7443 26.0688C8.80679 26.0371 8.86207 25.9785 8.90253 25.9264C8.94619 25.8701 8.98739 25.8019 9.01589 25.733M1.22097 17.9849C1.22059 17.9851 1.22021 17.9852 1.21982 17.9854L1.27995 18.1228L1.22226 17.9844C1.22183 17.9846 1.2214 17.9847 1.22097 17.9849ZM9.01589 25.733C9.01603 25.7327 9.01617 25.7324 9.01631 25.732L8.87761 25.6749L9.01548 25.734C9.01562 25.7337 9.01575 25.7334 9.01589 25.733Z" fill="#004717" stroke="#004717" stroke-width="0.3"/>
|
||||
<path d="M24.8979 18.2405L24.8983 18.2398C24.9279 18.1854 24.9725 18.1336 25.0183 18.0918C25.0637 18.0503 25.12 18.0099 25.1793 17.9849C25.3191 17.9241 25.4808 17.921 25.6226 17.9519C25.764 17.9827 25.907 18.052 26.0022 18.1608L26.0023 18.1607L26.0065 18.1659C26.0549 18.2264 26.0813 18.2968 26.0988 18.4085C26.1156 18.5165 26.1263 18.6783 26.1337 18.934C26.1484 19.4478 26.15 20.3702 26.15 22.0682V22.0766C26.15 23.8628 26.15 24.7823 26.1336 25.2706C26.1255 25.5128 26.1132 25.6607 26.0915 25.7583C26.0801 25.8093 26.065 25.8526 26.043 25.8911C26.0206 25.9302 25.9953 25.9569 25.9759 25.9763C25.9565 25.9957 25.9298 26.021 25.8907 26.0434C25.8521 26.0654 25.8089 26.0806 25.7578 26.0919C25.6602 26.1136 25.5123 26.126 25.2702 26.1341C24.7818 26.1504 23.8623 26.1504 22.0759 26.1504H22.0677C20.3179 26.1504 19.395 26.1488 18.8923 26.1325C18.6424 26.1243 18.4873 26.1124 18.3835 26.093C18.2711 26.0719 18.2095 26.0403 18.1526 25.994C18.0788 25.9364 18.0208 25.869 17.9845 25.7772C17.9499 25.6894 17.9398 25.5908 17.9398 25.4796C17.9398 25.3684 17.9499 25.2698 17.9845 25.182C18.0208 25.0902 18.0788 25.0228 18.1526 24.9652C18.2078 24.9203 18.2679 24.8882 18.3744 24.8667C18.4723 24.8469 18.6152 24.8349 18.8404 24.8268C19.2939 24.8104 20.1195 24.8088 21.6771 24.8088H24.8083V21.6971C24.8083 20.6062 24.8148 19.7797 24.8271 19.215C24.8332 18.9328 24.8408 18.7146 24.8498 18.5608C24.8543 18.4842 24.8592 18.4216 24.8648 18.3744C24.8676 18.3509 24.8708 18.329 24.8746 18.31C24.8774 18.2958 24.8836 18.2671 24.8979 18.2405Z" fill="#004717" stroke="#004717" stroke-width="0.3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
BIN
src/Images/dash_icon_3n.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
3
src/Images/dash_icon_4.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="25" height="26" viewBox="0 0 25 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M24.125 15.8268L22.8695 14.5725C22.6775 14.379 22.4489 14.2255 22.197 14.1211C21.9452 14.0167 21.6751 13.9635 21.4024 13.9644C21.1293 13.9639 20.8588 14.0177 20.6067 14.1227C20.3546 14.2278 20.126 14.382 19.9341 14.5763L12.9775 21.5646C12.8894 21.6525 12.8195 21.7569 12.7718 21.872C12.7242 21.987 12.6998 22.1103 12.7001 22.2348V25.0498C12.7001 25.3018 12.8002 25.5435 12.9784 25.7217C13.1566 25.8999 13.3982 26 13.6502 26H16.4666C16.7178 25.9996 16.9588 25.8999 17.1368 25.7225L24.125 18.7673C24.3182 18.5743 24.4716 18.3451 24.5762 18.0928C24.6808 17.8405 24.7346 17.5701 24.7346 17.297C24.7346 17.0239 24.6808 16.7535 24.5762 16.5012C24.4716 16.2489 24.3182 16.0197 24.125 15.8268ZM21.4024 15.8648C21.426 15.8642 21.4494 15.8685 21.4712 15.8774C21.493 15.8864 21.5127 15.8997 21.5291 15.9167L22.7833 17.171C22.8001 17.1875 22.8133 17.2072 22.8222 17.229C22.8312 17.2508 22.8356 17.2741 22.8353 17.2976C22.8357 17.3212 22.8314 17.3446 22.8224 17.3664C22.8135 17.3882 22.8002 17.4079 22.7833 17.4243L21.9776 18.2263L20.4776 16.7263L21.2795 15.9205C21.2953 15.9036 21.3143 15.89 21.3354 15.8804C21.3565 15.8708 21.3793 15.8655 21.4024 15.8648ZM16.0713 24.0996H14.5979V22.6262L19.1347 18.0654L20.6283 19.5591L16.0713 24.0996ZM9.84699 22.8327H4.77939C2.78148 22.8327 1.92886 21.9801 1.92886 19.9822V4.77939C1.92886 2.78148 2.78148 1.92886 4.77939 1.92886H11.4306V4.77939C11.3562 5.42127 11.4279 6.07168 11.6404 6.68194C11.8528 7.2922 12.2005 7.84653 12.6574 8.30345C13.1144 8.76037 13.6687 9.10806 14.279 9.32051C14.8892 9.53296 15.5396 9.60467 16.1815 9.53027H19.032V11.1139C19.032 11.3659 19.1321 11.6076 19.3103 11.7858C19.4885 11.964 19.7302 12.0641 19.9822 12.0641C20.2342 12.0641 20.4759 11.964 20.6541 11.7858C20.8323 11.6076 20.9324 11.3659 20.9324 11.1139V8.58009C20.9325 8.45532 20.9079 8.33177 20.8601 8.21653C20.8122 8.1013 20.7421 7.99666 20.6537 7.90863L13.0523 0.30722C12.9642 0.218794 12.8596 0.148646 12.7444 0.100813C12.6291 0.0529792 12.5056 0.0284043 12.3808 0.028502H4.77939C4.1375 -0.0458957 3.4871 0.0258118 2.87683 0.23826C2.26657 0.450709 1.71224 0.798399 1.25532 1.25532C0.798399 1.71224 0.450709 2.26657 0.23826 2.87683C0.0258118 3.4871 -0.0458957 4.1375 0.028502 4.77939V19.9822C-0.0458957 20.6241 0.0258118 21.2745 0.23826 21.8848C0.450709 22.495 0.798399 23.0494 1.25532 23.5063C1.71224 23.9632 2.26657 24.3109 2.87683 24.5233C3.4871 24.7358 4.1375 24.8075 4.77939 24.7331H9.84699C10.099 24.7331 10.3407 24.633 10.5189 24.4548C10.6971 24.2766 10.7972 24.0349 10.7972 23.7829C10.7972 23.5309 10.6971 23.2892 10.5189 23.111C10.3407 22.9328 10.099 22.8327 9.84699 22.8327ZM13.331 4.77939V3.27304L17.6879 7.62992H16.1815C14.1836 7.62992 13.331 6.77729 13.331 4.77939ZM6.04629 11.4306C5.79429 11.4306 5.5526 11.5307 5.37441 11.7089C5.19622 11.8871 5.09611 12.1288 5.09611 12.3808C5.09611 12.6328 5.19622 12.8745 5.37441 13.0527C5.5526 13.2309 5.79429 13.331 6.04629 13.331H14.9146C15.1666 13.331 15.4083 13.2309 15.5865 13.0527C15.7647 12.8745 15.8648 12.6328 15.8648 12.3808C15.8648 12.1288 15.7647 11.8871 15.5865 11.7089C15.4083 11.5307 15.1666 11.4306 14.9146 11.4306H6.04629ZM11.1139 16.4982H6.04629C5.79429 16.4982 5.5526 16.5983 5.37441 16.7765C5.19622 16.9547 5.09611 17.1964 5.09611 17.4484C5.09611 17.7004 5.19622 17.9421 5.37441 18.1203C5.5526 18.2985 5.79429 18.3986 6.04629 18.3986H11.1139C11.3659 18.3986 11.6076 18.2985 11.7858 18.1203C11.964 17.9421 12.0641 17.7004 12.0641 17.4484C12.0641 17.1964 11.964 16.9547 11.7858 16.7765C11.6076 16.5983 11.3659 16.4982 11.1139 16.4982Z" fill="#004717"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
3
src/Images/dash_icon_5.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="36" height="24" viewBox="0 0 36 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.5257 11.8995C11.9061 11.3689 11.1971 10.946 10.4241 10.6563C11.3784 9.91683 12.0006 8.75408 12.0006 7.45123C12.0006 5.20903 10.187 3.39548 7.94484 3.39548C5.70264 3.39548 3.88909 5.20903 3.88909 7.45123C3.88909 8.75391 4.50502 9.91698 5.4651 10.6567C2.79743 11.6588 0.9 14.2336 0.9 17.2481V17.7005C0.9 17.7399 0.918683 17.7709 0.937861 17.7901C0.957039 17.8093 0.988047 17.828 1.02742 17.828H9.29909C9.25911 18.1738 9.23655 18.53 9.23655 18.8866V19.3528C9.23655 21.4236 10.913 23.1 12.9838 23.1H23.6102C25.681 23.1 27.3574 21.4236 27.3574 19.3528V18.8866C27.3574 18.53 27.3348 18.1738 27.2949 17.828H35.6214C35.6607 17.828 35.6918 17.8093 35.7109 17.7901C35.7301 17.7709 35.7488 17.7399 35.7488 17.7005L35.7488 17.2481L35.7488 17.2476C35.7352 14.2268 33.8442 11.6517 31.1762 10.6496C32.1306 9.9101 32.7528 8.74729 32.7528 7.44438C32.7528 5.20217 30.9393 3.38863 28.6971 3.38863C26.4549 3.38863 24.6413 5.20217 24.6413 7.44438C24.6413 8.74713 25.2573 9.91024 26.2175 10.65C25.4315 10.9457 24.7099 11.3755 24.0884 11.9192C23.2212 11.1947 22.2146 10.6295 21.117 10.2719C22.4903 9.35643 23.4016 7.78683 23.4016 6.01153C23.4016 3.18659 21.1151 0.9 18.2901 0.9C15.4651 0.9 13.1786 3.19354 13.1786 6.01153C13.1786 7.78699 14.0838 9.35703 15.4635 10.2726C14.3792 10.6294 13.3856 11.1879 12.5257 11.8995ZM25.9383 7.43752C25.9383 5.91593 27.1755 4.67868 28.6971 4.67868C30.2187 4.67868 31.4559 5.91593 31.4559 7.43752C31.4559 8.93853 30.2459 10.1627 28.7508 10.1964H28.6431C27.1419 10.1694 25.9383 8.94585 25.9383 7.43752ZM14.4618 6.01153C14.4618 3.90721 16.1721 2.19692 18.2764 2.19692C20.3807 2.19692 22.091 3.90721 22.091 6.01153C22.091 8.04131 20.4958 9.70433 18.4998 9.81929H18.053C16.057 9.70433 14.4618 8.04131 14.4618 6.01153ZM5.16544 7.43752C5.16544 5.91593 6.40269 4.67868 7.92427 4.67868C9.44586 4.67868 10.6831 5.91593 10.6831 7.43752C10.6831 8.93853 9.47305 10.1627 7.97802 10.1964H7.87029C6.37576 10.1694 5.16544 8.94569 5.16544 7.43752ZM11.5575 12.7948C10.6118 13.8433 9.90437 15.119 9.5269 16.5242H2.22283C2.57581 13.7067 4.97707 11.5134 7.88341 11.4933H7.96532C9.3291 11.4999 10.5782 11.9915 11.5575 12.7948ZM26.0468 19.3528C26.0468 20.703 24.9466 21.8031 23.5964 21.8031H12.9701C11.6199 21.8031 10.5198 20.703 10.5198 19.3528V18.8866C10.5198 14.6853 13.874 11.248 18.0473 11.1232C18.1255 11.1299 18.209 11.1299 18.2811 11.1299H18.2833H18.2855C18.3575 11.1299 18.4411 11.1299 18.5193 11.1232C22.6926 11.248 26.0468 14.6853 26.0468 18.8866V19.3528ZM34.3985 16.5242H27.0395C26.6624 15.126 25.9676 13.8694 25.0288 12.8218C26.0149 11.9992 27.2778 11.5065 28.6564 11.4933H28.738C31.6443 11.5134 34.0456 13.7067 34.3985 16.5242Z" fill="#004717" stroke="#004717" stroke-width="0.2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
5
src/Images/dash_icon_6.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg width="26" height="24" viewBox="0 0 26 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6.88412 15.6108L6.88412 15.6108H6.88636H8.75862V15.6108L8.76086 15.6108C9.11843 15.6028 9.47392 15.6673 9.80586 15.8004C10.1378 15.9336 10.4393 16.1326 10.6922 16.3856C10.9451 16.6385 11.1442 16.94 11.2773 17.2719C11.4105 17.6039 11.475 17.9594 11.467 18.3169H11.467V18.3192V18.5532C11.467 18.7129 11.4036 18.866 11.2906 18.979C11.1777 19.0919 11.0246 19.1553 10.8649 19.1553H4.78008C4.62039 19.1553 4.46725 19.0919 4.35433 18.979C4.24142 18.866 4.17798 18.7129 4.17798 18.5532V18.3192H4.17801L4.17796 18.3169C4.16995 17.9594 4.23447 17.6039 4.36763 17.2719C4.50079 16.94 4.69983 16.6385 4.95274 16.3856C5.20564 16.1326 5.50717 15.9336 5.83912 15.8004C6.17106 15.6673 6.52655 15.6028 6.88412 15.6108ZM3.77206 16.0109C3.27964 16.6786 3.02281 17.4909 3.04186 18.3203V18.5532C3.04186 19.0142 3.22499 19.4563 3.55097 19.7823C3.87695 20.1083 4.31907 20.2914 4.78008 20.2914H10.8649C11.3259 20.2914 11.768 20.1083 12.094 19.7823C12.42 19.4563 12.6031 19.0142 12.6031 18.5532V18.3203C12.6222 17.4909 12.3653 16.6786 11.8729 16.0109C11.4146 15.3894 10.7763 14.9259 10.0467 14.6817C10.4535 14.2742 10.7413 13.7618 10.877 13.1999C11.0264 12.5817 10.9846 11.9326 10.7573 11.3386C10.5299 10.7446 10.1276 10.2335 9.60362 9.87302C9.07961 9.51251 8.45854 9.31949 7.82249 9.31949C7.18644 9.31949 6.56537 9.51251 6.04136 9.87302C5.51735 10.2335 5.11507 10.7446 4.88771 11.3386C4.66034 11.9326 4.61859 12.5817 4.76797 13.1999C4.90372 13.7618 5.19153 14.2742 5.59829 14.6817C4.86865 14.9259 4.23038 15.3894 3.77206 16.0109ZM7.82249 10.4621C8.2193 10.4621 8.60719 10.5798 8.93712 10.8002C9.26705 11.0207 9.5242 11.334 9.67605 11.7006C9.82791 12.0672 9.86764 12.4706 9.79022 12.8598C9.71281 13.249 9.52173 13.6065 9.24115 13.887C8.96056 14.1676 8.60308 14.3587 8.2139 14.4361C7.82472 14.5135 7.42132 14.4738 7.05472 14.322C6.68812 14.1701 6.37478 13.9129 6.15432 13.583C5.93387 13.2531 5.8162 12.8652 5.8162 12.4684C5.8162 11.9363 6.02758 11.426 6.40383 11.0497C6.78008 10.6735 7.29039 10.4621 7.82249 10.4621Z" fill="#004717" stroke="#004717" stroke-width="0.2"/>
|
||||
<path d="M21.8554 6.21372L21.8555 6.2138C21.9634 6.11569 22.1049 6.06283 22.2507 6.06616C22.3965 6.06949 22.5354 6.12875 22.6387 6.23168C22.742 6.33461 22.8017 6.47332 22.8056 6.6191C22.8094 6.76487 22.757 6.90654 22.6593 7.01477L22.6559 7.01855L22.6558 7.01846L19.3796 10.2947L21.8554 6.21372ZM21.8554 6.21372L21.8521 6.21707M21.8554 6.21372L21.8521 6.21707M21.8521 6.21707L18.9787 9.09048M21.8521 6.21707L18.9787 9.09048M18.9791 10.4623L18.9788 10.4623C18.9038 10.4623 18.8296 10.4476 18.7603 10.4188C18.6912 10.3901 18.6284 10.348 18.5756 10.2949L18.9791 10.4623ZM18.9791 10.4623C19.1294 10.4616 19.2733 10.4015 19.3794 10.2949L18.9791 10.4623ZM18.9787 9.09048L17.1959 7.30766C17.0893 7.20108 16.9447 7.1412 16.794 7.1412C16.6433 7.1412 16.4987 7.20108 16.3921 7.30766C16.2855 7.41424 16.2257 7.5588 16.2257 7.70952C16.2257 7.86025 16.2855 8.00481 16.3921 8.11139L18.5754 10.2947L18.9787 9.09048ZM22.3323 14.9429C22.1817 14.9429 22.0372 15.0028 21.9307 15.1093C21.8241 15.2158 21.7643 15.3603 21.7643 15.511V21.3618C21.7643 21.5214 21.7008 21.6746 21.5879 21.7875C21.475 21.9004 21.3219 21.9639 21.1622 21.9639H1.9716C1.81191 21.9639 1.65876 21.9004 1.54585 21.7875C1.43294 21.6746 1.3695 21.5214 1.3695 21.3618V7.78793C1.3695 7.62824 1.43294 7.47509 1.54585 7.36218C1.65876 7.24927 1.81191 7.18583 1.9716 7.18583H12.269C12.4196 7.18583 12.5641 7.12598 12.6707 7.01945C12.7772 6.91292 12.8371 6.76843 12.8371 6.61777C12.8371 6.46711 12.7772 6.32262 12.6707 6.21609C12.5641 6.10955 12.4196 6.0497 12.269 6.0497H1.9716C1.51059 6.0497 1.06847 6.23284 0.742487 6.55882C0.416508 6.8848 0.233374 7.32692 0.233374 7.78793V21.3618C0.233374 21.8228 0.416508 22.2649 0.742487 22.5909C1.06847 22.9168 1.51059 23.1 1.9716 23.1H21.1622C21.6232 23.1 22.0653 22.9168 22.3913 22.5909C22.7173 22.2649 22.9004 21.8228 22.9004 21.3618V15.511C22.9004 15.3603 22.8406 15.2158 22.734 15.1093C22.6275 15.0028 22.483 14.9429 22.3323 14.9429Z" fill="#004717" stroke="#004717" stroke-width="0.2"/>
|
||||
<path d="M25.3058 3.67485L25.3058 3.67474C25.2917 3.54354 25.2325 3.42133 25.1381 3.32908C25.0444 3.23737 24.9217 3.18095 24.7911 3.16936C23.9086 3.055 23.0469 2.81493 22.2323 2.45646L22.2323 2.45644L22.2305 2.45567C21.3893 2.10541 20.6056 1.63065 19.9057 1.04733C19.8012 0.952547 19.6652 0.900015 19.524 0.900015C19.3829 0.900015 19.2469 0.952552 19.1424 1.04734C18.4426 1.63091 17.6589 2.10569 16.8177 2.45566L16.8177 2.45564L16.8158 2.45647C16.0056 2.8134 15.1488 3.05342 14.2711 3.16934C14.1401 3.18039 14.017 3.23651 13.9228 3.32819C13.8279 3.4205 13.7682 3.54306 13.754 3.67469L13.754 3.67485C13.7433 3.77648 13.6206 4.99904 13.6455 6.48637C13.6704 7.96886 13.842 9.73448 14.431 10.9103L14.4311 10.9103C15.1328 12.309 16.3173 13.3963 17.3378 14.1402C18.3451 14.8745 19.2002 15.2797 19.2928 15.3235L19.2963 15.3252L19.2972 15.3256C19.3719 15.3602 19.4534 15.3781 19.5358 15.3781C19.6181 15.3781 19.6996 15.3602 19.7743 15.3256L19.7752 15.3252L19.7787 15.3235C19.8713 15.2796 20.7264 14.8745 21.7337 14.1402C22.7542 13.3963 23.9387 12.309 24.6404 10.9103L24.6406 10.9099C25.2237 9.73421 25.3923 7.96873 25.4157 6.48627C25.4392 4.99899 25.3165 3.77646 25.3058 3.67485ZM23.6121 10.4017L23.6121 10.4018C23.0959 11.433 22.2396 12.2905 21.42 12.9377C20.636 13.557 19.8913 13.9794 19.5241 14.174C19.1569 13.9794 18.4121 13.557 17.6281 12.9377C16.8085 12.2905 15.9522 11.433 15.436 10.4018C15.0156 9.56088 14.8438 8.287 14.79 7.07033C14.7388 5.91103 14.7951 4.81856 14.8369 4.2336C15.6706 4.08231 16.4845 3.83662 17.2628 3.50119C18.0667 3.16119 18.8261 2.72441 19.524 2.2006C20.222 2.72441 20.9814 3.16119 21.7853 3.50119C22.5637 3.83664 23.3776 4.08234 24.2114 4.23363C24.2542 4.81842 24.3111 5.91094 24.2598 7.07033C24.2061 8.28699 24.0337 9.56085 23.6121 10.4017ZM14.8434 20.2916H19.524C19.6747 20.2916 19.8192 20.2318 19.9257 20.1252C20.0323 20.0187 20.0921 19.8742 20.0921 19.7236C20.0921 19.5729 20.0323 19.4284 19.9257 19.3219C19.8192 19.2154 19.6747 19.1555 19.524 19.1555H14.8434C14.6928 19.1555 14.5483 19.2154 14.4417 19.3219C14.3352 19.4284 14.2754 19.5729 14.2754 19.7236C14.2754 19.8742 14.3352 20.0187 14.4417 20.1252C14.5483 20.2318 14.6928 20.2916 14.8434 20.2916ZM14.8434 17.4832H17.6518C17.8025 17.4832 17.9469 17.4234 18.0535 17.3169C18.16 17.2103 18.2199 17.0658 18.2199 16.9152C18.2199 16.7645 18.16 16.62 18.0535 16.5135C17.9469 16.407 17.8025 16.3471 17.6518 16.3471H14.8434C14.6928 16.3471 14.5483 16.407 14.4417 16.5135C14.3352 16.62 14.2754 16.7645 14.2754 16.9152C14.2754 17.0658 14.3352 17.2103 14.4417 17.3169C14.5483 17.4234 14.6928 17.4832 14.8434 17.4832Z" fill="#004717" stroke="#004717" stroke-width="0.2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.6 KiB |
BIN
src/Images/dash_icon_6n.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
3
src/Images/dash_icon_7.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="21" height="21" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.3266 4.69537e-06C9.04078 -0.00159744 7.78798 0.406843 6.75022 1.16597C5.71246 1.92511 4.9438 2.99538 4.55594 4.22126C4.16807 5.44715 4.18122 6.76477 4.59346 7.98268C5.0057 9.20058 5.79556 10.2553 6.84826 10.9936C5.02658 11.7216 3.46442 12.9781 2.36278 14.6013C1.26114 16.2245 0.670418 18.1403 0.666626 20.102C0.681557 20.3447 0.788501 20.5726 0.965653 20.7392C1.14281 20.9058 1.37683 20.9986 1.62 20.9986C1.86318 20.9986 2.0972 20.9058 2.27435 20.7392C2.45151 20.5726 2.55845 20.3447 2.57338 20.102C2.57019 18.6931 2.94414 17.3091 3.6564 16.0935C4.36867 14.8779 5.3933 13.8751 6.62395 13.1891C7.85459 12.5032 9.24639 12.1591 10.6549 12.1926C12.0634 12.2262 13.4373 12.636 14.6339 13.3797C14.7409 13.446 14.8598 13.4905 14.984 13.5108C15.1082 13.5311 15.2352 13.5267 15.3577 13.498C15.4802 13.4692 15.5958 13.4165 15.698 13.3431C15.8001 13.2696 15.8868 13.1767 15.9531 13.0697C16.0194 12.9628 16.0639 12.8438 16.0842 12.7196C16.1045 12.5954 16.1001 12.4684 16.0713 12.3459C16.0425 12.2234 15.9899 12.1078 15.9164 12.0056C15.843 11.9035 15.7501 11.8168 15.6431 11.7505C15.0892 11.4171 14.5036 11.1394 13.895 10.9215C15.398 9.82213 16.382 8.05235 16.382 6.05548C16.382 2.72857 13.6535 4.69537e-06 10.3266 4.69537e-06ZM10.3266 1.91036C12.6226 1.91036 14.4717 3.75945 14.4717 6.05548C14.4717 8.35152 12.6226 10.197 10.3266 10.197C8.03052 10.197 6.18504 8.35873 6.18504 6.05548C6.18504 3.75945 8.02692 1.91036 10.3266 1.91036ZM19.9757 13.3581C19.8208 13.3625 19.6694 13.4045 19.5343 13.4805C19.3993 13.5565 19.2848 13.6641 19.2007 13.7942L15.9135 18.7215L13.8517 17.341C13.7473 17.264 13.6284 17.2089 13.5021 17.1792C13.3759 17.1494 13.2449 17.1456 13.1171 17.1679C12.9893 17.1903 12.8673 17.2384 12.7587 17.3092C12.65 17.3801 12.5568 17.4722 12.4848 17.5801C12.4128 17.688 12.3634 17.8094 12.3397 17.937C12.3159 18.0645 12.3183 18.1956 12.3467 18.3222C12.3751 18.4487 12.4289 18.5683 12.5048 18.6735C12.5807 18.7787 12.6772 18.8674 12.7884 18.9342L15.6539 20.8409C15.8648 20.9807 16.1225 21.0312 16.3705 20.9812C16.6185 20.9311 16.8365 20.7848 16.9768 20.5742L20.7939 14.8503C20.893 14.7048 20.9499 14.5346 20.9584 14.3587C20.9668 14.1828 20.9265 14.008 20.8418 13.8536C20.7572 13.6992 20.6315 13.5712 20.4786 13.4838C20.3257 13.3963 20.1517 13.3528 19.9757 13.3581Z" fill="#004717"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -1,6 +1,5 @@
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { CgProfile } from "react-icons/cg";
|
||||
import { useDispatch } from "react-redux";
|
||||
import logoMiniDark from "../assets/favicon.png";
|
||||
import logoMini from "../assets/logo-min.png";
|
||||
import logoDark from "../assets/logo.png";
|
||||
@@ -24,23 +23,26 @@ import {
|
||||
Button,
|
||||
Image,
|
||||
Text,
|
||||
Tooltip
|
||||
Tooltip,
|
||||
} from "@chakra-ui/react";
|
||||
import Cookies from "js-cookie"; // Import the Cookies library
|
||||
import { GrManual } from "react-icons/gr";
|
||||
import { HiOutlineChartSquareBar } from "react-icons/hi";
|
||||
import { HiOutlineBanknotes } from "react-icons/hi2";
|
||||
import { LuContact } from "react-icons/lu";
|
||||
import { MdNotificationsNone, MdOutlineAddChart } from "react-icons/md";
|
||||
import {
|
||||
RiAccountBoxLine,
|
||||
RiBankLine,
|
||||
RiExchangeBoxLine,
|
||||
RiFileUserLine,
|
||||
RiMoneyDollarBoxLine,
|
||||
} from "react-icons/ri";
|
||||
import {
|
||||
TbLayoutDashboard,
|
||||
TbListDetails,
|
||||
TbReportMoney,
|
||||
TbTransactionDollar
|
||||
TbTransactionDollar,
|
||||
} from "react-icons/tb";
|
||||
import { VscSymbolClass } from "react-icons/vsc";
|
||||
import {
|
||||
@@ -52,6 +54,7 @@ import {
|
||||
useNavigate,
|
||||
} from "react-router-dom";
|
||||
import HeaderMain from "../Components/HeaderMain";
|
||||
import { isMaker } from "../Constants/Constants";
|
||||
import GlobalStateContext from "../Contexts/GlobalStateContext";
|
||||
import CreateRequest from "../Pages/Fawateer/CreateRequest";
|
||||
import ApproveHistory from "../Pages/FawateerChecker/ApproveHistory/ApproveHistoryChecker";
|
||||
@@ -139,6 +142,21 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
switch (true) {
|
||||
case "/":
|
||||
return "👋🏻 Hi, Admin";
|
||||
|
||||
// case path.startsWith("/"):
|
||||
// return (z
|
||||
// <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">
|
||||
<TbLayoutDashboard className="h4 m-0" />
|
||||
dashboard / Open Opportunities
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/sponser"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
@@ -148,7 +166,7 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
case path.startsWith("/email"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<AtSignIcon className="h4 m-0" /> Email Notifiation
|
||||
<AtSignIcon className="h4 m-0" /> Email Notification
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/investment-type"):
|
||||
@@ -167,7 +185,7 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<RiExchangeBoxLine className="h4 m-0 fw-normal" />
|
||||
Echange rate
|
||||
Exchange rate
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/create-io"):
|
||||
@@ -218,7 +236,7 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<RiExchangeBoxLine className="h4 m-0 fw-normal" />
|
||||
Deposite Request
|
||||
Deposit Request
|
||||
</span>
|
||||
);
|
||||
|
||||
@@ -241,21 +259,21 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
|
||||
Withdrawal pending request
|
||||
Withdrawal Pending Request
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/withdraw-history"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<RiExchangeBoxLine className="h4 m-0 fw-normal" />
|
||||
Withdrawal request
|
||||
Withdrawal Request
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/investor-request"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
|
||||
Investor pending request
|
||||
Investor Pending Request
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/investor-history"):
|
||||
@@ -269,16 +287,39 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
|
||||
Deletion pending request
|
||||
Deletion Pending Request
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/deletion-history"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<RiExchangeBoxLine className="h4 m-0 fw-normal" />
|
||||
Deletion request
|
||||
Deletion Request
|
||||
</span>
|
||||
);
|
||||
|
||||
case path.startsWith("/bank-deposit-request"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<RiBankLine className="h4 m-0 fw-normal" />
|
||||
Reversal Transaction / Deposit Request
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/reversal-fawateer-deposit"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<HiOutlineBanknotes className="h4 m-0 fw-normal" />
|
||||
Reversal Transaction / Fawateer Deposit
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/account-deletion-request"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<RiAccountBoxLine className="h4 m-0 fw-normal" />
|
||||
Reversal Transaction / Account Deletion Request
|
||||
</span>
|
||||
);
|
||||
|
||||
case path.startsWith("/bank-investor"):
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
@@ -297,7 +338,7 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<MdNotificationsNone className="h4 m-0 fw-normal" />
|
||||
Notification
|
||||
Push Notification
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/contact"):
|
||||
@@ -325,7 +366,7 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
|
||||
Deletion pending request
|
||||
Deletion Pending Request
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/deletion-history"):
|
||||
@@ -339,7 +380,7 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
return (
|
||||
<span className="d-flex align-items-end gap-2">
|
||||
<RiMoneyDollarBoxLine className="h4 m-0 fw-normal" />
|
||||
Deletion pending request
|
||||
Deletion Pending Request
|
||||
</span>
|
||||
);
|
||||
case path.startsWith("/deletion-history"):
|
||||
@@ -385,7 +426,17 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
return <SplashScreen />;
|
||||
}
|
||||
|
||||
const filteredNav = nav.map((item) => {
|
||||
const _filteredNav = isMaker()
|
||||
? nav.filter(
|
||||
(item) =>
|
||||
item.title !== "REVERSAL TRANSACTION" &&
|
||||
item.path !== "/bank-deposit-request" &&
|
||||
item.path !== "/reversal-fawateer-deposit" &&
|
||||
item.path !== "/account-deletion-request"
|
||||
)
|
||||
: nav;
|
||||
|
||||
const filteredNav = _filteredNav.map((item) => {
|
||||
if (item.submenu) {
|
||||
return {
|
||||
...item,
|
||||
@@ -395,6 +446,9 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
),
|
||||
};
|
||||
}
|
||||
// if (item.title === "REVERSAL TRANSACTION" && item.type === "title") {
|
||||
// }
|
||||
|
||||
return item;
|
||||
});
|
||||
|
||||
@@ -515,7 +569,8 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
index={openIndex}
|
||||
onChange={handleAccordionChange}
|
||||
>
|
||||
{filteredNav.map(({ title, type, Icon, submenu, path }, index) => {
|
||||
{filteredNav.map(
|
||||
({ title, type, Icon, submenu, path }, index) => {
|
||||
if (type === "accordion") {
|
||||
return (
|
||||
<AccordionItem key={index} border={"none"}>
|
||||
@@ -575,7 +630,11 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
>
|
||||
{submenu?.map(
|
||||
(
|
||||
{ title: subMenuTitle, path: link, icon: SubIcon },
|
||||
{
|
||||
title: subMenuTitle,
|
||||
path: link,
|
||||
icon: SubIcon,
|
||||
},
|
||||
i
|
||||
) => (
|
||||
<Tooltip
|
||||
@@ -589,7 +648,10 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
>
|
||||
<Box
|
||||
key={i}
|
||||
style={{ height: "auto", position: "relative" }}
|
||||
style={{
|
||||
height: "auto",
|
||||
position: "relative",
|
||||
}}
|
||||
className={`${
|
||||
isDrawerOpen || openDrawerClick
|
||||
? " web-text-medium ps-4"
|
||||
@@ -671,6 +733,7 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
} else if (type === "single") {
|
||||
return (
|
||||
<Tooltip
|
||||
isDisabled={isDrawerOpen || openDrawerClick}
|
||||
hasArrow
|
||||
bg={"#fff"}
|
||||
fontSize={"xs"}
|
||||
@@ -685,7 +748,7 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
isDrawerOpen || openDrawerClick
|
||||
? "p-2 web-text-medium"
|
||||
: "p-2 ps-0 web-text-xlarge justify-content-start"
|
||||
} rounded-1 link d-flex align-items-center gap-2 w-100`}
|
||||
} rounded-1 link d-flex align-items-center gap-2 w-100 mb-2`}
|
||||
to={path}
|
||||
>
|
||||
{Icon && <Icon className="web-text-large ms-2" />}
|
||||
@@ -705,7 +768,8 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})}
|
||||
}
|
||||
)}
|
||||
</Accordion>
|
||||
</Box>
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import {
|
||||
Input,
|
||||
Text,
|
||||
Tooltip,
|
||||
useBoolean,
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
@@ -19,25 +21,37 @@ import { formatDate } from "../../Components/Functions/UTCConvertor";
|
||||
import { CheckIcon, CloseIcon } from "@chakra-ui/icons";
|
||||
import { useGetDeleteHistoryQuery } from "../../Services/delete.request.service";
|
||||
import { TABLE_PAGINATION } from "../../Constants/Paginations";
|
||||
import InitiateReversalPopup from "../../Components/Popups/InitiateReversalPopups";
|
||||
import ToastBox from "../../Components/ToastBox";
|
||||
import { useCreateAccountDeletionReversalRequestMutation } from "../../Services/reversal.account.deletion.service";
|
||||
import { isMaker } from "../../Constants/Constants";
|
||||
// import { formatDate } from "../../Components/Functions/UTCConvertor";
|
||||
|
||||
const DeletionHistory = () => {
|
||||
const toast = useToast();
|
||||
const { slideFromRight, setDeleteHistory } =
|
||||
useContext(GlobalStateContext);
|
||||
const { slideFromRight, setDeleteHistory } = useContext(GlobalStateContext);
|
||||
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||
const [actionId, setActionId] = useState(false);
|
||||
const [mouseEntered, setMouseEntered] = useState(false);
|
||||
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||
|
||||
|
||||
|
||||
// =========================== [Use State] =============================
|
||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||
|
||||
const [reversalId, setReversalId] = useState();
|
||||
const {
|
||||
isOpen: isOpenInRev,
|
||||
onOpen: onOpenInRev,
|
||||
onClose: onCloseInRev,
|
||||
} = useDisclosure();
|
||||
const [isReversalLoading, setIsReversalLoading] = useBoolean();
|
||||
|
||||
const [createAccountDeletionReversalRequest] =
|
||||
useCreateAccountDeletionReversalRequestMutation();
|
||||
|
||||
// Debounce the search term to avoid making a request on every keystroke
|
||||
useEffect(() => {
|
||||
const handler = setTimeout(() => {
|
||||
@@ -48,25 +62,26 @@ const DeletionHistory = () => {
|
||||
};
|
||||
}, [searchTerm]);
|
||||
|
||||
|
||||
const {
|
||||
data: deleteHistory,
|
||||
isLoading,
|
||||
refetch
|
||||
} = useGetDeleteHistoryQuery({
|
||||
refetch,
|
||||
} = useGetDeleteHistoryQuery(
|
||||
{
|
||||
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 formatDate = (date) => {
|
||||
return new Date(date).toLocaleDateString('en-GB', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
return new Date(date).toLocaleDateString("en-GB", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
});
|
||||
};
|
||||
|
||||
@@ -75,7 +90,6 @@ const DeletionHistory = () => {
|
||||
refetch();
|
||||
}, [refetch]);
|
||||
|
||||
|
||||
// ====================================================[Table Setup]================================================================
|
||||
const tableHeadRow = [
|
||||
"Sr No.",
|
||||
@@ -85,7 +99,8 @@ const DeletionHistory = () => {
|
||||
"Last Name",
|
||||
"Country",
|
||||
"Phone Number",
|
||||
"Status"
|
||||
"Status",
|
||||
isMaker() && "Reversal Action",
|
||||
];
|
||||
|
||||
const extractedArray = deleteHistory?.data?.rows?.map((item, index) => ({
|
||||
@@ -96,7 +111,7 @@ const DeletionHistory = () => {
|
||||
as={"span"}
|
||||
color={"gray.800"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
fontWeight={'500'}
|
||||
fontWeight={"500"}
|
||||
>
|
||||
{index + 1}.
|
||||
</Text>
|
||||
@@ -107,7 +122,7 @@ const DeletionHistory = () => {
|
||||
as={"span"}
|
||||
color={"gray.600"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
fontWeight={'500'}
|
||||
fontWeight={"500"}
|
||||
>
|
||||
{formatDate(item.Requested_on)}
|
||||
</Text>
|
||||
@@ -118,7 +133,7 @@ const DeletionHistory = () => {
|
||||
as={"span"}
|
||||
color={"gray.600"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
fontWeight={'500'}
|
||||
fontWeight={"500"}
|
||||
>
|
||||
{item.clientId}
|
||||
</Text>
|
||||
@@ -129,7 +144,7 @@ const DeletionHistory = () => {
|
||||
as={"span"}
|
||||
color={"gray.800"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
fontWeight={'500'}
|
||||
fontWeight={"500"}
|
||||
>
|
||||
{item.firstName}
|
||||
{/* {formatDate(item.charge)} */}
|
||||
@@ -141,18 +156,18 @@ const DeletionHistory = () => {
|
||||
as={"span"}
|
||||
color={"gray.800"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
fontWeight={'500'}
|
||||
fontWeight={"500"}
|
||||
>
|
||||
{item.lastName}
|
||||
</Text>
|
||||
),
|
||||
"Country": (
|
||||
Country: (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"gray.600"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
fontWeight={'500'}
|
||||
fontWeight={"500"}
|
||||
>
|
||||
{item.country}
|
||||
</Text>
|
||||
@@ -163,29 +178,55 @@ const DeletionHistory = () => {
|
||||
as={"span"}
|
||||
color={"gray.600"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
fontWeight={'500'}
|
||||
fontWeight={"500"}
|
||||
>
|
||||
{item.phoneNumber}
|
||||
</Text>
|
||||
),
|
||||
"Status": (
|
||||
Status: (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "center"}
|
||||
as={"span"}
|
||||
color={item?.deletionStatus? "red.500": "blue.500"}
|
||||
color={item?.deletionStatus === "Approved" ? "red.500" : "blue.500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
|
||||
fontWeight={'600'}
|
||||
fontWeight={"600"}
|
||||
>
|
||||
{item.deletionStatus}
|
||||
</Text>
|
||||
),
|
||||
"Reversal Action": (
|
||||
<Box w={"120px"} isTruncated={true} cursor={"pointer"}>
|
||||
{item.deletionStatus === "Approved" ? (
|
||||
<Text
|
||||
as={"span"}
|
||||
color={!item.isReversal ? "green.500" : "#FFBB00"}
|
||||
fontWeight={700}
|
||||
>
|
||||
{!item.isReversal ? (
|
||||
<Button
|
||||
onClick={() => {
|
||||
onOpenInRev(); // Call the function
|
||||
setReversalId(item.id);
|
||||
}}
|
||||
colorScheme="teal"
|
||||
size="xs"
|
||||
variant="outline"
|
||||
>
|
||||
Initiate Reversal
|
||||
</Button>
|
||||
) : (
|
||||
"Under process"
|
||||
)}
|
||||
</Text>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</Box>
|
||||
),
|
||||
}));
|
||||
|
||||
const handleDelete = () => {
|
||||
const deleteHistory = sponser.filter(
|
||||
(sponsor) => sponsor.id !== actionId
|
||||
);
|
||||
const deleteHistory = sponser.filter((sponsor) => sponsor.id !== actionId);
|
||||
|
||||
setTimeout(() => {
|
||||
setSponser(deleteHistory);
|
||||
@@ -195,6 +236,45 @@ const DeletionHistory = () => {
|
||||
setIsLoading(true);
|
||||
};
|
||||
|
||||
const handleApproved = async (data) => {
|
||||
setIsReversalLoading.on(); // Start loading
|
||||
try {
|
||||
const { error, data: responseData } =
|
||||
await createAccountDeletionReversalRequest({
|
||||
id: reversalId,
|
||||
data,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
throw error; // Explicitly handle the error
|
||||
}
|
||||
|
||||
// Success: Perform necessary actions
|
||||
refetch();
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={responseData?.message || "Action successful!"} />
|
||||
),
|
||||
});
|
||||
onCloseInRev();
|
||||
} catch (error) {
|
||||
// Handle errors
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox
|
||||
message={
|
||||
error?.data?.message || "Something went wrong. Please try again."
|
||||
}
|
||||
status="error"
|
||||
/>
|
||||
),
|
||||
});
|
||||
console.error("Error:", error);
|
||||
} finally {
|
||||
setIsReversalLoading.off(); // Ensure loading is toggled off
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||
<Box bg="white.500">
|
||||
@@ -244,6 +324,12 @@ const DeletionHistory = () => {
|
||||
alertHandler={handleDelete}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
<InitiateReversalPopup
|
||||
onClose={onCloseInRev}
|
||||
isOpen={isOpenInRev}
|
||||
handelApproved={handleApproved}
|
||||
isLoading={isReversalLoading}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -91,17 +91,17 @@ const DeletionRequest = () => {
|
||||
// ====================================================[Table Setup]================================================================
|
||||
const tableHeadRow = [
|
||||
"Sr No.",
|
||||
"Requested on",
|
||||
"Requested On",
|
||||
"Client ID",
|
||||
"First name",
|
||||
"Last name",
|
||||
"First Name",
|
||||
"Last Name",
|
||||
"Country",
|
||||
"Phone number",
|
||||
"Phone Number",
|
||||
"Status",
|
||||
"Action"
|
||||
];
|
||||
|
||||
const extractedArray = filteredData?.map((item, index) => ({
|
||||
const extractedArray = data?.data?.rows?.map((item, index) => ({
|
||||
id: item?.id,
|
||||
"Sr No.": (
|
||||
<Text
|
||||
@@ -114,7 +114,7 @@ const DeletionRequest = () => {
|
||||
{index + 1}.
|
||||
</Text>
|
||||
),
|
||||
"Requested on": (
|
||||
"Requested On": (
|
||||
<Text
|
||||
justifyContent={"left"}
|
||||
as={"span"}
|
||||
@@ -136,7 +136,7 @@ const DeletionRequest = () => {
|
||||
{item?.clientId}
|
||||
</Text>
|
||||
),
|
||||
"First name": (
|
||||
"First Name": (
|
||||
<Text
|
||||
justifyContent={"left"}
|
||||
as={"span"}
|
||||
@@ -148,7 +148,7 @@ const DeletionRequest = () => {
|
||||
{/* {formatDate(item.charge)} */}
|
||||
</Text>
|
||||
),
|
||||
"Last name": (
|
||||
"Last Name": (
|
||||
<Text
|
||||
justifyContent={"left"}
|
||||
as={"span"}
|
||||
@@ -171,7 +171,7 @@ const DeletionRequest = () => {
|
||||
</Text>
|
||||
),
|
||||
|
||||
"Phone number": (
|
||||
"Phone Number": (
|
||||
<Text
|
||||
justifyContent={"left"}
|
||||
as={"span"}
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
Box,
|
||||
Button,
|
||||
FormControl,
|
||||
FormHelperText,
|
||||
FormLabel,
|
||||
Input,
|
||||
Modal,
|
||||
@@ -21,60 +22,78 @@ import React, { useEffect, useState } from "react";
|
||||
import * as yup from "yup";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useGetDepositRequestByIdQuery, useGetDepositRequestQuery, useUpdateDepositRequestMutation } from "../../Services/deposit.request.service";
|
||||
import {
|
||||
useGetDepositRequestByIdQuery,
|
||||
useGetDepositRequestQuery,
|
||||
useUpdateDepositRequestMutation,
|
||||
} from "../../Services/deposit.request.service";
|
||||
import FullscreenLoaders from "../../Components/Loaders/FullscreenLoaders";
|
||||
import ToastBox from "../../Components/ToastBox";
|
||||
import { useGetDrawalRequestQuery } from "../../Services/drawal.request.service";
|
||||
import { useApproveDepositRequestMutation, useGetDeleteRequestByIdQuery } from "../../Services/delete.request.service";
|
||||
import {
|
||||
useApproveDepositRequestMutation,
|
||||
useGetDeleteRequestByIdQuery,
|
||||
useGetDeleteRequestQuery,
|
||||
} from "../../Services/delete.request.service";
|
||||
|
||||
const FILE_TYPES = ["image/jpeg", "image/png", "image/gif"];
|
||||
|
||||
// export const conformModalSchema = yup.object().shape({
|
||||
// adminComment: yup.string().notRequired(),
|
||||
// });
|
||||
|
||||
export const conformModalSchema = yup.object().shape({
|
||||
adminComment: yup.string().notRequired(),
|
||||
});
|
||||
|
||||
const DeletionRequestApprove = ({ isOpen, onClose, firstField, id, data:requestData }) => {
|
||||
const toast = useToast()
|
||||
const DeletionRequestApprove = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
firstField,
|
||||
id,
|
||||
data: requestData,
|
||||
}) => {
|
||||
const toast = useToast();
|
||||
const [file, setFile] = useState();
|
||||
const [isBtnLoading , setIsBtnLoading] = useState(false)
|
||||
const [isBtnLoadingReject , setIsBtnLoadingReject] = useState(false)
|
||||
const [isReject , setIsReject] = useState(false)
|
||||
const [isBtnLoading, setIsBtnLoading] = useState(false);
|
||||
const [isBtnLoadingReject, setIsBtnLoadingReject] = useState(false);
|
||||
const [isReject, setIsReject] = useState(false);
|
||||
|
||||
const fileredData = requestData?.find((item)=> item?.id === id)
|
||||
const [ updateApproveRequest ] = useApproveDepositRequestMutation()
|
||||
const fileredData = requestData?.find((item) => item?.id === id);
|
||||
const [updateApproveRequest] = useApproveDepositRequestMutation();
|
||||
const { data, isLoading } = useGetDeleteRequestByIdQuery(id, {
|
||||
skip: !id,
|
||||
});
|
||||
|
||||
|
||||
const {
|
||||
register,
|
||||
reset,
|
||||
watch,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: yupResolver(conformModalSchema),
|
||||
mode: "all",
|
||||
});
|
||||
|
||||
const { refetch } = useGetDeleteRequestQuery();
|
||||
|
||||
useEffect(() => {
|
||||
reset({
|
||||
comment:fileredData?.comment
|
||||
})
|
||||
|
||||
|
||||
}, [requestData, id])
|
||||
comment: fileredData?.comment,
|
||||
});
|
||||
}, [requestData, id]);
|
||||
|
||||
const onSubmit = async (data) => {
|
||||
setIsBtnLoading(isReject?false:true)
|
||||
setIsBtnLoadingReject(isReject)
|
||||
setIsBtnLoading(isReject ? false : true);
|
||||
setIsBtnLoadingReject(isReject);
|
||||
const approveReq = {
|
||||
adminComment: data?.adminComment,
|
||||
deletionStatus: isReject?"Reject": "Approved"
|
||||
}
|
||||
deletionStatus: isReject ? "Reject" : "Approved",
|
||||
};
|
||||
|
||||
try {
|
||||
const res = await updateApproveRequest({ id ,data:approveReq })
|
||||
|
||||
const res = await updateApproveRequest({ id, data: approveReq });
|
||||
|
||||
if (res?.error) {
|
||||
toast({
|
||||
@@ -82,27 +101,20 @@ const DeletionRequestApprove = ({ isOpen, onClose, firstField, id, data:requestD
|
||||
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||
),
|
||||
});
|
||||
heandleOnClose()
|
||||
heandleOnClose();
|
||||
} else if (res?.data?.statusCode === 200) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={res?.data?.message} />
|
||||
),
|
||||
render: () => <ToastBox message={res?.data?.message} />,
|
||||
});
|
||||
heandleOnClose()
|
||||
refetch();
|
||||
heandleOnClose();
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const onReject = () => {
|
||||
|
||||
}
|
||||
|
||||
|
||||
const onReject = () => {};
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
@@ -113,15 +125,19 @@ const DeletionRequestApprove = ({ isOpen, onClose, firstField, id, data:requestD
|
||||
}, [data, reset]);
|
||||
|
||||
const heandleOnClose = () => {
|
||||
reset()
|
||||
onClose()
|
||||
setIsBtnLoading(false)
|
||||
setIsReject(false)
|
||||
setIsBtnLoadingReject(false)
|
||||
}
|
||||
reset();
|
||||
onClose();
|
||||
setIsBtnLoading(false);
|
||||
setIsReject(false);
|
||||
setIsBtnLoadingReject(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={heandleOnClose} initialFocusRef={firstField}>
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onClose={heandleOnClose}
|
||||
initialFocusRef={firstField}
|
||||
>
|
||||
<ModalOverlay />
|
||||
|
||||
<ModalContent pb={4}>
|
||||
@@ -133,7 +149,10 @@ const DeletionRequestApprove = ({ isOpen, onClose, firstField, id, data:requestD
|
||||
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
||||
<ModalBody>
|
||||
<FormControl mt={6} mb={4}>
|
||||
<FormLabel fontSize="sm">Investor Comment <Badge colorScheme="green">{fileredData?.currencyCode}</Badge></FormLabel>
|
||||
<FormLabel fontSize="sm">
|
||||
Investor Comment{" "}
|
||||
<Badge colorScheme="green">{fileredData?.currencyCode}</Badge>
|
||||
</FormLabel>
|
||||
{/* <Textarea
|
||||
focusBorderColor="green.400"
|
||||
name="comment"
|
||||
@@ -150,8 +169,9 @@ const DeletionRequestApprove = ({ isOpen, onClose, firstField, id, data:requestD
|
||||
</Text>
|
||||
)} */}
|
||||
|
||||
|
||||
<Text fontSize="sm" fontWeight={500} color={'gray.600'}>{data?.data?.comment}</Text>
|
||||
<Text fontSize="sm" fontWeight={500} color={"gray.600"}>
|
||||
{data?.data?.comment}
|
||||
</Text>
|
||||
</FormControl>
|
||||
<FormControl mb={4} isRequired>
|
||||
<FormLabel fontSize="sm">Admin Comment</FormLabel>
|
||||
@@ -163,14 +183,22 @@ const DeletionRequestApprove = ({ isOpen, onClose, firstField, id, data:requestD
|
||||
fontSize="sm"
|
||||
type="textarea"
|
||||
size="sm"
|
||||
placeholder={"Enter your comments...."}
|
||||
placeholder={"Enter your comment...."}
|
||||
resize={"none"}
|
||||
mb={2}
|
||||
/>
|
||||
{errors.adminComment && (
|
||||
<Text fontSize="xs" color="red">
|
||||
{errors.adminComment.message}
|
||||
</Text>
|
||||
)}
|
||||
<FormHelperText fontSize="xs" color="gray.500">
|
||||
<Text as={"span"} me={2}>
|
||||
{" "}
|
||||
Maximum length should be 200 characters. You have entered
|
||||
</Text>
|
||||
{watch("adminComment")?.length || 0} characters.
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
@@ -180,9 +208,10 @@ const DeletionRequestApprove = ({ isOpen, onClose, firstField, id, data:requestD
|
||||
type="submit"
|
||||
size={"sm"}
|
||||
rounded={"sm"}
|
||||
variant={'ghost'}
|
||||
variant={"ghost"}
|
||||
onClick={() => setIsReject(true)}
|
||||
isLoading={isBtnLoadingReject}
|
||||
fontWeight={500}
|
||||
>
|
||||
Reject
|
||||
</Button>
|
||||
|
||||
@@ -3,6 +3,9 @@ import {
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
HStack,
|
||||
Input,
|
||||
Select,
|
||||
Text,
|
||||
Tooltip,
|
||||
useToast,
|
||||
@@ -23,15 +26,16 @@ import ToastBox from "../../Components/ToastBox";
|
||||
import NormalTable from "../../Components/DataTable/NormalTable";
|
||||
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
||||
import { useGetInvestorsQuery } from "../../Services/investor.details.service";
|
||||
import { TABLE_PAGINATION } from "../../Constants/Paginations";
|
||||
import {
|
||||
INVESTOR_TABLE_PAGINATION,
|
||||
TABLE_PAGINATION,
|
||||
} from "../../Constants/Paginations";
|
||||
import { formatDate, generateSerialNumber } from "../../Constants/Constants";
|
||||
import { ViewIcon } from "@chakra-ui/icons";
|
||||
import { useGetUnbanInvestorQuery } from "../../Services/ban.investor.service";
|
||||
|
||||
export const notification = yup.object().shape({
|
||||
title: yup
|
||||
.string()
|
||||
.required("Investment Name is required"),
|
||||
title: yup.string().required("Notification Header is required"),
|
||||
ManualDate: yup
|
||||
.date()
|
||||
.required("Manual Date is required")
|
||||
@@ -43,33 +47,28 @@ export const notification = yup.object().shape({
|
||||
/^([01]\d|2[0-3]):?([0-5]\d)$/,
|
||||
"Invalid time format, must be in HH:mm"
|
||||
),
|
||||
expectedReturn: yup
|
||||
.string()
|
||||
.required("Expected Return is required"),
|
||||
expectedReturn: yup.string().required("Expected Return is required"),
|
||||
});
|
||||
|
||||
export const notificationNew = yup.object().shape({
|
||||
title: yup
|
||||
.string()
|
||||
.required("Investment Name is required"),
|
||||
message: yup
|
||||
.string()
|
||||
.required("Message is required"),
|
||||
|
||||
title: yup.string().required("Notification Header is required"),
|
||||
message: yup.string().notRequired(),
|
||||
});
|
||||
|
||||
|
||||
|
||||
const Notification = () => {
|
||||
const toast = useToast();
|
||||
const navigate = useNavigate();
|
||||
const [form, setForm] = useState({});
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [ selectedRadio, setSelectedRadio] = useState([])
|
||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||
const [selectedRadio, setSelectedRadio] = useState([]);
|
||||
const [pageSize, setPageSize] = useState(INVESTOR_TABLE_PAGINATION?.size);
|
||||
const [currentPage, setCurrentPage] = useState(
|
||||
INVESTOR_TABLE_PAGINATION?.page
|
||||
);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||
const [country, setCountry] = useState("");
|
||||
const [kyc, setKyc] = useState("");
|
||||
|
||||
const {
|
||||
control,
|
||||
@@ -81,8 +80,8 @@ const Notification = () => {
|
||||
resolver: yupResolver(notificationNew),
|
||||
|
||||
defaultValues: {
|
||||
title: '',
|
||||
message: '',
|
||||
title: "",
|
||||
message: "",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -94,7 +93,6 @@ const Notification = () => {
|
||||
error,
|
||||
} = useGetContactQuery();
|
||||
|
||||
|
||||
const formatDate = (date) => {
|
||||
return new Date(date).toLocaleDateString("en-GB", {
|
||||
day: "2-digit",
|
||||
@@ -109,28 +107,40 @@ const Notification = () => {
|
||||
// // error,
|
||||
// } = useGetInvestorsQuery({ page: currentPage, size: pageSize });
|
||||
|
||||
useEffect(() => {
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedSearchTerm(searchTerm.trim()); // Trim to remove leading/trailing spaces
|
||||
}, 300);
|
||||
return () => clearTimeout(handler);
|
||||
}, [searchTerm]);
|
||||
|
||||
const {
|
||||
data: investorDetails,
|
||||
isLoading: investorDetailsLoading,
|
||||
refetch,
|
||||
} = useGetUnbanInvestorQuery({
|
||||
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||
search: debouncedSearchTerm,
|
||||
} = useGetUnbanInvestorQuery(
|
||||
{
|
||||
page: 1, // Omit pagination for search
|
||||
size: 10000, // Omit pagination for search
|
||||
// page: debouncedSearchTerm ? undefined : currentPage, // Disable pagination for search
|
||||
// size: debouncedSearchTerm ? undefined : 10000 || pageSize || 500, // Disable pagination for search
|
||||
search: debouncedSearchTerm, // Pass search term
|
||||
country_xid: country,
|
||||
KYCStatus: kyc,
|
||||
},
|
||||
{
|
||||
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||
});;
|
||||
|
||||
|
||||
|
||||
console.log(investorDetails);
|
||||
skip: searchTerm !== "" && debouncedSearchTerm === "", // Skip if search not debounced yet
|
||||
}
|
||||
);
|
||||
|
||||
// useEffect(() => {
|
||||
// console.log("Search Term:", searchTerm);
|
||||
// console.log("Debounced Search Term:", debouncedSearchTerm);
|
||||
// console.log("Investor Details:", investorDetails);
|
||||
// }, [searchTerm, debouncedSearchTerm, investorDetails]);
|
||||
|
||||
const [sendNotification] = useSendNotificationMutation();
|
||||
|
||||
|
||||
if (contactLoading) {
|
||||
return <FullscreenLoaders />;
|
||||
}
|
||||
@@ -143,7 +153,9 @@ const Notification = () => {
|
||||
type: "text",
|
||||
width: "100%",
|
||||
maxLength: 100,
|
||||
helperText:`Maximum length should be 100 characters. You have entered ${watch()?.title?.length || 0} characters.`,
|
||||
helperText: `Maximum length should be 100 characters. You have entered ${
|
||||
watch()?.title?.length || 0
|
||||
} characters.`,
|
||||
isRequired: true,
|
||||
section: "Send Custom Push Notification",
|
||||
// value: contact?.phoneNumber || "",
|
||||
@@ -156,11 +168,12 @@ const Notification = () => {
|
||||
type: "textarea",
|
||||
isRequired: true,
|
||||
maxLength: 200,
|
||||
helperText:`Maximum length should be 200 characters. You have entered ${watch()?.message?.length || 0} characters.`,
|
||||
helperText: `Maximum length should be 200 characters. You have entered ${
|
||||
watch()?.message?.length || 0
|
||||
} characters.`,
|
||||
section: "Send Custom Push Notification",
|
||||
// value: contact?.phoneNumber || "",
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
const groupedFields = formFields.reduce((groups, field) => {
|
||||
@@ -173,15 +186,13 @@ const Notification = () => {
|
||||
}, {});
|
||||
|
||||
const onSubmit = async (data) => {
|
||||
|
||||
const dataToPass = {
|
||||
...data,
|
||||
principal_xid:selectedRadio
|
||||
}
|
||||
principal_xid: selectedRadio,
|
||||
};
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const res = await sendNotification(dataToPass);
|
||||
console.log(res);
|
||||
|
||||
if (res?.error) {
|
||||
toast({
|
||||
@@ -189,39 +200,32 @@ const Notification = () => {
|
||||
<ToastBox status={"error"} message={res?.error?.data?.message} />
|
||||
),
|
||||
});
|
||||
setIsLoading(false)
|
||||
setIsLoading(false);
|
||||
} else if (res?.data) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={res?.data?.message} />
|
||||
),
|
||||
render: () => <ToastBox message={res?.data?.message} />,
|
||||
});
|
||||
setIsLoading(false)
|
||||
setSelectedRadio([])
|
||||
setIsLoading(false);
|
||||
setSelectedRadio([]);
|
||||
reset({
|
||||
title: '', // Resetting specific fields
|
||||
message: '',
|
||||
title: "", // Resetting specific fields
|
||||
message: "",
|
||||
}); // Clears the form fields
|
||||
} else {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox status={'error'} message={"Something went wrong"} />
|
||||
<ToastBox status={"error"} message={"Something went wrong"} />
|
||||
),
|
||||
});
|
||||
setIsLoading(false)
|
||||
setIsLoading(false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// ====================================================[Table Setup]================================================================
|
||||
const tableHeadRow = [
|
||||
"Sr N/O",
|
||||
@@ -235,7 +239,6 @@ const Notification = () => {
|
||||
"KYC Status",
|
||||
];
|
||||
|
||||
|
||||
const extractedArray = investorDetails?.data?.rows?.map((item, idx) => ({
|
||||
id: item?.principal_xid,
|
||||
"Sr N/O": (
|
||||
@@ -305,9 +308,9 @@ const Notification = () => {
|
||||
color={item?.KYCStatus === false ? "red" : "blue"}
|
||||
px={2}
|
||||
py={0.5}
|
||||
variant={'ghost'}
|
||||
variant={"ghost"}
|
||||
>
|
||||
{item?.KYCStatus === true ? "Completed" : "Incompleted"}
|
||||
{item?.KYCStatus === true ? "Completed" : "Not Completed"}
|
||||
</Badge>
|
||||
</Box>
|
||||
),
|
||||
@@ -322,13 +325,72 @@ const Notification = () => {
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
btnLoading={isLoading}
|
||||
>
|
||||
<Box overflow={'scroll'} h={'58vh'}>
|
||||
<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 className="col" justifyContent={"end"}>
|
||||
<Select
|
||||
w={250}
|
||||
focusBorderColor="green.500"
|
||||
size={"sm"}
|
||||
fontSize={"xs"}
|
||||
cursor={"pointer"}
|
||||
onChange={(e) => setCountry(e.target.value)}
|
||||
value={country}
|
||||
>
|
||||
<option value="" defaultValue={""} disabled hidden>
|
||||
Country
|
||||
</option>
|
||||
<option value="">All</option>
|
||||
<option value="1">Bahrain</option>
|
||||
<option value="2">Kuwait</option>
|
||||
<option value="3">Oman</option>
|
||||
<option value="4">Qatar</option>
|
||||
<option value="5">Saudi arabia</option>
|
||||
<option value="6">United arab emirates</option>
|
||||
</Select>
|
||||
<Select
|
||||
w={250}
|
||||
focusBorderColor="green.500"
|
||||
size={"sm"}
|
||||
fontSize={"xs"}
|
||||
cursor={"pointer"}
|
||||
onChange={(e) => setKyc(e.target.value)}
|
||||
value={kyc}
|
||||
>
|
||||
<option value="" defaultValue={""} disabled hidden>
|
||||
KYC Status
|
||||
</option>
|
||||
<option value="">KYC Status</option>
|
||||
<option value="0">Not Completed</option>
|
||||
<option value="1">Completed</option>
|
||||
</Select>
|
||||
</HStack>
|
||||
</HStack>
|
||||
<Box overflow={"scroll"} h={"58vh"}>
|
||||
<NormalTable
|
||||
centered={true}
|
||||
emptyMessage={`We don't have any Sponers `}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={extractedArray}
|
||||
// isLoading={isLoading}
|
||||
isLoading={investorDetailsLoading}
|
||||
setSelectedRadio={setSelectedRadio}
|
||||
selectedRadio={selectedRadio}
|
||||
showRadioButton={true}
|
||||
|
||||
463
src/Pages/BankDepositRequest/BankDepositRequest.jsx
Normal file
@@ -0,0 +1,463 @@
|
||||
import {
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
HStack,
|
||||
Input,
|
||||
Switch,
|
||||
Text,
|
||||
Tooltip,
|
||||
useToast,
|
||||
useDisclosure,
|
||||
Link,
|
||||
useBoolean,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import { CheckIcon, CloseIcon, ExternalLinkIcon } from "@chakra-ui/icons";
|
||||
import { debounce } from "../Admin/Contact";
|
||||
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
||||
import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
||||
import ToastBox from "../../Components/ToastBox";
|
||||
import NormalTable from "../../Components/DataTable/NormalTable";
|
||||
import { TABLE_PAGINATION } from "../../Constants/Paginations";
|
||||
import { generateSerialNumber } from "../../Constants/Constants";
|
||||
import { useGetDepositHistoryQuery } from "../../Services/deposit.request.service";
|
||||
import Pagination from "../../Components/Pagination";
|
||||
import ConfirmModal from "./ConfirmModal";
|
||||
import RejectModal from "./RejectModal";
|
||||
import {
|
||||
useApproveBankDepositRequestMutation,
|
||||
useGetBankDepositMasterQuery,
|
||||
useRejectbankDepositRequestMutation,
|
||||
} from "../../Services/bankdeposit.request.service";
|
||||
import RejectReversalPopups from "../../Components/Popups/RejectReversalPopups";
|
||||
import ConfirmReversalPopups from "../../Components/Popups/ConfirmReversalPopups";
|
||||
|
||||
const formatDate = (date) => {
|
||||
return new Date(date).toLocaleDateString("en-GB", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
});
|
||||
}; // Simple date formatter
|
||||
|
||||
const BankDepositRequest = () => {
|
||||
const navigate = useNavigate();
|
||||
const toast = useToast();
|
||||
const { depositHistory, setDepositHistory, 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: isConfirmOpen,
|
||||
onOpen: onConfirmOpen,
|
||||
onClose: onConfirmClose,
|
||||
} = useDisclosure();
|
||||
const {
|
||||
isOpen: isRejectOpen,
|
||||
onOpen: onRejectOpen,
|
||||
onClose: onRejectClose,
|
||||
} = useDisclosure();
|
||||
|
||||
// =========================== [Use State] =============================
|
||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||
|
||||
const [rejectbankDepositRequest] = useRejectbankDepositRequestMutation();
|
||||
|
||||
const [approveBankDepositRequest] = useApproveBankDepositRequestMutation();
|
||||
|
||||
const [isReversalLoading, setIsReversalLoading] = useBoolean();
|
||||
|
||||
// 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,
|
||||
error,
|
||||
refetch,
|
||||
isLoading: depositHistoryLoading,
|
||||
} = useGetBankDepositMasterQuery(
|
||||
{
|
||||
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
|
||||
}
|
||||
);
|
||||
|
||||
// Use useEffect to refetch data when the component mounts
|
||||
useEffect(() => {
|
||||
refetch();
|
||||
}, [refetch]);
|
||||
|
||||
// ====================================================[Table Setup]================================================================
|
||||
const tableHeadRow = [
|
||||
"Sr.no",
|
||||
"Request Date",
|
||||
"Client ID",
|
||||
"First Name",
|
||||
"Last Name",
|
||||
"Country",
|
||||
"Phone Number",
|
||||
"Deposit Amount",
|
||||
"Action",
|
||||
];
|
||||
|
||||
const handleUpdateStatus = debounce((id) => {
|
||||
setDepositHistory((prevDepositHistory) =>
|
||||
prevDepositHistory.map((depositHistory) =>
|
||||
depositHistory.id === id
|
||||
? { ...depositHistory, status: !depositHistory.status }
|
||||
: depositHistory
|
||||
)
|
||||
);
|
||||
toast({
|
||||
render: () => <ToastBox message={"Status changed succesfully.!"} />,
|
||||
});
|
||||
}, 300);
|
||||
|
||||
const filteredData = data?.data?.rows
|
||||
.filter((item) => {
|
||||
// Filter by name (case insensitive)
|
||||
const name = [item.firstName, item.lastName, item.countryName]
|
||||
.filter(Boolean)
|
||||
.join(" ");
|
||||
const searchLower = searchTerm.toLowerCase();
|
||||
const nameMatches = name.toLowerCase().includes(searchLower);
|
||||
|
||||
// Filter by status (Uncomment and use if needed)
|
||||
// const status = item.status;
|
||||
// const statusLower = status ? "active" : "inactive";
|
||||
|
||||
// const statusMatches =
|
||||
// statusFilter === "all" ||
|
||||
// (statusFilter === "active" && status === true) ||
|
||||
// (statusFilter === "inactive" && status === false);
|
||||
|
||||
return nameMatches;
|
||||
})
|
||||
.sort((b, a) => new Date(a.createdAt) - new Date(b.createdAt));
|
||||
|
||||
// const handleView = (id) => {
|
||||
// setActionId(id);
|
||||
// onViewOpen();
|
||||
// };
|
||||
|
||||
const extractedArray = data?.data?.rows?.map((item, idx) => ({
|
||||
"Sr.no": (
|
||||
<Text
|
||||
w={"10px"}
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{generateSerialNumber(idx, currentPage, pageSize)}
|
||||
</Text>
|
||||
),
|
||||
"Request Date": (
|
||||
<Text
|
||||
w={"60px"}
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{formatDate(item?.isReversalDate)}
|
||||
</Text>
|
||||
),
|
||||
"Client ID": (
|
||||
<Text
|
||||
w={"60px"}
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item?.clientReference_id}
|
||||
</Text>
|
||||
),
|
||||
"First Name": (
|
||||
<Box isTruncated={true} w={"60px"}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{item?.firstName}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Last Name": (
|
||||
<Box w={"70px"} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{item?.lastName}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
Country: (
|
||||
<Box isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{item?.countryName}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Phone Number": (
|
||||
<Box isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{item?.ISDCode} {item?.mobileNumber}
|
||||
{/* {item?.ISDcode + " " + item?.mobileNumber} */}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Deposit Amount": (
|
||||
<Box isTruncated={true} display={"flex"} justifyContent={"end"}>
|
||||
<Text as={"span"} color={"teal.900"} textAlign={"right"}>
|
||||
{parseFloat(item?.investorAmount || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
<Badge ms={1} colorScheme="green">
|
||||
{item?.currencyCode}
|
||||
</Badge>
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
Action: (
|
||||
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||
<Tooltip
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
label="Approve"
|
||||
bg="#fff"
|
||||
color={"green.500"}
|
||||
placement="left-start"
|
||||
>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={2}
|
||||
py={1}
|
||||
onClick={() => {
|
||||
setActionId(item.id);
|
||||
onConfirmOpen();
|
||||
}}
|
||||
colorScheme="green"
|
||||
variant={"solid"}
|
||||
cursor={"pointer"}
|
||||
>
|
||||
<CheckIcon fontSize={"12px"} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
label="Reject"
|
||||
bg="#fff"
|
||||
color={"red.500"}
|
||||
placement="left-start"
|
||||
>
|
||||
<Button
|
||||
colorScheme="red"
|
||||
// color="red.500"
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={2}
|
||||
onClick={() => {
|
||||
setActionId(item.id);
|
||||
onRejectOpen();
|
||||
}}
|
||||
py={1}
|
||||
// variant={"solid"}
|
||||
>
|
||||
<CloseIcon fontSize={"10px"} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
),
|
||||
}));
|
||||
|
||||
const handleDelete = () => {
|
||||
const IOtype = investmentType.filter(
|
||||
(investmentType) => investmentType.id !== actionId
|
||||
);
|
||||
|
||||
setTimeout(() => {
|
||||
setInvestmentType(IOtype);
|
||||
setDeleteAlert(false);
|
||||
setIsLoading(false);
|
||||
}, 100);
|
||||
setIsLoading(true);
|
||||
};
|
||||
|
||||
const handleApproved = async (data) => {
|
||||
setIsReversalLoading.on(); // Start loading
|
||||
try {
|
||||
const { error, data: responseData } = await rejectbankDepositRequest({
|
||||
id: actionId,
|
||||
data,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
throw error; // Explicitly handle the error
|
||||
}
|
||||
|
||||
// Success: Perform necessary actions
|
||||
refetch();
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={responseData?.message || "Action successful!"} />
|
||||
),
|
||||
});
|
||||
onRejectClose();
|
||||
} catch (error) {
|
||||
// Handle errors
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox
|
||||
message={
|
||||
error?.data?.message || "Something went wrong. Please try again."
|
||||
}
|
||||
status="error"
|
||||
/>
|
||||
),
|
||||
});
|
||||
console.error("Error:", error);
|
||||
} finally {
|
||||
setIsReversalLoading.off(); // Ensure loading is toggled off
|
||||
}
|
||||
};
|
||||
|
||||
const handleConfirm = async (data) => {
|
||||
|
||||
setIsReversalLoading.on(); // Start loading
|
||||
try {
|
||||
const { error, data: responseData } = await approveBankDepositRequest({
|
||||
id: actionId,
|
||||
data,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
throw error; // Explicitly handle the error
|
||||
}
|
||||
|
||||
// Success: Perform necessary actions
|
||||
refetch();
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={responseData?.message || "Action successful!"} />
|
||||
),
|
||||
});
|
||||
onRejectClose();
|
||||
} catch (error) {
|
||||
// Handle errors
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox
|
||||
message={
|
||||
error?.data?.message || "Something went wrong. Please try again."
|
||||
}
|
||||
status="error"
|
||||
/>
|
||||
),
|
||||
});
|
||||
console.error("Error:", error);
|
||||
} finally {
|
||||
setIsReversalLoading.off(); // Ensure loading is toggled off
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||
{/* <ConfirmModal isOpen={isConfirmOpen} onClose={onConfirmClose} /> */}
|
||||
<RejectReversalPopups
|
||||
isOpen={isRejectOpen}
|
||||
onClose={onRejectClose}
|
||||
handelApproved={handleApproved}
|
||||
isLoading={isReversalLoading}
|
||||
/>
|
||||
<ConfirmReversalPopups
|
||||
isOpen={isConfirmOpen}
|
||||
onClose={onConfirmClose}
|
||||
handleConfirm={handleConfirm}
|
||||
isLoading={isReversalLoading}
|
||||
/>
|
||||
<Box bg="white.500">
|
||||
<HStack
|
||||
display={"flex"}
|
||||
justifyContent={"space-between"}
|
||||
ps={1}
|
||||
pe={1}
|
||||
pb={4}
|
||||
pt={4}
|
||||
spacing="24px"
|
||||
>
|
||||
<Input
|
||||
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={depositHistoryLoading}
|
||||
pageSize={pageSize}
|
||||
setPageSize={setPageSize}
|
||||
currentPage={currentPage}
|
||||
setCurrentPage={setCurrentPage}
|
||||
totalItems={data?.data?.totalItems}
|
||||
/>
|
||||
</HStack>
|
||||
</HStack>
|
||||
</Box>
|
||||
|
||||
<NormalTable
|
||||
emptyMessage={`We don't have any Investment type `}
|
||||
tableHeadRow={tableHeadRow}
|
||||
// setData={setExtractedArray}
|
||||
data={extractedArray}
|
||||
isLoading={depositHistoryLoading}
|
||||
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 BankDepositRequest;
|
||||
149
src/Pages/BankDepositRequest/ConfirmModal.jsx
Normal file
@@ -0,0 +1,149 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Checkbox,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Input,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Text,
|
||||
Textarea,
|
||||
useDisclosure,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useState } from "react";
|
||||
import * as yup from "yup";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import { useForm } from "react-hook-form";
|
||||
import ReactQuill from "react-quill";
|
||||
|
||||
export const conformModalSchema = yup.object().shape({
|
||||
fees: yup.string().required("File name is required"),
|
||||
totalAmount: yup.string().required("File name is required"),
|
||||
});
|
||||
|
||||
const ConfirmModal = ({ isOpen, onClose, firstField }) => {
|
||||
|
||||
const [emailApproval,setEmailApproval] = useState(false)
|
||||
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: yupResolver(conformModalSchema),
|
||||
});
|
||||
|
||||
const onSubmit = (data) => {
|
||||
setFile(data.document[0]);
|
||||
|
||||
const newDocument = {
|
||||
...data,
|
||||
document: data.document[0].name, // Store the document name
|
||||
status: true,
|
||||
id: uuidv4(),
|
||||
createdAt: new Date().toISOString(),
|
||||
Type: getFileIcon(file.type),
|
||||
};
|
||||
|
||||
setCreate((prevCreate) => [...prevCreate, newDocument]);
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleFileChange = (event) => {
|
||||
const selectedFile = event.target.files[0];
|
||||
setFile(selectedFile);
|
||||
};
|
||||
|
||||
const modules = {
|
||||
toolbar: [
|
||||
// [{ header: "1" }, { header: "2" },
|
||||
// // { font: [] }
|
||||
// ],
|
||||
// [{ size: [] }],
|
||||
["bold", "italic", "underline", "strike", "blockquote"],
|
||||
[{ list: "ordered" }, { list: "bullet" }],
|
||||
["clean"],
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose} initialFocusRef={firstField}>
|
||||
<ModalOverlay />
|
||||
<ModalContent pb={4}>
|
||||
<ModalHeader fontSize={"md"}>Confirm</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
||||
<ModalBody>
|
||||
<FormControl mb={4} isRequired>
|
||||
<FormLabel fontSize="sm">Comment</FormLabel>
|
||||
<Textarea rows={5}
|
||||
focusBorderColor='green.400'
|
||||
name="fileName"
|
||||
{...register("fileName")}
|
||||
fontSize="sm"
|
||||
type="textarea"
|
||||
size="md"
|
||||
placeholder={"Enter your comments...."}
|
||||
rounded={'md'}
|
||||
resize={'none'}
|
||||
/>
|
||||
{errors.comment && (
|
||||
<Text fontSize="xs" color="red">
|
||||
{errors.comment.message}
|
||||
</Text>
|
||||
)}
|
||||
</FormControl>
|
||||
|
||||
<Checkbox colorScheme='forestGreen'
|
||||
onChange={(e) =>setEmailApproval(e.target.checked)}
|
||||
>
|
||||
<Text mb={0} fontSize={'sm'}>Send an email to the user upon approval</Text>
|
||||
</Checkbox>
|
||||
{emailApproval && <Box className="messageBox">
|
||||
<FormControl mb={4}>
|
||||
<FormLabel fontSize="sm" mb={1}>Subject</FormLabel>
|
||||
<Input
|
||||
focusBorderColor='green.400'
|
||||
name="fileName"
|
||||
{...register("fileName")}
|
||||
fontSize="sm"
|
||||
type="text"
|
||||
size="sm"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl mb={12}>
|
||||
<FormLabel fontSize="sm" mb={1}>Message</FormLabel>
|
||||
<ReactQuill
|
||||
theme="snow"
|
||||
style={{
|
||||
height: 150,
|
||||
}}
|
||||
// value={value}
|
||||
// onChange={setValue}
|
||||
modules={modules}
|
||||
placeholder="Start typing here..."
|
||||
/>
|
||||
</FormControl>
|
||||
</Box>}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button colorScheme="gray" mr={3} onClick={onClose} size={'sm'} rounded={'sm'}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button colorScheme="forestGreen" variant="solid" size={'sm'} rounded={'sm'}>
|
||||
Confirm
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Box>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConfirmModal;
|
||||
139
src/Pages/BankDepositRequest/RejectModal.jsx
Normal file
@@ -0,0 +1,139 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Text,
|
||||
Textarea,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useState } from "react";
|
||||
import * as yup from "yup";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useRejectbankDepositRequestMutation } from "../../Services/bankdeposit.request.service";
|
||||
import ToastBox from "../../Components/ToastBox";
|
||||
|
||||
export const conformModalSchema = yup.object().shape({
|
||||
comments: yup.string().required("Comment is required"),
|
||||
});
|
||||
|
||||
const RejectModal = ({ isOpen, onClose, firstField ,id}) => {
|
||||
const [isBtnLoading , setIsBtnLoading] = useState(false)
|
||||
|
||||
const toast = useToast()
|
||||
|
||||
const {
|
||||
register,
|
||||
reset,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: yupResolver(conformModalSchema),
|
||||
});
|
||||
|
||||
const [ rejectbankDepositRequest ] = useRejectbankDepositRequestMutation()
|
||||
|
||||
const onSubmit = async(data) => {
|
||||
console.log(id);
|
||||
setIsBtnLoading(true)
|
||||
try {
|
||||
const res = await rejectbankDepositRequest({ id ,data})
|
||||
console.log(res);
|
||||
|
||||
if (res?.error) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={res?.error?.data?.message} status={"error"} />
|
||||
),
|
||||
});
|
||||
heandleOnClose()
|
||||
|
||||
}else if(res?.data) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={res?.data?.success} />
|
||||
),
|
||||
});
|
||||
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"}>Reject</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}
|
||||
>
|
||||
Send
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Box>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default RejectModal;
|
||||
@@ -135,9 +135,6 @@ const Dashbaord = () => {
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
|
||||
|
||||
|
||||
<Box boxShadow={'lg'} position={"relative"} bg={'#fff'} rounded={'xl'} w={'40%'} display={'flex'} justifyContent={'space-between'} flexDirection={'column'} h={"95%"} mt={1} p={4}>
|
||||
<Text as={'span'} fontSize={'sm'}>IO Status</Text>
|
||||
<Box display={'flex'} w={'100%'} h={'100%'} alignItems={'center'} justifyContent={'space-around'} >
|
||||
@@ -151,9 +148,6 @@ const Dashbaord = () => {
|
||||
</VStack>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
|
||||
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
504
src/Pages/Dashboard/Dashbaord.jsx
Normal file
@@ -0,0 +1,504 @@
|
||||
import {
|
||||
Box,
|
||||
Divider,
|
||||
Flex,
|
||||
Heading,
|
||||
HStack,
|
||||
Image,
|
||||
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 { Link } from "react-router-dom";
|
||||
import { useGetDashboardMasterQuery } from "../../Services/dashboard.service";
|
||||
import InvestmentOpportunities from "./InvestmentOpportunities";
|
||||
import IconOne from '../../Images/dash_icon_1.svg';
|
||||
import IconTwo from '../../Images/dash_icon_2.svg';
|
||||
import IconThree from '../../Images/dash_icon_3n.png';
|
||||
import IconFour from '../../Images/dash_icon_4.svg'
|
||||
import IconFive from '../../Images/dash_icon_5.svg';
|
||||
import IconSix from '../../Images/dash_icon_6n.png';
|
||||
import IconSeven from '../../Images/dash_icon_7.svg'
|
||||
|
||||
// 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: IconOne,
|
||||
label: "Pending deposit requests",
|
||||
count: parseFloat(
|
||||
data?.data?.pendingRequests?.pendingDepositReq?.totalDepositReq || 0
|
||||
).toLocaleString(),
|
||||
},
|
||||
{
|
||||
icon: IconTwo,
|
||||
label: "Pending withdrawal requests",
|
||||
count: parseFloat(
|
||||
data?.data?.pendingRequests?.pendingWithdrawalReq || 0
|
||||
).toLocaleString(),
|
||||
},
|
||||
{
|
||||
icon: IconThree,
|
||||
label: "Pending KYC review request",
|
||||
count: parseFloat(
|
||||
data?.data?.pendingRequests?.pendingKYCReviewReq || 0
|
||||
).toLocaleString(),
|
||||
},
|
||||
{
|
||||
icon: IconFour,
|
||||
label: "Pending Acc modification request",
|
||||
count: parseFloat(
|
||||
data?.data?.pendingRequests?.pendingAccModReq?.totalAccModReq || 0
|
||||
).toLocaleString(),
|
||||
},
|
||||
];
|
||||
|
||||
const userActivity = [
|
||||
{
|
||||
icon: IconFive,
|
||||
label: "Total number of users",
|
||||
count: data?.data?.userActivity?.totalCount, //totalCount
|
||||
},
|
||||
{
|
||||
icon: IconSix,
|
||||
label: "Total number of users with completed KYC (%)",
|
||||
count: data?.data?.userActivity?.KYCCompletedCount, //KYCCompletedCount
|
||||
percentage: data?.data?.userActivity?.completedKYCPer, //completedKYCPer
|
||||
},
|
||||
{
|
||||
icon: IconSeven,
|
||||
label: "Total number of Active users",
|
||||
count: data?.data?.userActivity?.ActiveUsers, //ActiveUsers
|
||||
},
|
||||
];
|
||||
|
||||
const closedOpportunities = [
|
||||
{
|
||||
icon: IconOne,
|
||||
label: "Closed Opportunities",
|
||||
count: parseFloat(
|
||||
data?.data?.investmentOpportunity?.closedOpportunityDetails
|
||||
?.numberOfClosedOpportunities || 0
|
||||
).toLocaleString(),
|
||||
},
|
||||
{
|
||||
icon: IconOne,
|
||||
label: "Total assets under management",
|
||||
count: `$ ${parseFloat(
|
||||
data?.data?.investmentOpportunity?.closedOpportunityDetails?.totalAUM ||
|
||||
0
|
||||
).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}`,
|
||||
},
|
||||
{
|
||||
icon: IconOne,
|
||||
label: "Total number of investors",
|
||||
count: parseFloat(
|
||||
data?.data?.investmentOpportunity?.closedOpportunityDetails
|
||||
?.totalNumberOfInvestors || 0
|
||||
).toLocaleString(),
|
||||
},
|
||||
{
|
||||
icon: IconOne,
|
||||
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>
|
||||
<Divider borderBottom={'1px solid #00471785'} />
|
||||
<SimpleGrid columns={2} spacing={3}>
|
||||
{panddingReguest.map((item, index) => (
|
||||
<Box key={index} bg="white" p={3} pb={2} rounded={10} border={'1px solid #00471785'}>
|
||||
<Text fontSize={"18px"} mb={2}>
|
||||
<Image w={"20px"} src={item.icon} />
|
||||
</Text>
|
||||
<Text mb={0} mt={0} fontSize={"11px"} fontWeight={500}>
|
||||
{item.label}
|
||||
</Text>
|
||||
<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>
|
||||
<Divider borderBottom={'1px solid #00471785'} />
|
||||
<SimpleGrid columns={3} spacing={3}>
|
||||
{userActivity.map((item, index) => (
|
||||
<Box key={index} bg="white" p={3} pb={2} rounded={10} border={'1px solid #00471785'}>
|
||||
<Flex alignContent={"center"}>
|
||||
<Text fontSize={"18px"} mb={0}>
|
||||
{item.icon === IconSix ? (
|
||||
<Image w={"35px"} src={item.icon} />
|
||||
) : item.icon === IconSeven ? (
|
||||
<Image w={"18px"} src={item.icon} />
|
||||
) : (
|
||||
<Image w={"25px"} src={item.icon} />
|
||||
)}
|
||||
</Text>
|
||||
|
||||
<Text
|
||||
fontSize={"11px"}
|
||||
fontWeight={500}
|
||||
mb={0}
|
||||
minH={"38px"}
|
||||
ml={1}
|
||||
mt={0}
|
||||
>
|
||||
{item.label}
|
||||
</Text>
|
||||
</Flex>
|
||||
<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"} px={4} rounded={10} border={'1px solid #0047171f'}>
|
||||
<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} mb={0}>
|
||||
Users that opened the app today
|
||||
</Text>
|
||||
</Box>
|
||||
<Divider orientation="vertical" h={'70px'} borderLeft={'1px solid #00471785'} />
|
||||
<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} mb={0}>
|
||||
Users who logged in during the last month
|
||||
</Text>
|
||||
</Box>
|
||||
</HStack>
|
||||
</Box>
|
||||
<Box
|
||||
w={"50%"}
|
||||
bg={"#fff"}
|
||||
px={4}
|
||||
rounded={10}
|
||||
alignItems={"inherit"}
|
||||
border={'1px solid #0047171f'}
|
||||
>
|
||||
<Box display={"flex"} justifyContent={"end"} position={'relative'} top={3}>
|
||||
<Select
|
||||
bg={"#0047170F"}
|
||||
w={"108px"}
|
||||
display={"flex"}
|
||||
alignItems={"center"}
|
||||
// placeholder="Select"
|
||||
size="xs"
|
||||
fontSize={'10px'}
|
||||
fontWeight={600}
|
||||
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}
|
||||
>
|
||||
{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} mb={0}>
|
||||
New sign-ups{" "}
|
||||
</Text>
|
||||
</Box>
|
||||
<Divider orientation="vertical" h={'70px'} borderLeft={'1px solid #00471785'} />
|
||||
<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} mb={0}>
|
||||
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>
|
||||
<Divider borderBottom={'1px solid #00471785'} />
|
||||
<Box mb={5} bg={"#fff"} py={2} rounded={4} border={'1px solid #0047171f'}>
|
||||
<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={"150px"} overflowY={"scroll"} position={"relative"}>
|
||||
<InvestmentOpportunities
|
||||
showSearch={false}
|
||||
selectStyle={{
|
||||
right: "5px",
|
||||
marginBottom: "5px",
|
||||
bg:'#e6f3e9'
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<SimpleGrid columns={2} spacing={4}>
|
||||
{closedOpportunities.map((item, index) => (
|
||||
<Box key={index} bg="white" p={4} rounded={10} border={'1px solid #00471785'}>
|
||||
<HStack alignItems={"center"}>
|
||||
<Text fontSize={"17px"} mb={0}>
|
||||
<Image w={'20px'} src={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}>
|
||||
{/* {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>
|
||||
<Divider borderBottom={'1px solid #00471785'} />
|
||||
<Box bg={"#fff"} p={4} rounded={4} mb={5} border={'1px solid #0047171f'}>
|
||||
<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={2} spacing={2} mb={2}>
|
||||
{walletCase.slice(0, 4).map((item, index) => (
|
||||
<Box key={index} bg={"#fff"} p={3} rounded={4} border={'1px solid #00471785'}>
|
||||
<Text mb={1} fontSize={"md"} fontWeight={500}>
|
||||
{item.amount}
|
||||
</Text>
|
||||
<Text mb={0} fontSize={"md"} color={"#00000075"}>
|
||||
{item.currency}
|
||||
</Text>
|
||||
</Box>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
|
||||
<SimpleGrid columns={3} spacing={2}>
|
||||
{walletCase.slice(4).map((item, index) => (
|
||||
<Box key={index} bg={"#fff"} p={3} rounded={4} border={'1px solid #00471785'}>
|
||||
<Text mb={1} fontSize={"md"} fontWeight={500}>
|
||||
{item.amount}
|
||||
</Text>
|
||||
<Text mb={0} fontSize={"md"} color={"#00000075"}>
|
||||
{item.currency}
|
||||
</Text>
|
||||
</Box>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default Dashbaord;
|
||||
169
src/Pages/Dashboard/InvestmentOpportunities.jsx
Normal file
@@ -0,0 +1,169 @@
|
||||
import { Badge, 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";
|
||||
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>
|
||||
</Box>
|
||||
),
|
||||
"Amount Remaining %": (
|
||||
<Box w={"90px"} textAlign={'end'} isTruncated>
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{parseFloat(item?.Amount_remaining_per || 0).toLocaleString(
|
||||
undefined,
|
||||
{
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
}
|
||||
)}<Badge ms={1} colorScheme="green">%</Badge>
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Total Deal Size": (
|
||||
<Box w={"auto"} isTruncated>
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
<Badge me={1} ms={1} colorScheme="green">$</Badge>{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"}>
|
||||
{filter === "last30days"
|
||||
? item?.Views_mtd
|
||||
: filter === "last7days"
|
||||
? item?.Views_last_7_days
|
||||
: item?.Views_today}
|
||||
</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"
|
||||
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>
|
||||
)}
|
||||
<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>
|
||||
</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 this opportunity?"}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default InvestmentOpportunities;
|
||||
@@ -4,39 +4,34 @@ import {
|
||||
Button,
|
||||
HStack,
|
||||
Input,
|
||||
Switch,
|
||||
Text,
|
||||
Tooltip,
|
||||
useToast,
|
||||
useDisclosure,
|
||||
Link,
|
||||
Text,
|
||||
useBoolean,
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { HiDotsVertical } from "react-icons/hi";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { debounce } from "../../Master/Sponser/AddSponser";
|
||||
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||
import Pagination from "../../../Components/Pagination";
|
||||
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
|
||||
import ToastBox from "../../../Components/ToastBox";
|
||||
import NormalTable from "../../../Components/DataTable/NormalTable";
|
||||
import ConfirmModal from "./ConfirmModal";
|
||||
import RejectModal from "./RejectModal";
|
||||
import {
|
||||
useDepositRejectMutation,
|
||||
useGetDepositHistoryQuery,
|
||||
} from "../../../Services/deposit.request.service";
|
||||
import Pagination from "../../../Components/Pagination";
|
||||
import ToastBox from "../../../Components/ToastBox";
|
||||
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
|
||||
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||
import { useGetDepositHistoryQuery } from "../../../Services/deposit.request.service";
|
||||
import { debounce } from "../../Master/Sponser/AddSponser";
|
||||
|
||||
import { ExternalLinkIcon } from "@chakra-ui/icons";
|
||||
import InitiateReversalPopup from "../../../Components/Popups/InitiateReversalPopups";
|
||||
import { generateSerialNumber, isMaker } from "../../../Constants/Constants";
|
||||
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
||||
import { generateSerialNumber } from "../../../Constants/Constants";
|
||||
import { useCreateBankDepositReversalRequestMutation } from "../../../Services/bankdeposit.request.service";
|
||||
|
||||
const formatDate = (date) => {
|
||||
return new Date(date).toLocaleDateString('en-GB', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
return new Date(date).toLocaleDateString("en-GB", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
});
|
||||
}; // Simple date formatter
|
||||
|
||||
@@ -50,22 +45,22 @@ const DepositHistory = () => {
|
||||
const [actionId, setActionId] = useState(false);
|
||||
const [mouseEntered, setMouseEntered] = useState(false);
|
||||
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||
// const {
|
||||
// isOpen: isConfirmOpen,
|
||||
// onOpen: onConfirmOpen,
|
||||
// onClose: onConfirmClose,
|
||||
// } = useDisclosure();
|
||||
// const {
|
||||
// isOpen: isRejectOpen,
|
||||
// onOpen: onRejectOpen,
|
||||
// onClose: onRejectClose,
|
||||
// } = useDisclosure();
|
||||
|
||||
const [createBankDepositReversalRequest] =
|
||||
useCreateBankDepositReversalRequestMutation();
|
||||
|
||||
// =========================== [Use State] =============================
|
||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||
const [reversalId, setReversalId] = useState();
|
||||
const {
|
||||
isOpen: isOpenInRev,
|
||||
onOpen: onOpenInRev,
|
||||
onClose: onCloseInRev,
|
||||
} = useDisclosure();
|
||||
const [isReversalLoading, setIsReversalLoading] = useBoolean();
|
||||
|
||||
// Debounce the search term to avoid making a request on every keystroke
|
||||
useEffect(() => {
|
||||
@@ -77,20 +72,21 @@ const DepositHistory = () => {
|
||||
};
|
||||
}, [searchTerm]);
|
||||
|
||||
|
||||
const {
|
||||
data,
|
||||
error,
|
||||
refetch,
|
||||
isLoading: depositHistoryLoading,
|
||||
} = useGetDepositHistoryQuery({
|
||||
} = useGetDepositHistoryQuery(
|
||||
{
|
||||
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
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// Use useEffect to refetch data when the component mounts
|
||||
useEffect(() => {
|
||||
@@ -109,6 +105,7 @@ const DepositHistory = () => {
|
||||
"Deposit Date",
|
||||
"Status",
|
||||
"Supporting's",
|
||||
isMaker() && "Reversal Action",
|
||||
];
|
||||
|
||||
const handleUpdateStatus = debounce((id) => {
|
||||
@@ -205,11 +202,7 @@ const DepositHistory = () => {
|
||||
</Box>
|
||||
),
|
||||
"Deposit Amount": (
|
||||
<Box
|
||||
isTruncated={true}
|
||||
display={"flex"}
|
||||
justifyContent={"end"}
|
||||
>
|
||||
<Box isTruncated={true} display={"flex"} justifyContent={"end"}>
|
||||
<Text as={"span"} color={"teal.900"} textAlign={"right"}>
|
||||
{parseFloat(item?.investorAmount || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
@@ -283,31 +276,91 @@ const DepositHistory = () => {
|
||||
) : (
|
||||
""
|
||||
),
|
||||
"Reversal Action": (
|
||||
<Box w={"120px"} isTruncated={true} cursor={"pointer"}>
|
||||
{item.transactionStatus === "Approved" ? (
|
||||
<Text
|
||||
as={"span"}
|
||||
color={!item.isReversal ? "green.500" : "#FFBB00"}
|
||||
fontWeight={700}
|
||||
>
|
||||
{!item.isReversal ? (
|
||||
<Button
|
||||
onClick={() => {
|
||||
onOpenInRev(); // Call the function
|
||||
setReversalId(item.id);
|
||||
}}
|
||||
colorScheme="teal"
|
||||
size="xs"
|
||||
variant="outline"
|
||||
>
|
||||
Initiate Reversal
|
||||
</Button>
|
||||
) : (
|
||||
"Under process"
|
||||
)}
|
||||
</Text>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</Box>
|
||||
),
|
||||
}));
|
||||
|
||||
const handleDelete = () => {
|
||||
const IOtype = investmentType.filter(
|
||||
(investmentType) => investmentType.id !== actionId
|
||||
);
|
||||
// const handleDelete = () => {
|
||||
// const IOtype = investmentType.filter(
|
||||
// (investmentType) => investmentType.id !== actionId
|
||||
// );
|
||||
|
||||
setTimeout(() => {
|
||||
setInvestmentType(IOtype);
|
||||
setDeleteAlert(false);
|
||||
setIsLoading(false);
|
||||
}, 100);
|
||||
setIsLoading(true);
|
||||
// setTimeout(() => {
|
||||
// setInvestmentType(IOtype);
|
||||
// setDeleteAlert(false);
|
||||
// setIsLoading(false);
|
||||
// }, 100);
|
||||
// setIsLoading(true);
|
||||
// };
|
||||
|
||||
const handleApproved = async (data) => {
|
||||
setIsReversalLoading.on(); // Start loading
|
||||
try {
|
||||
const { error, data: responseData } =
|
||||
await createBankDepositReversalRequest({
|
||||
id: reversalId,
|
||||
data,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
throw error; // Explicitly handle the error
|
||||
}
|
||||
|
||||
// Success: Perform necessary actions
|
||||
refetch();
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={responseData?.message || "Action successful!"} />
|
||||
),
|
||||
});
|
||||
onCloseInRev();
|
||||
} catch (error) {
|
||||
// Handle errors
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox
|
||||
message={
|
||||
error?.data?.message || "Something went wrong. Please try again."
|
||||
}
|
||||
status="error"
|
||||
/>
|
||||
),
|
||||
});
|
||||
console.error("Error:", error);
|
||||
} finally {
|
||||
setIsReversalLoading.off(); // Ensure loading is toggled off
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||
{/* <ConfirmModal
|
||||
isOpen={isConfirmOpen}
|
||||
onClose={onConfirmClose}
|
||||
/>
|
||||
<RejectModal
|
||||
isOpen={isRejectOpen}
|
||||
onClose={onRejectClose}
|
||||
/> */}
|
||||
<Box bg="white.500">
|
||||
<HStack
|
||||
display={"flex"}
|
||||
@@ -354,12 +407,19 @@ const DepositHistory = () => {
|
||||
setMouseEntered={setMouseEntered}
|
||||
/>
|
||||
|
||||
<CustomAlertDialog
|
||||
{/* <CustomAlertDialog
|
||||
onClose={() => setDeleteAlert(false)}
|
||||
isOpen={deleteAlert}
|
||||
message={"Are you sure you want to delete sponers?"}
|
||||
alertHandler={handleDelete}
|
||||
isLoading={isLoading}
|
||||
/> */}
|
||||
|
||||
<InitiateReversalPopup
|
||||
onClose={onCloseInRev}
|
||||
isOpen={isOpenInRev}
|
||||
handelApproved={handleApproved}
|
||||
isLoading={isReversalLoading}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -7,10 +7,11 @@ import {
|
||||
FormLabel,
|
||||
HStack,
|
||||
Input,
|
||||
Select,
|
||||
Text,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||
import NormalTable from "../../Components/DataTable/NormalTable";
|
||||
import { useGetUnbanInvestorQuery } from "../../Services/ban.investor.service";
|
||||
@@ -28,8 +29,11 @@ const EmailNotification = () => {
|
||||
const [subject, setSubject] = useState("");
|
||||
const [value, setValue] = useState(""); // Quill content (body)
|
||||
const toast = useToast();
|
||||
|
||||
const [sendCustomNotification] = useSendCustomEmailMutation();
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||
const [country, setCountry] = useState("");
|
||||
const [kyc, setKyc] = useState("");
|
||||
|
||||
// ===========================[Table Setup]==============================
|
||||
const tableHeadRow = [
|
||||
@@ -47,14 +51,40 @@ const EmailNotification = () => {
|
||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||
|
||||
// const {
|
||||
// data: investorDetails,
|
||||
// isLoading: investorDetailsLoading,
|
||||
// refetch,
|
||||
// } = useGetUnbanInvestorQuery({
|
||||
// page: currentPage, // Omit pagination for search
|
||||
// size: 10000, // Omit pagination for search
|
||||
// });
|
||||
|
||||
useEffect(() => {
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedSearchTerm(searchTerm.trim()); // Trim to remove leading/trailing spaces
|
||||
}, 300);
|
||||
return () => clearTimeout(handler);
|
||||
}, [searchTerm]);
|
||||
|
||||
const {
|
||||
data: investorDetails,
|
||||
isLoading: investorDetailsLoading,
|
||||
refetch,
|
||||
} = useGetUnbanInvestorQuery({
|
||||
page: currentPage, // Omit pagination for search
|
||||
} = useGetUnbanInvestorQuery(
|
||||
{
|
||||
page: 1, // Omit pagination for search
|
||||
size: 10000, // Omit pagination for search
|
||||
});
|
||||
// page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||
// size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||
search: debouncedSearchTerm,
|
||||
country_xid: country,
|
||||
KYCStatus: kyc,
|
||||
},
|
||||
{
|
||||
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||
}
|
||||
);
|
||||
|
||||
const extractedArray = investorDetails?.data?.rows?.map((item, idx) => ({
|
||||
id: item?.principal_xid,
|
||||
@@ -127,7 +157,7 @@ const EmailNotification = () => {
|
||||
py={0.5}
|
||||
variant={"ghost"}
|
||||
>
|
||||
{item?.KYCStatus === true ? "Completed" : "Incompleted"}
|
||||
{item?.KYCStatus === true ? "Completed" : "Not Completed"}
|
||||
</Badge>
|
||||
</Box>
|
||||
),
|
||||
@@ -152,7 +182,10 @@ const EmailNotification = () => {
|
||||
if (!subject || !value) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox status={"error"} message={"Subject or email body cannot be empty"} />
|
||||
<ToastBox
|
||||
status={"error"}
|
||||
message={"Subject or email body cannot be empty"}
|
||||
/>
|
||||
),
|
||||
});
|
||||
return;
|
||||
@@ -161,7 +194,10 @@ const EmailNotification = () => {
|
||||
if (selectedRadio.length === 0) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox status={"error"} message={"Please select at least one recipient"} />
|
||||
<ToastBox
|
||||
status={"error"}
|
||||
message={"Please select at least one recipient"}
|
||||
/>
|
||||
),
|
||||
});
|
||||
return;
|
||||
@@ -175,9 +211,8 @@ const EmailNotification = () => {
|
||||
principal_xid: selectedRadio,
|
||||
};
|
||||
|
||||
|
||||
try {
|
||||
const res = await sendCustomNotification(emailPayload)
|
||||
const res = await sendCustomNotification(emailPayload);
|
||||
console.log(res);
|
||||
if (res?.error) {
|
||||
toast({
|
||||
@@ -185,31 +220,24 @@ const EmailNotification = () => {
|
||||
<ToastBox status={"error"} message={res?.error?.data?.message} />
|
||||
),
|
||||
});
|
||||
setIsLoading(false)
|
||||
setIsLoading(false);
|
||||
} else if (res?.data) {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={res?.data?.message} />
|
||||
),
|
||||
render: () => <ToastBox message={res?.data?.message} />,
|
||||
});
|
||||
setIsLoading(false)
|
||||
setSubject("")
|
||||
setValue("")
|
||||
setSelectedRadio([])
|
||||
|
||||
setIsLoading(false);
|
||||
setSubject("");
|
||||
setValue("");
|
||||
setSelectedRadio([]);
|
||||
} else {
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox status={'error'} message={"Something went wrong"} />
|
||||
<ToastBox status={"error"} message={"Something went wrong"} />
|
||||
),
|
||||
});
|
||||
setIsLoading(false)
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -247,31 +275,83 @@ const EmailNotification = () => {
|
||||
{/* <FormHelperText>Entered subject will be reflected on emails subject body.</FormHelperText> */}
|
||||
</FormControl>
|
||||
|
||||
|
||||
<FormControl minH={400} isRequired mb={3} p={1}>
|
||||
<FormLabel fontSize={"sm"}>Create Custom body</FormLabel>
|
||||
<ReactQuill
|
||||
theme="snow"
|
||||
style={{
|
||||
height:300
|
||||
height: 300,
|
||||
}}
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
modules={modules}
|
||||
placeholder="Start typing here..."
|
||||
|
||||
/>
|
||||
</FormControl>
|
||||
{/* <FormHelperText fontSize={"xs"}>
|
||||
We'll never share your email.
|
||||
</FormHelperText> */}
|
||||
|
||||
|
||||
|
||||
|
||||
</FormControl>
|
||||
|
||||
<Box overflow={'scroll'} h={'58vh'}>
|
||||
<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 className="col" justifyContent={"end"}>
|
||||
<Select
|
||||
w={250}
|
||||
focusBorderColor="green.500"
|
||||
size={"sm"}
|
||||
fontSize={"xs"}
|
||||
cursor={"pointer"}
|
||||
onChange={(e) => setCountry(e.target.value)}
|
||||
value={country}
|
||||
>
|
||||
<option value="" defaultValue={""} disabled hidden>
|
||||
Country
|
||||
</option>
|
||||
<option value="">All</option>
|
||||
<option value="1">Bahrain</option>
|
||||
<option value="2">Kuwait</option>
|
||||
<option value="3">Oman</option>
|
||||
<option value="4">Qatar</option>
|
||||
<option value="5">Saudi arabia</option>
|
||||
<option value="6">United arab emirates</option>
|
||||
</Select>
|
||||
<Select
|
||||
w={250}
|
||||
focusBorderColor="green.500"
|
||||
size={"sm"}
|
||||
fontSize={"xs"}
|
||||
cursor={"pointer"}
|
||||
onChange={(e) => setKyc(e.target.value)}
|
||||
value={kyc}
|
||||
>
|
||||
<option value="" defaultValue={""} disabled hidden>
|
||||
KYC Status
|
||||
</option>
|
||||
<option value="">KYC Status</option>
|
||||
<option value="0">Not Completed</option>
|
||||
<option value="1">Completed</option>
|
||||
</Select>
|
||||
</HStack>
|
||||
</HStack>
|
||||
<Box overflow={"scroll"} h={"58vh"}>
|
||||
<NormalTable
|
||||
centered={true}
|
||||
emptyMessage={`We don't have any Sponsors`}
|
||||
|
||||
@@ -1,46 +1,25 @@
|
||||
import {
|
||||
Avatar,
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
HStack,
|
||||
Input,
|
||||
Menu,
|
||||
MenuButton,
|
||||
MenuItem,
|
||||
MenuList,
|
||||
Portal,
|
||||
Select,
|
||||
Switch,
|
||||
Tag,
|
||||
Text,
|
||||
Tooltip,
|
||||
useDisclosure,
|
||||
useToast,
|
||||
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 React, { useContext, useEffect, useRef, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
||||
import NormalTable from "../../Components/DataTable/NormalTable";
|
||||
import Pagination from "../../Components/Pagination";
|
||||
import ToastBox from "../../Components/ToastBox";
|
||||
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
||||
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||
import { debounce } from "../Master/Sponser/AddSponser";
|
||||
// import InvestmentDetailsEdit from "./InvestmentDetailsEdit";
|
||||
import { useGetInvestorsQuery } from "../../Services/investor.details.service";
|
||||
import { generateSerialNumber } from "../../Constants/Constants";
|
||||
import { TABLE_PAGINATION } from "../../Constants/Paginations";
|
||||
import { exportToExcel, generateSerialNumber } from "../../Constants/Constants";
|
||||
import { LuFileSpreadsheet } from "react-icons/lu";
|
||||
|
||||
import { useGetInvestorsQuery } from "../../Services/investor.details.service";
|
||||
|
||||
const FawateerRequest = () => {
|
||||
const navigate = useNavigate();
|
||||
@@ -60,7 +39,6 @@ const FawateerRequest = () => {
|
||||
} = useDisclosure();
|
||||
const btnRef = React.useRef();
|
||||
|
||||
|
||||
// =========================== [Use State] =============================
|
||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||
@@ -77,12 +55,12 @@ const FawateerRequest = () => {
|
||||
};
|
||||
}, [searchTerm]);
|
||||
|
||||
|
||||
const {
|
||||
data: investorDetails,
|
||||
isLoading: investorDetailsLoading,
|
||||
error,
|
||||
} = useGetInvestorsQuery({
|
||||
} = useGetInvestorsQuery(
|
||||
{
|
||||
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||
search: debouncedSearchTerm,
|
||||
@@ -92,7 +70,6 @@ const FawateerRequest = () => {
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
// Simulate loading
|
||||
const timer = setTimeout(() => {
|
||||
@@ -131,7 +108,15 @@ const FawateerRequest = () => {
|
||||
// ====================================================[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 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);
|
||||
|
||||
@@ -147,8 +132,6 @@ const FawateerRequest = () => {
|
||||
return nameMatches;
|
||||
});
|
||||
|
||||
|
||||
|
||||
const customHeaders = [
|
||||
{ label: "ID", key: "id" },
|
||||
{ label: "Client ID", key: "clientReference_id" },
|
||||
@@ -162,12 +145,11 @@ const FawateerRequest = () => {
|
||||
{ label: "KYC Status", key: "KYCStatus" }, // Simple property
|
||||
];
|
||||
|
||||
|
||||
const extractedArray = investorDetails?.data?.rows?.map((item, idx) => ({
|
||||
id: item?.id,
|
||||
"Sr No": (
|
||||
<Text
|
||||
w={'24px'}
|
||||
w={"24px"}
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"gray.600"}
|
||||
@@ -175,7 +157,6 @@ const FawateerRequest = () => {
|
||||
>
|
||||
{/* {item.id} */}
|
||||
{generateSerialNumber(idx, currentPage, pageSize)}
|
||||
|
||||
</Text>
|
||||
),
|
||||
"Client ID": (
|
||||
@@ -220,10 +201,16 @@ const FawateerRequest = () => {
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Type": (
|
||||
Type: (
|
||||
<Box w={"auto"} isTruncated={true}>
|
||||
<Text as={"span"}>
|
||||
<Badge color={"forestGreen.500"} variant={'ghost'} fontWeight={"700"} px={2} py={0.5}>
|
||||
<Badge
|
||||
color={"forestGreen.500"}
|
||||
variant={"ghost"}
|
||||
fontWeight={"700"}
|
||||
px={2}
|
||||
py={0.5}
|
||||
>
|
||||
{item?.investor_type?.investorTypeName}
|
||||
</Badge>
|
||||
</Text>
|
||||
@@ -264,8 +251,6 @@ const FawateerRequest = () => {
|
||||
|
||||
console.log(investorDetails?.data?.totalItems);
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||
<Box bg="white.500">
|
||||
@@ -290,11 +275,7 @@ const FawateerRequest = () => {
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
/>
|
||||
|
||||
|
||||
|
||||
<HStack display={"flex"} alignItems={"center"}>
|
||||
|
||||
|
||||
<Pagination
|
||||
isLoading={investorDetailsLoading}
|
||||
pageSize={pageSize}
|
||||
@@ -302,10 +283,8 @@ const FawateerRequest = () => {
|
||||
currentPage={currentPage}
|
||||
setCurrentPage={setCurrentPage}
|
||||
totalItems={investorDetails?.data?.totalItems}
|
||||
|
||||
/>
|
||||
|
||||
|
||||
{/*
|
||||
<Button
|
||||
leftIcon={<AddIcon />}
|
||||
@@ -317,7 +296,6 @@ const FawateerRequest = () => {
|
||||
>
|
||||
Create request
|
||||
</Button> */}
|
||||
|
||||
</HStack>
|
||||
</HStack>
|
||||
</Box>
|
||||
@@ -345,4 +323,4 @@ const FawateerRequest = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default FawateerRequest
|
||||
export default FawateerRequest;
|
||||
|
||||
@@ -37,6 +37,7 @@ const ApproveHistory = () => {
|
||||
const [actionId, setActionId] = useState(false);
|
||||
const [mouseEntered, setMouseEntered] = useState(false);
|
||||
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||
|
||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||
@@ -60,12 +61,31 @@ const ApproveHistory = () => {
|
||||
onClose: onRejectClose,
|
||||
} = useDisclosure();
|
||||
|
||||
// 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,
|
||||
isLoading: drawalRequestLoading,
|
||||
error,
|
||||
refetch,
|
||||
} = useGetApproveHistoryQuery();
|
||||
} = useGetApproveHistoryQuery(
|
||||
{
|
||||
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||
size: debouncedSearchTerm ? undefined : pageSize, // Omit pagination for search
|
||||
searchTerm: debouncedSearchTerm,
|
||||
},
|
||||
{
|
||||
skip: debouncedSearchTerm === "" && searchTerm !== "", // Skip if search is empty and it's not the initial request
|
||||
}
|
||||
);
|
||||
|
||||
console.log(data?.data?.rows);
|
||||
|
||||
@@ -84,6 +104,15 @@ const ApproveHistory = () => {
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedSearchTerm(searchTerm);
|
||||
}, 500); // Adjust delay as needed
|
||||
return () => {
|
||||
clearTimeout(handler);
|
||||
};
|
||||
}, [searchTerm]);
|
||||
// ====================================================[Table Filter]================================================================
|
||||
const filteredData = data?.data?.rows?.filter((item) => {
|
||||
// Filter by name (case insensitive)
|
||||
@@ -117,7 +146,7 @@ const ApproveHistory = () => {
|
||||
"Status",
|
||||
];
|
||||
|
||||
const extractedArray = filteredData?.map((item, idx) => ({
|
||||
const extractedArray = data?.data?.rows?.map((item, idx) => ({
|
||||
// id: item?.id,
|
||||
"Sr.no": (
|
||||
<Text
|
||||
@@ -172,11 +201,7 @@ const ApproveHistory = () => {
|
||||
</Box>
|
||||
),
|
||||
"Deposit Date": (
|
||||
<Box
|
||||
w={"100px"}
|
||||
isTruncated={true}
|
||||
display={"flex"}
|
||||
>
|
||||
<Box w={"100px"} isTruncated={true} display={"flex"}>
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{formatDate(item?.transaction_date)}
|
||||
</Text>
|
||||
@@ -202,7 +227,8 @@ const ApproveHistory = () => {
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item?.spportFile_path&&<Badge
|
||||
{item?.spportFile_path && (
|
||||
<Badge
|
||||
px={2}
|
||||
py={0.5}
|
||||
textTransform={"inherit"}
|
||||
@@ -215,15 +241,13 @@ const ApproveHistory = () => {
|
||||
display={"flex"}
|
||||
alignItems={"center"}
|
||||
>
|
||||
<Box me={"1px"}
|
||||
as="span"
|
||||
cursor={"pointer"}
|
||||
>
|
||||
<Box me={"1px"} as="span" cursor={"pointer"}>
|
||||
View
|
||||
</Box>
|
||||
<ExternalLinkIcon />
|
||||
</Link>
|
||||
</Badge>}
|
||||
</Badge>
|
||||
)}
|
||||
</Text>
|
||||
),
|
||||
Status: (
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
Link,
|
||||
Text,
|
||||
Tooltip,
|
||||
useBoolean,
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
@@ -19,7 +20,7 @@ import {
|
||||
import DrawalRequestReject from "../../WithDrawal/DrawalRequest/DrawalRequestReject";
|
||||
import NormalTable from "../../../Components/DataTable/NormalTable";
|
||||
import DrawalRequestApprove from "../../WithDrawal/DrawalRequest/DrawalRequestApprove";
|
||||
import { generateSerialNumber } from "../../../Constants/Constants";
|
||||
import { generateSerialNumber, isMaker } from "../../../Constants/Constants";
|
||||
import {
|
||||
useGetApproveHistoryQuery,
|
||||
useGetFawateerForMakerRequestQuery,
|
||||
@@ -27,6 +28,9 @@ import {
|
||||
} from "../../../Services/fawateer.request.service";
|
||||
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
|
||||
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
|
||||
import InitiateReversalPopup from "../../../Components/Popups/InitiateReversalPopups";
|
||||
import ToastBox from "../../../Components/ToastBox";
|
||||
import { useCreateFawateerReversalRequestMutation } from "../../../Services/reversal.fawateer.deposit.service";
|
||||
|
||||
const ApproveHistoryMaker = () => {
|
||||
const toast = useToast();
|
||||
@@ -43,6 +47,17 @@ import {
|
||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||
|
||||
const [createFawateerReversalRequest] =
|
||||
useCreateFawateerReversalRequestMutation();
|
||||
|
||||
const [reversalId, setReversalId] = useState();
|
||||
const {
|
||||
isOpen: isOpenInRev,
|
||||
onOpen: onOpenInRev,
|
||||
onClose: onCloseInRev,
|
||||
} = useDisclosure();
|
||||
const [isReversalLoading, setIsReversalLoading] = useBoolean();
|
||||
|
||||
const formatDate = (date) => {
|
||||
return new Date(date).toLocaleDateString("en-GB", {
|
||||
day: "2-digit",
|
||||
@@ -66,7 +81,7 @@ import {
|
||||
data,
|
||||
isLoading: drawalRequestLoading,
|
||||
error,
|
||||
refetch
|
||||
refetch,
|
||||
} = useGetFawateerForMakerRequestQuery(
|
||||
{
|
||||
page: debouncedSearchTerm ? undefined : currentPage, // Omit pagination for search
|
||||
@@ -78,8 +93,6 @@ import {
|
||||
}
|
||||
);
|
||||
|
||||
console.log(data);
|
||||
|
||||
useEffect(() => {
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedSearchTerm(searchTerm);
|
||||
@@ -135,10 +148,10 @@ import {
|
||||
"Deposit Amount (BHD)",
|
||||
"Support Image",
|
||||
"Status",
|
||||
isMaker() && "Reversal Action",
|
||||
];
|
||||
|
||||
const extractedArray = data?.data?.rows?.map((item, idx) => ({
|
||||
|
||||
// id: item?.id,
|
||||
"Sr.no": (
|
||||
<Text
|
||||
@@ -193,11 +206,7 @@ import {
|
||||
</Box>
|
||||
),
|
||||
"Deposit Date": (
|
||||
<Box
|
||||
w={"100px"}
|
||||
isTruncated={true}
|
||||
display={"flex"}
|
||||
>
|
||||
<Box w={"100px"} isTruncated={true} display={"flex"}>
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{formatDate(item?.transaction_date)}
|
||||
</Text>
|
||||
@@ -223,7 +232,8 @@ import {
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item?.spportFile_path&&<Badge
|
||||
{item?.spportFile_path && (
|
||||
<Badge
|
||||
px={2}
|
||||
py={0.5}
|
||||
textTransform={"inherit"}
|
||||
@@ -236,15 +246,13 @@ import {
|
||||
display={"flex"}
|
||||
alignItems={"center"}
|
||||
>
|
||||
<Box me={"1px"}
|
||||
as="span"
|
||||
cursor={"pointer"}
|
||||
>
|
||||
<Box me={"1px"} as="span" cursor={"pointer"}>
|
||||
View
|
||||
</Box>
|
||||
<ExternalLinkIcon />
|
||||
</Link>
|
||||
</Badge>}
|
||||
</Badge>
|
||||
)}
|
||||
</Text>
|
||||
),
|
||||
Status: (
|
||||
@@ -269,6 +277,36 @@ import {
|
||||
</Badge>
|
||||
</Box>
|
||||
),
|
||||
"Reversal Action": (
|
||||
<Box w={"120px"} isTruncated={true} cursor={"pointer"}>
|
||||
{item.transactionStatus === "Approved" ? (
|
||||
<Text
|
||||
as={"span"}
|
||||
color={!item.isReversal ? "green.500" : "#FFBB00"}
|
||||
fontWeight={700}
|
||||
>
|
||||
{!item.isReversal ? (
|
||||
<Button
|
||||
onClick={() => {
|
||||
onOpenInRev(); // Call the function
|
||||
// setReversalId(item.transaction_xid);
|
||||
setReversalId(item.id);
|
||||
}}
|
||||
colorScheme="teal"
|
||||
size="xs"
|
||||
variant="outline"
|
||||
>
|
||||
Initiate Reversal
|
||||
</Button>
|
||||
) : (
|
||||
"Under process"
|
||||
)}
|
||||
</Text>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</Box>
|
||||
),
|
||||
}));
|
||||
|
||||
const handleDelete = () => {
|
||||
@@ -284,6 +322,46 @@ import {
|
||||
setIsLoading(true);
|
||||
};
|
||||
|
||||
const handleApproved = async (data) => {
|
||||
setIsReversalLoading.on(); // Start loading
|
||||
try {
|
||||
const { error, data: responseData } = await createFawateerReversalRequest(
|
||||
{
|
||||
id: reversalId,
|
||||
data,
|
||||
}
|
||||
);
|
||||
|
||||
if (error) {
|
||||
throw error; // Explicitly handle the error
|
||||
}
|
||||
|
||||
// Success: Perform necessary actions
|
||||
refetch();
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={responseData?.message || "Action successful!"} />
|
||||
),
|
||||
});
|
||||
onCloseInRev();
|
||||
} catch (error) {
|
||||
// Handle errors
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox
|
||||
message={
|
||||
error?.data?.message || "Something went wrong. Please try again."
|
||||
}
|
||||
status="error"
|
||||
/>
|
||||
),
|
||||
});
|
||||
console.error("Error:", error);
|
||||
} finally {
|
||||
setIsReversalLoading.off(); // Ensure loading is toggled off
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||
<Box bg="white.500">
|
||||
@@ -350,9 +428,15 @@ import {
|
||||
onClose={onRejectClose}
|
||||
id={actionId}
|
||||
/>
|
||||
|
||||
<InitiateReversalPopup
|
||||
onClose={onCloseInRev}
|
||||
isOpen={isOpenInRev}
|
||||
handelApproved={handleApproved}
|
||||
isLoading={isReversalLoading}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default ApproveHistoryMaker;
|
||||
|
||||
@@ -104,6 +104,12 @@ const RequestApproveModal = ({ isOpen, onClose, firstField ,id}) => {
|
||||
}
|
||||
}, [data, reset]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
reset();
|
||||
}
|
||||
}, [isOpen, reset]);
|
||||
|
||||
const heandleOnClose = () =>{
|
||||
reset()
|
||||
onClose()
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
Box,
|
||||
Button,
|
||||
FormControl,
|
||||
FormHelperText,
|
||||
FormLabel,
|
||||
Input,
|
||||
Modal,
|
||||
@@ -24,8 +25,18 @@ import { useDepositRejectMutation } from "../../../Services/deposit.request.serv
|
||||
import ToastBox from "../../../Components/ToastBox";
|
||||
import { useRejectCommentMutation } from "../../../Services/fawateer.request.service";
|
||||
|
||||
// export const conformModalSchema = yup.object().shape({
|
||||
// comments: yup.string().required("Comment is required")
|
||||
// .max(200, "Approve Comment cannot be more than 200 characters"),
|
||||
// });
|
||||
|
||||
export const conformModalSchema = yup.object().shape({
|
||||
comments: yup.string().required("Comment is required"),
|
||||
// checkerComment: yup.string().required("Comment is required")
|
||||
// .max(50, "Investment name cannot be more than 50 characters"),
|
||||
comments: yup
|
||||
.string()
|
||||
.required("Comment is required")
|
||||
.max(200, "Approve Comment cannot be more than 200 characters"),
|
||||
});
|
||||
|
||||
const RequestRejectModal = ({ isOpen, onClose, firstField ,id}) => {
|
||||
@@ -36,12 +47,20 @@ const RequestRejectModal = ({ isOpen, onClose, firstField ,id}) => {
|
||||
const {
|
||||
register,
|
||||
reset,
|
||||
watch,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: yupResolver(conformModalSchema),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
reset(); // Clear the form state
|
||||
}
|
||||
}, [isOpen, reset]);
|
||||
|
||||
|
||||
const [ rejectFawateer ] = useRejectCommentMutation()
|
||||
|
||||
|
||||
@@ -126,12 +145,17 @@ const RequestRejectModal = ({ isOpen, onClose, firstField ,id}) => {
|
||||
placeholder={"Enter your comments...."}
|
||||
rounded={"md"}
|
||||
resize={"none"}
|
||||
maxLength={200}
|
||||
/>
|
||||
{errors.comments && (
|
||||
<Text fontSize="xs" color="red">
|
||||
{errors.comments.message}
|
||||
</Text>
|
||||
)}
|
||||
<FormHelperText fontSize="xs" color="gray.500">
|
||||
Maximum length should be 200 characters. You have entered
|
||||
<Text as={'span'} ml={2}>{watch("comments")?.length || 0} </Text>characters.
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
|
||||
@@ -119,7 +119,7 @@ import AddCaseDetails from "./AddCaseDetails";
|
||||
<Badge ms={1} colorScheme="green" me={1}>
|
||||
$
|
||||
</Badge>
|
||||
{parseFloat(IODetails?.ioCash || 0).toLocaleString(undefined, {
|
||||
{parseFloat(item?.transactionAmount || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
|
||||
@@ -108,7 +108,7 @@ const ViewDistributionInvestor = ({ isOpen, onClose, id: exitId, amount }) => {
|
||||
"Last Name",
|
||||
"Amount",
|
||||
"Holding (%)",
|
||||
"Distriution Amt($)",
|
||||
"Distribution Amt($)",
|
||||
"Yeild (%)",
|
||||
];
|
||||
|
||||
@@ -169,10 +169,10 @@ const ViewDistributionInvestor = ({ isOpen, onClose, id: exitId, amount }) => {
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Distriution Amt($)": (
|
||||
"Distribution Amt($)": (
|
||||
<Box minW={24} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{IODetails?.ioTransactionRecords?.Pending[index]?.transactionAmount?.toLocaleString(undefined, {
|
||||
{item?.distribution_amt?.toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
|
||||
@@ -60,9 +60,9 @@ export const investmentDocSchema = yup.object().shape({
|
||||
// return value && value.size <= 2 * 1024 * 1024; // 2MB in bytes
|
||||
// })
|
||||
fileName: yup.string().required("File name is required")
|
||||
.max(30, "File name must be at most 30 characters"), // Maximum length validation,
|
||||
.max(35, "File name must be at most 30 characters"), // Maximum length validation,
|
||||
documentNameArabic: yup.string().required("File name Arabic is required")
|
||||
.max(25, "File name must be at most 30 characters"),
|
||||
.max(25, "File name must be at most 35 characters"),
|
||||
});
|
||||
|
||||
const InvestmentDocuments = ({
|
||||
|
||||
@@ -17,6 +17,9 @@ import {
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
FormErrorMessage,
|
||||
Text,
|
||||
Textarea,
|
||||
Box,
|
||||
} from "@chakra-ui/react";
|
||||
import {
|
||||
useGetIOprepopulateDataQuery,
|
||||
@@ -37,6 +40,8 @@ const UpdateIOStatus = ({ isOpen, onClose, status }) => {
|
||||
const { data } = useGetIOprepopulateDataQuery();
|
||||
const [updateStatusIo] = useUpdateStatusIoMutation();
|
||||
const [updateCancleStatus] = useUpdateCancleStatusToMutation();
|
||||
const [message, setMessage] = useState(null);
|
||||
const [messageError, setMessageError] = useState(null);
|
||||
|
||||
// useEffect(() => {
|
||||
// setSelectedStatusId(status?.[0]?.id);
|
||||
@@ -47,11 +52,14 @@ const UpdateIOStatus = ({ isOpen, onClose, status }) => {
|
||||
setSelectedStatusId(id);
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const handleSubmit = async (data) => {
|
||||
if (!selectedStatusId) {
|
||||
setError("Please select status");
|
||||
return;
|
||||
}
|
||||
if (selectedStatusId == 6 && !message) {
|
||||
return setMessageError("message is required");
|
||||
}
|
||||
setError("");
|
||||
setIsLoading(true);
|
||||
try {
|
||||
@@ -60,7 +68,8 @@ const UpdateIOStatus = ({ isOpen, onClose, status }) => {
|
||||
// If selectedItem is 'Cancelled', make the updateCancelStatus API call
|
||||
if (selectedItem === import.meta.env.VITE_STATUS_CANCELLED) {
|
||||
res = await updateCancleStatus({
|
||||
id
|
||||
id: id,
|
||||
data: { comments: message },
|
||||
});
|
||||
}
|
||||
// Otherwise, make the updateStatusIo API call
|
||||
@@ -84,6 +93,8 @@ const UpdateIOStatus = ({ isOpen, onClose, status }) => {
|
||||
const handleClose = () => {
|
||||
setSelectedItem(null);
|
||||
setSelectedStatusId(null);
|
||||
setMessage(null);
|
||||
setMessageError(null);
|
||||
onClose();
|
||||
setError("");
|
||||
};
|
||||
@@ -121,7 +132,8 @@ const UpdateIOStatus = ({ isOpen, onClose, status }) => {
|
||||
colorScheme={
|
||||
selectedItem === import.meta.env.VITE_STATUS_DRAFT
|
||||
? "gray"
|
||||
: selectedItem === import.meta.env.VITE_STATUS_PROCESSING
|
||||
: selectedItem ===
|
||||
import.meta.env.VITE_STATUS_PROCESSING
|
||||
? "yellow"
|
||||
: selectedItem === import.meta.env.VITE_STATUS_OPEN
|
||||
? "blue"
|
||||
@@ -163,7 +175,8 @@ const UpdateIOStatus = ({ isOpen, onClose, status }) => {
|
||||
colorScheme={
|
||||
statusAdmin === import.meta.env.VITE_STATUS_DRAFT
|
||||
? "gray"
|
||||
: statusAdmin === import.meta.env.VITE_STATUS_PROCESSING
|
||||
: statusAdmin ===
|
||||
import.meta.env.VITE_STATUS_PROCESSING
|
||||
? "yellow"
|
||||
: statusAdmin === import.meta.env.VITE_STATUS_OPEN
|
||||
? "blue"
|
||||
@@ -171,7 +184,8 @@ const UpdateIOStatus = ({ isOpen, onClose, status }) => {
|
||||
? "green"
|
||||
: statusAdmin === import.meta.env.VITE_STATUS_EXITED
|
||||
? "red"
|
||||
: statusAdmin === import.meta.env.VITE_STATUS_CANCELLED
|
||||
: statusAdmin ===
|
||||
import.meta.env.VITE_STATUS_CANCELLED
|
||||
? "orange"
|
||||
: "purple"
|
||||
}
|
||||
@@ -191,6 +205,24 @@ const UpdateIOStatus = ({ isOpen, onClose, status }) => {
|
||||
{error}
|
||||
</FormErrorMessage>
|
||||
</FormControl>
|
||||
{selectedItem === import.meta.env.VITE_STATUS_CANCELLED && (
|
||||
<FormControl mt={5} isRequired>
|
||||
<FormLabel fontSize={"sm"} fontWeight={400}>
|
||||
Message
|
||||
</FormLabel>
|
||||
<Textarea
|
||||
resize={"none"}
|
||||
rounded={5}
|
||||
size="sm"
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
/>
|
||||
</FormControl>
|
||||
)}
|
||||
{messageError && (
|
||||
<Text fontSize={"sm"} color={"red"}>
|
||||
{messageError}
|
||||
</Text>
|
||||
)}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button
|
||||
|
||||
@@ -203,7 +203,7 @@ const BankDetails = () => {
|
||||
return (
|
||||
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={38}>
|
||||
<HStack>
|
||||
<Text as={'span'} fontSize={'sm'} fontWeight={700}>Bank Deatils</Text>
|
||||
<Text as={'span'} fontSize={'sm'} fontWeight={700}>Bank Details</Text>
|
||||
</HStack>
|
||||
<HStack
|
||||
display={"flex"}
|
||||
|
||||
@@ -105,14 +105,16 @@ const InvestorDetails = () => {
|
||||
"Country",
|
||||
"Phone Number",
|
||||
"E-mail ID",
|
||||
"Type",
|
||||
// "Type",
|
||||
"Wallet Balance",
|
||||
"Investor Portfolio",
|
||||
"KYC Status",
|
||||
"Status",
|
||||
// "Status",
|
||||
"Action",
|
||||
];
|
||||
|
||||
// ====================================================[Table Filter]================================================================
|
||||
const exportInvestor = investorDetails?.data?.rows?.map((item, idx) => ({
|
||||
const exportInvestor = investorDetails?.data?.rows?.map((item) => ({
|
||||
Id: parseInt(item?.id, 10) || item?.id, // Convert to integer, fallback to string if conversion fails
|
||||
"Client ID": item?.clientReference_id, // This is likely a string
|
||||
"First Name": item?.principal?.firstName,
|
||||
@@ -120,8 +122,10 @@ const InvestorDetails = () => {
|
||||
Country: item?.country?.countryName,
|
||||
"Phone Number": item?.principal?.mobileNumber, // Skipping integer conversion, as this is likely a string
|
||||
"E-mail ID": item?.principal?.emailAddress,
|
||||
Type: item?.investor_type?.investorTypeName,
|
||||
Status: item.ioStatus ? "Ban" : "Unban",
|
||||
"Wallet Balance": item?.principal?.WalletBalance_InInvCur, // Skipping integer conversion, as this is likely a string
|
||||
"Investor Portfolio": item?.principal?.Portfolio_InInvCur,
|
||||
// Type: item?.investor_type?.investorTypeName,
|
||||
// Status: item.ioStatus ? "Ban" : "Unban",
|
||||
"KYC Status": item.KYCStatus ? "Completed" : "Not complete",
|
||||
}));
|
||||
|
||||
@@ -181,32 +185,72 @@ const InvestorDetails = () => {
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
Type: (
|
||||
<Box w={"auto"} isTruncated={true}>
|
||||
<Text as={"span"}>
|
||||
<Badge
|
||||
color={"forestGreen.500"}
|
||||
variant={"ghost"}
|
||||
fontWeight={"700"}
|
||||
px={2}
|
||||
py={0.5}
|
||||
// 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>
|
||||
// ),
|
||||
// Status: (
|
||||
// <Box w={"auto"} isTruncated={true}>
|
||||
// <Badge
|
||||
// fontWeight={"700"}
|
||||
// textTransform={"none"}
|
||||
// colorScheme={item.ioStatus ? "red" : "green"}
|
||||
// px={2}
|
||||
// py={0.5}
|
||||
// >
|
||||
// {item.ioStatus ? "Ban" : "Unban"}
|
||||
// </Badge>
|
||||
// </Box>
|
||||
// ),
|
||||
"Wallet Balance": (
|
||||
<Box
|
||||
display={"flex"}
|
||||
justifyContent={"end"}
|
||||
w={"130px"}
|
||||
isTruncated={true}
|
||||
>
|
||||
{item?.investor_type?.investorTypeName}
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{/* {formatCurrency(removeTrailingZeros(item?.investorAmount))} */}
|
||||
{parseFloat(item?.WalletBalance_InInvCur || 0).toLocaleString(
|
||||
undefined,
|
||||
{
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
}
|
||||
)}
|
||||
<Badge ms={1} colorScheme="green">
|
||||
{item?.currencyCode}
|
||||
</Badge>
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
Status: (
|
||||
<Box w={"auto"} isTruncated={true}>
|
||||
<Badge
|
||||
fontWeight={"700"}
|
||||
textTransform={"none"}
|
||||
colorScheme={item.ioStatus ? "red" : "green"}
|
||||
px={2}
|
||||
py={0.5}
|
||||
"Investor Portfolio": (
|
||||
<Box
|
||||
display={"flex"}
|
||||
justifyContent={"end"}
|
||||
w={"130px"}
|
||||
isTruncated={true}
|
||||
>
|
||||
{item.ioStatus ? "Ban" : "Unban"}
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{parseFloat(item?.Portfolio_InInvCur || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
<Badge ms={1} colorScheme="green">
|
||||
{item?.currencyCode}
|
||||
</Badge>
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"KYC Status": (
|
||||
@@ -321,7 +365,7 @@ const InvestorDetails = () => {
|
||||
KYC Status
|
||||
</option>
|
||||
<option value="">KYC Status</option>
|
||||
<option value="0">Incompleted</option>
|
||||
<option value="0">Not Completed</option>
|
||||
<option value="1">Completed</option>
|
||||
</Select>
|
||||
|
||||
@@ -337,7 +381,7 @@ const InvestorDetails = () => {
|
||||
Country
|
||||
</option>
|
||||
<option value="">All</option>
|
||||
<option value="1">Behrain</option>
|
||||
<option value="1">Bahrain</option>
|
||||
<option value="2">Kuwait</option>
|
||||
<option value="3">Oman</option>
|
||||
<option value="4">Qatar</option>
|
||||
|
||||
@@ -150,6 +150,22 @@ const Kyc = () => {
|
||||
/>
|
||||
</FormControl>
|
||||
</HStack>
|
||||
<HStack spacing={4} mb={4}>
|
||||
<FormControl>
|
||||
<FormLabel mb={1} fontSize={"sm"}>
|
||||
PEP Status
|
||||
</FormLabel>
|
||||
<Input
|
||||
bg={"#ccc3"}
|
||||
border={"none"}
|
||||
size={"sm"}
|
||||
value={data?.data?.KYC?.PEPStatus ? "Yes" : "No"}
|
||||
type="text"
|
||||
readOnly
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl></FormControl>
|
||||
</HStack>
|
||||
{/* <HStack spacing={4}>
|
||||
<FormControl>
|
||||
<FormLabel mb={1} fontSize={"sm"}>Address</FormLabel>
|
||||
|
||||
@@ -78,7 +78,7 @@ const Login = () => {
|
||||
setIsLoading(false);
|
||||
setIsAuthenticate(true);
|
||||
Cookies.set("isAuthenticated", true, { expires: 7 });
|
||||
navigate("/sponser");
|
||||
navigate("/");
|
||||
reset();
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,37 @@ import {
|
||||
} from "../../../Services/exchange.rate.service";
|
||||
import ToastBox from "../../../Components/ToastBox";
|
||||
import { getTomorrowDate } from "../../../Constants/Constants";
|
||||
import * as yup from "yup";
|
||||
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
|
||||
|
||||
// const editExchange = yup.object().shape({
|
||||
// rate: yup
|
||||
// .number()
|
||||
// .required("Rate is required")
|
||||
// .positive("Rate must be greater than 0")
|
||||
// .test(
|
||||
// "is-decimal",
|
||||
// "Rate must have at most 8 decimal places",
|
||||
// (value) =>
|
||||
// value !== undefined && value.toString().match(/^\d+(\.\d{1,8})?$/)
|
||||
// ),
|
||||
// });
|
||||
|
||||
const editExchange = yup.object().shape({
|
||||
rate: yup
|
||||
.string()
|
||||
.required("Rate is required")
|
||||
.matches(
|
||||
/^\d+\.\d{8}$/,
|
||||
"Rate must have exactly 8 decimal places"
|
||||
)
|
||||
.test(
|
||||
"is-positive",
|
||||
"Rate must be greater than 0",
|
||||
(value) => parseFloat(value) > 0
|
||||
),
|
||||
});
|
||||
|
||||
// Convert date to YYYY-MM-DD format
|
||||
const formatDateValue = (date) => {
|
||||
if (!date) return "";
|
||||
@@ -57,8 +86,9 @@ const EditExchangeRate = ({
|
||||
const toast = useToast();
|
||||
const {} = useDisclosure();
|
||||
const [isBtnLoading, setIsBtnLoading] = useState(false);
|
||||
const [rateError, setRateError] = useState("");
|
||||
|
||||
const { data, isLoading, errors } = useGetExchangeRateByIdQuery(id, {
|
||||
const { data, isLoading, errors,refetch, isFetching } = useGetExchangeRateByIdQuery(id, {
|
||||
skip: !id,
|
||||
});
|
||||
|
||||
@@ -67,17 +97,45 @@ const EditExchangeRate = ({
|
||||
const [rate, setRate] = useState("");
|
||||
const [alert, setAlert] = useState(false);
|
||||
|
||||
console.log(rate);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (id) {refetch()}
|
||||
if (foundObject) {
|
||||
setRate(foundObject.rate);
|
||||
const numericRate = parseFloat(foundObject.rate) || 0; // Convert to number or default to 0 if invalid
|
||||
setRate(numericRate.toFixed(8)); // Set rate with exactly 8 decimal places
|
||||
}
|
||||
}, [foundObject]);
|
||||
}, [foundObject, isOpen]);
|
||||
|
||||
|
||||
// useEffect(()=>{
|
||||
// if (id) {
|
||||
// refetch()
|
||||
// }
|
||||
// },[isOpen])
|
||||
|
||||
const validateRate = async () => {
|
||||
try {
|
||||
await editExchange.validate({ rate });
|
||||
setRateError(""); // Clear validation error if valid
|
||||
return true;
|
||||
} catch (error) {
|
||||
setRateError(error.message); // Display validation error
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
const isValid = await validateRate();
|
||||
if (!isValid) {
|
||||
return; // Prevent submission if validation fails
|
||||
}
|
||||
|
||||
setIsBtnLoading(true);
|
||||
try {
|
||||
const data = {
|
||||
rate: rate,
|
||||
rate,
|
||||
};
|
||||
const res = await updateExchange({ data, id });
|
||||
if (res?.data?.statusCode === 200) {
|
||||
@@ -88,9 +146,31 @@ const EditExchangeRate = ({
|
||||
setAlert(false);
|
||||
onClose();
|
||||
}
|
||||
} catch (error) {}
|
||||
} catch (error) {
|
||||
setIsBtnLoading(false);
|
||||
// Handle error
|
||||
}
|
||||
};
|
||||
|
||||
const checkValidate = async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
// Wait for the validation to complete
|
||||
const isValid = await validateRate();
|
||||
|
||||
if (!isValid) {
|
||||
return; // Prevent submission if validation fails
|
||||
} else {
|
||||
setAlert(true); // Only trigger modal if validation passes
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (rate) {
|
||||
validateRate();
|
||||
}
|
||||
}, [rate]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Drawer
|
||||
@@ -100,18 +180,13 @@ const EditExchangeRate = ({
|
||||
onClose={onClose}
|
||||
finalFocusRef={btnRef}
|
||||
>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
setAlert(true);
|
||||
}}
|
||||
>
|
||||
<form onSubmit={(e) => checkValidate(e)}>
|
||||
<DrawerOverlay />
|
||||
<DrawerContent>
|
||||
<DrawerCloseButton />
|
||||
<DrawerHeader fontSize={"md"}>Edit rate</DrawerHeader>
|
||||
|
||||
{isLoading ? (
|
||||
{isFetching ? (
|
||||
<FullscreenLoaders />
|
||||
) : (
|
||||
<>
|
||||
@@ -153,16 +228,26 @@ const EditExchangeRate = ({
|
||||
<Text fontSize={"sm"}>{formatDate(getTomorrowDate())}</Text>
|
||||
</FormControl>
|
||||
|
||||
<FormControl mb={4} isRequired>
|
||||
<FormControl mb={4} isRequired isInvalid={!!rateError}>
|
||||
<FormLabel fontSize={"sm"}>Rate</FormLabel>
|
||||
<Input
|
||||
required
|
||||
type="number"
|
||||
placeholder="Type rate here..."
|
||||
size={"sm"}
|
||||
value={rate}
|
||||
onChange={(e) => setRate(e.target.value)}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
// Match numbers with at most 8 decimal places
|
||||
if (/^\d*\.?\d{0,8}$/.test(value)) {
|
||||
setRate(value);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{rateError && (
|
||||
<Text color="red.500" fontSize="sm" mt={1}>
|
||||
{rateError}
|
||||
</Text>
|
||||
)}
|
||||
</FormControl>
|
||||
</DrawerBody>
|
||||
<DrawerFooter>
|
||||
@@ -173,6 +258,15 @@ const EditExchangeRate = ({
|
||||
size={"sm"}
|
||||
mr={3}
|
||||
onClick={onClose}
|
||||
// onClick={() => {
|
||||
// window.location.reload();
|
||||
// onClose();
|
||||
// }}
|
||||
// onClick={() => {
|
||||
// setRate("");
|
||||
// setRateError("");
|
||||
// onClose();
|
||||
// }}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
|
||||
@@ -254,7 +254,7 @@ const AddSponser = () => {
|
||||
} characters.`,
|
||||
},
|
||||
{
|
||||
label: "Email adress",
|
||||
label: "Email address",
|
||||
name: "email",
|
||||
placeHolder: " ",
|
||||
type: "email",
|
||||
|
||||
149
src/Pages/ReversalAccountDeletion/ConfirmModal.jsx
Normal file
@@ -0,0 +1,149 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Checkbox,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Input,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Text,
|
||||
Textarea,
|
||||
useDisclosure,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useState } from "react";
|
||||
import * as yup from "yup";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import { useForm } from "react-hook-form";
|
||||
import ReactQuill from "react-quill";
|
||||
|
||||
export const conformModalSchema = yup.object().shape({
|
||||
fees: yup.string().required("File name is required"),
|
||||
totalAmount: yup.string().required("File name is required"),
|
||||
});
|
||||
|
||||
const ConfirmModal = ({ isOpen, onClose, firstField }) => {
|
||||
|
||||
const [emailApproval,setEmailApproval] = useState(false)
|
||||
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: yupResolver(conformModalSchema),
|
||||
});
|
||||
|
||||
const onSubmit = (data) => {
|
||||
setFile(data.document[0]);
|
||||
|
||||
const newDocument = {
|
||||
...data,
|
||||
document: data.document[0].name, // Store the document name
|
||||
status: true,
|
||||
id: uuidv4(),
|
||||
createdAt: new Date().toISOString(),
|
||||
Type: getFileIcon(file.type),
|
||||
};
|
||||
|
||||
setCreate((prevCreate) => [...prevCreate, newDocument]);
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleFileChange = (event) => {
|
||||
const selectedFile = event.target.files[0];
|
||||
setFile(selectedFile);
|
||||
};
|
||||
|
||||
const modules = {
|
||||
toolbar: [
|
||||
// [{ header: "1" }, { header: "2" },
|
||||
// // { font: [] }
|
||||
// ],
|
||||
// [{ size: [] }],
|
||||
["bold", "italic", "underline", "strike", "blockquote"],
|
||||
[{ list: "ordered" }, { list: "bullet" }],
|
||||
["clean"],
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose} initialFocusRef={firstField}>
|
||||
<ModalOverlay />
|
||||
<ModalContent pb={4}>
|
||||
<ModalHeader fontSize={"md"}>Confirm</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
||||
<ModalBody>
|
||||
<FormControl mb={4} isRequired>
|
||||
<FormLabel fontSize="sm">Comment</FormLabel>
|
||||
<Textarea rows={5}
|
||||
focusBorderColor='green.400'
|
||||
name="fileName"
|
||||
{...register("fileName")}
|
||||
fontSize="sm"
|
||||
type="textarea"
|
||||
size="md"
|
||||
placeholder={"Enter your comments...."}
|
||||
rounded={'md'}
|
||||
resize={'none'}
|
||||
/>
|
||||
{errors.comment && (
|
||||
<Text fontSize="xs" color="red">
|
||||
{errors.comment.message}
|
||||
</Text>
|
||||
)}
|
||||
</FormControl>
|
||||
|
||||
<Checkbox colorScheme='forestGreen'
|
||||
onChange={(e) =>setEmailApproval(e.target.checked)}
|
||||
>
|
||||
<Text mb={0} fontSize={'sm'}>Send an email to the user upon approval</Text>
|
||||
</Checkbox>
|
||||
{emailApproval && <Box className="messageBox">
|
||||
<FormControl mb={4}>
|
||||
<FormLabel fontSize="sm" mb={1}>Subject</FormLabel>
|
||||
<Input
|
||||
focusBorderColor='green.400'
|
||||
name="fileName"
|
||||
{...register("fileName")}
|
||||
fontSize="sm"
|
||||
type="text"
|
||||
size="sm"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl mb={12}>
|
||||
<FormLabel fontSize="sm" mb={1}>Message</FormLabel>
|
||||
<ReactQuill
|
||||
theme="snow"
|
||||
style={{
|
||||
height: 150,
|
||||
}}
|
||||
// value={value}
|
||||
// onChange={setValue}
|
||||
modules={modules}
|
||||
placeholder="Start typing here..."
|
||||
/>
|
||||
</FormControl>
|
||||
</Box>}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button colorScheme="gray" mr={3} onClick={onClose} size={'sm'} rounded={'sm'}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button colorScheme="forestGreen" variant="solid" size={'sm'} rounded={'sm'}>
|
||||
Confirm
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Box>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConfirmModal;
|
||||
98
src/Pages/ReversalAccountDeletion/RejectModal.jsx
Normal file
@@ -0,0 +1,98 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Input,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Text,
|
||||
Textarea,
|
||||
useDisclosure,
|
||||
} from "@chakra-ui/react";
|
||||
import React from "react";
|
||||
import * as yup from "yup";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
export const conformModalSchema = yup.object().shape({
|
||||
comment: yup.string().required("Comment is required"),
|
||||
});
|
||||
|
||||
const RejectModal = ({ isOpen, onClose, firstField }) => {
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: yupResolver(conformModalSchema),
|
||||
});
|
||||
|
||||
const onSubmit = (data) => {
|
||||
setFile(data.document[0]);
|
||||
|
||||
const newDocument = {
|
||||
...data,
|
||||
document: data.document[0].name, // Store the document name
|
||||
comment: true,
|
||||
id: uuidv4(),
|
||||
Type: getFileIcon(file.type),
|
||||
};
|
||||
|
||||
setCreate((prevCreate) => [...prevCreate, newDocument]);
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleFileChange = (event) => {
|
||||
const selectedFile = event.target.files[0];
|
||||
setFile(selectedFile);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose} initialFocusRef={firstField}>
|
||||
<ModalOverlay />
|
||||
<ModalContent pb={4}>
|
||||
<ModalHeader fontSize={"md"}>Reject</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="fileName"
|
||||
{...register("fileName")}
|
||||
fontSize="sm"
|
||||
type="textarea"
|
||||
size="md"
|
||||
placeholder={"Enter your comments...."}
|
||||
rounded={'md'}
|
||||
resize={'none'}
|
||||
/>
|
||||
{errors.comment && (
|
||||
<Text fontSize="xs" color="red">
|
||||
{errors.comment.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'}>
|
||||
Send
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Box>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default RejectModal;
|
||||
404
src/Pages/ReversalAccountDeletion/ReversalAccountDeletion.jsx
Normal file
@@ -0,0 +1,404 @@
|
||||
import { CheckIcon, CloseIcon } from "@chakra-ui/icons";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
HStack,
|
||||
Input,
|
||||
Text,
|
||||
Tooltip,
|
||||
useBoolean,
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
||||
import NormalTable from "../../Components/DataTable/NormalTable";
|
||||
import { TABLE_PAGINATION } from "../../Constants/Paginations";
|
||||
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
||||
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||
import {
|
||||
useApproveAccountDeletionRequestMutation,
|
||||
useGetAccountDeletionMasterQuery,
|
||||
useRejectAccountDeletionRequestMutation,
|
||||
} from "../../Services/reversal.account.deletion.service";
|
||||
import ConfirmModal from "./ConfirmModal";
|
||||
import RejectModal from "./RejectModal";
|
||||
import RejectReversalPopups from "../../Components/Popups/RejectReversalPopups";
|
||||
import ToastBox from "../../Components/ToastBox";
|
||||
import ConfirmReversalPopups from "../../Components/Popups/ConfirmReversalPopups";
|
||||
// import { formatDate } from "../../Components/Functions/UTCConvertor";
|
||||
|
||||
const ReversalAccountDeletion = () => {
|
||||
const toast = useToast();
|
||||
const { slideFromRight, setDeleteHistory } = useContext(GlobalStateContext);
|
||||
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||
const [actionId, setActionId] = useState(false);
|
||||
const [mouseEntered, setMouseEntered] = useState(false);
|
||||
const [mouseEnteredId, setMouseEnteredId] = useState("");
|
||||
|
||||
// =========================== [Use State] =============================
|
||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||
|
||||
const [isReversalLoading, setIsReversalLoading] = useBoolean();
|
||||
|
||||
const {
|
||||
isOpen: isConfirmOpen,
|
||||
onOpen: onConfirmOpen,
|
||||
onClose: onConfirmClose,
|
||||
} = useDisclosure();
|
||||
const {
|
||||
isOpen: isRejectOpen,
|
||||
onOpen: onRejectOpen,
|
||||
onClose: onRejectClose,
|
||||
} = useDisclosure();
|
||||
|
||||
const [rejectAccountDeletionRequest] = useRejectAccountDeletionRequestMutation();
|
||||
|
||||
const [approveAccountDeletionRequest] = useApproveAccountDeletionRequestMutation();
|
||||
|
||||
// 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: deleteHistory,
|
||||
isLoading,
|
||||
refetch,
|
||||
} = useGetAccountDeletionMasterQuery(
|
||||
{
|
||||
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 formatDate = (date) => {
|
||||
return new Date(date).toLocaleDateString("en-GB", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
});
|
||||
};
|
||||
|
||||
// Use useEffect to refetch data when the component mounts
|
||||
useEffect(() => {
|
||||
refetch();
|
||||
}, [refetch]);
|
||||
|
||||
// ====================================================[Table Setup]================================================================
|
||||
const tableHeadRow = [
|
||||
"Sr No.",
|
||||
"Request Date",
|
||||
"Client ID",
|
||||
"First Name",
|
||||
"Last Name",
|
||||
"Phone Number",
|
||||
"Country",
|
||||
"Action",
|
||||
];
|
||||
|
||||
const extractedArray = deleteHistory?.data?.rows?.map((item, index) => ({
|
||||
id: item?.id,
|
||||
"Sr No.": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"gray.800"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
fontWeight={"500"}
|
||||
>
|
||||
{index + 1}.
|
||||
</Text>
|
||||
),
|
||||
"Request Date": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"gray.600"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
fontWeight={"500"}
|
||||
>
|
||||
{formatDate(item.isReversalDate)}
|
||||
</Text>
|
||||
),
|
||||
"Client ID": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"gray.600"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
fontWeight={"500"}
|
||||
>
|
||||
{item?.iamPrincipal?.investor_details?.clientReference_id}
|
||||
</Text>
|
||||
),
|
||||
"First Name": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"gray.800"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
fontWeight={"500"}
|
||||
>
|
||||
{item?.iamPrincipal?.firstName}
|
||||
{/* {formatDate(item.charge)} */}
|
||||
</Text>
|
||||
),
|
||||
"Last Name": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"gray.800"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
fontWeight={"500"}
|
||||
>
|
||||
{item?.iamPrincipal?.lastName}
|
||||
</Text>
|
||||
),
|
||||
"Phone Number": (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"gray.600"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
fontWeight={"500"}
|
||||
>
|
||||
{item?.iamPrincipal?.ISDcode + " " + item?.iamPrincipal?.mobileNumber}
|
||||
</Text>
|
||||
),
|
||||
Country: (
|
||||
<Text
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"gray.600"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
fontWeight={"500"}
|
||||
>
|
||||
{item?.iamPrincipal?.investor_details?.country?.countryName}
|
||||
</Text>
|
||||
),
|
||||
Action: (
|
||||
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||
<Tooltip
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
label="Approve"
|
||||
bg="#fff"
|
||||
color={"green.500"}
|
||||
placement="left-start"
|
||||
>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={2}
|
||||
py={1}
|
||||
onClick={() => {
|
||||
setActionId(item.id);
|
||||
onConfirmOpen();
|
||||
}}
|
||||
colorScheme="green"
|
||||
variant={"solid"}
|
||||
cursor={"pointer"}
|
||||
>
|
||||
<CheckIcon fontSize={"12px"} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
label="Reject"
|
||||
bg="#fff"
|
||||
color={"red.500"}
|
||||
placement="left-start"
|
||||
>
|
||||
<Button
|
||||
colorScheme="red"
|
||||
// color="red.500"
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={2}
|
||||
onClick={() => {
|
||||
setActionId(item.id);
|
||||
onRejectOpen();
|
||||
}}
|
||||
py={1}
|
||||
// variant={"solid"}
|
||||
>
|
||||
<CloseIcon fontSize={"10px"} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
),
|
||||
}));
|
||||
|
||||
const handleDelete = () => {
|
||||
const deleteHistory = sponser.filter((sponsor) => sponsor.id !== actionId);
|
||||
|
||||
setTimeout(() => {
|
||||
setSponser(deleteHistory);
|
||||
setDeleteAlert(false);
|
||||
setIsLoading(false);
|
||||
}, 100);
|
||||
setIsLoading(true);
|
||||
};
|
||||
|
||||
const handleApproved = async (data) => {
|
||||
setIsReversalLoading.on(); // Start loading
|
||||
try {
|
||||
const { error, data: responseData } = await rejectAccountDeletionRequest({
|
||||
id: actionId,
|
||||
data,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
throw error; // Explicitly handle the error
|
||||
}
|
||||
|
||||
// Success: Perform necessary actions
|
||||
refetch();
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={responseData?.message || "Action successful!"} />
|
||||
),
|
||||
});
|
||||
onRejectClose();
|
||||
} catch (error) {
|
||||
// Handle errors
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox
|
||||
message={
|
||||
error?.data?.message || "Something went wrong. Please try again."
|
||||
}
|
||||
status="error"
|
||||
/>
|
||||
),
|
||||
});
|
||||
console.error("Error:", error);
|
||||
} finally {
|
||||
setIsReversalLoading.off(); // Ensure loading is toggled off
|
||||
}
|
||||
};
|
||||
|
||||
const handleConfirm = async (data) => {
|
||||
|
||||
setIsReversalLoading.on(); // Start loading
|
||||
try {
|
||||
const { error, data: responseData } = await approveAccountDeletionRequest({
|
||||
id: actionId,
|
||||
data,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
throw error; // Explicitly handle the error
|
||||
}
|
||||
|
||||
// Success: Perform necessary actions
|
||||
refetch();
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={responseData?.message || "Action successful!"} />
|
||||
),
|
||||
});
|
||||
onRejectClose();
|
||||
} catch (error) {
|
||||
// Handle errors
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox
|
||||
message={
|
||||
error?.data?.message || "Something went wrong. Please try again."
|
||||
}
|
||||
status="error"
|
||||
/>
|
||||
),
|
||||
});
|
||||
console.error("Error:", error);
|
||||
} finally {
|
||||
setIsReversalLoading.off(); // Ensure loading is toggled off
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
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 totalItems={10} />
|
||||
</HStack> */}
|
||||
</HStack>
|
||||
</Box>
|
||||
|
||||
<NormalTable
|
||||
emptyMessage={`We don't have any Sponers `}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={extractedArray}
|
||||
isLoading={isLoading}
|
||||
viewActionId={actionId}
|
||||
setViewActionId={setActionId}
|
||||
// totalPages={10}
|
||||
|
||||
setMouseEnteredId={setMouseEnteredId}
|
||||
setMouseEntered={setMouseEntered}
|
||||
/>
|
||||
|
||||
<CustomAlertDialog
|
||||
onClose={() => setDeleteAlert(false)}
|
||||
isOpen={deleteAlert}
|
||||
message={"Are you sure you want to delete sponers?"}
|
||||
alertHandler={handleDelete}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
<ConfirmReversalPopups
|
||||
isOpen={isConfirmOpen}
|
||||
onClose={onConfirmClose}
|
||||
handleConfirm={handleConfirm}
|
||||
isLoading={isReversalLoading}
|
||||
/>
|
||||
<RejectReversalPopups
|
||||
isOpen={isRejectOpen}
|
||||
onClose={onRejectClose}
|
||||
handelApproved={handleApproved}
|
||||
isLoading={isReversalLoading}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default ReversalAccountDeletion;
|
||||
149
src/Pages/ReversalFawateerDeposit/ConfirmModal.jsx
Normal file
@@ -0,0 +1,149 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Checkbox,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Input,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Text,
|
||||
Textarea,
|
||||
useDisclosure,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useState } from "react";
|
||||
import * as yup from "yup";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import { useForm } from "react-hook-form";
|
||||
import ReactQuill from "react-quill";
|
||||
|
||||
export const conformModalSchema = yup.object().shape({
|
||||
fees: yup.string().required("File name is required"),
|
||||
totalAmount: yup.string().required("File name is required"),
|
||||
});
|
||||
|
||||
const ConfirmModal = ({ isOpen, onClose, firstField }) => {
|
||||
|
||||
const [emailApproval,setEmailApproval] = useState(false)
|
||||
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: yupResolver(conformModalSchema),
|
||||
});
|
||||
|
||||
const onSubmit = (data) => {
|
||||
setFile(data.document[0]);
|
||||
|
||||
const newDocument = {
|
||||
...data,
|
||||
document: data.document[0].name, // Store the document name
|
||||
status: true,
|
||||
id: uuidv4(),
|
||||
createdAt: new Date().toISOString(),
|
||||
Type: getFileIcon(file.type),
|
||||
};
|
||||
|
||||
setCreate((prevCreate) => [...prevCreate, newDocument]);
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleFileChange = (event) => {
|
||||
const selectedFile = event.target.files[0];
|
||||
setFile(selectedFile);
|
||||
};
|
||||
|
||||
const modules = {
|
||||
toolbar: [
|
||||
// [{ header: "1" }, { header: "2" },
|
||||
// // { font: [] }
|
||||
// ],
|
||||
// [{ size: [] }],
|
||||
["bold", "italic", "underline", "strike", "blockquote"],
|
||||
[{ list: "ordered" }, { list: "bullet" }],
|
||||
["clean"],
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose} initialFocusRef={firstField}>
|
||||
<ModalOverlay />
|
||||
<ModalContent pb={4}>
|
||||
<ModalHeader fontSize={"md"}>Confirm</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
|
||||
<ModalBody>
|
||||
<FormControl mb={4} isRequired>
|
||||
<FormLabel fontSize="sm">Comment</FormLabel>
|
||||
<Textarea rows={5}
|
||||
focusBorderColor='green.400'
|
||||
name="fileName"
|
||||
{...register("fileName")}
|
||||
fontSize="sm"
|
||||
type="textarea"
|
||||
size="md"
|
||||
placeholder={"Enter your comments...."}
|
||||
rounded={'md'}
|
||||
resize={'none'}
|
||||
/>
|
||||
{errors.comment && (
|
||||
<Text fontSize="xs" color="red">
|
||||
{errors.comment.message}
|
||||
</Text>
|
||||
)}
|
||||
</FormControl>
|
||||
|
||||
<Checkbox colorScheme='forestGreen'
|
||||
onChange={(e) =>setEmailApproval(e.target.checked)}
|
||||
>
|
||||
<Text mb={0} fontSize={'sm'}>Send an email to the user upon approval</Text>
|
||||
</Checkbox>
|
||||
{emailApproval && <Box className="messageBox">
|
||||
<FormControl mb={4}>
|
||||
<FormLabel fontSize="sm" mb={1}>Subject</FormLabel>
|
||||
<Input
|
||||
focusBorderColor='green.400'
|
||||
name="fileName"
|
||||
{...register("fileName")}
|
||||
fontSize="sm"
|
||||
type="text"
|
||||
size="sm"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl mb={12}>
|
||||
<FormLabel fontSize="sm" mb={1}>Message</FormLabel>
|
||||
<ReactQuill
|
||||
theme="snow"
|
||||
style={{
|
||||
height: 150,
|
||||
}}
|
||||
// value={value}
|
||||
// onChange={setValue}
|
||||
modules={modules}
|
||||
placeholder="Start typing here..."
|
||||
/>
|
||||
</FormControl>
|
||||
</Box>}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button colorScheme="gray" mr={3} onClick={onClose} size={'sm'} rounded={'sm'}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button colorScheme="forestGreen" variant="solid" size={'sm'} rounded={'sm'}>
|
||||
Confirm
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Box>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConfirmModal;
|
||||
98
src/Pages/ReversalFawateerDeposit/RejectModal.jsx
Normal file
@@ -0,0 +1,98 @@
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Input,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Text,
|
||||
Textarea,
|
||||
useDisclosure,
|
||||
} from "@chakra-ui/react";
|
||||
import React from "react";
|
||||
import * as yup from "yup";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
export const conformModalSchema = yup.object().shape({
|
||||
comment: yup.string().required("Comment is required"),
|
||||
});
|
||||
|
||||
const RejectModal = ({ isOpen, onClose, firstField }) => {
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
} = useForm({
|
||||
resolver: yupResolver(conformModalSchema),
|
||||
});
|
||||
|
||||
const onSubmit = (data) => {
|
||||
setFile(data.document[0]);
|
||||
|
||||
const newDocument = {
|
||||
...data,
|
||||
document: data.document[0].name, // Store the document name
|
||||
comment: true,
|
||||
id: uuidv4(),
|
||||
Type: getFileIcon(file.type),
|
||||
};
|
||||
|
||||
setCreate((prevCreate) => [...prevCreate, newDocument]);
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleFileChange = (event) => {
|
||||
const selectedFile = event.target.files[0];
|
||||
setFile(selectedFile);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onClose={onClose} initialFocusRef={firstField}>
|
||||
<ModalOverlay />
|
||||
<ModalContent pb={4}>
|
||||
<ModalHeader fontSize={"md"}>Reject</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="fileName"
|
||||
{...register("fileName")}
|
||||
fontSize="sm"
|
||||
type="textarea"
|
||||
size="md"
|
||||
placeholder={"Enter your comments...."}
|
||||
rounded={'md'}
|
||||
resize={'none'}
|
||||
/>
|
||||
{errors.comment && (
|
||||
<Text fontSize="xs" color="red">
|
||||
{errors.comment.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'}>
|
||||
Send
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Box>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default RejectModal;
|
||||
427
src/Pages/ReversalFawateerDeposit/ReversalFawateerDeposit.jsx
Normal file
@@ -0,0 +1,427 @@
|
||||
import {
|
||||
Avatar,
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
HStack,
|
||||
Input,
|
||||
Link,
|
||||
Text,
|
||||
Tooltip,
|
||||
useBoolean,
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { CheckIcon, CloseIcon, ExternalLinkIcon } from "@chakra-ui/icons";
|
||||
import Pagination from "../../Components/Pagination";
|
||||
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
||||
import CustomAlertDialog from "../../Components/CustomAlertDialog";
|
||||
import NormalTable from "../../Components/DataTable/NormalTable";
|
||||
import { generateSerialNumber } from "../../Constants/Constants";
|
||||
import { TABLE_PAGINATION } from "../../Constants/Paginations";
|
||||
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||
import { useGetFawateerForMakerRequestQuery } from "../../Services/fawateer.request.service";
|
||||
import ConfirmModal from "./ConfirmModal";
|
||||
import RejectModal from "./RejectModal";
|
||||
import {
|
||||
useApproveFawateerRequestMutation,
|
||||
useGetFawateerDepositMasterQuery,
|
||||
useRejectFawateerRequestMutation,
|
||||
} from "../../Services/reversal.fawateer.deposit.service";
|
||||
import RejectReversalPopups from "../../Components/Popups/RejectReversalPopups";
|
||||
import ToastBox from "../../Components/ToastBox";
|
||||
import ConfirmReversalPopups from "../../Components/Popups/ConfirmReversalPopups";
|
||||
|
||||
const ReversalFawateerDeposit = () => {
|
||||
const toast = useToast();
|
||||
const { slideFromRight, approveHistory, setApproveHistory } =
|
||||
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 [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||
const [isReversalLoading, setIsReversalLoading] = useBoolean();
|
||||
|
||||
const [rejectFawateerRequest] = useRejectFawateerRequestMutation();
|
||||
|
||||
const [approveFawateerRequest] = useApproveFawateerRequestMutation();
|
||||
|
||||
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
|
||||
const [currentPage, setCurrentPage] = useState(TABLE_PAGINATION?.page);
|
||||
|
||||
const formatDate = (date) => {
|
||||
return new Date(date).toLocaleDateString("en-GB", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
});
|
||||
};
|
||||
|
||||
const {
|
||||
isOpen: isConfirmOpen,
|
||||
onOpen: onConfirmOpen,
|
||||
onClose: onConfirmClose,
|
||||
} = useDisclosure();
|
||||
const {
|
||||
isOpen: isRejectOpen,
|
||||
onOpen: onRejectOpen,
|
||||
onClose: onRejectClose,
|
||||
} = useDisclosure();
|
||||
|
||||
const {
|
||||
data,
|
||||
isLoading: drawalRequestLoading,
|
||||
error,
|
||||
refetch,
|
||||
} = useGetFawateerDepositMasterQuery(
|
||||
{
|
||||
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(() => {
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedSearchTerm(searchTerm);
|
||||
}, 500); // Adjust delay as needed
|
||||
return () => {
|
||||
clearTimeout(handler);
|
||||
};
|
||||
}, [searchTerm]);
|
||||
|
||||
// Use useEffect to refetch data when the component mounts
|
||||
useEffect(() => {
|
||||
refetch();
|
||||
}, [refetch]);
|
||||
|
||||
useEffect(() => {
|
||||
// Simulate loading
|
||||
const timer = setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
}, 1500);
|
||||
|
||||
// Cleanup the timer on component unmount
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
// ====================================================[Table Filter]================================================================
|
||||
const filteredData = data?.data?.rows?.filter((item) => {
|
||||
// Filter by name (case insensitive)
|
||||
const name = item.principal?.firstName;
|
||||
const searchLower = searchTerm.toLowerCase();
|
||||
const nameMatches = name.toLowerCase().includes(searchLower);
|
||||
|
||||
return nameMatches;
|
||||
});
|
||||
|
||||
// ====================================================[Table Setup]================================================================
|
||||
const tableHeadRow = [
|
||||
"Sr.no",
|
||||
"Request Date",
|
||||
"Client ID",
|
||||
"First Name",
|
||||
"Last Name",
|
||||
"Phone Number",
|
||||
"Deposit Amount (BHD)",
|
||||
"Action",
|
||||
];
|
||||
|
||||
const extractedArray = data?.data?.rows?.map((item, idx) => ({
|
||||
// id: item?.id,
|
||||
"Sr.no": (
|
||||
<Text
|
||||
w={"auto"}
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{generateSerialNumber(idx, currentPage, pageSize)}
|
||||
</Text>
|
||||
),
|
||||
"Request Date": (
|
||||
<Text
|
||||
w={"60px"}
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{formatDate(item?.transaction_details?.isReversalDate)}
|
||||
</Text>
|
||||
),
|
||||
"Client ID": (
|
||||
<Text
|
||||
w={"60px"}
|
||||
justifyContent={slideFromRight ? "right" : "left"}
|
||||
as={"span"}
|
||||
color={"teal.900"}
|
||||
fontWeight={"500"}
|
||||
className="d-flex align-items-center web-text-small"
|
||||
>
|
||||
{item?.principal?.investor_details?.clientReference_id}
|
||||
</Text>
|
||||
),
|
||||
"First Name": (
|
||||
<Box isTruncated={true} w={"80px"}>
|
||||
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
|
||||
{item?.principal?.firstName}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Last Name": (
|
||||
<Box isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{item?.principal?.lastName}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Phone Number": (
|
||||
<Box w={"100px"} isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"}>
|
||||
{/* {item?.principal?.ISDcode} {item?.principal?.mobileNumber} */}
|
||||
{item?.principal?.ISDcode + " " + item?.principal?.mobileNumber}
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
"Deposit Amount (BHD)": (
|
||||
<Box isTruncated={true}>
|
||||
<Text as={"span"} color={"teal.900"} textAlign={"right"}>
|
||||
{parseFloat(item?.transaction_details?.investorAmount || 0).toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
<Badge ms={1} colorScheme="green">
|
||||
{item?.currencyCode}
|
||||
</Badge>
|
||||
</Text>
|
||||
</Box>
|
||||
),
|
||||
Action: (
|
||||
<Box display={"flex"} justifyContent={"center"} gap={2}>
|
||||
<Tooltip
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
label="Approve"
|
||||
bg="#fff"
|
||||
color={"green.500"}
|
||||
placement="left-start"
|
||||
>
|
||||
<Button
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={2}
|
||||
py={1}
|
||||
onClick={() => {
|
||||
setActionId(item.id);
|
||||
onConfirmOpen();
|
||||
}}
|
||||
colorScheme="green"
|
||||
variant={"solid"}
|
||||
cursor={"pointer"}
|
||||
>
|
||||
<CheckIcon fontSize={"12px"} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
rounded={"sm"}
|
||||
fontSize={"xs"}
|
||||
label="Reject"
|
||||
bg="#fff"
|
||||
color={"red.500"}
|
||||
placement="left-start"
|
||||
>
|
||||
<Button
|
||||
colorScheme="red"
|
||||
// color="red.500"
|
||||
rounded={"sm"}
|
||||
size={"xs"}
|
||||
textTransform={"inherit"}
|
||||
fontWeight={500}
|
||||
px={2}
|
||||
onClick={() => {
|
||||
setActionId(item.id);
|
||||
onRejectOpen();
|
||||
}}
|
||||
py={1}
|
||||
// variant={"solid"}
|
||||
>
|
||||
<CloseIcon fontSize={"10px"} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
),
|
||||
}));
|
||||
|
||||
const handleDelete = () => {
|
||||
const updatedSponsors = sponser.filter(
|
||||
(sponsor) => sponsor.id !== actionId
|
||||
);
|
||||
|
||||
setTimeout(() => {
|
||||
setSponser(updatedSponsors);
|
||||
setDeleteAlert(false);
|
||||
setIsLoading(false);
|
||||
}, 100);
|
||||
setIsLoading(true);
|
||||
};
|
||||
|
||||
const handleApproved = async (data) => {
|
||||
setIsReversalLoading.on(); // Start loading
|
||||
try {
|
||||
const { error, data: responseData } = await rejectFawateerRequest({
|
||||
id: actionId,
|
||||
data,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
throw error; // Explicitly handle the error
|
||||
}
|
||||
|
||||
// Success: Perform necessary actions
|
||||
refetch();
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={responseData?.message || "Action successful!"} />
|
||||
),
|
||||
});
|
||||
onRejectClose();
|
||||
} catch (error) {
|
||||
// Handle errors
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox
|
||||
message={
|
||||
error?.data?.message || "Something went wrong. Please try again."
|
||||
}
|
||||
status="error"
|
||||
/>
|
||||
),
|
||||
});
|
||||
console.error("Error:", error);
|
||||
} finally {
|
||||
setIsReversalLoading.off(); // Ensure loading is toggled off
|
||||
}
|
||||
};
|
||||
|
||||
const handleConfirm = async (data) => {
|
||||
setIsReversalLoading.on(); // Start loading
|
||||
try {
|
||||
const { error, data: responseData } = await approveFawateerRequest({
|
||||
id: actionId,
|
||||
data,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
throw error; // Explicitly handle the error
|
||||
}
|
||||
|
||||
// Success: Perform necessary actions
|
||||
refetch();
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox message={responseData?.message || "Action successful!"} />
|
||||
),
|
||||
});
|
||||
onRejectClose();
|
||||
} catch (error) {
|
||||
// Handle errors
|
||||
toast({
|
||||
render: () => (
|
||||
<ToastBox
|
||||
message={
|
||||
error?.data?.message || "Something went wrong. Please try again."
|
||||
}
|
||||
status="error"
|
||||
/>
|
||||
),
|
||||
});
|
||||
console.error("Error:", error);
|
||||
} finally {
|
||||
setIsReversalLoading.off(); // Ensure loading is toggled off
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
type="search"
|
||||
width={300}
|
||||
placeholder="Search..."
|
||||
size="sm"
|
||||
rounded="sm"
|
||||
focusBorderColor="green.500"
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
/>
|
||||
|
||||
<Pagination
|
||||
isLoading={drawalRequestLoading}
|
||||
pageSize={pageSize}
|
||||
setPageSize={setPageSize}
|
||||
currentPage={currentPage}
|
||||
setCurrentPage={setCurrentPage}
|
||||
totalItems={data?.data?.totalItems}
|
||||
/>
|
||||
</HStack>
|
||||
</Box>
|
||||
|
||||
<NormalTable
|
||||
isLoading={drawalRequestLoading}
|
||||
emptyMessage={`We don't have any Sponers `}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={extractedArray}
|
||||
viewActionId={actionId}
|
||||
setViewActionId={setActionId}
|
||||
// totalPages={10}
|
||||
|
||||
setMouseEnteredId={setMouseEnteredId}
|
||||
setMouseEntered={setMouseEntered}
|
||||
/>
|
||||
|
||||
<CustomAlertDialog
|
||||
onClose={() => setDeleteAlert(false)}
|
||||
isOpen={deleteAlert}
|
||||
message={"Are you sure you want to delete sponers?"}
|
||||
alertHandler={handleDelete}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
<ConfirmReversalPopups
|
||||
isOpen={isConfirmOpen}
|
||||
onClose={onConfirmClose}
|
||||
handleConfirm={handleConfirm}
|
||||
isLoading={isReversalLoading}
|
||||
/>
|
||||
<RejectReversalPopups
|
||||
isOpen={isRejectOpen}
|
||||
onClose={onRejectClose}
|
||||
handelApproved={handleApproved}
|
||||
isLoading={isReversalLoading}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default ReversalFawateerDeposit;
|
||||
@@ -133,7 +133,7 @@ const ViewHistory = () => {
|
||||
"Status",
|
||||
];
|
||||
|
||||
const extractedArray = filteredData?.map((item, index) => ({
|
||||
const extractedArray = data?.data?.rows?.map((item, index) => ({
|
||||
// id: item?.id,
|
||||
"Sr.no": (
|
||||
<Text
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
TbReportMoney,
|
||||
} from "react-icons/tb";
|
||||
import {
|
||||
RiAccountBoxLine,
|
||||
RiBankLine,
|
||||
RiFileUserLine,
|
||||
RiMoneyDollarBoxLine,
|
||||
@@ -34,12 +35,12 @@ import { HiOutlineBanknotes } from "react-icons/hi2";
|
||||
import { AtSignIcon } from "@chakra-ui/icons";
|
||||
|
||||
export const nav = [
|
||||
// {
|
||||
// title: "Dashboard",
|
||||
// type: "single",
|
||||
// path: "/",
|
||||
// Icon: TbLayoutDashboard,
|
||||
// },
|
||||
{
|
||||
title: "Dashboard",
|
||||
type: "single",
|
||||
path: "/",
|
||||
Icon: TbLayoutDashboard,
|
||||
},
|
||||
{
|
||||
title: "MASTER MENU",
|
||||
type: "title",
|
||||
@@ -108,7 +109,7 @@ export const nav = [
|
||||
title: "Fawateer Deposit",
|
||||
submenu: [
|
||||
{
|
||||
title: "Aprover Request",
|
||||
title: "Approver Request",
|
||||
path: "/fawateer",
|
||||
icon: RiMoneyDollarBoxLine,
|
||||
},
|
||||
@@ -189,6 +190,34 @@ export const nav = [
|
||||
type: "accordion",
|
||||
Icon: AiOutlineUserDelete,
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
title: "REVERSAL TRANSACTION",
|
||||
type: "title",
|
||||
},
|
||||
{
|
||||
title: "Bank Deposit Request",
|
||||
type: "single",
|
||||
path: "/bank-deposit-request",
|
||||
Icon: RiBankLine,
|
||||
},
|
||||
{
|
||||
title: "Fawateer Deposit",
|
||||
type: "single",
|
||||
path: "/reversal-fawateer-deposit",
|
||||
Icon: HiOutlineBanknotes,
|
||||
},
|
||||
{
|
||||
title: "Account Deletion Request",
|
||||
type: "single",
|
||||
path: "/account-deletion-request",
|
||||
Icon: RiAccountBoxLine,
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
title: "MANAGE ADMIN",
|
||||
type: "title",
|
||||
|
||||
@@ -31,7 +31,7 @@ import DepositRequest from "../Pages/Deposit/DepositRequest/DepositRequest";
|
||||
import EditBankDetails from "../Pages/Admin/BankDetails/EditBankDetails";
|
||||
import ExchangeHistory from "../Pages/Master/ExchangeRate/ExchangeHistroy";
|
||||
import Welcome from "../Pages/PaymentSuccess";
|
||||
import Dashbaord from "../Pages/Dashbaord";
|
||||
import Dashbaord from "../Pages/Dashboard/Dashbaord";
|
||||
import UnderConstruction from "../Pages/UnderConstruction";
|
||||
import PendingRequest from "../Pages/WithDrawal/DrawalRequest/PendingRequest";
|
||||
import BankInvestor from "../Pages/Admin/Investor/BankInvestor/BankInvestor";
|
||||
@@ -48,12 +48,17 @@ import AddUser from "../Pages/User/AddUser";
|
||||
import Profile from "../Pages/Profile/Profile";
|
||||
import SubAdmin from "../Pages/SubAdmin/SubAdmin";
|
||||
import SubAdminUpdateCreate from "../Pages/SubAdmin/SubAdminUpdateCreate";
|
||||
import InvestmentOpportunities from "../Pages/Dashboard/InvestmentOpportunities";
|
||||
import BankDepositRequest from "../Pages/BankDepositRequest/BankDepositRequest";
|
||||
import ReversalFawateerDeposit from "../Pages/ReversalFawateerDeposit/ReversalFawateerDeposit";
|
||||
import ReversalAccountDeletion from "../Pages/ReversalAccountDeletion/ReversalAccountDeletion";
|
||||
|
||||
export const RouteLink = [
|
||||
// =============[ Tanami ]================
|
||||
// ===============[ Management]===============
|
||||
|
||||
{ path: "/", Component: Sponser },
|
||||
{ path: "/", Component: Dashbaord },
|
||||
{ path: "/investment-opportunities", Component: InvestmentOpportunities },
|
||||
{ path: "/sponser", Component: Sponser },
|
||||
{ path: "/sponser/add-sponser/:id", Component: AddSponser },
|
||||
{ path: "/sponser/add-sponser", Component: AddSponser },
|
||||
@@ -129,6 +134,11 @@ export const RouteLink = [
|
||||
{ path: "/subadmin/subadmin-update/:id", Component: SubAdminUpdateCreate },
|
||||
{ path: "/subadmin/subadmin-update", Component: SubAdminUpdateCreate },
|
||||
|
||||
// ===============[ REVERSAL TRANSACTION ]===============
|
||||
|
||||
{ path: "/bank-deposit-request", Component: BankDepositRequest },
|
||||
{ path: "/reversal-fawateer-deposit", Component: ReversalFawateerDeposit },
|
||||
{ path: "/account-deletion-request", Component: ReversalAccountDeletion },
|
||||
|
||||
|
||||
// ===============[ fawateer ]===============
|
||||
|
||||
@@ -20,9 +20,9 @@ export const banInvestorDetails = createApi({
|
||||
|
||||
|
||||
getUnbanInvestor: builder.query({
|
||||
query: ({ page, size, searchTerm, userStatus, KYCStatus, country_xid }) => {
|
||||
query: ({ page, size, search, userStatus, KYCStatus, country_xid }) => {
|
||||
// Start with the base URL, including searchTerm
|
||||
let baseURL = `/investorDetails/admin/getAllUnbanned?search=${searchTerm || ""}&userStatus=${userStatus ||""}&KYCStatus=${KYCStatus || ""}&country_xid=${country_xid||""}`;
|
||||
let baseURL = `/investorDetails/admin/getAllUnbanned?search=${search || ""}&userStatus=${userStatus ||""}&KYCStatus=${KYCStatus || ""}&country_xid=${country_xid||""}`;
|
||||
|
||||
// Conditionally append kycStatus if it's defined
|
||||
if (KYCStatus) {
|
||||
|
||||
61
src/Services/bankdeposit.request.service.js
Normal file
@@ -0,0 +1,61 @@
|
||||
// Need to use the React-specific entry point to import createApi
|
||||
import { createApi } from "@reduxjs/toolkit/query/react";
|
||||
import { baseQuery } from "./token.serivce";
|
||||
|
||||
// Define a service using a base URL and expected endpoints
|
||||
export const bankDepositRequestMaster = createApi({
|
||||
reducerPath: "BankDeposit",
|
||||
baseQuery: baseQuery,
|
||||
tagTypes: ["getBankDeposit"],
|
||||
endpoints: (builder) => ({
|
||||
// ======[Get All]=====
|
||||
|
||||
getBankDepositMaster: builder.query({
|
||||
query: ({ size, search, page }) => {
|
||||
let baseURL = `/reversal-transactions/bank-transfer/getAll?search=${search || ""}`
|
||||
|
||||
// Conditionally append page and size parameters if they are defined
|
||||
if (page !== undefined && size !== undefined) {
|
||||
baseURL += `&page=${page}&size=${size}`;
|
||||
}
|
||||
|
||||
return baseURL;
|
||||
},
|
||||
providesTags: ["getBankDeposit"],
|
||||
}),
|
||||
|
||||
approveBankDepositRequest: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
url: `/reversal-transactions/bank-transfer/approve/${id}`,
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
}),
|
||||
invalidatesTags: ["getDepositRequest", "getDepositHistory"],
|
||||
}),
|
||||
|
||||
createBankDepositReversalRequest: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
url: `/reversal-transactions/bank-transfer/create/${id}`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
invalidatesTags: ["getDepositRequest", "getDepositHistory"],
|
||||
}),
|
||||
|
||||
rejectbankDepositRequest: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
url: `/reversal-transactions/bank-transfer/reject/${id}`,
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
}),
|
||||
invalidatesTags: ["getDepositRequest", "getDepositHistory"],
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export const {
|
||||
useGetBankDepositMasterQuery,
|
||||
useApproveBankDepositRequestMutation,
|
||||
useRejectbankDepositRequestMutation,
|
||||
useCreateBankDepositReversalRequestMutation,
|
||||
} = bankDepositRequestMaster;
|
||||
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;
|
||||
@@ -50,8 +50,19 @@ export const fawateerRequest = createApi({
|
||||
providesTags: ["getFawateerMakerRequest"],
|
||||
}),
|
||||
|
||||
// getApproveHistory: builder.query({
|
||||
// query: () => `/fawateer/admin/getAll`,
|
||||
// providesTags: ["getApproveHistory"],
|
||||
// }),
|
||||
|
||||
getApproveHistory: builder.query({
|
||||
query: () => `/fawateer/admin/getAll`,
|
||||
query: ({ page, size, searchTerm }) => {
|
||||
let baseURL = `/fawateer/admin/getAll?search=${searchTerm || ""}`;
|
||||
if (page !== undefined && size !== undefined) {
|
||||
baseURL += `&page=${page}&size=${size}`; // Only add pagination if both are defined
|
||||
}
|
||||
return baseURL;
|
||||
},
|
||||
providesTags: ["getApproveHistory"],
|
||||
}),
|
||||
|
||||
|
||||
@@ -256,8 +256,9 @@ export const ioService = createApi({
|
||||
|
||||
updateCancleStatusTo: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
url: `/io/admin/transaction/${id}/cancel`,
|
||||
url: `/io/admin/maker-transaction/${id}/io-cancel`,
|
||||
method: "POST",
|
||||
body:data
|
||||
}),
|
||||
invalidatesTags: ["getIOById"],
|
||||
}),
|
||||
|
||||
61
src/Services/reversal.account.deletion.service.js
Normal file
@@ -0,0 +1,61 @@
|
||||
// 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 reversalAccountDeletionMaster = createApi({
|
||||
reducerPath: "accountDeletion",
|
||||
baseQuery: baseQuery,
|
||||
tagTypes: ["getAccountDeletion", "getHistory"],
|
||||
endpoints: (builder) => ({
|
||||
// ======[Get All]=====
|
||||
|
||||
getAccountDeletionMaster: builder.query({
|
||||
query: ({ page, size, search, }) => {
|
||||
let baseURL = `/reversal-transactions/account-deletion/getAll?search=${search || ""}`
|
||||
|
||||
// Conditionally append page and size parameters if they are defined
|
||||
if (page !== undefined && size !== undefined) {
|
||||
baseURL += `&page=${page}&size=${size}`;
|
||||
}
|
||||
|
||||
return baseURL;
|
||||
},
|
||||
providesTags: ["getAccountDeletion"],
|
||||
}),
|
||||
|
||||
approveAccountDeletionRequest: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
url: `/reversal-transactions/account-deletion/approve/${id}`,
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
}),
|
||||
invalidatesTags: ["getAccountDeletion", "getHistory"],
|
||||
}),
|
||||
|
||||
createAccountDeletionReversalRequest: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
url: `/reversal-transactions/account-deletion/create/${id}`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
invalidatesTags: ["getAccountDeletion", "getHistory"],
|
||||
}),
|
||||
|
||||
rejectAccountDeletionRequest: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
url: `/reversal-transactions/account-deletion/reject/${id}`,
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
}),
|
||||
invalidatesTags: ["getAccountDeletion", "getHistory"],
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export const {
|
||||
useGetAccountDeletionMasterQuery,
|
||||
useCreateAccountDeletionReversalRequestMutation,
|
||||
useApproveAccountDeletionRequestMutation,
|
||||
useRejectAccountDeletionRequestMutation
|
||||
} = reversalAccountDeletionMaster;
|
||||
60
src/Services/reversal.fawateer.deposit.service.js
Normal file
@@ -0,0 +1,60 @@
|
||||
// Need to use the React-specific entry point to import createApi
|
||||
import { createApi } from "@reduxjs/toolkit/query/react";
|
||||
import { baseQuery } from "./token.serivce";
|
||||
|
||||
// Define a service using a base URL and expected endpoints
|
||||
export const reversalFawateerDepositMaster = createApi({
|
||||
reducerPath: "FawateerDeposit",
|
||||
baseQuery: baseQuery,
|
||||
tagTypes: ["getFawateerDeposit", "getDepositHistory"],
|
||||
endpoints: (builder) => ({
|
||||
// ======[Get All]=====
|
||||
|
||||
getFawateerDepositMaster: builder.query({
|
||||
query: ({ search, page, size }) => {
|
||||
let baseURL = `/reversal-transactions/fawateer/getAll?search=${search || ""}`
|
||||
// Conditionally append page and size parameters if they are defined
|
||||
if (page !== undefined && size !== undefined) {
|
||||
baseURL += `&page=${page}&size=${size}`;
|
||||
}
|
||||
|
||||
return baseURL;
|
||||
},
|
||||
providesTags: ["getFawateerDeposit"],
|
||||
}),
|
||||
|
||||
approveFawateerRequest: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
url: `/reversal-transactions/fawateer/approve/${id}`,
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
}),
|
||||
invalidatesTags: ["getFawateerDeposit", "getDepositHistory"],
|
||||
}),
|
||||
|
||||
createFawateerReversalRequest: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
url: `/reversal-transactions/fawateer/create/${id}`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
invalidatesTags: ["getFawateerDeposit", "getDepositHistory"],
|
||||
}),
|
||||
|
||||
rejectFawateerRequest: builder.mutation({
|
||||
query: ({ id, data }) => ({
|
||||
url: `/reversal-transactions/fawateer/reject/${id}`,
|
||||
method: "PATCH",
|
||||
body: data,
|
||||
}),
|
||||
invalidatesTags: ["getFawateerDeposit", "getDepositHistory"],
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export const {
|
||||
useGetFawateerDepositMasterQuery,
|
||||
useApproveFawateerRequestMutation,
|
||||
useCreateFawateerReversalRequestMutation,
|
||||
useRejectFawateerRequestMutation,
|
||||
} = reversalFawateerDepositMaster;
|
||||
@@ -20,6 +20,10 @@ 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";
|
||||
import { bankDepositRequestMaster } from "../Services/bankdeposit.request.service";
|
||||
import { reversalFawateerDepositMaster } from "../Services/reversal.fawateer.deposit.service";
|
||||
import { reversalAccountDeletionMaster } from "../Services/reversal.account.deletion.service";
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
@@ -41,6 +45,10 @@ export const store = configureStore({
|
||||
[sabAdminMaster.reducerPath]: sabAdminMaster.reducer,
|
||||
[changePasswordMake.reducerPath]: changePasswordMake.reducer,
|
||||
[forgetPasswordMake.reducerPath]: forgetPasswordMake.reducer,
|
||||
[dashboardMaster.reducerPath]: dashboardMaster.reducer,
|
||||
[bankDepositRequestMaster.reducerPath]: bankDepositRequestMaster.reducer,
|
||||
[reversalFawateerDepositMaster.reducerPath]: reversalFawateerDepositMaster.reducer,
|
||||
[reversalAccountDeletionMaster.reducerPath]: reversalAccountDeletionMaster.reducer,
|
||||
|
||||
// Add other reducers as needed
|
||||
},
|
||||
@@ -68,6 +76,10 @@ export const store = configureStore({
|
||||
sabAdminMaster.middleware,
|
||||
changePasswordMake.middleware,
|
||||
forgetPasswordMake.middleware,
|
||||
dashboardMaster.middleware,
|
||||
bankDepositRequestMaster.middleware,
|
||||
reversalFawateerDepositMaster.middleware,
|
||||
reversalAccountDeletionMaster.middleware,
|
||||
),
|
||||
});
|
||||
|
||||
|
||||