This commit is contained in:
2024-07-05 20:05:26 +05:30
22 changed files with 2253 additions and 332 deletions

View File

@@ -0,0 +1,779 @@
import React, { useContext, useEffect, useState } from "react";
import { OPACITY_ON_LOAD } from "../../Layout/animations";
import {
Box,
Divider,
FormControl,
FormLabel,
Heading,
Input,
Select,
Textarea,
Button,
Text,
Image,
Tabs,
TabList,
Tab,
TabPanel,
TabPanels,
Tooltip,
Switch,
useDisclosure,
} from "@chakra-ui/react";
import { useForm, Controller } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
import {
AddIcon,
CloseIcon,
DeleteIcon,
EditIcon,
ViewIcon,
WarningTwoIcon,
} from "@chakra-ui/icons";
import { TiWarning } from "react-icons/ti";
import GlobalStateContext from "../../Contexts/GlobalStateContext";
import { useNavigate } from "react-router-dom";
import FormField from "../../Components/FormField";
import { v4 as uuidv4 } from "uuid";
import AddIOCharges from "./AddIOCharges";
import FormInputMain from "../../Components/FormInputMain";
import DataTable from "../../Components/DataTable/DataTable";
import { debounce } from "../Master/Sponser/AddSponser";
import CustomAlertDialog from "../../Components/CustomAlertDialog";
import { formatDate } from "../../Components/Functions/UTCConvertor";
import InvestmentDocuments from "./InvestmentDocuments";
const schema = yup.object().shape({
ioName: yup.string().required("Arabic name is required"),
ioNameArabic: yup.string().required("Investment Object name is required"),
discription: yup.string().required("Sponser name is required"),
discriptionArabic: yup.string().required("Arabic name is required"),
typeName: yup.string().required("Investment Object name is required"),
typeNameArabic: yup.string().required("Sponser name is required"),
sponserName: yup.string().required("Arabic name is required"),
sponserNameArabic: yup
.string()
.required("Investment Object name is required"),
holdingPeriod: yup.string().required("Sponser name is required"),
ioStartus: yup.string().required("Investment Object name is required"),
ioStartusArabic: yup.string().required("Sponser name is required"),
goalAmount: yup.string().required("Arabic name is required"),
closingDate: yup.string().required("Investment Object name is required"),
minInvestment: yup.string().required("Sponser name is required"),
maxInvestment: yup.string().required("Arabic name is required"),
expectedReturn: yup.string().required("Investment Object name is required"),
originalValue: yup.string().required("Sponser name is required"),
keyname: yup.string().required("Arabic name is required"),
keyNameArabic: yup.string().required("Investment Object name is required"),
keyDescription: yup.string().required("Sponser name is required"),
keyDescriptionArabic: yup.string().required("Sponser name is required"),
docType: yup.string().required("Sponser name is required"),
destributedAmount: yup
.number()
.required("Distributed Amount is required")
.positive("Must be a positive number"),
year: yup.string().required("Year is required"),
tenure: yup
.number()
.required("Tenure is required")
.positive("Must be a positive number"),
annualReturn: yup
.number()
.required("Annual Return is required")
.positive("Must be a positive number"),
miniInvest: yup
.number()
.required("Minimum Invest is required")
.positive("Must be a positive number"),
quaterly: yup.string().required("Quaterly is required"),
targetClose: yup.date().required("Target close date is required"),
annualyield: yup
.number()
.required("Annual Yield is required")
.positive("Must be a positive number"),
iconUpload: yup.mixed().required("Profile image is required"),
bannerImages: yup.mixed().required("Profile image is required"),
otherImage: yup.mixed().required("Profile image is required"),
docAttach: yup.mixed().required("Profile image is required"),
videos: yup.mixed().required("Profile image is required"),
});
const startYear = 2024;
const endYear = 2124;
const years = Array.from(
{ length: endYear - startYear + 1 },
(_, i) => startYear + i
).map((year) => ({ value: year, label: year }));
const CreateIO = () => {
const navigate = useNavigate();
const { create, setCreate, sponser, setSponser, investment, setInvestment } =
useContext(GlobalStateContext);
const [bannerImageData, setBannerImageData] = useState(null);
const [otherImageData, setOtherImageData] = useState(null);
const [selectedBannerImageData, setSelectedBannerImageData] = useState(null);
const [selectedOtherImageData, setSelectedOtherImageData] = useState(null);
const [charges, setCharges] = useState([]);
const [totalCharge, setTotalCharge] = useState(0.0);
const [totalAmount, setTotalAmount] = useState(0.0);
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 {
control,
handleSubmit,
reset,
watch,
setValue,
formState: { errors },
} = useForm({
resolver: yupResolver(schema),
});
console.log(errors);
useEffect(() => {
// Simulate loading
const timer = setTimeout(() => {
setIsLoading(false);
}, 1500);
// Cleanup the timer on component unmount
return () => clearTimeout(timer);
}, []);
const tableHeadRow = [
"Sponser name",
"Address",
"Mobile no",
"Created At",
"Action",
];
const handleUpdateStatus = debounce((id) => {
setCreate((prevCreate) =>
prevCreate.map((create) =>
create.id === id ? { ...create, status: !create.status } : create
)
);
toast({
render: () => <ToastBox message={"Status changed succesfully.!"} />,
});
}, 300);
const filteredData = create?.filter((item) => {
// Filter by name (case insensitive)
const name = item.sponserName;
const searchLower = searchTerm.toLowerCase();
const nameMatches = name.toLowerCase().includes(searchLower);
return nameMatches;
});
const handleDelete = () => {
const updatedCreate = create.filter((create) => create.id !== actionId);
setTimeout(() => {
setSponser(updatedCreate);
setDeleteAlert(false);
setIsLoading(false);
}, 100);
setIsLoading(true);
};
const extractedArray = filteredData?.map((item) => ({
id: item?.id,
"Sponser name": (
<Text
justifyContent={"left"}
as={"span"}
color={"teal.900"}
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
"{item.sponserName}"
</Text>
),
Address: (
<Box w={350} isTruncated={true}>
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
" {item.sponserAddress}"
</Text>
</Box>
),
"Mobile no": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
"{item.mobileNo}"
</Text>
</Box>
),
"Created At": (
<span className="d-flex justify-content-between align-items-center">
<Text as={"span"} color={"gray.600"} fontWeight={"500"}>
{formatDate(item.createdAt)}
</Text>
</span>
),
Action: <Box display={"flex"} justifyContent={"space-between"}></Box>,
}));
console.log(extractedArray);
const destributedAmount = Number(watch().destributedAmount) || 0;
useEffect(() => {
const calculateTotalCharge = () => {
const totalChargeValue = charges.reduce(
(acc, { value }) => acc + Number(value),
0
);
setTotalCharge(totalChargeValue);
};
const calculateTotalAmount = () => {
const totalChargeValue = charges.reduce(
(acc, { value }) => acc + Number(value),
0
);
setTotalAmount(destributedAmount + totalChargeValue);
};
calculateTotalCharge();
calculateTotalAmount();
}, [charges, destributedAmount]);
const onSubmit = (data) => {
// setValue("banner_image", selectedBannerImageData);
data.banner_image = selectedBannerImageData;
const updatedData = { ...data, status: "Available" };
console.log(selectedBannerImageData);
setInvestment([...investment, updatedData]);
navigate("/view-io");
reset();
};
// Extract options for the select input
const createOptions = create.map((item) => ({
value: item.sponserName,
label: item.sponserName,
}));
const handleBannerImageChange = (e) => {
const file = e.target.files[0];
setBannerImageData(file);
if (file) {
const reader = new FileReader();
reader.onloadend = () => {
setSelectedBannerImageData(reader.result);
};
reader.readAsDataURL(file);
}
};
const { isOpen, onOpen, onClose } = useDisclosure();
const firstField = React.useRef();
// Handler for file input
const handleOtherImageChange = (e) => {
const files = Array.from(e.target.files);
const newImageData = [...(otherImageData || []), ...files]; // Ensure otherImageData is an array
setOtherImageData(newImageData);
const readers = files.map((file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => {
resolve(reader.result);
};
reader.onerror = reject;
reader.readAsDataURL(file);
});
});
Promise.all(readers)
.then((results) => {
setSelectedOtherImageData([
...(selectedOtherImageData || []),
...results,
]); // Ensure selectedOtherImageData is an array
})
.catch((error) => {
console.error("Error reading files:", error);
});
};
// Function to remove a specific image
const removeOtherImage = (index) => {
const newImageData = otherImageData.filter((_, i) => i !== index);
const newSelectedImageData = selectedOtherImageData.filter(
(_, i) => i !== index
);
setOtherImageData(newImageData);
setSelectedOtherImageData(newSelectedImageData);
};
const formFields = [
{
label: "IO Name (English)",
placeHolder: " ",
name: "ioName",
type: "text",
isRequired: true,
section: " ",
width: "49%",
},
{
label: "IO Name (Arabic)",
placeHolder: " ",
name: "ioNameArabic",
type: "text",
isRequired: true,
section: " ",
width: "49%",
},
{
label: "Description (English)",
placeHolder: " ",
name: "discription",
type: "textarea",
isRequired: true,
section: " ",
width: "49%",
},
{
label: "Description (Arabic)",
placeHolder: " ",
name: "discriptionArabic",
type: "textarea",
isRequired: true,
section: " ",
width: "49%",
},
{
label: "Investment Type (English)",
placeHolder: " ",
name: "typeName",
type: "select",
isRequired: true,
section: " ",
width: "49%",
options: [
{
label: "option 1",
value: "option 1",
},
{
label: "option 2",
value: "option 2",
},
{
label: "option 3",
value: "option 3",
},
{
label: "option 4",
value: "option 4",
},
],
},
{
label: "Investment Type (Arabic)",
placeHolder: " ",
name: "typeNameArabic",
type: "select",
isRequired: true,
section: " ",
width: "49%",
options: [
{
label: "option 1",
value: "option 1",
},
{
label: "option 2",
value: "option 2",
},
{
label: "option 3",
value: "option 3",
},
{
label: "option 4",
value: "option 4",
},
],
},
{
label: "Sponser Name (English)",
placeHolder: " ",
name: "sponserName",
type: "text",
isRequired: true,
section: " ",
width: "49%",
},
{
label: "Goal Amount (English)",
placeHolder: " ",
name: "goalAmount",
type: "Number",
isRequired: true,
section: " ",
width: "49%",
},
{
label: "Minimum Investment Amount (English)",
placeHolder: " ",
name: "minInvestment",
type: "number",
isRequired: true,
section: " ",
width: "32.3%",
},
{
label: "Maximum Investment Amount (English)",
placeHolder: " ",
name: "maxInvestment",
type: "number",
isRequired: true,
section: " ",
width: "32.3%",
},
{
label: "Holding Period (English)",
placeHolder: " ",
name: "holdingPeriod",
type: "number",
isRequired: true,
section: " ",
width: "32.3%",
},
{
label: "Expected Return Estimated (English)",
placeHolder: " ",
name: "expectedReturn",
type: "number",
isRequired: true,
section: " ",
width: "32.3%",
},
{
label: "Closing Date (English)",
placeHolder: " ",
name: "closingDate",
type: "date",
isRequired: true,
section: " ",
width: "32.3%",
},
{
label: "IO Status (English)",
placeHolder: " ",
name: "minInvestment",
type: "text",
isRequired: true,
section: " ",
width: "32.3%",
},
];
const keyMerits = [
{
label: "Name (English)",
placeHolder: " ",
name: "keyname",
type: "text",
isRequired: true,
section: " ",
width: "32.3%",
},
{
label: "Name (Arabic)",
placeHolder: " ",
name: "keyNameArabic",
type: "text",
isRequired: true,
section: " ",
width: "32.3%",
},
{
label: "Icon",
placeHolder: " ",
name: "iconUpload",
type: "fileNormal",
isRequired: true,
section: " ",
width: "32.3%",
},
{
label: "Description (English)",
placeHolder: " ",
name: "keyDescription",
type: "textarea",
isRequired: true,
section: " ",
width: "32.3%",
},
{
label: "Description (Arabic)",
placeHolder: " ",
name: "keyDescriptionArabic",
type: "textarea",
isRequired: true,
section: " ",
width: "32.3%",
},
];
const images = [
{
label: "Banner Images ",
placeHolder: " ",
name: "bannerImages",
type: "fileNormal",
isRequired: true,
section: " ",
width: "32.3%",
},
{
label: "Other Images",
placeHolder: " ",
name: "otherImage",
type: "fileNormal",
isRequired: true,
section: " ",
width: "32.3%",
},
];
const documents = [
{
label: "Type",
placeHolder: " ",
name: "docType",
type: "text",
isRequired: true,
section: " ",
width: "32.3%",
},
{
label: "Attachment",
placeHolder: " ",
name: "type",
type: "docAttach",
isRequired: true,
section: " ",
width: "32.3%",
},
];
const Videos = [
{
label: "Videos",
placeHolder: " ",
name: "videos",
type: "fileNormal",
isRequired: true,
section: " ",
width: "32.3%",
},
];
const groupedFields = formFields.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
groups[section] = [];
}
groups[section].push(field);
return groups;
}, {});
const groupedFieldsTwo = keyMerits.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
groups[section] = [];
}
groups[section].push(field);
return groups;
}, {});
const groupedFieldsThree = images.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
groups[section] = [];
}
groups[section].push(field);
return groups;
}, {});
const groupedFieldsFour = documents.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
groups[section] = [];
}
groups[section].push(field);
return groups;
}, {});
const groupedFieldsFive = Videos.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
groups[section] = [];
}
groups[section].push(field);
return groups;
}, {});
return (
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
<Tabs mt={4}>
<TabList>
<Tab
fontSize={"sm"}
_selected={{ color: "#004118", borderBottom: "2px solid #38a169" }}
>
IO Details
</Tab>
<Tab
fontSize={"sm"}
_selected={{ color: "#004118", borderBottom: "2px solid #38a169" }}
>
Investment Documents
</Tab>
<Tab
fontSize={"sm"}
_selected={{ color: "#004118", borderBottom: "2px solid #38a169" }}
>
Key Merits
</Tab>
<Tab
fontSize={"sm"}
_selected={{ color: "#004118", borderBottom: "2px solid #38a169" }}
>
IO artifacts
</Tab>
<Tab
fontSize={"sm"}
_selected={{ color: "#004118", borderBottom: "2px solid #38a169" }}
>
Investors
</Tab>
<Tab
fontSize={"sm"}
_selected={{ color: "#004118", borderBottom: "2px solid #38a169" }}
>
IO Cash detail
</Tab>
<Tab
fontSize={"sm"}
_selected={{ color: "#004118", borderBottom: "2px solid #38a169" }}
>
IO NAV detail
</Tab>
<Tab
fontSize={"sm"}
_selected={{ color: "#004118", borderBottom: "2px solid #38a169" }}
>
Distribution
</Tab>
</TabList>
<TabPanels>
<TabPanel>
<FormInputMain
width={"23.8%"}
groupedFields={groupedFields}
control={control}
errors={errors}
></FormInputMain>
</TabPanel>
<TabPanel>
<Box display={'flex'} justifyContent={'space-between'} mb={4}>
<Input
type="search"
width={300}
placeholder="Search..."
size="sm"
rounded="sm"
focusBorderColor="green.500"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
<Button leftIcon={<AddIcon />} onClick={onOpen}
size={"sm"}
// width={"44.5%"}
fontSize={'xs'}
rounded={"sm"}
colorScheme='green'
>
Add
</Button>
<InvestmentDocuments isOpen={isOpen} onClose={onClose} firstField={firstField} />
</Box>
<DataTable
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}
/>
</TabPanel>
<TabPanel>
<FormInputMain
width={"23.8%"}
groupedFields={groupedFieldsThree}
control={control}
errors={errors}
onSubmit={handleSubmit(onSubmit)}
></FormInputMain>
</TabPanel>
<TabPanel>
<FormInputMain
width={"23.8%"}
groupedFields={groupedFieldsFour}
control={control}
errors={errors}
onSubmit={handleSubmit(onSubmit)}
></FormInputMain>
</TabPanel>
<TabPanel>
<FormInputMain
width={"23.8%"}
groupedFields={groupedFieldsFive}
control={control}
errors={errors}
onSubmit={handleSubmit(onSubmit)}
></FormInputMain>
</TabPanel>
<TabPanel></TabPanel>
</TabPanels>
</Tabs>
</Box>
);
};
export default CreateIO;

