From feb301c3c08008e5f6b9a6e12d7121255f44eebd Mon Sep 17 00:00:00 2001 From: Ebube Date: Sun, 16 Jul 2023 01:08:37 +0100 Subject: [PATCH 1/3] . --- .../MyWallet/Popup/AddFundDollars.jsx | 11 ++++----- .../MyWallet/Popup/ConfirmAddFund.jsx | 24 +++++++++++++++---- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/components/MyWallet/Popup/AddFundDollars.jsx b/src/components/MyWallet/Popup/AddFundDollars.jsx index f9bbfa1..40b805b 100644 --- a/src/components/MyWallet/Popup/AddFundDollars.jsx +++ b/src/components/MyWallet/Popup/AddFundDollars.jsx @@ -65,8 +65,7 @@ function AddFundDollars(props) { const { firstname, lastname } = userDetails; const [prevCardDetails, setPrevCardDetails] = useState({}); const [payListCards, setPayListCards] = useState({ loading: true, data: [] }); - let __awaitComponent = props.confirmCredit.show.awaitConfirm; - let __acceptComponent = props.confirmCredit.show.awaitConfirm; + const handleInputChange = (event) => { const { name, value } = event.target; setPrevCardDetails((prevState) => ({ @@ -96,11 +95,11 @@ function AddFundDollars(props) { return; } - if (tab === "previous") { - if (!prevCardDetails) { - return; - } + if (!prevCardDetails) { + return; + } + if (tab === "previous") { props.setConfirmCredit((prev) => ({ ...prev, show: { awaitConfirm: { loader: true } }, diff --git a/src/components/MyWallet/Popup/ConfirmAddFund.jsx b/src/components/MyWallet/Popup/ConfirmAddFund.jsx index a157d87..43d1fcf 100644 --- a/src/components/MyWallet/Popup/ConfirmAddFund.jsx +++ b/src/components/MyWallet/Popup/ConfirmAddFund.jsx @@ -179,7 +179,13 @@ function ConfirmAddFund({ {`${walletItem?.symbol} ${ - Number(__confirmData?.amount).toLocaleString() || "" + Number(__confirmData?.amount).toLocaleString( + undefined, + { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + } + ) || "" }`} @@ -194,14 +200,17 @@ function ConfirmAddFund({ {`${walletItem?.symbol} ${ - Number(__confirmData?.fee).toLocaleString() || "" + Number(__confirmData?.fee).toLocaleString(undefined, { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + }) || "" }`} {/* Total */}

@@ -212,7 +221,10 @@ function ConfirmAddFund({ ( Number(__confirmData?.amount) + Number(__confirmData?.fee) - ).toLocaleString() || "" + ).toLocaleString(undefined, { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + }) || "" }`}

@@ -235,7 +247,9 @@ function ConfirmAddFund({

From fb7913c563915534bf2125a61d00a9cf29ba0c17 Mon Sep 17 00:00:00 2001 From: Ebube Date: Sun, 16 Jul 2023 01:36:27 +0100 Subject: [PATCH 2/3] Another fix --- .../MyWallet/Popup/AddFundDollars.jsx | 4 +- .../MyWallet/Popup/ConfirmAddFund.jsx | 293 +++++++++--------- 2 files changed, 148 insertions(+), 149 deletions(-) diff --git a/src/components/MyWallet/Popup/AddFundDollars.jsx b/src/components/MyWallet/Popup/AddFundDollars.jsx index 40b805b..28a4190 100644 --- a/src/components/MyWallet/Popup/AddFundDollars.jsx +++ b/src/components/MyWallet/Popup/AddFundDollars.jsx @@ -95,7 +95,7 @@ function AddFundDollars(props) { return; } - if (!prevCardDetails) { + if (!prevCardDetails["payment-card"]?.card_uid) { return; } @@ -171,6 +171,8 @@ function AddFundDollars(props) { const handleClose = props.onClose; + console.log(prevCardDetails) + return ( <>
diff --git a/src/components/MyWallet/Popup/ConfirmAddFund.jsx b/src/components/MyWallet/Popup/ConfirmAddFund.jsx index 43d1fcf..2457371 100644 --- a/src/components/MyWallet/Popup/ConfirmAddFund.jsx +++ b/src/components/MyWallet/Popup/ConfirmAddFund.jsx @@ -1,11 +1,78 @@ import { FlutterWaveButton, closePaymentModal } from "flutterwave-react-v3"; import React, { useState } from "react"; -import { useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; import { toast } from "react-toastify"; import usersService from "../../../services/UsersService"; import LoadingSpinner from "../../Spinners/LoadingSpinner"; +function ThePaymentText({ value }) { + return ( +
+
+

+ {value.description} Card +

+

+ Bank **************{value.digits} +

+
+
+ ); +} + +function AmountSection({ currency, amount, country }) { + const formattedAmount = (Number(amount) / 100).toFixed(2); + return ( +
+

+ Amount({currency}) +

+ + {formattedAmount} + +
+ ); +} + +function TransactionFeeSection({ currency, fee, country }) { + const formattedFee = (Number(fee) / 100).toFixed(2); + return ( +
+

+ Transaction Fee +

+ + {formattedFee} + +
+ ); +} + +function TotalSection({ currency, amount, fee, country }) { + const total = (Number(amount) + Number(fee)) / 100; + const formattedTotal = total.toFixed(2); + return ( +
+

+ Total +

+ + {formattedTotal} + +
+ ); +} + function ConfirmAddFund({ confirmCredit, onClose, @@ -17,65 +84,21 @@ function ConfirmAddFund({ const __confirmCardDetails = __confirmData.card ? JSON.parse(__confirmData.card) : ""; - let { userDetails } = useSelector((state) => state.userDetails); // TO GET LOGGEDIN USER DETAILS - - let [requestStatus, setRequestStatus] = useState({ - message: "", - loading: false, - status: false, - }); // STATE FOR API REQUEST const apiURL = new usersService(); const navigate = useNavigate(); - //FUNCTION TO HANDLE SUBMIT - const onSuccessPayment = () => { - setRequestStatus({ message: "", loading: true, status: false }); - let reqData = { amount: __confirmData?.account, currency: "NGN" }; - apiURL - .startTopUp(reqData) - .then((res) => { - if (res.data.internal_return < 0) { - setRequestStatus({ - message: "Could not finish transaction", - loading: false, - status: false, - }); - toast.success("Opps! something went wrong"); - } - // do something - setRequestStatus({ - message: "Topup successful", - loading: false, - status: true, - }); - toast.success("Account Topup was successful"); - setTimeout(() => { - navigate("/my-wallet", { replace: true }); - }, 1000); - }) - .catch((err) => { - // do something - setRequestStatus({ - message: "Opps! An Error Occured", - loading: false, - status: false, - }); - toast.success("Opps! something went wrong"); - }); - }; + const [requestStatus, setRequestStatus] = useState({ + message: "", + loading: false, + status: false, + }); const config = { public_key: process.env.REACT_APP_FLUTTERWAVE_APIKEY, tx_ref: Date.now(), - amount: __confirmData?.amount, currency: "NGN", payment_options: "card,mobilemoney,ussd", - customer: { - email: `${userDetails.email}`, - phone_number: userDetails.phone, - name: `${userDetails.lastname} ${userDetails.firstname}`, - }, customizations: { title: "WrenchBoard", description: "Topup Payment", @@ -88,12 +111,47 @@ function ConfirmAddFund({ text: "Proceed", callback: (response) => { onSuccessPayment(); - closePaymentModal(); // this will close the modal programmatically + closePaymentModal(); }, onClose: () => {}, }; - // Handling Previous Card + const onSuccessPayment = () => { + setRequestStatus({ message: "", loading: true, status: false }); + const reqData = { amount: __confirmData?.account, currency: "NGN" }; + + apiURL + .startTopUp(reqData) + .then((res) => { + if (res.data.internal_return < 0) { + setRequestStatus({ + message: "Could not finish transaction", + loading: false, + status: false, + }); + toast.success("Opps! something went wrong"); + } else { + setRequestStatus({ + message: "Topup successful", + loading: false, + status: true, + }); + toast.success("Account Topup was successful"); + setTimeout(() => { + navigate("/my-wallet", { replace: true }); + }, 1000); + } + }) + .catch((err) => { + setRequestStatus({ + message: "Opps! An Error Occured", + loading: false, + status: false, + }); + toast.success("Opps! something went wrong"); + }); + }; + const handlePrevCard = async () => { const { amount, credit_reference, currency } = __confirmData; const { card_uid } = __confirmCardDetails; @@ -124,18 +182,16 @@ function ConfirmAddFund({ return; } - return setTimeout( - () => - setConfirmCredit((prev) => ({ - ...prev, - show: { - awaitConfirm: { loader: false, state: false }, - acceptConfirm: { loader: false, state: true }, - }, - data: _response, - })), - 1500 - ); + setTimeout(() => { + setConfirmCredit((prev) => ({ + ...prev, + show: { + awaitConfirm: { loader: false, state: false }, + acceptConfirm: { loader: false, state: true }, + }, + data: _response, + })); + }, 1500); } catch (error) { setConfirmCredit((prev) => ({ ...prev, @@ -147,107 +203,48 @@ function ConfirmAddFund({ } }; - const ThePaymentText = ({ value }) => ( -
-
-

- {value.description} Card -

-

- Bank **************{value.digits} -

-
-
- ); - return (
- {confirmCredit?.show?.awaitConfirm?.state ? ( + {confirmCredit?.show?.awaitConfirm?.state && (
- {/* Amount */} -
-

- Amount({__confirmData?.currency}) -

- - {`${walletItem?.symbol} ${ - Number(__confirmData?.amount).toLocaleString( - undefined, - { - minimumFractionDigits: 2, - maximumFractionDigits: 2, - } - ) || "" - }`} - -
- {/* Transaction Fee */} -
-

- Transaction Fee -

- - {`${walletItem?.symbol} ${ - Number(__confirmData?.fee).toLocaleString(undefined, { - minimumFractionDigits: 2, - maximumFractionDigits: 2, - }) || "" - }`} - -
- {/* Total */} -
-

- Total -

- - {`${walletItem?.symbol} ${ - ( - Number(__confirmData?.amount) + - Number(__confirmData?.fee) - ).toLocaleString(undefined, { - minimumFractionDigits: 2, - maximumFractionDigits: 2, - }) || "" - }`} - -
- - {__confirmCountry == "US" && ( + + + + {__confirmCountry === "US" && (
- + {__confirmCardDetails ? ( ) : null}
)} -
- ) : null} + )}

@@ -277,7 +274,7 @@ function ConfirmAddFund({ > Cancel - {__confirmCountry == "US" && ( + {__confirmCountry === "US" && (
)} {passIcon && ( -
+
)} @@ -128,7 +135,8 @@ const inputConfigs = { amount: { minLength: 1, maxLength: 9, pattern: "[0-9]+" }, description: { minLength: 5, maxLength: 299 }, title: { minLength: 5, maxLength: 149 }, - job_detail: { minLength: 4, maxLength: 1440 } + job_detail: { minLength: 4, maxLength: 1440 }, + cardNum: { minLength: 4, maxLength: 19 }, }; /* Numbers Only: strictly numbers diff --git a/src/components/MyWallet/Popup/AddFundDollars.jsx b/src/components/MyWallet/Popup/AddFundDollars.jsx index 28a4190..b60c3ae 100644 --- a/src/components/MyWallet/Popup/AddFundDollars.jsx +++ b/src/components/MyWallet/Popup/AddFundDollars.jsx @@ -1,22 +1,31 @@ -import React, { useEffect, useState } from "react"; -import { useNavigate } from "react-router-dom"; +import { Form, Formik } from "formik"; +import { useEffect, useState } from "react"; +import { useSelector } from "react-redux"; +import * as Yup from "yup"; import usersService from "../../../services/UsersService"; +import Icons from "../../Helpers/Icons"; import InputCom from "../../Helpers/Inputs/InputCom"; import LoadingSpinner from "../../Spinners/LoadingSpinner"; -import { Form, Formik } from "formik"; -import { useSelector } from "react-redux"; -import * as Yup from "yup"; -import Icons from "../../Helpers/Icons"; - const validationSchema = Yup.object().shape({ - name: Yup.string() - .min(3, "3 chars min.") - .max(50, "50 chars max.") - .required("required"), cardNum: Yup.string() - .min(3, "3 chars min.") - .max(25, "25 chars max.") + .min(6, "not a card number") + .max(19, "16 chars max.") //16 chars + 3 spaces + .test("luhn-validation", "Invalid Card Number", (value) => { + const sanitizedNumber = value?.replace(/\D/g, ""); + const digits = Array?.from(sanitizedNumber, Number); + + for (let i = digits.length - 2; i >= 0; i -= 2) { + digits[i] *= 2; + if (digits[i] > 9) { + digits[i] -= 9; + } + } + + const sum = digits.reduce((acc, digit) => acc + digit, 0); + + return sum % 10 === 0; + }) .required("required"), code: Yup.string() .min(3, "3 chars min.") @@ -45,7 +54,6 @@ const validationSchema = Yup.object().shape({ }); const initialValues = { - name: "", cardNum: "", code: "", state: "", @@ -56,24 +64,53 @@ const initialValues = { }; function AddFundDollars(props) { - const navigate = useNavigate(); const apiCall = new usersService(); let countryWallet = props.walletItem.country; const [tab, setTab] = useState("previous"); - const [loader, setLoader] = useState(false); const { userDetails } = useSelector((state) => state?.userDetails); - const { firstname, lastname } = userDetails; const [prevCardDetails, setPrevCardDetails] = useState({}); const [payListCards, setPayListCards] = useState({ loading: true, data: [] }); + const [cardIcons, setCardIcons] = useState("atm-card"); + const { firstname, lastname } = userDetails; + + // Handling Card Icons + const handleCards = (event) => { + const { name, value } = event.target; + + if (name == "cardNum") { + // Check if the first character is 4 or 5 and set the card icon accordingly + const cardIcon = + value.length > 0 + ? value[0] === "4" + ? "visa-card" + : value[0] === "5" + ? "master-card" + : "atm-card" + : "atm-card"; + setCardIcons(cardIcon); + } + }; + + // Handling card change const handleInputChange = (event) => { const { name, value } = event.target; + setPrevCardDetails((prevState) => ({ ...prevState, [name]: value, })); }; + // Handling card number grouping + const handleCardNumberChange = (value) => { + return value + ?.replace(/\s/g, "") // Remove existing spaces + .match(/.{1,4}/g) // Group every four characters + ?.join(" "); + }; + + // card slicer const indexOfFirstItem = 0; const indexOfLastItem = indexOfFirstItem + Number(process.env.REACT_APP_ITEM_PER_PAGE); @@ -82,78 +119,70 @@ function AddFundDollars(props) { indexOfLastItem ); + // Submission for both prev and new cards const handleSubmit = async (values, helpers) => { props.setInputError(""); if (!props.input || props.input === "0") { props.setInputError("Please Enter Amount"); + setTimeout(() => props.setInputError(""), 5000); return; } if (isNaN(props.input)) { props.setInputError("Amount must be a Number"); - return; - } - - if (!prevCardDetails["payment-card"]?.card_uid) { + setTimeout(() => props.setInputError(""), 5000); return; } if (tab === "previous") { - props.setConfirmCredit((prev) => ({ - ...prev, - show: { awaitConfirm: { loader: true } }, - })); - - let stateData = { - amount: Number(props.input) * 100, - currency: props.walletItem?.code, - }; - - try { - const res = await apiCall.getStartCredit(stateData); - if (res.data.internal_return < 0) { - props.setConfirmCredit((prev) => ({ - ...prev, - show: { awaitConfirm: { loader: false } }, - })); - props.setInputError("An Error Occurred"); - setTimeout(() => props.setInputError(""), 5000); - return; - } - - const _response = res.data; - stateData.amount = Number(props.input); - stateData.card = prevCardDetails["payment-card"]; - stateData.cardType = "prev"; - stateData = { ...stateData, ..._response }; - - setTimeout(() => { - props.setConfirmCredit({ - show: { - awaitConfirm: { loader: false, state: true }, - acceptConfirm: { loader: false, state: false }, - }, - data: stateData, - }); - }, 1500); - } catch (error) { - props.setConfirmCredit((prev) => ({ - ...prev, - show: { awaitConfirm: { loader: false } }, - })); - console.log(error); + // To check if card is empty + if (Object.keys(prevCardDetails).length === 0) { + return; } } - if (tab === "new") { - const stateData = { - amount: Number(props.input), - currency: props.currency, - ...values, - }; + props.setConfirmCredit((prev) => ({ + ...prev, + show: { awaitConfirm: { loader: true } }, + })); - // Rest of the code for tab "new" + let stateData = { + amount: Number(props.input) * 100, + currency: props.walletItem?.code, + }; + + try { + const res = await apiCall.getStartCredit(stateData); + if (res.data.internal_return < 0) { + props.setInputError("An Error Occurred"); + throw new Error("An Error Occurred"); + } + + const _response = res.data; + stateData.amount = Number(props.input); + stateData.card = + tab === "previous" ? prevCardDetails["payment-card"] : { ...values }; + stateData.cardType = tab === "previous" ? "prev" : "new"; + stateData = { ...stateData, ..._response }; + + setTimeout(() => { + props.setConfirmCredit({ + show: { + awaitConfirm: { loader: false, state: true }, + acceptConfirm: { loader: false, state: false }, + }, + data: stateData, + }); + }, 1500); + } catch (error) { + props.setInputError(error.message); + setTimeout(() => props.setInputError(""), 5000); + props.setConfirmCredit((prev) => ({ + ...prev, + show: { awaitConfirm: { loader: false } }, + })); + console.log(error); } }; @@ -171,8 +200,6 @@ function AddFundDollars(props) { const handleClose = props.onClose; - console.log(prevCardDetails) - return ( <>
@@ -222,7 +249,7 @@ function AddFundDollars(props) { {/* END OF switch button */} {/* previous tab */} - {tab === "previous" ? ( + {tab === "previous" && (
{payListCards.loading ? ( @@ -269,7 +296,9 @@ function AddFundDollars(props) {
)}
- ) : ( + )} + + {tab === "new" && (
+ {/* Expire Year, Year */}
@@ -358,6 +391,7 @@ function AddFundDollars(props) {
+
+ {/* Address and CVV */}
- {/* Address and CVV */}
)}
+ {tab == "previous" && (
diff --git a/src/components/MyWallet/Popup/ConfirmAddFund.jsx b/src/components/MyWallet/Popup/ConfirmAddFund.jsx index 2457371..4a4dd1a 100644 --- a/src/components/MyWallet/Popup/ConfirmAddFund.jsx +++ b/src/components/MyWallet/Popup/ConfirmAddFund.jsx @@ -5,11 +5,21 @@ import { toast } from "react-toastify"; import usersService from "../../../services/UsersService"; import LoadingSpinner from "../../Spinners/LoadingSpinner"; -function ThePaymentText({ value }) { +function ThePaymentText({ value, type }) { + const cardDetails = value; + value.description = + type === "new" + ? cardDetails.cardNum[0] === "4" + ? "Visa" + : value[0] === "5" + ? "Master" + : "ATM" + : value.description; + value.digits = type === "new" ? cardDetails.cardNum.slice(-4) : value.digits; return (
-

+

{value.description} Card

@@ -21,7 +31,7 @@ function ThePaymentText({ value }) { } function AmountSection({ currency, amount, country }) { - const formattedAmount = (Number(amount) / 100).toFixed(2); + const formattedAmount = Number(amount).toFixed(2); return (

{ + const { amount, credit_reference, uid } = __confirmData; + const { address, cardNum, cvv, expirationMonth, expirationYear } = + __confirmCardDetails; + + const reqData = { + amount: amount * 100, + cardnumber: cardNum.replace(/\s/g, ""), + credit_reference, + cvc: cvv, + description: address, + exp_month: expirationMonth, + exp_year: expirationYear, + paymenttype: 100, + uid, + }; + + try { + setConfirmCredit((prev) => ({ + ...prev, + show: { + acceptConfirm: { loader: true }, + }, + })); + const res = await apiURL.getPaidNewCard(reqData); + const _response = res.data; + if (res.data.internal_return < 0) { + setConfirmCredit((prev) => ({ + ...prev, + show: { + awaitConfirm: { loader: false, state: false }, + acceptConfirm: { loader: false, state: true }, + }, + data: _response, + })); + return; + } + + setTimeout(() => { + setConfirmCredit((prev) => ({ + ...prev, + show: { + awaitConfirm: { loader: false, state: false }, + acceptConfirm: { loader: false, state: true }, + }, + data: _response, + })); + }, 1500); + } catch (error) { + setConfirmCredit((prev) => ({ + ...prev, + show: { + acceptConfirm: { loader: false }, + }, + })); + setTimeout(() => onClose, 10000) + console.log(error); + } + }; + + console.log(confirmCredit?.data); + return (
@@ -236,9 +309,10 @@ function ConfirmAddFund({ Payment Method - {__confirmCardDetails ? ( - - ) : null} +
)} @@ -246,7 +320,7 @@ function ConfirmAddFund({ className={`${ __confirmCountry === "US" ? "gap-[3.7rem]" - : "gap-[9.81rem]" + : "gap-[1.81rem]" } flex items-center`} >

@@ -263,7 +337,7 @@ function ConfirmAddFund({

@@ -280,7 +354,7 @@ function ConfirmAddFund({ onClick={ __confirmData?.cardType === "prev" ? handlePrevCard - : () => console.log("Test me") + : handleNewCard } > {confirmCredit?.show?.acceptConfirm?.loader ? ( diff --git a/src/services/UsersService.js b/src/services/UsersService.js index f78ad17..261567e 100644 --- a/src/services/UsersService.js +++ b/src/services/UsersService.js @@ -216,6 +216,7 @@ class usersService { return this.postAuxEnd("/sendmoneyfee", postData); } + // Start Credit for Cards getStartCredit(value) { var postData = { uid: localStorage.getItem("uid"), @@ -227,6 +228,7 @@ class usersService { return this.postAuxEnd("/startcredit", postData); } + // Paying using Previous Cards getPaidPrevCard(value) { var postData = { uid: localStorage.getItem("uid"), @@ -238,6 +240,18 @@ class usersService { return this.postAuxEnd("/payprevcard", postData); } + // Paying using New Card + getPaidNewCard(value) { + var postData = { + uid: localStorage.getItem("uid"), + member_id: localStorage.getItem("member_id"), + sessionid: localStorage.getItem("session_token"), + action: 11054, + ...value, + }; + return this.postAuxEnd("/paynewcard", postData); + } + getFamilySampleTasks() { var postData = { uid: localStorage.getItem("uid"),