From 85e3c3412068773154605d1a4908b7ecf4679e2a Mon Sep 17 00:00:00 2001 From: YasinShaikh123 <123150391+YasinShaikh123@users.noreply.github.com> Date: Tue, 19 Nov 2024 19:19:45 +0530 Subject: [PATCH] update transaction status modal --- src/Pages/Fawateer/CreateRequest.jsx | 287 +++++++---- .../CreateIO/IOCashDetails/Approved.jsx | 26 +- .../CreateIO/IOCashDetails/Pending.jsx | 2 +- .../CreateIO/IOCashDetails/Rejected.jsx | 2 +- .../CreateIO/IONAVDetails/Approved.jsx | 2 +- .../CreateIO/IONAVDetails/Pending.jsx | 31 +- .../CreateIO/IONAVDetails/Rejected.jsx | 2 +- .../ApproveDistrubationModal.jsx | 178 +++++++ .../IOTransaction/ApproveInvestedModal.jsx | 176 +++++++ .../CreateIO/IOTransaction/Approved.jsx | 22 +- .../ApprovedCancelTransaction.jsx | 160 ++++++ .../CreateIO/IOTransaction/ApprovedExit.jsx | 174 +++++++ .../CreateIO/IOTransaction/Pending.jsx | 476 +++++++++--------- .../CreateIO/IOTransaction/Rejected.jsx | 4 +- .../IOTransaction/RequestRejectModal.jsx | 44 +- .../IOTransaction/ViewAmountInvested.jsx | 304 +++++++++++ .../CreateIO/IOTransaction/ViewCancel.jsx | 363 +++++++++++++ .../ViewDistributionInvestor.jsx | 267 ++++++++++ .../CreateIO/IOTransaction/ViewExit.jsx | 324 ++++++++++++ .../IO_Management/CreateIO/Investors.jsx | 2 +- .../ViewIO/HeaderModal/AmountInvested.jsx | 2 +- src/Services/io.service.js | 45 +- 22 files changed, 2510 insertions(+), 383 deletions(-) create mode 100644 src/Pages/IO_Management/CreateIO/IOTransaction/ApproveDistrubationModal.jsx create mode 100644 src/Pages/IO_Management/CreateIO/IOTransaction/ApproveInvestedModal.jsx create mode 100644 src/Pages/IO_Management/CreateIO/IOTransaction/ApprovedCancelTransaction.jsx create mode 100644 src/Pages/IO_Management/CreateIO/IOTransaction/ApprovedExit.jsx create mode 100644 src/Pages/IO_Management/CreateIO/IOTransaction/ViewAmountInvested.jsx create mode 100644 src/Pages/IO_Management/CreateIO/IOTransaction/ViewCancel.jsx create mode 100644 src/Pages/IO_Management/CreateIO/IOTransaction/ViewDistributionInvestor.jsx create mode 100644 src/Pages/IO_Management/CreateIO/IOTransaction/ViewExit.jsx diff --git a/src/Pages/Fawateer/CreateRequest.jsx b/src/Pages/Fawateer/CreateRequest.jsx index 3bd9e39..0529ef9 100644 --- a/src/Pages/Fawateer/CreateRequest.jsx +++ b/src/Pages/Fawateer/CreateRequest.jsx @@ -1,17 +1,27 @@ import React, { useState } from "react"; import { OPACITY_ON_LOAD } from "../../Layout/animations"; -import { Box, Button, HStack, Input, InputGroup, InputRightAddon, Textarea, useDisclosure, Image, Icon, VStack, Text, useToast } from "@chakra-ui/react"; import { - FormControl, - FormLabel, - FormHelperText, + Box, + Button, + HStack, + Input, + InputGroup, + InputRightAddon, + Textarea, + useDisclosure, + Image, + Icon, + VStack, + Text, + useToast, } from "@chakra-ui/react"; +import { FormControl, FormLabel, FormHelperText } from "@chakra-ui/react"; import { DeleteIcon, Search2Icon } from "@chakra-ui/icons"; import SelectInvestorModal from "./SelectInvestorModal"; import { Controller, useForm } from "react-hook-form"; // Import useForm import { yupResolver } from "@hookform/resolvers/yup"; // Import resolver for Yup import * as Yup from "yup"; // Import Yup for validation -import { motion } from 'framer-motion'; // Import Framer Motion for animations +import { motion } from "framer-motion"; // Import Framer Motion for animations import { bytesToMB } from "../../Constants/Constants"; import { useCreateFawateerRequestMutation } from "../../Services/fawateer.maker.service"; import ToastBox from "../../Components/ToastBox"; @@ -23,60 +33,66 @@ const validationSchema = Yup.object().shape({ investorName: Yup.string().required("Investor name is required"), clientId: Yup.string().required("Client ID is required"), transaction_date: Yup.date() - .required('Date is required') - .transform((value, originalValue) => { - return originalValue === "" ? null : value; // Convert empty strings to null - }) - .typeError('Please enter a valid date').max(new Date(), "Date cannot be in the future"), + .required("Date is required") + .transform((value, originalValue) => { + return originalValue === "" ? null : value; // Convert empty strings to null + }) + .typeError("Please enter a valid date") + .max(new Date(), "Date cannot be in the future"), transaction_amount: Yup.number() - .required("Transaction amount is required") - .transform((value, originalValue) => originalValue === "" ? null : value) // Convert empty strings to null - .typeError('Transaction amount must be a number') // Custom error message if it's not a number - .positive('Transaction amount must be greater than zero'), + .required("Transaction amount is required") + .transform((value, originalValue) => (originalValue === "" ? null : value)) // Convert empty strings to null + .typeError("Transaction amount must be a number") // Custom error message if it's not a number + .positive("Transaction amount must be greater than zero"), spportFile_path: Yup.mixed().required("Support file is required"), makerComment: Yup.string(), }); const CreateRequest = () => { - const toast = useToast() - const navigate=useNavigate() + const toast = useToast(); + const navigate = useNavigate(); const { isOpen, onOpen, onClose } = useDisclosure(); const [selectedInvestor, setSelectorInvestor] = useState({}); const [filePreview, setFilePreview] = useState(null); // State for previewing the file const [fileType, setFileType] = useState(null); // State to store file type for conditional rendering - const[ isLoading, setIsLoading ] = useState(false) - const [id, setId ] = useState(null) + const [isLoading, setIsLoading] = useState(false); + const [id, setId] = useState(null); // Initialize useForm with the resolver for Yup validation - const {control, register, handleSubmit, setValue,reset, formState: { errors } } = useForm({ + const { + control, + register, + handleSubmit, + setValue, + reset, + formState: { errors }, + } = useForm({ resolver: yupResolver(validationSchema), }); - - const [ creatFawaateerRequest ] = useCreateFawateerRequestMutation() - + const [creatFawaateerRequest] = useCreateFawateerRequestMutation(); const onSubmit = async (data) => { console.log(data); - setIsLoading(true) - + setIsLoading(true); + // Convert data to FormData const formData = new FormData(); - - // Append each field from the data object to the FormData - Object.keys(data).forEach((key) => { - if (key === "spportFile_path" && data[key] instanceof FileList) { - // Append the first file from FileList (assuming single file input) - formData.append(key, data[key][0]); // Append the file - } else { - formData.append(key, data[key]); // Append other fields - } - }); - + + // Append each field from the data object to the FormData + Object.keys(data).forEach((key) => { + if (key === "spportFile_path" && data[key] instanceof FileList) { + // Append the first file from FileList (assuming single file input) + formData.append(key, data[key][0]); // Append the file + } else { + formData.append(key, data[key]); // Append other fields + } + }); + try { // Make the API call with formData const res = await creatFawaateerRequest({ data: formData, id }); - + if (res?.error) { toast({ render: () => ( @@ -84,39 +100,35 @@ const CreateRequest = () => { ), }); setIsLoading(false); - reset() - return + reset(); + return; } else if (res?.data) { toast({ - render: () => ( - - ), + render: () => , }); setIsLoading(false); - navigate('/fawateer-history') - return + navigate("/fawateer-history"); + return; } else { toast({ render: () => ( - + ), }); setIsLoading(false); - return + return; } - } catch (error) { console.error("Error:", error); toast({ render: () => ( - + ), }); setIsLoading(false); - return + return; } }; - // Handle file change and preview const handleFileChange = (e) => { @@ -137,15 +149,12 @@ const CreateRequest = () => { } }; - - - return ( { onSubmit={handleSubmit(onSubmit)} > {/* Investor Name Field */} - + Investor name - + { {...register("investorName")} _placeholder={{ fontSize: "sm" }} /> - + Search - {errors.investorName?.message} + + {errors.investorName?.message} + {/* Client ID Field */} @@ -193,7 +220,13 @@ const CreateRequest = () => { placeholder={"Client ID"} {...register("clientId")} /> - {errors.clientId?.message} + + {errors.clientId?.message} + {/* Date Field */} @@ -208,10 +241,21 @@ const CreateRequest = () => { fontSize={"sm"} rounded={"sm"} type={"date"} - max={new Date().toISOString().split("T")[0]} // Disable future dates - {...register("transaction_date")} + max={new Date().toLocaleDateString("en-CA")} // Ensures max is in local timezone + {...register("transaction_date", { + setValueAs: (value) => { + // Convert date string to local timezone Date object + return value ? new Date(value) : undefined; + }, + })} /> - {errors.transaction_date?.message} + + {errors.transaction_date?.message} + {/* Amount Field */} @@ -220,19 +264,35 @@ const CreateRequest = () => { Amount (BHD) ( - - )} - /> - + name="transaction_amount" + control={control} + render={({ field }) => ( + + )} + /> + {errors.transaction_amount?.message} - + {/* Support File Field with Preview */} - + Support file @@ -249,7 +309,13 @@ const CreateRequest = () => { {...register("spportFile_path")} // onChange={handleFileChange} /> - {errors.spportFile_path?.message} + + {errors.spportFile_path?.message} + {/* Animated Preview */} {filePreview && fileType?.type.startsWith("image/") && ( @@ -259,14 +325,55 @@ const CreateRequest = () => { transition={{ duration: 0.5 }} style={{ marginTop: "10px" }} > - - File preview - setFilePreview(null)} className="link" rounded={'md'} color={'red.700'} cursor={'pointer'} p={1.5} position={'absolute'} top={0} right={0} as={DeleteIcon} boxSize={7} /> - - File Name: {fileType?.name} - File Size: {bytesToMB(fileType?.size)} Mb - File Type: {fileType?.type} - + + File preview + setFilePreview(null)} + className="link" + rounded={"md"} + color={"red.700"} + cursor={"pointer"} + p={1.5} + position={"absolute"} + top={0} + right={0} + as={DeleteIcon} + boxSize={7} + /> + + + File Name:{" "} + + {" "} + {fileType?.name} + + + + File Size:{" "} + + {" "} + {bytesToMB(fileType?.size)} Mb + + + + File Type:{" "} + + {" "} + {fileType?.type} + + @@ -274,7 +381,7 @@ const CreateRequest = () => { {/* Description Field */} - + Description @@ -287,12 +394,18 @@ const CreateRequest = () => { placeholder={"Description"} {...register("makerComment")} /> - {errors.makerComment?.message} + + {errors.makerComment?.message} + {/* Submit Button */} - - */} {IODetails?.isInvestedAmount ? ( - localStorage?.getItem('role') ==="Maker"&& - ) : null} + {IODetails?.isInvestedAmount + ? localStorage?.getItem("role") === "Maker" && ( + + ) + : null} diff --git a/src/Pages/IO_Management/CreateIO/IONAVDetails/Rejected.jsx b/src/Pages/IO_Management/CreateIO/IONAVDetails/Rejected.jsx index 351e5dc..8b69230 100644 --- a/src/Pages/IO_Management/CreateIO/IONAVDetails/Rejected.jsx +++ b/src/Pages/IO_Management/CreateIO/IONAVDetails/Rejected.jsx @@ -82,7 +82,7 @@ import AddNavDetails from "./AddNavDetails"; "Last Nav Update", "Investment Closed", "Comments", - // "Updated By", + "Updated By", ]; const extractedArray = filteredData?.map((item, index) => ({ diff --git a/src/Pages/IO_Management/CreateIO/IOTransaction/ApproveDistrubationModal.jsx b/src/Pages/IO_Management/CreateIO/IOTransaction/ApproveDistrubationModal.jsx new file mode 100644 index 0000000..c54738d --- /dev/null +++ b/src/Pages/IO_Management/CreateIO/IOTransaction/ApproveDistrubationModal.jsx @@ -0,0 +1,178 @@ +import { + Box, + Button, + FormControl, + FormHelperText, + FormLabel, + Input, + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, + Text, + Textarea, + useDisclosure, + useToast, + } from "@chakra-ui/react"; + import React, { useEffect, useState } from "react"; + import * as yup from "yup"; + import { yupResolver } from "@hookform/resolvers/yup"; + import { useForm } from "react-hook-form"; + import ToastBox from "../../../../Components/ToastBox"; + import { useApproveDistributedMutation } from "../../../../Services/io.service"; + + export const conformModalSchema = yup.object().shape({ + // checkerComment: yup.string().required("Comment is required") + // .max(50, "Investment name cannot be more than 50 characters"), + checkerComment: yup + .string() + .required("Comment is required") + .max(200, "Approve Comment cannot be more than 200 characters"), + }); + + const ApproveDistrubationModal = ({ isOpen, onClose, firstField ,id}) => { + const [isBtnLoading , setIsBtnLoading] = useState(false) + + const toast = useToast() + + + + const { + register, + reset, + watch, + handleSubmit, + formState: { errors }, + } = useForm({ + resolver: yupResolver(conformModalSchema), + }); + + const [ approveDistributed ] = useApproveDistributedMutation() + + + const onSubmit = async(data) => { + setIsBtnLoading(true) + try { + const res = await approveDistributed({data,id}) + if (res?.error) { + toast({ + render: () => ( + + ), + }); + setIsBtnLoading(false) + }else if(res?.data){ + toast({ + render: () => ( + + ), + }); + onClose() + setIsBtnLoading(false) + }else{ + toast({ + render: () => ( + + ), + }); + setIsBtnLoading(false) + } + } catch (error) { + + } + }; + + const handleFileChange = (event) => { + const selectedFile = event.target.files[0]; + setFile(selectedFile); + }; + + + const { data, isLoading } = + (id, { + skip: !id, + }); + + useEffect(() => { + if (data) { + reset({ + investorAmount: data?.data?.investorAmount, + }); + } + }, [data, reset]); + + const heandleOnClose = () =>{ + reset() + onClose() + } + + return ( + + + + Approve Comment + + {isLoading ? ( + + ) : ( + + + + Comment +