View File

@@ -16,6 +16,7 @@ const FormInputView = ({
{Object?.entries(groupedFields, groupedFieldsTwo).map(
([section, fields], index) => (
<Box key={section}>
{console.log(fields)}
<Heading as="h6" size="xs" mt={index === 0 ? 3 : 4}>
{section}
</Heading>
@@ -27,7 +28,7 @@ const FormInputView = ({
flexWrap={"wrap"}
gap={4}
>
{fields.map(({ value, label, id, width }, key) => (
{fields.map(({ value, label, id, width, btn }, key) => (
<Box w={!width ? "49%" : width}>
<FormLabel key={id} color={"gray.500"} fontSize={"xs"}>
{label}

View File

@@ -3,6 +3,12 @@ import React, { useState } from "react";
import GlobalStateContext from "./GlobalStateContext";
import { effect, useColorMode } from "@chakra-ui/react";
import { v4 as uuidv4 } from "uuid";
import { TbClock2 } from "react-icons/tb";
import { CiWallet } from "react-icons/ci";
import { HiOutlineReceiptPercent } from "react-icons/hi2";
import { IoMdQrScanner } from "react-icons/io";
const getRandomDate = (start, end) => {
const date = new Date(
@@ -280,51 +286,118 @@ const GlobalStateProvider = ({ children }) => {
const [create, setCreate] = useState([
{
id: 1,
sponserName: "Commercial",
description: "Investment Private Company",
Type: "PDF",
fileName: "Investment Private Company",
document:"Investment.pdf",
status: true,
},
{
id: 2,
sponserName: "Commercial",
description: "Investment Private",
Type: "PDF",
fileName: "Investment Private",
document:"Investment.pdf",
status: true,
},
{
id: 3,
sponserName: "Commercial",
description: "Investment Private",
Type: "PDF",
fileName: "Investment Private",
document:"Investment.pdf",
status: true,
},
{
id: 4,
sponserName: "Commercial",
description: "Investment Private",
Type: "PDF",
fileName: "Investment Private",
document:"Investment.pdf",
status: true,
},
{
id: 5,
Type: "PDF",
fileName: "Investment Private",
document:"Investment.pdf",
status: true,
},
{
id: 6,
Type: "PDF",
fileName: "Investment Private",
document:"Investment.pdf",
status: true,
},
{
id: 7,
Type: "PDF",
fileName: "Investment Private",
document:"Investment.pdf",
status: true,
},
]);
const [keyMerits, setKeyMerits] = useState([
{
id: 1,
title: "Diversified Holdings",
subTitle: "Private equity portfolio of over 60 companies in various sectors and different countries around the world",
icon:<TbClock2 fontSize={'18px'} />,
status: true,
},
{
id: 2,
title: "Top-Tier Manager",
subTitle: "KKR is a world-class global PE manager with over $570bn in assets under management",
icon:<CiWallet fontSize={'18px'} />,
status: true,
},
{
id: 3,
title: "Strong performance",
subTitle: "Direct exposure to the KKRs best performing Buyout and Growth funds",
icon:<HiOutlineReceiptPercent fontSize={'18px'} />,
status: true,
},
{
id: 4,
title: "Leading Track Record",
subTitle: "Almost 50 year track record since 1977 of consistent, double-digit annual returns",
icon:<IoMdQrScanner fontSize={'18px'} />,
status: true,
},
]);
const [iOArtifacts, setIOArtifacts] = useState([
{
id: 1,
type: "JPG",
fileName: "Banner image",
document:"Banner.jpg",
status: true,
},
{
id: 2,
type: "JPG",
fileName: "Banner image",
document:"Banner.jpg",
status: true,
},
{
id: 3,
type: "JPG",
fileName: "Banner image",
document:"Banner.jpg",
status: true,
},
{
id: 4,
type: "JPG",
fileName: "Banner image",
document:"Banner.jpg",
status: true,
},
]);
const [investmentType, setInvestmentType] = useState([
// {
// id: 1,
// investmentName: "Commercial",
// mobileNo: "0987654321",
// investmentAddress: "1725 Slough Ave, Scranton, USA",
// accountHolderName: "Michael Scott",
// bankName: "Dunder Mifflin Bank",
// accountNumber: "1111222233",
// bankBranch: "Scranton Branch",
// branchAddress: "101 Paper St, Scranton, USA",
// ifscCode: "IFSC11111",
// swiftCode: "SWIFT12345",
// routingNumber: "123450987",
// iban: "IBAN1111222233",
// accountType: "checking",
// bankPhoneNumber: "0987654321",
// bankEmail: "michael.scott@example.com",
// status: true,
// createdAt: "45",
// },
{
id: 1,
investmentName: "Commercial",
@@ -1311,6 +1384,10 @@ const GlobalStateProvider = ({ children }) => {
setViewIO,
create,
setCreate,
keyMerits,
setKeyMerits,
iOArtifacts,
setIOArtifacts
}}
>
{children}

View File

@@ -141,12 +141,12 @@ const CreateIO = () => {
{
label: "Key merits",
content: <KeyMerits control={control} errors={errors} />,
isDisabled: true,
isDisabled: false,
},
{
label: "IO artifacts",
content: <IOArtifacts control={control} errors={errors} />,
isDisabled: true,
isDisabled: false,
},
{
label: "Investors",

View File

@@ -1,9 +1,252 @@
import React from 'react'
import {
Box,
Button,
Input,
Text,
Tooltip,
useDisclosure,
} from "@chakra-ui/react";
import React, { useContext, useEffect, useRef, useState } from "react";
import InvestmentDocuments from "../InvestmentDocuments";
import DataTable from "../../../Components/DataTable/DataTable";
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
import { debounce } from "../../Master/Sponser/AddSponser";
import { formatDate } from "../../../Components/Functions/UTCConvertor";
import {
AddIcon,
DeleteIcon,
DownloadIcon,
EditIcon,
ViewIcon,
} from "@chakra-ui/icons";
const IOArtifacts = () => {
return (
<div>IOArtifacts</div>
)
}
const { iOArtifacts, setIOArtifacts, slideFromRight } =
useContext(GlobalStateContext);
const firstField = useRef();
const [searchTerm, setSearchTerm] = useState("");
const [isLoading, setIsLoading] = useState(true);
const [deleteAlert, setDeleteAlert] = useState(false);
const [actionId, setActionId] = useState(false);
const [mouseEntered, setMouseEntered] = useState(false);
const [mouseEnteredId, setMouseEnteredId] = useState("");
const { isOpen, onOpen, onClose } = useDisclosure();
export default IOArtifacts
useEffect(() => {
// Simulate loading
const timer = setTimeout(() => {
setIsLoading(false);
}, 1500);
// Cleanup the timer on component unmount
return () => clearTimeout(timer);
}, []);
const tableHeadRow = [
"Sr.no",
"Type",
"File Name",
"Document",
"Action"
];
const handleUpdateStatus = debounce((id) => {
setIOArtifacts((prevIOArtifacts) =>
prevIOArtifacts.map((iOArtifacts) =>
iOArtifacts.id === id
? { ...iOArtifacts, status: !iOArtifacts.status }
: iOArtifacts
)
);
toast({
render: () => <ToastBox message={"Status changed succesfully.!"} />,
});
}, 300);
const filteredData = iOArtifacts?.filter((item) => {
// Filter by name (case insensitive)
const name = item.type;
const searchLower = searchTerm.toLowerCase();
const nameMatches = name.toLowerCase().includes(searchLower);
return nameMatches;
});
const handleDelete = () => {
const updatedIOArtifacts = iOArtifacts.filter(
(iOArtifacts) => iOArtifacts.id !== actionId
);
setTimeout(() => {
setSponser(updatedIOArtifacts);
setDeleteAlert(false);
setIsLoading(false);
}, 100);
setIsLoading(true);
};
const extractedArray = filteredData?.map((item, index) => ({
"Sr.no": (
<Text
justifyContent={slideFromRight ? "right" : "left"}
as={"span"}
color={"teal.900"}
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
{index + 1}
</Text>
),
Type: (
<Text
justifyContent={slideFromRight ? "right" : "left"}
as={"span"}
color={"teal.900"}
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
{item.type}
</Text>
),
"File Name": (
<Box isTruncated={true}>
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
{item.fileName}
</Text>
</Box>
),
"Document": (
<Text
color={"green.500"}
justifyContent={slideFromRight ? "right" : "left"}
as={"span"}
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
{item.document}
</Text>
),
Action: (
<Box display={"flex"} justifyContent={"space-evenly"}>
<Tooltip
rounded={"sm"}
fontSize={"xs"}
label="View"
bg="#fff"
color={"green.500"}
placement="top"
>
<Button
_hover={{ color: "green.500" }}
// transition={"0.5s all"}
onClick={() => {
navigate(`view-investment/${item.id}`);
}}
color="green.300"
rounded={"sm"}
size={"xs"}
>
<ViewIcon />
</Button>
</Tooltip>
<Tooltip
rounded={"sm"}
fontSize={"xs"}
label="Edit"
bg="#fff"
color={"blue.500"}
placement="top"
>
<Button
_hover={{ color: "blue.500" }}
// transition={"0.5s all"}
color="blue.400"
rounded={"sm"}
size={"xs"}
>
<EditIcon />
</Button>
</Tooltip>
<Tooltip
rounded={"sm"}
fontSize={"xs"}
label="Delete"
bg="#fff"
color={"red.500"}
placement="top"
>
<Button
onClick={() => {
setActionId(item?.id);
setDeleteAlert(true);
}}
_hover={{ color: "red.500" }}
// transition={"0.5s all"}
color="red.300"
rounded={"sm"}
size={"xs"}
>
<DeleteIcon />
</Button>
</Tooltip>
</Box>
),
}));
return (
<Box>
<Box display={"flex"} justifyContent={"space-between"} mb={4}>
<Input
type="search"
width={300}
placeholder="Search..."
size="sm"
rounded="sm"
focusBorderColor="green.500"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
<Button
leftIcon={<AddIcon />}
onClick={onOpen}
size={"xs"}
// width={"44.5%"}
fontSize={"xs"}
rounded={"sm"}
ps={3}
pe={4}
colorScheme="green"
>
Add
</Button>
<InvestmentDocuments
isOpen={isOpen}
onClose={onClose}
firstField={firstField}
/>
</Box>
<DataTable
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}
/>
</Box>
);
};
export default IOArtifacts;

View File

@@ -1,4 +1,4 @@
import { Box, Button, Input, Text, useDisclosure } from "@chakra-ui/react";
import { Box, Button, Input, Text, Tooltip, useDisclosure } from "@chakra-ui/react";
import React, { useContext, useEffect, useRef, useState } from "react";
import InvestmentDocuments from "../InvestmentDocuments";
import DataTable from "../../../Components/DataTable/DataTable";
@@ -6,10 +6,10 @@ import CustomAlertDialog from "../../../Components/CustomAlertDialog";
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
import { debounce } from "../../Master/Sponser/AddSponser";
import { formatDate } from "../../../Components/Functions/UTCConvertor";
import { AddIcon } from "@chakra-ui/icons";
import { AddIcon, DeleteIcon, DownloadIcon, EditIcon, ViewIcon } from "@chakra-ui/icons";
const InvestmentDocument = ({ control, errors }) => {
const { create, setCreate, sponser, setSponser, investment, setInvestment } =
const { create, setCreate, sponser, setSponser,slideFromRight} =
useContext(GlobalStateContext);
const firstField = useRef();
const [searchTerm, setSearchTerm] = useState("");
@@ -33,10 +33,10 @@ const InvestmentDocument = ({ control, errors }) => {
const tableHeadRow = [
"Sponser name",
"Address",
"Mobile no",
"Created At",
"Sr.no",
"Type",
"File Name",
"Document",
"Action",
];
@@ -53,7 +53,7 @@ const InvestmentDocument = ({ control, errors }) => {
const filteredData = create?.filter((item) => {
// Filter by name (case insensitive)
const name = item.sponserName;
const name = item.Type;
const searchLower = searchTerm.toLowerCase();
const nameMatches = name.toLowerCase().includes(searchLower);
@@ -71,43 +71,130 @@ const InvestmentDocument = ({ control, errors }) => {
setIsLoading(true);
};
const extractedArray = filteredData?.map((item) => ({
id: item?.id,
"Sponser name": (
const extractedArray = filteredData?.map((item, index) => ({
"Sr.no": (
<Text
justifyContent={"left"}
justifyContent={slideFromRight ? "right" : "left"}
as={"span"}
color={"teal.900"}
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
h={7}
>
"{item.sponserName}"
{index + 1}
</Text>
),
Address: (
<Box w={350} isTruncated={true}>
"Type": (
<Text
justifyContent={slideFromRight ? "right" : "left"}
as={"span"}
color={"teal.900"}
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
{item.Type}
</Text>
),
"File Name": (
<Box w={"200px"} isTruncated={true}>
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
" {item.sponserAddress}"
{item.fileName}
</Text>
</Box>
),
"Mobile no": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
"{item.mobileNo}"
</Text>
"Document": (
<Text
justifyContent={slideFromRight ? "right" : "left"}
as={"span"}
color={"teal.900"}
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
{item.document}
</Text>
),
Action: (
<Box display={"flex"} justifyContent={"space-evenly"}>
<Tooltip
rounded={"sm"}
fontSize={"xs"}
label="View"
bg="#fff"
color={"green.500"}
placement="top"
>
<Button
_hover={{ color: "green.500" }}
// transition={"0.5s all"}
onClick={() => {
navigate(`view-investment/${item.id}`);
}}
color="green.300"
rounded={"sm"}
size={"xs"}
>
<ViewIcon />
</Button>
</Tooltip>
<Tooltip
rounded={"sm"}
fontSize={"xs"}
label="Edit"
bg="#fff"
color={"blue.500"}
placement="top"
>
<Button
_hover={{ color: "blue.500" }}
// transition={"0.5s all"}
color="blue.400"
rounded={"sm"}
size={"xs"}
>
<EditIcon />
</Button>
</Tooltip>
<Tooltip
rounded={"sm"}
fontSize={"xs"}
label="Edit"
bg="#fff"
color={"blue.500"}
placement="top"
>
<Button
_hover={{ color: "blue.500" }}
// transition={"0.5s all"}
color="blue.400"
rounded={"sm"}
size={"xs"}
>
<DownloadIcon />
</Button>
</Tooltip>
<Tooltip
rounded={"sm"}
fontSize={"xs"}
label="Delete"
bg="#fff"
color={"red.500"}
placement="top"
>
<Button
onClick={() => {
setActionId(item?.id);
setDeleteAlert(true);
}}
_hover={{ color: "red.500" }}
// transition={"0.5s all"}
color="red.300"
rounded={"sm"}
size={"xs"}
>
<DeleteIcon />
</Button>
</Tooltip>
</Box>
),
"Created At": (
<span className="d-flex justify-content-between align-items-center">
<Text as={"span"} color={"gray.600"} fontWeight={"500"}>
{formatDate(item.createdAt)}
</Text>
</span>
),
Action: <Box display={"flex"} justifyContent={"space-between"}></Box>,
}));

View File

@@ -1,9 +1,239 @@
import React from 'react'
import { Box, Button, Input, Text, Tooltip, useDisclosure } from "@chakra-ui/react";
import React, { useContext, useEffect, useRef, useState } from "react";
import InvestmentDocuments from "../InvestmentDocuments";
import DataTable from "../../../Components/DataTable/DataTable";
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
import { debounce } from "../../Master/Sponser/AddSponser";
import { formatDate } from "../../../Components/Functions/UTCConvertor";
import { AddIcon, DeleteIcon, DownloadIcon, EditIcon, ViewIcon } from "@chakra-ui/icons";
const KeyMerits = () => {
return (
<div>KeyMerits</div>
)
}
const { keyMerits, setKeyMerits,slideFromRight} =
useContext(GlobalStateContext);
const firstField = useRef();
const [searchTerm, setSearchTerm] = useState("");
const [isLoading, setIsLoading] = useState(true);
const [deleteAlert, setDeleteAlert] = useState(false);
const [actionId, setActionId] = useState(false);
const [mouseEntered, setMouseEntered] = useState(false);
const [mouseEnteredId, setMouseEnteredId] = useState("");
const { isOpen, onOpen, onClose } = useDisclosure();
export default KeyMerits
useEffect(() => {
// Simulate loading
const timer = setTimeout(() => {
setIsLoading(false);
}, 1500);
// Cleanup the timer on component unmount
return () => clearTimeout(timer);
}, []);
const tableHeadRow = [
"Sr.no",
"Title",
"Sub title",
"Icon",
"Action",
];
const handleUpdateStatus = debounce((id) => {
setKeyMerits((prevKeyMerits) =>
prevKeyMerits.map((keyMerits) =>
keyMerits.id === id ? { ...keyMerits, status: !keyMerits.status } : keyMerits
)
);
toast({
render: () => <ToastBox message={"Status changed succesfully.!"} />,
});
}, 300);
const filteredData = keyMerits?.filter((item) => {
// Filter by name (case insensitive)
const name = item.title;
const searchLower = searchTerm.toLowerCase();
const nameMatches = name.toLowerCase().includes(searchLower);
return nameMatches;
});
const handleDelete = () => {
const updatedKeyMerits = keyMerits.filter((keyMerits) => keyMerits.id !== actionId);
setTimeout(() => {
setSponser(updatedKeyMerits);
setDeleteAlert(false);
setIsLoading(false);
}, 100);
setIsLoading(true);
};
const extractedArray = filteredData?.map((item, index) => ({
"Sr.no": (
<Text
justifyContent={slideFromRight ? "right" : "left"}
as={"span"}
color={"teal.900"}
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
{index + 1}
</Text>
),
"Title": (
<Text
justifyContent={slideFromRight ? "right" : "left"}
as={"span"}
color={"teal.900"}
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
{item.title}
</Text>
),
"Sub title": (
<Box w={"300px"} isTruncated={true}>
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
{item.subTitle}
</Text>
</Box>
),
"Icon": (
<Text
color={'green.500'}
justifyContent={slideFromRight ? "right" : "left"}
as={"span"}
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
{item.icon}
</Text>
),
Action: (
<Box display={"flex"} justifyContent={"space-evenly"}>
<Tooltip
rounded={"sm"}
fontSize={"xs"}
label="View"
bg="#fff"
color={"green.500"}
placement="top"
>
<Button
_hover={{ color: "green.500" }}
// transition={"0.5s all"}
onClick={() => {
navigate(`view-investment/${item.id}`);
}}
color="green.300"
rounded={"sm"}
size={"xs"}
>
<ViewIcon />
</Button>
</Tooltip>
<Tooltip
rounded={"sm"}
fontSize={"xs"}
label="Edit"
bg="#fff"
color={"blue.500"}
placement="top"
>
<Button
_hover={{ color: "blue.500" }}
// transition={"0.5s all"}
color="blue.400"
rounded={"sm"}
size={"xs"}
>
<EditIcon />
</Button>
</Tooltip>
<Tooltip
rounded={"sm"}
fontSize={"xs"}
label="Delete"
bg="#fff"
color={"red.500"}
placement="top"
>
<Button
onClick={() => {
setActionId(item?.id);
setDeleteAlert(true);
}}
_hover={{ color: "red.500" }}
// transition={"0.5s all"}
color="red.300"
rounded={"sm"}
size={"xs"}
>
<DeleteIcon />
</Button>
</Tooltip>
</Box>
),
}));
return (
<Box>
<Box display={"flex"} justifyContent={"space-between"} mb={4}>
<Input
type="search"
width={300}
placeholder="Search..."
size="sm"
rounded="sm"
focusBorderColor="green.500"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
<Button
leftIcon={<AddIcon />}
onClick={onOpen}
size={"xs"}
// width={"44.5%"}
fontSize={"xs"}
rounded={"sm"}
ps={3}
pe={4}
colorScheme="green"
>
Add
</Button>
<InvestmentDocuments
isOpen={isOpen}
onClose={onClose}
firstField={firstField}
/>
</Box>
<DataTable
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}
/>
</Box>
);
};
export default KeyMerits;

View File

@@ -0,0 +1,456 @@
import React, { useContext, useEffect, useState } from "react";
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
import {
Box,
Divider,
FormControl,
FormLabel,
Heading,
Input,
Select,
Textarea,
Button,
Text,
Image,
Tabs,
TabList,
Tab,
TabPanel,
TabPanels,
Tooltip,
Switch,
useDisclosure,
} from "@chakra-ui/react";
import { useForm, Controller } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
import {
AddIcon,
CloseIcon,
DeleteIcon,
EditIcon,
ViewIcon,
WarningTwoIcon,
} from "@chakra-ui/icons";
import { TiWarning } from "react-icons/ti";
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
import { useNavigate } from "react-router-dom";
import FormField from "../../../Components/FormField";
import { v4 as uuidv4 } from "uuid";
import AddIOCharges from "../AddIOCharges";
import FormInputMain from "../../../Components/FormInputMain";
import DataTable from "../../../Components/DataTable/DataTable";
import { debounce } from "../../Master/Sponser/AddSponser";
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
import { formatDate } from "../../../Components/Functions/UTCConvertor";
import IODetails from "./IODetails";
import KeyMerits from "./KeyMerits";
import IOArtifacts from "./IOArtifacts";
import Investors from "./Investors";
import IOCashDetails from "./IOCashDetails";
import IONAVDetails from "./IONAVDetails";
import Distribution from "./Destribution";
import InvestmentDocuments from "../InvestmentDocuments";
import InvestmentDocument from "./InvestmentDocument";
const schema = yup.object().shape({
ioName: yup.string().required("Arabic name is required"),
ioNameArabic: yup.string().required("Investment Object name is required"),
discription: yup.string().required("Sponser name is required"),
discriptionArabic: yup.string().required("Arabic name is required"),
typeName: yup.string().required("Investment Object name is required"),
typeNameArabic: yup.string().required("Sponser name is required"),
sponserName: yup.string().required("Arabic name is required"),
sponserNameArabic: yup
.string()
.required("Investment Object name is required"),
holdingPeriod: yup.string().required("Sponser name is required"),
ioStartus: yup.string().required("Investment Object name is required"),
ioStartusArabic: yup.string().required("Sponser name is required"),
goalAmount: yup.string().required("Arabic name is required"),
closingDate: yup.string().required("Investment Object name is required"),
minInvestment: yup.string().required("Sponser name is required"),
maxInvestment: yup.string().required("Arabic name is required"),
expectedReturn: yup.string().required("Investment Object name is required"),
originalValue: yup.string().required("Sponser name is required"),
keyname: yup.string().required("Arabic name is required"),
keyNameArabic: yup.string().required("Investment Object name is required"),
keyDescription: yup.string().required("Sponser name is required"),
keyDescriptionArabic: yup.string().required("Sponser name is required"),
docType: yup.string().required("Sponser name is required"),
destributedAmount: yup
.number()
.required("Distributed Amount is required")
.positive("Must be a positive number"),
year: yup.string().required("Year is required"),
tenure: yup
.number()
.required("Tenure is required")
.positive("Must be a positive number"),
annualReturn: yup
.number()
.required("Annual Return is required")
.positive("Must be a positive number"),
miniInvest: yup
.number()
.required("Minimum Invest is required")
.positive("Must be a positive number"),
quaterly: yup.string().required("Quaterly is required"),
targetClose: yup.date().required("Target close date is required"),
annualyield: yup
.number()
.required("Annual Yield is required")
.positive("Must be a positive number"),
iconUpload: yup.mixed().required("Profile image is required"),
bannerImages: yup.mixed().required("Profile image is required"),
otherImage: yup.mixed().required("Profile image is required"),
docAttach: yup.mixed().required("Profile image is required"),
videos: yup.mixed().required("Profile image is required"),
});
const startYear = 2024;
const endYear = 2124;
const years = Array.from(
{ length: endYear - startYear + 1 },
(_, i) => startYear + i
).map((year) => ({ value: year, label: year }));
const EditViewIO = () => {
const navigate = useNavigate();
const { create, setCreate, sponser, setSponser, investment, setInvestment } =
useContext(GlobalStateContext);
const [bannerImageData, setBannerImageData] = useState(null);
const [otherImageData, setOtherImageData] = useState(null);
const [selectedBannerImageData, setSelectedBannerImageData] = useState(null);
const [selectedOtherImageData, setSelectedOtherImageData] = useState(null);
const [charges, setCharges] = useState([]);
const [totalCharge, setTotalCharge] = useState(0.0);
const [totalAmount, setTotalAmount] = useState(0.0);
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 {
control,
handleSubmit,
reset,
watch,
setValue,
formState: { errors },
} = useForm({
resolver: yupResolver(schema),
});
const tabs = [
{
label: "IO Details",
content: <IODetails control={control} errors={errors} />,
},
{
label: "Investment documents",
content: <InvestmentDocument control={control} errors={errors} />,
},
{
label: "Key merits",
content: <KeyMerits control={control} errors={errors} />,
},
{
label: "IO artifacts",
content: <IOArtifacts control={control} errors={errors} />,
},
{
label: "Investors",
content: <Investors control={control} errors={errors} />,
},
{
label: "IO Cash Details",
content: <IOCashDetails control={control} errors={errors} />,
},
{
label: "IO NAV Details",
content: <IONAVDetails control={control} errors={errors} />,
},
{
label: "Distribution",
content: <Distribution control={control} errors={errors} />,
},
];
useEffect(() => {
// Simulate loading
const timer = setTimeout(() => {
setIsLoading(false);
}, 1500);
// Cleanup the timer on component unmount
return () => clearTimeout(timer);
}, []);
const destributedAmount = Number(watch().destributedAmount) || 0;
useEffect(() => {
const calculateTotalCharge = () => {
const totalChargeValue = charges.reduce(
(acc, { value }) => acc + Number(value),
0
);
setTotalCharge(totalChargeValue);
};
const calculateTotalAmount = () => {
const totalChargeValue = charges.reduce(
(acc, { value }) => acc + Number(value),
0
);
setTotalAmount(destributedAmount + totalChargeValue);
};
calculateTotalCharge();
calculateTotalAmount();
}, [charges, destributedAmount]);
const onSubmit = (data) => {
// setValue("banner_image", selectedBannerImageData);
data.banner_image = selectedBannerImageData;
const updatedData = { ...data, status: "Available" };
console.log(selectedBannerImageData);
setInvestment([...investment, updatedData]);
navigate("/view-io");
reset();
};
// Extract options for the select input
const createOptions = create.map((item) => ({
value: item.sponserName,
label: item.sponserName,
}));
const handleBannerImageChange = (e) => {
const file = e.target.files[0];
setBannerImageData(file);
if (file) {
const reader = new FileReader();
reader.onloadend = () => {
setSelectedBannerImageData(reader.result);
};
reader.readAsDataURL(file);
}
};
const { isOpen, onOpen, onClose } = useDisclosure();
const firstField = React.useRef();
// Handler for file input
const handleOtherImageChange = (e) => {
const files = Array.from(e.target.files);
const newImageData = [...(otherImageData || []), ...files]; // Ensure otherImageData is an array
setOtherImageData(newImageData);
const readers = files.map((file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => {
resolve(reader.result);
};
reader.onerror = reject;
reader.readAsDataURL(file);
});
});
Promise.all(readers)
.then((results) => {
setSelectedOtherImageData([
...(selectedOtherImageData || []),
...results,
]); // Ensure selectedOtherImageData is an array
})
.catch((error) => {
console.error("Error reading files:", error);
});
};
// Function to remove a specific image
const removeOtherImage = (index) => {
const newImageData = otherImageData.filter((_, i) => i !== index);
const newSelectedImageData = selectedOtherImageData.filter(
(_, i) => i !== index
);
setOtherImageData(newImageData);
setSelectedOtherImageData(newSelectedImageData);
};
const keyMerits = [
{
label: "Name (English)",
placeHolder: " ",
name: "keyname",
type: "text",
isRequired: true,
section: " ",
width: "32.3%",
},
{
label: "Name (Arabic)",
placeHolder: " ",
name: "keyNameArabic",
type: "text",
isRequired: true,
section: " ",
width: "32.3%",
},
{
label: "Icon",
placeHolder: " ",
name: "iconUpload",
type: "fileNormal",
isRequired: true,
section: " ",
width: "32.3%",
},
{
label: "Description (English)",
placeHolder: " ",
name: "keyDescription",
type: "textarea",
isRequired: true,
section: " ",
width: "32.3%",
},
{
label: "Description (Arabic)",
placeHolder: " ",
name: "keyDescriptionArabic",
type: "textarea",
isRequired: true,
section: " ",
width: "32.3%",
},
];
const images = [
{
label: "Banner Images ",
placeHolder: " ",
name: "bannerImages",
type: "fileNormal",
isRequired: true,
section: " ",
width: "32.3%",
},
{
label: "Other Images",
placeHolder: " ",
name: "otherImage",
type: "fileNormal",
isRequired: true,
section: " ",
width: "32.3%",
},
];
const documents = [
{
label: "Type",
placeHolder: " ",
name: "docType",
type: "text",
isRequired: true,
section: " ",
width: "32.3%",
},
{
label: "Attachment",
placeHolder: " ",
name: "type",
type: "docAttach",
isRequired: true,
section: " ",
width: "32.3%",
},
];
const Videos = [
{
label: "Videos",
placeHolder: " ",
name: "videos",
type: "fileNormal",
isRequired: true,
section: " ",
width: "32.3%",
},
];
const groupedFieldsTwo = keyMerits.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
groups[section] = [];
}
groups[section].push(field);
return groups;
}, {});
const groupedFieldsThree = images.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
groups[section] = [];
}
groups[section].push(field);
return groups;
}, {});
const groupedFieldsFour = documents.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
groups[section] = [];
}
groups[section].push(field);
return groups;
}, {});
const groupedFieldsFive = Videos.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
groups[section] = [];
}
groups[section].push(field);
return groups;
}, {});
return (
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={10}>
<Tabs mt={2}>
<TabList>
{tabs.map(({ label }, index) => (
<Tab
disabled={true}
key={index}
fontSize={"sm"}
_selected={{
color: "#004118",
borderBottom: "2px solid #38a169",
}}
>
{label}
</Tab>
))}
</TabList>
<TabPanels>
{tabs.map(({ content }, index) => (
<TabPanel key={index}>{content}</TabPanel>
))}
</TabPanels>
</Tabs>
</Box>
);
};
export default EditViewIO;

View File

@@ -0,0 +1,7 @@
import React from "react";
const ViewDistribution = () => {
return <div>ViewDistribution</div>;
};
export default ViewDistribution;

View File

@@ -15,11 +15,11 @@ import {
// import error from "../assets/Error.svg"
// import robot from "../../../assets/robot.png"
import { useContext, useEffect, useState } from "react";
import { OPACITY_ON_LOAD } from "../../Layout/animations";
import InvestmentCard from "../../Components/InvestmentCard/InvestmentCard";
import GlobalStateContext from "../../Contexts/GlobalStateContext";
import Pagination from "../../Components/Pagination";
import EmptySearchList from "../../Components/EmptySearchList";
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
import InvestmentCard from "../../../Components/InvestmentCard/InvestmentCard";
import Pagination from "../../../Components/Pagination";
import EmptySearchList from "../../../Components/EmptySearchList";
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
const ExchangeRate = () => {
const [searchTerm, setSearchTerm] = useState("");
@@ -27,6 +27,9 @@ const ExchangeRate = () => {
const [isLoading, setIsLoading] = useState(true);
const [statusFilter, setStatusFilter] = useState("all");
console.log(investment);
useEffect(() => {
// Simulate loading
const timer = setTimeout(() => {
@@ -53,7 +56,7 @@ const ExchangeRate = () => {
(statusFilter === "Upcomming" && status === "Upcomming") ||
(statusFilter === "Closed" && status === "Closed");
return nameMatches && statusMatches;
return nameMatches && statusMatches;
});
const availableInvestments = filteredData.filter(
@@ -68,7 +71,7 @@ const ExchangeRate = () => {
return (
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"}>
<Tabs position="relative" variant="unstyled" mt={2} >
<Tabs position="relative" variant="unstyled" mt={2}>
<TabList>
{/* <Tab fontSize={"sm"}>All</Tab> */}
{/* <Tab fontSize={"sm"}>Available</Tab>
@@ -94,21 +97,22 @@ const ExchangeRate = () => {
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
<Box display={"flex"} gap={2} >
<Select pb={1}
className="pointer web-text-small"
width={"100px"}
rounded="sm"
size="sm"
value={statusFilter}
onChange={(e) => setStatusFilter(e.target.value)}
>
<option value="all">All</option>
<option value="Available">Available</option>
<option value="Upcomming">Upcomming</option>
<option value="Closed">Closed</option>
</Select>
<Pagination pageCount={false} totalItems={50} />
<Box display={"flex"} gap={2}>
<Select
pb={1}
className="pointer web-text-small"
width={"100px"}
rounded="sm"
size="sm"
value={statusFilter}
onChange={(e) => setStatusFilter(e.target.value)}
>
<option value="all">All</option>
<option value="Available">Available</option>
<option value="Upcomming">Upcomming</option>
<option value="Closed">Closed</option>
</Select>
<Pagination pageCount={false} totalItems={50} />
</Box>
</Box>
{filteredData?.length === 0 ? (

View File

@@ -18,8 +18,8 @@ import {
useToast,
} from "@chakra-ui/react";
import React, { useContext, useEffect, useState } from "react";
import { OPACITY_ON_LOAD } from "../../Layout/animations";
import DataTable from "../../Components/DataTable/DataTable";
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
import DataTable from "../../../Components/DataTable/DataTable";
import { HiDotsVertical } from "react-icons/hi";
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
import {
@@ -31,10 +31,10 @@ import {
EmailIcon,
ViewIcon,
} from "@chakra-ui/icons";
import Pagination from "../../Components/Pagination";
import GlobalStateContext from "../../Contexts/GlobalStateContext";
import CustomAlertDialog from "../../Components/CustomAlertDialog";
import ToastBox from "../../Components/ToastBox";
import Pagination from "../../../Components/Pagination";
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
import ToastBox from "../../../Components/ToastBox";
// import { debounce } from "./AddIOCharges";
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
@@ -50,6 +50,8 @@ const ViewIOTable = () => {
const [mouseEntered, setMouseEntered] = useState(false);
const [mouseEnteredId, setMouseEnteredId] = useState("");
console.log(viewIO);
useEffect(() => {
// Simulate loading
const timer = setTimeout(() => {

View File

@@ -0,0 +1,9 @@
import React from 'react'
const ViewIOartifacts = () => {
return (
<div>ViewIOartifacts</div>
)
}
export default ViewIOartifacts

View File

@@ -0,0 +1,9 @@
import React from 'react'
const ViewIOcash = () => {
return (
<div>ViewIOcash</div>
)
}
export default ViewIOcash

View File

@@ -0,0 +1,84 @@
import {
Box,
Button,
Input,
Tab,
TabList,
TabPanel,
TabPanels,
Tabs,
Text,
} from "@chakra-ui/react";
import { useNavigate, useParams } from "react-router-dom";
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
import { useContext, useEffect, useState } from "react";
import FormInputView from "../../../Components/FormInputView";
import { useForm } from "react-hook-form"; // assuming react-hook-form is used
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
import { ArrowBackIcon } from "@chakra-ui/icons";
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
import ViewIOdataHeader from "./ViewIOdataHeader";
import ViewIOdetails from "./ViewIOdetails";
import ViewIOdocs from "./ViewIOdocs";
import ViewKeyMerits from "./ViewKeyMerits";
import ViewIOartifacts from "./ViewIOartifacts";
import ViewInvestors from "./ViewInvestors";
import ViewIOcash from "./ViewIOcash";
import ViewIOnav from "./ViewIOnav";
import ViewDistribution from "./ViewDistribution";
const ViewIOdata = () => {
const [isEditing, setIsEditing] = useState(false);
const navigate = useNavigate();
const tabs = [
{ label: "IO Details", content: <ViewIOdetails /> },
{ label: "Investment documents", content: <ViewIOdocs /> },
{ label: "Key merits", content: <ViewKeyMerits /> },
{ label: "IO artifacts", content: <ViewIOartifacts /> },
{ label: "Investors", content: <ViewInvestors /> },
{ label: "IO Cash Details", content: <ViewIOcash /> },
{ label: "IO NAV Details", content: <ViewIOnav /> },
{ label: "Distribution", content: <ViewDistribution /> },
];
return (
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
<Box paddingInline={"12px"}>
<span
onClick={() => navigate(-1)}
style={{ fontSize: "15px", cursor: "pointer" }}
>
<ArrowBackIcon cursor={"pointer"} /> Back
</span>
<ViewIOdataHeader />
</Box>
<Tabs mt={4}>
<TabList>
{tabs.map(({ label }, index) => (
<Tab
disabled={true}
key={index}
fontSize={"sm"}
_selected={{
color: "#004118",
borderBottom: "2px solid #38a169",
}}
>
{label}
</Tab>
))}
</TabList>
<TabPanels>
{tabs.map(({ content }, index) => (
<TabPanel key={index}>{content}</TabPanel>
))}
</TabPanels>
</Tabs>
</Box>
);
};
export default ViewIOdata;

View File

@@ -1,5 +1,5 @@
import { Box, Image, Text } from "@chakra-ui/react";
import header from "../../../src/assets/IOheader.png";
import header from "../../../assets/IOheader.png";
const ViewIOdataHeader = () => {
return (

View File

@@ -0,0 +1,124 @@
import { Box } from "@chakra-ui/react";
import React, { useContext } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { useForm } from "react-hook-form";
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
import DataTable from "../../../Components/DataTable/DataTable";
import FormInputView from "../../../Components/FormInputView";
const ViewIOdetails = () => {
const params = useParams();
const { viewIO } = useContext(GlobalStateContext);
console.log(viewIO);
const { reset } = useForm(); // assuming react-hook-form
const id = params?.id;
const foundObject = viewIO?.find(
(item) => item?.id.toString() === id.toString()
);
const formFields = [
{
label: "IO Name (English)",
value: foundObject.DealName,
width: "49%",
section: "",
},
{
label: "IO Name (Arabic)",
value: foundObject.SponsorName,
width: "49%",
section: "",
},
{
label: "Description (English)",
value: foundObject.IOstatus,
width: "49%",
section: "",
},
{
label: "Description (Arabic)",
value: foundObject.IOstatus,
width: "49%",
section: "",
},
{
label: "Investment Type (English)",
value: foundObject.DealName,
width: "49%",
section: "",
},
{
label: "Investment Type (Arabic)",
value: foundObject.DealID,
width: "49%",
section: "",
},
{
label: "Sponser Name (English)",
value: foundObject.IOstatus,
width: "49%",
section: "",
},
{
label: "Goal Amount (English)",
value: foundObject.IOstatus,
width: "49%",
section: "",
},
{
label: "Minimum Investment Amount (English)",
value: foundObject.IOstatus,
width: "32.3%",
section: "",
},
{
label: "Maximum Investment Amount (English)",
value: foundObject.IOstatus,
width: "32.3%",
section: "",
},
{
label: "Holding Period (English)",
value: foundObject.IOstatus,
width: "32.3%",
section: "",
},
{
label: "Expected Return Estimated (English)",
value: foundObject.IOstatus,
width: "32.3%",
section: "",
},
{
label: "Closing Date (English)",
value: foundObject.IOstatus,
width: "32.3%",
section: "",
},
{
label: "IO Status (English)",
value: foundObject.IOstatus,
width: "32.3%",
section: "",
},
];
const groupedFields = formFields.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
groups[section] = [];
}
groups[section].push(field);
return groups;
}, {});
if (!foundObject) {
return <Box>Loading...</Box>;
}
return <FormInputView groupedFields={groupedFields} />;
};
export default ViewIOdetails;

View File

@@ -0,0 +1,7 @@
import React from "react";
const ViewIOdocs = () => {
return <div>ViewIOdocs</div>;
};
export default ViewIOdocs;

View File

@@ -0,0 +1,9 @@
import React from 'react'
const ViewIOnav = () => {
return (
<div>ViewIOnav</div>
)
}
export default ViewIOnav

View File

@@ -0,0 +1,9 @@
import React from 'react'
const ViewInvestors = () => {
return (
<div>ViewInvestors</div>
)
}
export default ViewInvestors

View File

@@ -0,0 +1,9 @@
import React from 'react'
const ViewKeyMerits = () => {
return (
<div>ViewKeyMerits</div>
)
}
export default ViewKeyMerits

View File

@@ -1,225 +0,0 @@
import {
Box,
Button,
Input,
Tab,
TabList,
TabPanel,
TabPanels,
Tabs,
Text,
} from "@chakra-ui/react";
import { useNavigate, useParams } from "react-router-dom";
import GlobalStateContext from "../../Contexts/GlobalStateContext";
import { useContext, useEffect, useState } from "react";
import FormInputView from "../../Components/FormInputView";
import { useForm } from "react-hook-form"; // assuming react-hook-form is used
import { OPACITY_ON_LOAD } from "../../Layout/animations";
import { ArrowBackIcon } from "@chakra-ui/icons";
import DataTable from "../../Components/DataTable/DataTable";
import CustomAlertDialog from "../../Components/CustomAlertDialog";
import FormInputMain from "../../Components/FormInputMain";
import InvestmentDocuments from "./InvestmentDocuments";
import ViewIOdataHeader from "./ViewIOdataHeader";
const ViewIOdata = () => {
const navigate = useNavigate();
const params = useParams();
const { viewIO } = useContext(GlobalStateContext);
const { reset } = useForm(); // assuming react-hook-form
const id = params?.id;
const foundObject = viewIO.find(
(item) => item?.id.toString() === id.toString()
);
if (!foundObject) {
return <Box>Loading...</Box>;
}
const formFields = [
{
label: "IO Name (English)",
value: foundObject.DealName,
width: "49%",
section: "",
},
{
label: "IO Name (Arabic)",
value: foundObject.SponsorName,
width: "49%",
section: "",
},
{
label: "Description (English)",
value: foundObject.IOstatus,
width: "49%",
section: "",
},
{
label: "Description (Arabic)",
value: foundObject.IOstatus,
width: "49%",
section: "",
},
{
label: "Investment Type (English)",
value: foundObject.DealName,
width: "49%",
section: "",
},
{
label: "Investment Type (Arabic)",
value: foundObject.DealID,
width: "49%",
section: "",
},
{
label: "Sponser Name (English)",
value: foundObject.IOstatus,
width: "49%",
section: "",
},
{
label: "Goal Amount (English)",
value: foundObject.IOstatus,
width: "49%",
section: "",
},
{
label: "Minimum Investment Amount (English)",
value: foundObject.IOstatus,
width: "32.3%",
section: "",
},
{
label: "Maximum Investment Amount (English)",
value: foundObject.IOstatus,
width: "32.3%",
section: "",
},
{
label: "Holding Period (English)",
value: foundObject.IOstatus,
width: "32.3%",
section: "",
},
{
label: "Expected Return Estimated (English)",
value: foundObject.IOstatus,
width: "32.3%",
section: "",
},
{
label: "Closing Date (English)",
value: foundObject.IOstatus,
width: "32.3%",
section: "",
},
{
label: "IO Status (English)",
value: foundObject.IOstatus,
width: "32.3%",
section: "",
},
];
const groupedFields = formFields.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
groups[section] = [];
}
groups[section].push(field);
return groups;
}, {});
return (
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
<Box paddingInline={"12px"}>
<span
onClick={() => navigate(-1)}
style={{ fontSize: "15px", cursor: "pointer" }}
>
<ArrowBackIcon cursor={"pointer"} /> Back
</span>
<ViewIOdataHeader />
</Box>
<Tabs mt={4}>
<TabList>
<Tab
fontSize={"sm"}
_selected={{ color: "#004118", borderBottom: "2px solid #38a169" }}
>
IO Details
</Tab>
<Tab
fontSize={"sm"}
_selected={{ color: "#004118", borderBottom: "2px solid #38a169" }}
>
Investment Documents
</Tab>
<Tab
fontSize={"sm"}
_selected={{ color: "#004118", borderBottom: "2px solid #38a169" }}
>
Key Merits
</Tab>
<Tab
fontSize={"sm"}
_selected={{ color: "#004118", borderBottom: "2px solid #38a169" }}
>
IO artifacts
</Tab>
<Tab
fontSize={"sm"}
_selected={{ color: "#004118", borderBottom: "2px solid #38a169" }}
>
Investors
</Tab>
<Tab
fontSize={"sm"}
_selected={{ color: "#004118", borderBottom: "2px solid #38a169" }}
>
IO Cash detail
</Tab>
<Tab
fontSize={"sm"}
_selected={{ color: "#004118", borderBottom: "2px solid #38a169" }}
>
IO NAV detail
</Tab>
<Tab
fontSize={"sm"}
_selected={{ color: "#004118", borderBottom: "2px solid #38a169" }}
>
Distribution
</Tab>
</TabList>
<TabPanels>
<TabPanel>
<FormInputView groupedFields={groupedFields} />
</TabPanel>
<TabPanel>
<FormInputView groupedFields={groupedFields} />
</TabPanel>
<TabPanel>
<FormInputView groupedFields={groupedFields} />
</TabPanel>
<TabPanel>
<FormInputView groupedFields={groupedFields} />
</TabPanel>
<TabPanel>
<FormInputView groupedFields={groupedFields} />
</TabPanel>
<TabPanel></TabPanel>
</TabPanels>
</Tabs>
</Box>
);
};
export default ViewIOdata;

View File

@@ -10,10 +10,10 @@ import Users from "../Pages/Admin/Users";
import CreateIO from "../Pages/IO_Management/CreateIO/CreateIO";
// import CreateIO from "../Pages/IO_Management/InputComponents";
import Create from "../Pages/IO_Management/InputComponents";
import ViewIO from "../Pages/IO_Management/ViewIO";
import View from "../Pages/IO_Management/ViewIO";
import ViewIOTable from "../Pages/IO_Management/ViewIOTable";
import ViewIOdata from "../Pages/IO_Management/ViewIOdata";
import ViewIO from "../Pages/IO_Management/ViewIO/ViewIO";
import View from "../Pages/IO_Management/ViewIO/ViewIO";
import ViewIOTable from "../Pages/IO_Management/ViewIO/ViewIOTable";
import ViewIOdata from "../Pages/IO_Management/ViewIO/ViewIOdata";
import InvestorPendingRequest from "../Pages/InvestorUpgrade/InvestorRequest";
import UpgradeHistory from "../Pages/InvestorUpgrade/UpgradeHistory";
import upgradeHistory from "../Pages/InvestorUpgrade/UpgradeHistory";