Compare commits

...

9 Commits

Author SHA1 Message Date
victorAnumudu ab700edcf2 resources question page added 2023-07-17 13:42:21 +01:00
ameye 8b3c586456 Merge branch 'withdrwal-popup' of WrenchBoard/Users-Wrench into master 2023-07-17 10:38:48 +00:00
ameye e456b55e16 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-17 10:38:41 +00:00
Ebube 54bf020c55 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-17 11:04:59 +01:00
Ebube 78145eee77 Paying using new card 2023-07-17 11:04:31 +01:00
ameye bf5c9d4671 Merge branch 'profile-bug' of WrenchBoard/Users-Wrench into master 2023-07-17 08:06:43 +00:00
victorAnumudu d2db38ba21 profile bug fixed 2023-07-17 02:01:37 +01:00
Ebube fb7913c563 Another fix 2023-07-16 01:36:27 +01:00
Ebube feb301c3c0 . 2023-07-16 01:08:37 +01:00
9 changed files with 431 additions and 255 deletions
+3 -3
View File
@@ -504,11 +504,11 @@ export default function Icons({ name }) {
></path> ></path>
</svg> </svg>
) : name === "atm-card" ? ( ) : name === "atm-card" ? (
<img className="w-[20px]" src={ATMCard} alt="card" /> <img className="w-[30px]" src={ATMCard} alt="card" />
) : name === "visa-card" ? ( ) : name === "visa-card" ? (
<img className="w-[20px]" src={VisaCard} alt="card" /> <img className="w-[30px]" src={VisaCard} alt="card" />
) : name === "master-card" ? ( ) : name === "master-card" ? (
<img className="w-[20px]" src={MasterCard} alt="card" /> <img className="w-[30px]" src={MasterCard} alt="card" />
) : name === "new-dashboard" ? ( ) : name === "new-dashboard" ? (
<img className="w-[17px] h-[17px]" src={localImgLoad('images/icons/dashboard.svg')} alt="dashboard" /> <img className="w-[17px] h-[17px]" src={localImgLoad('images/icons/dashboard.svg')} alt="dashboard" />
) : name === "new-family" ? ( ) : name === "new-family" ? (
@@ -21,6 +21,9 @@ export default function InputCom({
blurHandler, blurHandler,
spanTag, spanTag,
inputBg, inputBg,
onInput,
maxLength = 30,
minLength = 0,
direction, direction,
error, error,
}) { }) {
@@ -29,13 +32,13 @@ export default function InputCom({
// for Min Length: // for Min Length:
const minLengthValidation = () => { const minLengthValidation = () => {
const inputConfig = inputConfigs[inputRef?.current?.name]?.minLength; const inputConfig = inputConfigs[inputRef?.current?.name]?.minLength;
return inputConfig || 0; return inputConfig || minLength;
}; };
// for MaxLength // for MaxLength
const maxLengthValidation = () => { const maxLengthValidation = () => {
const inputConfig = inputConfigs[inputRef?.current?.name]?.maxLength; const inputConfig = inputConfigs[inputRef?.current?.name]?.maxLength;
return inputConfig || 30; return inputConfig || maxLength;
}; };
// for Patterns // for Patterns
@@ -63,7 +66,9 @@ export default function InputCom({
</span> </span>
)} )}
{/* displays error is any */} {/* displays error is any */}
{error && <span className="text-[12px] text-red-500 italic">{error}</span>} {error && (
<span className="text-[12px] text-red-500 italic">{error}</span>
)}
</label> </label>
)} )}
{forgotPassword && ( {forgotPassword && (
@@ -76,7 +81,11 @@ export default function InputCom({
)} )}
</div> </div>
<div <div
className={`input-wrapper w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-base ${inputClass ? inputClass : "text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] border"}`} className={`input-wrapper w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-base ${
inputClass
? inputClass
: "text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] border"
}`}
> >
<input <input
placeholder={placeholder} placeholder={placeholder}
@@ -88,6 +97,7 @@ export default function InputCom({
type={type} type={type}
id={name} id={name}
name={name} name={name}
onInput={onInput}
minLength={minLengthValidation()} minLength={minLengthValidation()}
maxLength={maxLengthValidation()} maxLength={maxLengthValidation()}
// pattern={inputPatterns()} // pattern={inputPatterns()}
@@ -104,10 +114,7 @@ export default function InputCom({
</div> </div>
)} )}
{passIcon && ( {passIcon && (
<div <div className="absolute right-6 bottom-3 z-10" onClick={onClick}>
className="absolute right-6 bottom-3 z-10"
onClick={onClick}
>
<Icons name={passIcon} /> <Icons name={passIcon} />
</div> </div>
)} )}
@@ -128,7 +135,8 @@ const inputConfigs = {
amount: { minLength: 1, maxLength: 9, pattern: "[0-9]+" }, amount: { minLength: 1, maxLength: 9, pattern: "[0-9]+" },
description: { minLength: 5, maxLength: 299 }, description: { minLength: 5, maxLength: 299 },
title: { minLength: 5, maxLength: 149 }, title: { minLength: 5, maxLength: 149 },
job_detail: { minLength: 4, maxLength: 1440 } job_detail: { minLength: 4, maxLength: 1440 },
cardNum: { minLength: 4, maxLength: 19 },
}; };
/* Numbers Only: <input type="text" pattern="[0-9]*" /> strictly numbers /* Numbers Only: <input type="text" pattern="[0-9]*" /> strictly numbers
+121 -82
View File
@@ -1,22 +1,31 @@
import React, { useEffect, useState } from "react"; import { Form, Formik } from "formik";
import { useNavigate } from "react-router-dom"; import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import * as Yup from "yup";
import usersService from "../../../services/UsersService"; import usersService from "../../../services/UsersService";
import Icons from "../../Helpers/Icons";
import InputCom from "../../Helpers/Inputs/InputCom"; import InputCom from "../../Helpers/Inputs/InputCom";
import LoadingSpinner from "../../Spinners/LoadingSpinner"; 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({ const validationSchema = Yup.object().shape({
name: Yup.string()
.min(3, "3 chars min.")
.max(50, "50 chars max.")
.required("required"),
cardNum: Yup.string() cardNum: Yup.string()
.min(3, "3 chars min.") .min(6, "not a card number")
.max(25, "25 chars max.") .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"), .required("required"),
code: Yup.string() code: Yup.string()
.min(3, "3 chars min.") .min(3, "3 chars min.")
@@ -45,7 +54,6 @@ const validationSchema = Yup.object().shape({
}); });
const initialValues = { const initialValues = {
name: "",
cardNum: "", cardNum: "",
code: "", code: "",
state: "", state: "",
@@ -56,25 +64,53 @@ const initialValues = {
}; };
function AddFundDollars(props) { function AddFundDollars(props) {
const navigate = useNavigate();
const apiCall = new usersService(); const apiCall = new usersService();
let countryWallet = props.walletItem.country; let countryWallet = props.walletItem.country;
const [tab, setTab] = useState("previous"); const [tab, setTab] = useState("previous");
const [loader, setLoader] = useState(false);
const { userDetails } = useSelector((state) => state?.userDetails); const { userDetails } = useSelector((state) => state?.userDetails);
const { firstname, lastname } = userDetails;
const [prevCardDetails, setPrevCardDetails] = useState({}); const [prevCardDetails, setPrevCardDetails] = useState({});
const [payListCards, setPayListCards] = useState({ loading: true, data: [] }); const [payListCards, setPayListCards] = useState({ loading: true, data: [] });
let __awaitComponent = props.confirmCredit.show.awaitConfirm; const [cardIcons, setCardIcons] = useState("atm-card");
let __acceptComponent = props.confirmCredit.show.awaitConfirm;
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 handleInputChange = (event) => {
const { name, value } = event.target; const { name, value } = event.target;
setPrevCardDetails((prevState) => ({ setPrevCardDetails((prevState) => ({
...prevState, ...prevState,
[name]: value, [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 indexOfFirstItem = 0;
const indexOfLastItem = const indexOfLastItem =
indexOfFirstItem + Number(process.env.REACT_APP_ITEM_PER_PAGE); indexOfFirstItem + Number(process.env.REACT_APP_ITEM_PER_PAGE);
@@ -83,78 +119,70 @@ function AddFundDollars(props) {
indexOfLastItem indexOfLastItem
); );
// Submission for both prev and new cards
const handleSubmit = async (values, helpers) => { const handleSubmit = async (values, helpers) => {
props.setInputError(""); props.setInputError("");
if (!props.input || props.input === "0") { if (!props.input || props.input === "0") {
props.setInputError("Please Enter Amount"); props.setInputError("Please Enter Amount");
setTimeout(() => props.setInputError(""), 5000);
return; return;
} }
if (isNaN(props.input)) { if (isNaN(props.input)) {
props.setInputError("Amount must be a Number"); props.setInputError("Amount must be a Number");
setTimeout(() => props.setInputError(""), 5000);
return; return;
} }
if (tab === "previous") { if (tab === "previous") {
if (!prevCardDetails) { // To check if card is empty
if (Object.keys(prevCardDetails).length === 0) {
return; return;
} }
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);
}
} }
if (tab === "new") { props.setConfirmCredit((prev) => ({
const stateData = { ...prev,
amount: Number(props.input), show: { awaitConfirm: { loader: true } },
currency: props.currency, }));
...values,
};
// 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);
} }
}; };
@@ -221,7 +249,7 @@ function AddFundDollars(props) {
{/* END OF switch button */} {/* END OF switch button */}
{/* previous tab */} {/* previous tab */}
{tab === "previous" ? ( {tab === "previous" && (
<div className="p-4 previous-details w-full min-h-[16rem] flex flex-col justify-between items-center"> <div className="p-4 previous-details w-full min-h-[16rem] flex flex-col justify-between items-center">
{payListCards.loading ? ( {payListCards.loading ? (
<LoadingSpinner size="10" color="sky-blue" /> <LoadingSpinner size="10" color="sky-blue" />
@@ -268,7 +296,9 @@ function AddFundDollars(props) {
</div> </div>
)} )}
</div> </div>
) : ( )}
{tab === "new" && (
<div className="new-details w-full max-h-[23rem]"> <div className="new-details w-full max-h-[23rem]">
<div className="w-full flex flex-col justify-between"> <div className="w-full flex flex-col justify-between">
<Formik <Formik
@@ -297,17 +327,21 @@ function AddFundDollars(props) {
<InputCom <InputCom
fieldClass="px-6" fieldClass="px-6"
spanTag="*" spanTag="*"
iconName="master-card visa-card atm-card" iconName={cardIcons}
label="Card Number" label="Card Number"
type="text" type="text"
name="cardNum" name="cardNum"
onInput={handleCards}
placeholder="Enter Card Number" placeholder="Enter Card Number"
value={props.values.cardNum} value={handleCardNumberChange(
props.values.cardNum
)}
inputHandler={props.handleChange} inputHandler={props.handleChange}
blurHandler={props.handleBlur} blurHandler={props.handleBlur}
error={props.errors.cardNum} error={props.errors.cardNum}
/> />
</div> </div>
{/* Expire Year, Year */} {/* Expire Year, Year */}
<div className="sm:grid gap-5 grid-cols-2 flex-[0.4]"> <div className="sm:grid gap-5 grid-cols-2 flex-[0.4]">
<div className="field w-full mb-6 xl:mb-0 col-span-1"> <div className="field w-full mb-6 xl:mb-0 col-span-1">
@@ -357,6 +391,7 @@ function AddFundDollars(props) {
</div> </div>
</div> </div>
</div> </div>
<div className="field w-full mb-6 xl:mb-0 col-span-1"> <div className="field w-full mb-6 xl:mb-0 col-span-1">
<div className="select-option"> <div className="select-option">
<div <div
@@ -404,17 +439,18 @@ function AddFundDollars(props) {
</div> </div>
</div> </div>
{/* Address and CVV */}
<div className="flex items-center flex-1 gap-3 my-2"> <div className="flex items-center flex-1 gap-3 my-2">
{/* Address and CVV */}
<div className="field w-full col-span-1 flex-[0.4]"> <div className="field w-full col-span-1 flex-[0.4]">
<InputCom <InputCom
fieldClass="px-6" fieldClass="px-6"
spanTag="*" spanTag="*"
iconName="atm-card" iconName={cardIcons}
label="CVV" label="CVV"
type="text" type="number"
name="cvv" name="cvv"
placeholder="CVV" placeholder="CVV"
maxLength={3}
value={props.values.cvv} value={props.values.cvv}
inputHandler={props.handleChange} inputHandler={props.handleChange}
blurHandler={props.handleBlur} blurHandler={props.handleBlur}
@@ -448,6 +484,7 @@ function AddFundDollars(props) {
name="code" name="code"
placeholder="Postal Code" placeholder="Postal Code"
value={props.values.code} value={props.values.code}
maxLength={6}
inputHandler={props.handleChange} inputHandler={props.handleChange}
blurHandler={props.handleBlur} blurHandler={props.handleBlur}
error={props.errors.code} error={props.errors.code}
@@ -481,9 +518,9 @@ function AddFundDollars(props) {
</button> </button>
<button <button
type="submit" type="submit"
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center btn-gradient text-base rounded-full text-white" className="px-4 py-1 h-11 max-w-[115px] w-full flex justify-center items-center btn-gradient text-base rounded-full text-white"
> >
{loader ? ( {props.confirmCredit?.show?.awaitConfirm?.loader ? (
<LoadingSpinner size="6" color="sky-blue" /> <LoadingSpinner size="6" color="sky-blue" />
) : ( ) : (
<> <>
@@ -501,6 +538,7 @@ function AddFundDollars(props) {
</div> </div>
)} )}
</div> </div>
{tab == "previous" && ( {tab == "previous" && (
<div className="md:py-8 px-[38px] add-fund-btn flex justify-end items-center gap-4 py-4"> <div className="md:py-8 px-[38px] add-fund-btn flex justify-end items-center gap-4 py-4">
<button <button
@@ -511,8 +549,9 @@ function AddFundDollars(props) {
</button> </button>
<button <button
onClick={handleSubmit} onClick={handleSubmit}
name="previous"
type="button" type="button"
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center btn-gradient text-base rounded-full text-white" className="px-4 py-1 h-11 max-w-[115px] w-full flex justify-center items-center btn-gradient text-base rounded-full text-white"
> >
{props.confirmCredit?.show?.awaitConfirm?.loader ? ( {props.confirmCredit?.show?.awaitConfirm?.loader ? (
<LoadingSpinner size="6" color="sky-blue" /> <LoadingSpinner size="6" color="sky-blue" />
@@ -53,7 +53,7 @@ function CompleteConfirmCredit({ onClose, confirmCredit }) {
<h1 className="text-xl font-semibold text-dark-gray dark:text-white tracking-tighter my-1"> <h1 className="text-xl font-semibold text-dark-gray dark:text-white tracking-tighter my-1">
{data?.result == "Charge success" {data?.result == "Charge success"
? "Credit was Successful!" ? "Credit was Successful!"
: "Credit was Unsuccessful"} : data?.result}
</h1> </h1>
</div> </div>
+227 -142
View File
@@ -1,11 +1,88 @@
import { FlutterWaveButton, closePaymentModal } from "flutterwave-react-v3"; import { FlutterWaveButton, closePaymentModal } from "flutterwave-react-v3";
import React, { useState } from "react"; import React, { useState } from "react";
import { useSelector } from "react-redux";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import usersService from "../../../services/UsersService"; import usersService from "../../../services/UsersService";
import LoadingSpinner from "../../Spinners/LoadingSpinner"; import LoadingSpinner from "../../Spinners/LoadingSpinner";
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 (
<div className="my-2 flex items-center gap-5">
<div className="card-details flex items-center gap-3">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1 space-x-1">
{value.description} Card
</h1>
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">
Bank **************{value.digits}
</p>
</div>
</div>
);
}
function AmountSection({ currency, amount, country }) {
const formattedAmount = Number(amount).toFixed(2);
return (
<div
className={`flex items-center ${country == "US" ? "gap-14" : "gap-4"}`}
>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Amount({currency})
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{formattedAmount}
</span>
</div>
);
}
function TransactionFeeSection({ currency, fee, country }) {
const formattedFee = Number(fee).toFixed(2);
return (
<div
className={`flex items-center border-b border-gray-600 ${
country == "US" ? "gap-[2.7rem]" : "gap-4"
}`}
>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Transaction Fee
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{formattedFee}
</span>
</div>
);
}
function TotalSection({ currency, amount, fee, country }) {
const total = Number(amount) + Number(fee);
const formattedTotal = total.toFixed(2);
return (
<div
className={`flex items-center ${
country == "US" ? "gap-[8rem]" : "gap-[6.3rem]"
}`}
>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Total
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{formattedTotal}
</span>
</div>
);
}
function ConfirmAddFund({ function ConfirmAddFund({
confirmCredit, confirmCredit,
onClose, onClose,
@@ -14,68 +91,25 @@ function ConfirmAddFund({
}) { }) {
const __confirmData = confirmCredit?.data; const __confirmData = confirmCredit?.data;
const __confirmCountry = walletItem?.country; const __confirmCountry = walletItem?.country;
const __confirmCardDetails = __confirmData.card const __confirmCardDetails =
? JSON.parse(__confirmData.card) __confirmData.cardType === "prev"
: ""; ? JSON.parse(__confirmData.card)
let { userDetails } = useSelector((state) => state.userDetails); // TO GET LOGGEDIN USER DETAILS : __confirmData.card;
let [requestStatus, setRequestStatus] = useState({
message: "",
loading: false,
status: false,
}); // STATE FOR API REQUEST
const apiURL = new usersService(); const apiURL = new usersService();
const navigate = useNavigate(); const navigate = useNavigate();
//FUNCTION TO HANDLE SUBMIT const [requestStatus, setRequestStatus] = useState({
const onSuccessPayment = () => { message: "",
setRequestStatus({ message: "", loading: true, status: false }); loading: false,
let reqData = { amount: __confirmData?.account, currency: "NGN" }; status: false,
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 config = { const config = {
public_key: process.env.REACT_APP_FLUTTERWAVE_APIKEY, public_key: process.env.REACT_APP_FLUTTERWAVE_APIKEY,
tx_ref: Date.now(), tx_ref: Date.now(),
amount: __confirmData?.amount,
currency: "NGN", currency: "NGN",
payment_options: "card,mobilemoney,ussd", payment_options: "card,mobilemoney,ussd",
customer: {
email: `${userDetails.email}`,
phone_number: userDetails.phone,
name: `${userDetails.lastname} ${userDetails.firstname}`,
},
customizations: { customizations: {
title: "WrenchBoard", title: "WrenchBoard",
description: "Topup Payment", description: "Topup Payment",
@@ -88,12 +122,47 @@ function ConfirmAddFund({
text: "Proceed", text: "Proceed",
callback: (response) => { callback: (response) => {
onSuccessPayment(); onSuccessPayment();
closePaymentModal(); // this will close the modal programmatically closePaymentModal();
}, },
onClose: () => {}, 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 handlePrevCard = async () => {
const { amount, credit_reference, currency } = __confirmData; const { amount, credit_reference, currency } = __confirmData;
const { card_uid } = __confirmCardDetails; const { card_uid } = __confirmCardDetails;
@@ -124,18 +193,16 @@ function ConfirmAddFund({
return; return;
} }
return setTimeout( setTimeout(() => {
() => setConfirmCredit((prev) => ({
setConfirmCredit((prev) => ({ ...prev,
...prev, show: {
show: { awaitConfirm: { loader: false, state: false },
awaitConfirm: { loader: false, state: false }, acceptConfirm: { loader: false, state: true },
acceptConfirm: { loader: false, state: true }, },
}, data: _response,
data: _response, }));
})), }, 1500);
1500
);
} catch (error) { } catch (error) {
setConfirmCredit((prev) => ({ setConfirmCredit((prev) => ({
...prev, ...prev,
@@ -147,18 +214,67 @@ function ConfirmAddFund({
} }
}; };
const ThePaymentText = ({ value }) => ( const handleNewCard = async () => {
<div className="my-2 flex items-center gap-5"> const { amount, credit_reference, uid } = __confirmData;
<div className="card-details flex items-center gap-3"> const { address, cardNum, cvv, expirationMonth, expirationYear } =
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1"> __confirmCardDetails;
{value.description} Card
</h1> const reqData = {
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide"> amount: amount * 100,
Bank **************{value.digits} cardnumber: cardNum.replace(/\s/g, ""),
</p> credit_reference,
</div> cvc: cvv,
</div> 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 ( return (
<div className="content-wrapper w-full h-[32rem]"> <div className="content-wrapper w-full h-[32rem]">
@@ -166,76 +282,45 @@ function ConfirmAddFund({
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl"> <div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl">
<div className="px-4 md:p-8 py-4 add-fund-info"> <div className="px-4 md:p-8 py-4 add-fund-info">
<div className="field w-full mb-3 min-h-[45px]"> <div className="field w-full mb-3 min-h-[45px]">
{confirmCredit?.show?.awaitConfirm?.state ? ( {confirmCredit?.show?.awaitConfirm?.state && (
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
{/* Amount */} <AmountSection
<div currency={__confirmData?.currency}
className={`flex items-center ${ amount={__confirmData?.amount}
__confirmCountry == "US" ? "gap-14" : "gap-4" country={__confirmCountry}
}`} />
> <TransactionFeeSection
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1"> currency={__confirmData?.currency}
Amount({__confirmData?.currency}) fee={__confirmData?.fee}
</h1> country={__confirmCountry}
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1"> />
{`${walletItem?.symbol} ${ <TotalSection
Number(__confirmData?.amount).toLocaleString() || "" currency={__confirmData?.currency}
}`} amount={__confirmData?.amount}
</span> fee={__confirmData?.fee}
</div> country={__confirmCountry}
{/* Transaction Fee */} />
<div {__confirmCountry === "US" && (
className={`flex items-center border-b border-gray-600 ${
__confirmCountry == "US" ? "gap-[2.7rem]" : "gap-4"
}`}
>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Transaction Fee
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{`${walletItem?.symbol} ${
Number(__confirmData?.fee).toLocaleString() || ""
}`}
</span>
</div>
{/* Total */}
<div
className={`flex items-center ${
__confirmCountry == "US" ? "gap-[8rem]" : "gap-4"
}`}
>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Total
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{`${walletItem?.symbol} ${
(
Number(__confirmData?.amount) +
Number(__confirmData?.fee)
).toLocaleString() || ""
}`}
</span>
</div>
{__confirmCountry == "US" && (
<div className="flex items-center gap-8"> <div className="flex items-center gap-8">
<label <label
htmlFor="payment" htmlFor="payment"
className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1" className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1"
> >
{__confirmCountry == "US" && "Payment Method"} Payment Method
</label> </label>
<span className="text-[#181c32] dark:text-white "> <span className="text-[#181c32] dark:text-white">
{__confirmCardDetails ? ( <ThePaymentText
<ThePaymentText value={__confirmCardDetails} /> value={__confirmCardDetails}
) : null} type={__confirmData?.cardType}
/>
</span> </span>
</div> </div>
)} )}
<div <div
className={`${ className={`${
__confirmCountry == "US" ? "gap-[3.7rem]" : "gap-8" __confirmCountry === "US"
? "gap-[3.7rem]"
: "gap-[1.81rem]"
} flex items-center`} } flex items-center`}
> >
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1"> <h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
@@ -246,13 +331,13 @@ function ConfirmAddFund({
</span> </span>
</div> </div>
</div> </div>
) : null} )}
</div> </div>
</div> </div>
<div <div
className={ className={
__confirmCountry == "US" ? "min-h-[96px]" : "min-h-[200px]" __confirmCountry === "US" ? "min-h-[96px]" : "min-h-[157px]"
} }
></div> ></div>
<hr /> <hr />
@@ -263,13 +348,13 @@ function ConfirmAddFund({
> >
Cancel Cancel
</button> </button>
{__confirmCountry == "US" && ( {__confirmCountry === "US" && (
<button <button
className="px-4 h-11 flex justify-center items-center btn-gradient text-white text-base rounded-full" className="px-4 h-11 flex justify-center items-center btn-gradient text-white text-base rounded-full"
onClick={ onClick={
__confirmData?.cardType === "prev" __confirmData?.cardType === "prev"
? handlePrevCard ? handlePrevCard
: () => console.log("Test me") : handleNewCard
} }
> >
{confirmCredit?.show?.acceptConfirm?.loader ? ( {confirmCredit?.show?.acceptConfirm?.loader ? (
@@ -279,7 +364,7 @@ function ConfirmAddFund({
)} )}
</button> </button>
)} )}
{__confirmCountry == "NG" && ( {__confirmCountry === "NG" && (
<FlutterWaveButton <FlutterWaveButton
{...fwConfig} {...fwConfig}
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white" className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
+19 -7
View File
@@ -472,10 +472,10 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
</Link> </Link>
</div> </div>
{/* profile */} {/* profile */}
<div className="user-profile relative lg:block hidden"> <div className="user-profile relative">
<div <div
onClick={() => handlerProfile()} onClick={() => handlerProfile()}
className="flex items-center space-x-3.5" className="hidden lg:flex items-center space-x-3.5"
> >
{/* profile-image */} {/* profile-image */}
<div className="lg:w-[62px] lg:h-[62px] w-[50px] h-[50px] rounded-full overflow-hidden"> <div className="lg:w-[62px] lg:h-[62px] w-[50px] h-[50px] rounded-full overflow-hidden">
@@ -492,6 +492,17 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
{userDetails && userDetails?.account_type !== "FAMILY" && <p className="text-sm text-thin-light-gray">@{userEmail}</p>} {userDetails && userDetails?.account_type !== "FAMILY" && <p className="text-sm text-thin-light-gray">@{userEmail}</p>}
</div> </div>
</div> </div>
<div className="for-mobile-profile lg:hidden block">
<div
// to="/profile"
onClick={() => handlerProfile()}
className="lg:w-[62px] lg:h-[62px] w-[50px] h-[50px] rounded-full overflow-hidden block"
>
<img src={profileImg} alt="profile" className="w-full h-full" />
</div>
</div>
<div <div
className={`profile-dropdown w-[293px] z-30 bg-white dark:bg-dark-white absolute lg:right-16 -right-[16px] rounded-lg ${ className={`profile-dropdown w-[293px] z-30 bg-white dark:bg-dark-white absolute lg:right-16 -right-[16px] rounded-lg ${
userProfileDropdown ? "active" : "" userProfileDropdown ? "active" : ""
@@ -684,14 +695,15 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
</div> </div>
</div> </div>
</div> </div>
<div className="for-mobile-profile lg:hidden block"> {/* <div className="for-mobile-profile lg:hidden block">
<Link <div
to="/profile" // to="/profile"
onClick={() => handlerProfile()}
className="lg:w-[62px] lg:h-[62px] w-[50px] h-[50px] rounded-full overflow-hidden block" className="lg:w-[62px] lg:h-[62px] w-[50px] h-[50px] rounded-full overflow-hidden block"
> >
<img src={profileImg} alt="profile" className="w-full h-full" /> <img src={profileImg} alt="profile" className="w-full h-full" />
</Link> </div>
</div> </div> */}
</div> </div>
</div> </div>
</div> </div>
+2 -2
View File
@@ -65,7 +65,8 @@ export default function Resources(props) {
if(name == 'blog'){ if(name == 'blog'){
return blogItems?.blogdata?.length return blogItems?.blogdata?.length
}else if(name == 'onsale'){ }else if(name == 'onsale'){
return onSaleProducts?.length // return onSaleProducts?.length
return null
}else if(name == 'owned'){ }else if(name == 'owned'){
return ownProducts?.length return ownProducts?.length
}else if(name == 'created'){ }else if(name == 'created'){
@@ -95,7 +96,6 @@ export default function Resources(props) {
: "text-thin-light-gray bg-[#F2B8FD]" : "text-thin-light-gray bg-[#F2B8FD]"
}`} }`}
> >
{/* 16 blog, onsale, owned,created */}
{countNumber(tabValue.name)} {countNumber(tabValue.name)}
</span> </span>
</li> </li>
+27 -9
View File
@@ -1,26 +1,44 @@
import ProductCardStyleTwo from "../../Cards/ProductCardStyleTwo"; import ProductCardStyleTwo from "../../Cards/ProductCardStyleTwo";
import DataIteration from "../../Helpers/DataIteration"; import DataIteration from "../../Helpers/DataIteration";
import SearchCom from "../../Helpers/SearchCom"; import SearchCom from "../../Helpers/SearchCom";
import localImgLoad from "../../../lib/localImgLoad";
export default function QuestionsTab({ className, products }) { export default function QuestionsTab({ className, products }) {
return ( return (
<> <>
<div className={`onsale-tab-wrapper w-full ${className || ""}`}> <div className={`onsale-tab-wrapper w-full ${className || ""}`}>
<div className="main-container w-full"> <div className="main-container w-full">
<div className="filter-section w-full items-center sm:flex justify-between mb-6"> <div className="filter-section w-fullmb-6">
{/* filter-search */} <h1 className="text-xl lg:text-2xl font-bold text-dark-gray dark:text-white tracking-wide">Ask our A.I</h1>
<div className="sm:w-1/2 w-full sm:pr-20 pr-0 mb-5 sm:mb-0"> <div className="mt-2 lg:grid grid-cols-2 gap-2 h-full lg:h-[500px]">
<SearchCom /> <div className="h-full mb-5 lg:mb-0">
<img className="w-full h-full" src={localImgLoad(`images/resources-ask.jpg`)} alt='AI' />
</div>
<div className="p-8 bg-white rounded-2xl h-full">
<div className="input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base">
<select className="input-field px-2 placeholder:text-base text-dark-gray w-full h-full tracking-wide dark:bg-[#11131F] bg-[#fafafa] focus:ring-0 focus:outline-none">
<option className="rounded-full">Find answer on:</option>
</select>
</div>
{/* filter-search */}
<div className="w-full my-5 border-2 rounded-full">
<SearchCom />
</div>
<div className="w-full flex justify-end items-center border-b-2 pb-4">
<button
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer"
>
Search
</button>
</div>
</div>
</div> </div>
</div> </div>
<div className="content-section w-full-width"> {/* <div className="content-section w-full-width">
<div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-[30px]"> <div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-[30px]">
</div> </div>
</div> </div> */}
</div> </div>
</div> </div>
</> </>
+14
View File
@@ -216,6 +216,7 @@ class usersService {
return this.postAuxEnd("/sendmoneyfee", postData); return this.postAuxEnd("/sendmoneyfee", postData);
} }
// Start Credit for Cards
getStartCredit(value) { getStartCredit(value) {
var postData = { var postData = {
uid: localStorage.getItem("uid"), uid: localStorage.getItem("uid"),
@@ -227,6 +228,7 @@ class usersService {
return this.postAuxEnd("/startcredit", postData); return this.postAuxEnd("/startcredit", postData);
} }
// Paying using Previous Cards
getPaidPrevCard(value) { getPaidPrevCard(value) {
var postData = { var postData = {
uid: localStorage.getItem("uid"), uid: localStorage.getItem("uid"),
@@ -238,6 +240,18 @@ class usersService {
return this.postAuxEnd("/payprevcard", postData); 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() { getFamilySampleTasks() {
var postData = { var postData = {
uid: localStorage.getItem("uid"), uid: localStorage.getItem("uid"),