diff --git a/src/Components/FormField.jsx b/src/Components/FormField.jsx
index 7005683..e11e1f3 100644
--- a/src/Components/FormField.jsx
+++ b/src/Components/FormField.jsx
@@ -1,97 +1,219 @@
-import { FormControl, FormLabel, Input, Textarea, Select, Checkbox, RadioGroup, Radio, Stack } from '@chakra-ui/react';
-import React from 'react';
+import { FormControl, FormLabel, Input, Textarea, Select, Checkbox, RadioGroup, Radio, Stack, Box, Heading, FormHelperText, Kbd } from '@chakra-ui/react';
import { Controller } from 'react-hook-form';
import { TiWarning } from 'react-icons/ti';
+import { motion } from 'framer-motion';
const FormField = ({
- label,
- control,
- name,
- type = "text",
- options = [],
- errors,
- isRequired,
- arabic,
- ...props
- }) => (
-
- {label}
- {
- switch (type) {
- case 'textarea':
- return (
-
- );
- case 'select':
- return (
-
- );
- case 'checkbox':
- return (
-
- {label}
-
- );
- case 'radio':
- return (
-
-
- {options.map((option, index) => (
-
- {option.label}
-
- ))}
+
+
+
+ Drop images here
+
+
+ or click to upload
+
+
-
- );
- default:
- return (
+
{
+ field.onChange(e);
+ handleImageChange(e);
+ }}
+ onDrop={(e) => {
+ field.onChange(e);
+ handleImageChange(e);
+ }}
/>
- );
- }
- }}
- />
- {errors[name] && (
-
- {errors[name].message}
-
- )}
-
- );
+
+
+ );
+ }else if (type === 'fileNormal') {
+ return (
+ <>
+ {
+ field.onChange(e);
+ handleImageChange(e);
+ }}
+ />
+ {multiple && (
+
+ You can select multiple images using{" "}
+
+ ctrl + select
+ .
+
+ )}
+ >
+ );
+ } else {
+ return (
+
+ );
+ }
+ }}
+ />
+ {errors[name] && (
+
+ {errors[name].message}
+
+ )}
+ {helperText &&
+ {helperText}
+ }
+ {type === 'file' && (
+
+ Maximum limit of image is 10MB.
+
+ )}
+
+);
export default FormField;
diff --git a/src/Components/Pagination.jsx b/src/Components/Pagination.jsx
index 8f0480d..3f3debb 100644
--- a/src/Components/Pagination.jsx
+++ b/src/Components/Pagination.jsx
@@ -36,6 +36,7 @@ const Pagination = ({ totalItems, itemsPerPageOptions = [ 10, 15] }) => {
{
))}
}
@@ -61,6 +63,7 @@ const Pagination = ({ totalItems, itemsPerPageOptions = [ 10, 15] }) => {
{displayRange.start} - {displayRange.end} of {totalItems}
}
size={'sm'}
rounded="sm"
diff --git a/src/Pages/IO_Management/CreateIO.jsx b/src/Pages/IO_Management/CreateIO.jsx
index 0e8d424..79c8354 100644
--- a/src/Pages/IO_Management/CreateIO.jsx
+++ b/src/Pages/IO_Management/CreateIO.jsx
@@ -1,4 +1,4 @@
-import React, { useContext } from "react";
+import React, { useContext, useState } from "react";
import { OPACITY_ON_LOAD } from "../../Layout/animations";
import {
Box,
@@ -11,11 +11,12 @@ import {
Textarea,
Button,
Text,
+ Image,
} from "@chakra-ui/react";
import { useForm, Controller } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
-import { WarningTwoIcon } from "@chakra-ui/icons";
+import { AddIcon, CloseIcon, WarningTwoIcon } from "@chakra-ui/icons";
import { TiWarning } from "react-icons/ti";
import GlobalStateContext from "../../Contexts/GlobalStateContext";
import { useNavigate } from "react-router-dom";
@@ -23,30 +24,66 @@ import FormField from "../../Components/FormField";
import { v4 as uuidv4 } from "uuid";
const schema = yup.object().shape({
+ ioNameArabic: yup.string().required("Arabic name is required"),
+ ioName: yup.string().required("Investment Object name is required"),
sponserName: yup.string().required("Sponser name is required"),
- mobileNo: yup.string().required("Mobile no is required"),
- sponserAddress: yup.string().required("Sponser address is required"),
-
- bankName: yup.string().required("Bank Name is required"),
- accountNumber: yup.string().required("Account Number is required"),
- swiftCode: yup.string().required("SWIFT/BIC Code is required"),
- bankEmail: yup.string().email("Invalid email format"),
-
- // routingNumber: yup.string().required("Routing Number is required"),
- // iban: yup.string().required("IBAN is required"),
- // accountType: yup.string().required("Account Type is required"),
- // bankPhoneNumber: yup.string().required("Bank Phone Number is required"),
- // bankBranch: yup.string().required("Bank Branch is required"),
- // branchAddress: yup.string().required("Branch Address is required"),
- // ifscCode: yup.string().required("IFSC Code is required"),
- // accountHolderName: yup.string().required("Account Holder's 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"),
+ banner_image: yup.mixed().required("Profile image is required"),
+ // .test(
+ // 'fileSize',
+ // 'File size is too large',
+ // value => value && value.size <= 10485760 // 10MB
+ // )
+ // .test(
+ // 'fileType',
+ // 'Unsupported file format',
+ // value => value && ['image/jpg', 'image/jpeg', 'image/gif', 'image/png'].includes(value.type)
+ // ),
+ other_image: yup.mixed().required("Profile image is required"),
+ // .test(
+ // 'fileSize',
+ // 'File size is too large',
+ // value => value && value.size <= 10485760 // 10MB
+ // )
+ // .test(
+ // 'fileType',
+ // 'Unsupported file format',
+ // value => value && ['image/jpg', 'image/jpeg', 'image/gif', 'image/png'].includes(value.type)
+ // ),
});
-
+const startYear = 2024;
+const endYear = 2124;
+// const years = Array.from({ length: endYear - startYear + 1 }, (_, i) => startYear + i);
+const years = Array.from({ length: 2124 - 2024 + 1 }, (_, i) => 2024 + i).map(
+ (year) => ({ value: year, label: year })
+);
export function debounce(func, delay) {
let debounceTimer;
- return function(...args) {
+ return function (...args) {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => func.apply(this, args), delay);
};
@@ -54,41 +91,92 @@ export function debounce(func, delay) {
const CreateIO = () => {
const navigate = useNavigate();
const { sponser, setSponser } = useContext(GlobalStateContext);
+ const [bannerImageData, setBannerImageData] = useState(null);
+ const [otherImageData, setOtherImageData] = useState(null);
+
+ const [selectedBannerImageData, setSelectedBannerImageData] = useState(null);
+ const [selectedOtherImageData, setSelectedOtherImageData] = useState(null);
+
+
const {
control,
handleSubmit,
+ reset,
formState: { errors },
} = useForm({
resolver: yupResolver(schema),
+ // defaultValues: {
+ // destributedAmount: 0,
+ // tenure: 0,
+ // annualReturn: 0,
+ // miniInvest: 0,
+ // annualyield: 0,
+ // },
});
console.log(errors);
const onSubmit = (data) => {
- setSponser([
- {
- ...data,
- status: true,
- id: uuidv4(),
- createdAt: new Date().toISOString(),
- },
- ...sponser,
- ]);
- navigate("/sponser");
+ console.log(data?.targetClose);
+ navigate("/view-io");
+ reset();
};
+ // Extract options for the select input
+ const sponserOptions = sponser.map((item) => ({
+ value: item.sponserName,
+ label: item.sponserName,
+ }));
- // Extract options for the select input
- const sponserOptions = sponser.map(item => ({
- value: item.id,
- 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);
+ }
+ };
+// 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);
+};
return (
-
-
+
+ {/* */}
);
};
diff --git a/src/Pages/IO_Management/ViewIO.jsx b/src/Pages/IO_Management/ViewIO.jsx
index 4c8fb4e..e12841c 100644
--- a/src/Pages/IO_Management/ViewIO.jsx
+++ b/src/Pages/IO_Management/ViewIO.jsx
@@ -2,6 +2,7 @@ import {
Box,
Image,
Input,
+ Select,
Skeleton,
Tab,
TabIndicator,
@@ -24,6 +25,7 @@ const ExchangeRate = () => {
const [searchTerm, setSearchTerm] = useState("");
const { investment, setInvestment } = useContext(GlobalStateContext);
const [isLoading, setIsLoading] = useState(true);
+ const [statusFilter, setStatusFilter] = useState("all");
useEffect(() => {
// Simulate loading
@@ -42,15 +44,16 @@ const ExchangeRate = () => {
const nameMatches = name.toLowerCase().includes(searchLower);
// Filter by status
- // const status = item.status;
+ const status = item.status;
// const statusLower = status ? "active" : "inactive";
- // const statusMatches =
- // statusFilter === "all" ||
- // (statusFilter === "active" && status === true) ||
- // (statusFilter === "inactive" && status === false);
+ const statusMatches =
+ statusFilter === "all" ||
+ (statusFilter === "Available" && status === "Available") ||
+ (statusFilter === "Upcomming" && status === "Upcomming") ||
+ (statusFilter === "Closed" && status === "Closed");
- return nameMatches;
+ return nameMatches && statusMatches;
});
const availableInvestments = filteredData.filter(
@@ -91,7 +94,22 @@ const ExchangeRate = () => {
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
+
+ setStatusFilter(e.target.value)}
+ >
+
+
+
+
+
+
{filteredData?.length === 0 ? (
@@ -166,7 +184,11 @@ const ExchangeRate = () => {
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
+
+
+
+
{closedInvestments?.length === 0 ? (