Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1a65b1daa3 | |||
| ba2c009896 | |||
| bc2b71ecda | |||
| 1d315018a4 | |||
| 56f8b75525 | |||
| 59531df377 | |||
| 06a7386211 | |||
| 4bb3a11261 | |||
| f308eeca8d | |||
| 8e562ed1a5 | |||
| 23dd7571a3 | |||
| 8530b2d1a0 | |||
| acdbddbc79 | |||
| 15fc5f4f14 | |||
| 2ba3b01646 | |||
| 4e960a2f53 | |||
| ab700edcf2 | |||
| 42e80c7a11 | |||
| d4472a881a | |||
| 5d12ab4f62 | |||
| 8b3c586456 | |||
| e456b55e16 | |||
| 89c5936212 | |||
| 7bedf76945 | |||
| 54bf020c55 | |||
| 78145eee77 | |||
| d75b6ee26c | |||
| bf5c9d4671 | |||
| eecbca6b0e | |||
| dd1430a350 | |||
| 0eca0c52ce | |||
| fb7913c563 | |||
| feb301c3c0 |
@@ -68,6 +68,8 @@ REACT_APP_APPLE_REDIRECT_URL='http://localhost:9082/login/auth/apple'
|
|||||||
REACT_APP_MAX_FILE_SIZE=1000000
|
REACT_APP_MAX_FILE_SIZE=1000000
|
||||||
REACT_APP_TOTAL_NUM_FILE=4
|
REACT_APP_TOTAL_NUM_FILE=4
|
||||||
|
|
||||||
|
REACT_APP_LOGOUT_TEXT="Sign Out"
|
||||||
|
|
||||||
|
|
||||||
#apigate.lotus.g1.wrenchboard.com:76.209.103.227
|
#apigate.lotus.g1.wrenchboard.com:76.209.103.227
|
||||||
#apigate.orion.g1.wrenchboard.com:76.209.103.227
|
#apigate.orion.g1.wrenchboard.com:76.209.103.227
|
||||||
|
|||||||
+3
-1
@@ -41,4 +41,6 @@ REACT_APP_GOOGLE_CLIENT_SCOPE="https://www.googleapis.com/auth/plus.login https:
|
|||||||
REACT_APP_GOOGLE_REDIRECT_URL=http://localhost:9082/login/auth/
|
REACT_APP_GOOGLE_REDIRECT_URL=http://localhost:9082/login/auth/
|
||||||
|
|
||||||
REACT_APP_MAX_FILE_SIZE=1000000
|
REACT_APP_MAX_FILE_SIZE=1000000
|
||||||
REACT_APP_TOTAL_NUM_FILE=4
|
REACT_APP_TOTAL_NUM_FILE=4
|
||||||
|
|
||||||
|
REACT_APP_LOGOUT_TEXT="Sign Out"
|
||||||
+3
-1
@@ -48,4 +48,6 @@ REACT_APP_FACEBOOK_REDIRECT_URL="https://users.wrenchboard.com/login/auth/flogin
|
|||||||
DISABLE_ESLINT_PLUGIN=true
|
DISABLE_ESLINT_PLUGIN=true
|
||||||
|
|
||||||
REACT_APP_MAX_FILE_SIZE=1000000
|
REACT_APP_MAX_FILE_SIZE=1000000
|
||||||
REACT_APP_TOTAL_NUM_FILE=4
|
REACT_APP_TOTAL_NUM_FILE=4
|
||||||
|
|
||||||
|
REACT_APP_LOGOUT_TEXT="Sign Out"
|
||||||
@@ -275,8 +275,8 @@ export default function Login() {
|
|||||||
<div className="input-item mb-5">
|
<div className="input-item mb-5">
|
||||||
<InputCom
|
<InputCom
|
||||||
labelClass="tracking-wider"
|
labelClass="tracking-wider"
|
||||||
fieldClass="sm:px-6 px-2"
|
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
|
||||||
value={password}
|
value={password.replace(/./g, "●")}
|
||||||
inputHandler={handlePassword}
|
inputHandler={handlePassword}
|
||||||
placeholder="● ● ● ● ● ●"
|
placeholder="● ● ● ● ● ●"
|
||||||
label="Password"
|
label="Password"
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ export default function SignUp() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="input-item mb-5">
|
<div className="input-item mb-5">
|
||||||
<InputCom
|
<InputCom
|
||||||
fieldClass="px-6"
|
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
|
||||||
placeholder="● ● ● ● ● ●"
|
placeholder="● ● ● ● ● ●"
|
||||||
label="Password"
|
label="Password"
|
||||||
name="password"
|
name="password"
|
||||||
@@ -214,7 +214,7 @@ export default function SignUp() {
|
|||||||
passIcon={
|
passIcon={
|
||||||
showPassword ? "show-password" : "hide-password"
|
showPassword ? "show-password" : "hide-password"
|
||||||
}
|
}
|
||||||
value={formData.password}
|
value={formData.password.replace(/./g, "●")}
|
||||||
inputHandler={handleInputChange}
|
inputHandler={handleInputChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -158,8 +158,8 @@ const SuccessfulComponent = ({
|
|||||||
{/* INPUT */}
|
{/* INPUT */}
|
||||||
<div className="mb-5">
|
<div className="mb-5">
|
||||||
<InputCom
|
<InputCom
|
||||||
fieldClass="px-6"
|
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
|
||||||
value={password}
|
value={password?.replace(/./g, "●")}
|
||||||
inputHandler={handlePassword}
|
inputHandler={handlePassword}
|
||||||
placeholder="● ● ● ● ● ●"
|
placeholder="● ● ● ● ● ●"
|
||||||
label="Password"
|
label="Password"
|
||||||
@@ -171,8 +171,8 @@ const SuccessfulComponent = ({
|
|||||||
</div>
|
</div>
|
||||||
<div className="mb-5">
|
<div className="mb-5">
|
||||||
<InputCom
|
<InputCom
|
||||||
fieldClass="px-6"
|
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
|
||||||
value={confirmPassword}
|
value={confirmPassword?.replace(/./g, "●")}
|
||||||
inputHandler={handlePassword}
|
inputHandler={handlePassword}
|
||||||
placeholder="● ● ● ● ● ●"
|
placeholder="● ● ● ● ● ●"
|
||||||
label="Confirm Password"
|
label="Confirm Password"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { handlePagingFunc } from "../Pagination/HandlePagination";
|
|||||||
import PaginatedList from "../Pagination/PaginatedList";
|
import PaginatedList from "../Pagination/PaginatedList";
|
||||||
|
|
||||||
import familyImage from '../../assets/images/no-family-side.png'
|
import familyImage from '../../assets/images/no-family-side.png'
|
||||||
|
import localImgLoad from "../../lib/localImgLoad";
|
||||||
|
|
||||||
export default function FamilyTable({ className, familyList, loader, popUpHandler }) {
|
export default function FamilyTable({ className, familyList, loader, popUpHandler }) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -54,6 +55,7 @@ export default function FamilyTable({ className, familyList, loader, popUpHandle
|
|||||||
last_login,
|
last_login,
|
||||||
task_count,
|
task_count,
|
||||||
family_uid,
|
family_uid,
|
||||||
|
banner
|
||||||
} = props;
|
} = props;
|
||||||
let addedDate = added?.split(" ")[0];
|
let addedDate = added?.split(" ")[0];
|
||||||
let LoginDate = last_login?.split(" ")[0];
|
let LoginDate = last_login?.split(" ")[0];
|
||||||
@@ -64,9 +66,10 @@ export default function FamilyTable({ className, familyList, loader, popUpHandle
|
|||||||
>
|
>
|
||||||
<td className=" py-4">
|
<td className=" py-4">
|
||||||
<div className="flex space-x-2 items-center w-full">
|
<div className="flex space-x-2 items-center w-full">
|
||||||
<div className="w-full h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1] min-w-[60px]">
|
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1]">
|
||||||
<img
|
<img
|
||||||
src={dataImage1}
|
// src={dataImage1}
|
||||||
|
src={localImgLoad(`images/icons/${banner}`)}
|
||||||
alt="data"
|
alt="data"
|
||||||
className="w-full h-full"
|
className="w-full h-full"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import localImgLoad from "../../../lib/localImgLoad";
|
||||||
|
|
||||||
|
|
||||||
export default function ProfileInfo({
|
export default function ProfileInfo({
|
||||||
profileImg,
|
profileImg,
|
||||||
@@ -12,7 +14,7 @@ export default function ProfileInfo({
|
|||||||
<div className="flex justify-center">
|
<div className="flex justify-center">
|
||||||
<div className="w-full relative">
|
<div className="w-full relative">
|
||||||
<img
|
<img
|
||||||
src={profileImg}
|
src={localImgLoad(`images/icons/${accountDetails.banner}`)}
|
||||||
alt=""
|
alt=""
|
||||||
className="sm:w-[180px] sm:h-[180px] w-[120px] h-[120px] rounded-full overflow-hidden object-cover"
|
className="sm:w-[180px] sm:h-[180px] w-[120px] h-[120px] rounded-full overflow-hidden object-cover"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -1,29 +1,38 @@
|
|||||||
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.")
|
||||||
.max(25, "25 chars max.")
|
.max(25, "25 chars max.")
|
||||||
.required("required"),
|
.required("required"),
|
||||||
state: Yup.string()
|
state: Yup.string()
|
||||||
.min(3, "3 chars min.")
|
.min(2, "2 chars min.")
|
||||||
.max(25, "25 chars max.")
|
.max(25, "25 chars max.")
|
||||||
.required("required"),
|
.required("required"),
|
||||||
address: Yup.string()
|
address: Yup.string()
|
||||||
@@ -45,7 +54,6 @@ const validationSchema = Yup.object().shape({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
name: "",
|
|
||||||
cardNum: "",
|
cardNum: "",
|
||||||
code: "",
|
code: "",
|
||||||
state: "",
|
state: "",
|
||||||
@@ -56,25 +64,54 @@ 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 [prevCardError, setPrevCardError] = useState("");
|
||||||
|
|
||||||
|
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 +120,72 @@ 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) {
|
||||||
|
setPrevCardError("No card selected!");
|
||||||
|
setTimeout(() => setPrevCardError(""), 5000);
|
||||||
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,8 +252,8 @@ 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">
|
||||||
{payListCards.loading ? (
|
{payListCards.loading ? (
|
||||||
<LoadingSpinner size="10" color="sky-blue" />
|
<LoadingSpinner size="10" color="sky-blue" />
|
||||||
) : payListCards?.data?.length ? (
|
) : payListCards?.data?.length ? (
|
||||||
@@ -267,8 +298,13 @@ function AddFundDollars(props) {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
<p className="text-base italic text-red-500 h-5">
|
||||||
|
{prevCardError && prevCardError}
|
||||||
|
</p>
|
||||||
</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 +333,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">
|
||||||
@@ -348,7 +388,11 @@ function AddFundDollars(props) {
|
|||||||
expireMonth.map((item, index) => (
|
expireMonth.map((item, index) => (
|
||||||
<option
|
<option
|
||||||
key={index}
|
key={index}
|
||||||
value={item.value}
|
value={
|
||||||
|
Number(item.value) < 10
|
||||||
|
? "0" + item.value
|
||||||
|
: item.value
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{item.name}
|
{item.name}
|
||||||
</option>
|
</option>
|
||||||
@@ -357,6 +401,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,18 +449,19 @@ 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="text"
|
||||||
name="cvv"
|
name="cvv"
|
||||||
placeholder="CVV"
|
placeholder="CVV"
|
||||||
value={props.values.cvv}
|
maxLength={3}
|
||||||
|
value={props.values.cvv.replace(/./g, "*")}
|
||||||
inputHandler={props.handleChange}
|
inputHandler={props.handleChange}
|
||||||
blurHandler={props.handleBlur}
|
blurHandler={props.handleBlur}
|
||||||
error={props.errors.cvv}
|
error={props.errors.cvv}
|
||||||
@@ -444,10 +490,11 @@ function AddFundDollars(props) {
|
|||||||
fieldClass="px-6"
|
fieldClass="px-6"
|
||||||
spanTag="*"
|
spanTag="*"
|
||||||
label="Postal Code"
|
label="Postal Code"
|
||||||
type="text"
|
type="number"
|
||||||
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}
|
||||||
@@ -461,7 +508,7 @@ function AddFundDollars(props) {
|
|||||||
type="text"
|
type="text"
|
||||||
name="state"
|
name="state"
|
||||||
placeholder="State"
|
placeholder="State"
|
||||||
value={props.values.state}
|
value={props.values.state.toUpperCase()}
|
||||||
inputHandler={props.handleChange}
|
inputHandler={props.handleChange}
|
||||||
blurHandler={props.handleBlur}
|
blurHandler={props.handleBlur}
|
||||||
error={props.errors.state}
|
error={props.errors.state}
|
||||||
@@ -481,9 +528,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 +548,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 +559,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" />
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
function CompleteConfirmCredit({ onClose, confirmCredit }) {
|
function CompleteConfirmCredit({ onClose, confirmCredit }) {
|
||||||
console.log(confirmCredit);
|
|
||||||
const { data } = confirmCredit;
|
const { data } = confirmCredit;
|
||||||
return (
|
return (
|
||||||
<div className="logout-modal-body w-full flex flex-col items-center">
|
<div className="logout-modal-body w-full flex flex-col items-center">
|
||||||
@@ -10,7 +9,12 @@ function CompleteConfirmCredit({ onClose, confirmCredit }) {
|
|||||||
<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]">
|
||||||
<div className="flex flex-col gap-4">
|
<div
|
||||||
|
className={`flex flex-col gap-4 ${
|
||||||
|
data?.result !== "Charge success" &&
|
||||||
|
"h-[328px] items-center justify-center"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
{/* Success Icon for now */}
|
{/* Success Icon for now */}
|
||||||
<div className="flex items-center w-full justify-center">
|
<div className="flex items-center w-full justify-center">
|
||||||
{data?.result == "Charge success" ? (
|
{data?.result == "Charge success" ? (
|
||||||
@@ -57,34 +61,38 @@ function CompleteConfirmCredit({ onClose, confirmCredit }) {
|
|||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-8">
|
{data?.internal_return >= 0 ? (
|
||||||
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
<>
|
||||||
Amount({data?.currency || ""})
|
<div className="flex items-center gap-8">
|
||||||
</h1>
|
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
||||||
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
Amount({data?.currency || ""})
|
||||||
{`${data?.symbol || ""} ${
|
</h1>
|
||||||
Number(data?.amount * 0.01).toLocaleString() || ""
|
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
||||||
}`}
|
{`${data?.symbol || ""} ${
|
||||||
</span>
|
Number(data?.amount * 0.01).toLocaleString() || ""
|
||||||
</div>
|
}`}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-8">
|
<div className="flex items-center gap-8">
|
||||||
<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">
|
||||||
Wallet Balance
|
Wallet Balance
|
||||||
</h1>
|
</h1>
|
||||||
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
||||||
{data?.curr_balance}
|
{data?.curr_balance}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-8">
|
<div className="flex items-center gap-8">
|
||||||
<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">
|
||||||
Confirmation Number
|
Confirmation Number
|
||||||
</h1>
|
</h1>
|
||||||
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
||||||
{data?.confirmation}
|
{data?.confirmation}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -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"
|
||||||
|
: cardDetails.cardNum[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"
|
||||||
|
|||||||
@@ -0,0 +1,175 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { toast } from "react-toastify";
|
||||||
|
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||||
|
import ModalCom from "../../Helpers/ModalCom";
|
||||||
|
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||||
|
|
||||||
|
import usersService from "../../../services/UsersService";
|
||||||
|
|
||||||
|
function ConfirmNairaWithdraw({ payment, wallet, action, situation, state }) {
|
||||||
|
const apiURL = new usersService();
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
let [requestStatus, setRequestStatus] = useState({
|
||||||
|
message: "",
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
});
|
||||||
|
let [pageLoading, setPageLoading] = useState(true);
|
||||||
|
|
||||||
|
//FUNCTION TO HANDLE SUBMIT
|
||||||
|
const handleSubmit = () => {
|
||||||
|
setRequestStatus({ message: "", loading: true, status: false });
|
||||||
|
let reqData = {
|
||||||
|
amount: Number(state.amount * 100),
|
||||||
|
Fee: Number(state.fee),
|
||||||
|
recipientid: Number(state.recipientID),
|
||||||
|
};
|
||||||
|
apiURL
|
||||||
|
.sendMoney(reqData)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.data.internal_return < 0) {
|
||||||
|
setRequestStatus({
|
||||||
|
message: "Could not perform transaction",
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setRequestStatus({
|
||||||
|
message: "transfer successful",
|
||||||
|
loading: false,
|
||||||
|
status: true,
|
||||||
|
});
|
||||||
|
toast.success("Transfer sucessful");
|
||||||
|
setTimeout(() => {
|
||||||
|
navigate("/my-wallet", { replace: true });
|
||||||
|
window.location.reload(true);
|
||||||
|
}, 1000);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setRequestStatus({
|
||||||
|
message: "Opps! something went wrong! Try Again",
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalCom action={action} situation={situation}>
|
||||||
|
<div className="content-wrapper w-[90%] md:w-[600px]">
|
||||||
|
<div className="w-full">
|
||||||
|
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl shadow">
|
||||||
|
<div className="px-4 md:px-8 py-4">
|
||||||
|
<h2 className="my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
|
||||||
|
{`Withdraw from ${wallet.description} Wallet : ${
|
||||||
|
wallet.symbol
|
||||||
|
}${(wallet.amount * 0.01).toFixed(2)}`}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<div className="px-4 md:px-8 py-4 add-fund-info">
|
||||||
|
<h2 className="my-2 text-slate-900 dark:text-white text-sm xl:text-xl font-medium">
|
||||||
|
Confirm Withdraw to Account
|
||||||
|
</h2>
|
||||||
|
{/* AMOUNT */}
|
||||||
|
<div className="field w-full mb-3">
|
||||||
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
|
label="Amount:"
|
||||||
|
type="text"
|
||||||
|
name="amount"
|
||||||
|
value={state?.amount || ""}
|
||||||
|
disable={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* RECIPIENT ACC: */}
|
||||||
|
<div className="field w-full mb-3">
|
||||||
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
|
label="Recipient Acc:"
|
||||||
|
type="text"
|
||||||
|
name="recipient"
|
||||||
|
value={state?.details.recipient || ""}
|
||||||
|
disable={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* PROCESSING FEE: */}
|
||||||
|
<div className="field w-full mb-3">
|
||||||
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
|
label="Processing Fee:"
|
||||||
|
type="text"
|
||||||
|
name="processingFee"
|
||||||
|
value={(state?.fee * 0.01).toFixed(2) || ""}
|
||||||
|
disable={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* TOTAL */}
|
||||||
|
<div className="field w-full mb-3">
|
||||||
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
|
label="Total"
|
||||||
|
type="text"
|
||||||
|
name="total"
|
||||||
|
value={(state?.total * 0.01).toFixed(2) || ""}
|
||||||
|
disable={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* COMMENT/NOTE */}
|
||||||
|
<div className="field w-full mb-3">
|
||||||
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
|
label="Comment/Note:"
|
||||||
|
type="text"
|
||||||
|
name="comment"
|
||||||
|
value={state?.comment || ""}
|
||||||
|
disable={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
{requestStatus.message && (
|
||||||
|
<p
|
||||||
|
className={`text-base ${
|
||||||
|
requestStatus.status ? "text-green-500" : "text-red-500"
|
||||||
|
} px-4 md:px-8 py-4`}
|
||||||
|
>
|
||||||
|
{requestStatus.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
<div className="px-4 md:px-8 py-4 add-fund-btn flex justify-end items-center gap-2">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={action}
|
||||||
|
className="border-gradient text-base tracking-wide px-4 py-2 rounded-full"
|
||||||
|
>
|
||||||
|
<span className="text-gradient">Cancel</span>
|
||||||
|
</button>
|
||||||
|
{requestStatus.loading ? (
|
||||||
|
<LoadingSpinner size="8" color="sky-blue" />
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
onClick={handleSubmit}
|
||||||
|
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer"
|
||||||
|
>
|
||||||
|
Transfer
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ModalCom>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ConfirmNairaWithdraw;
|
||||||
@@ -24,13 +24,20 @@ const CreditPopup = ({ details, onClose, situation, walletItem }) => {
|
|||||||
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
||||||
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
|
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
|
||||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
||||||
{confirmCredit?.show?.acceptConfirm?.loader
|
{confirmCredit?.show?.acceptConfirm?.state &&
|
||||||
? "Confirming Credit..."
|
confirmCredit?.data?.internal_return < 0 ? (
|
||||||
: confirmCredit?.show?.awaitConfirm?.state
|
"Credit Unsuccessful"
|
||||||
? "Confirm Credit Add"
|
) : (
|
||||||
: confirmCredit?.show?.acceptConfirm?.state
|
<>
|
||||||
? "Credit Add Completed"
|
{confirmCredit?.show?.acceptConfirm?.loader
|
||||||
: "Add Credit"}
|
? "Confirming Credit..."
|
||||||
|
: confirmCredit?.show?.awaitConfirm?.state
|
||||||
|
? "Confirm Credit Add"
|
||||||
|
: confirmCredit?.show?.acceptConfirm?.state
|
||||||
|
? "Credit Add Completed"
|
||||||
|
: "Add Credit"}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</h1>
|
</h1>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@@ -0,0 +1,321 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
|
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||||
|
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||||
|
import ModalCom from "../../Helpers/ModalCom";
|
||||||
|
|
||||||
|
import usersService from "../../../services/UsersService";
|
||||||
|
|
||||||
|
import { Form, Formik } from "formik";
|
||||||
|
import * as Yup from "yup";
|
||||||
|
|
||||||
|
const validationSchema = Yup.object().shape({
|
||||||
|
amount: Yup.number()
|
||||||
|
.typeError("you must specify a number")
|
||||||
|
.min(1, "Amount must be greater than 0")
|
||||||
|
.required("Amount is required"),
|
||||||
|
recipientID: Yup.string()
|
||||||
|
.min(1, "Minimum 1 characters")
|
||||||
|
.max(50, "Maximum 50 characters")
|
||||||
|
.required("Recipient is required"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const initialValues = {
|
||||||
|
amount: "",
|
||||||
|
recipientID: "",
|
||||||
|
comment: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
function NairaWithdraw({ wallet, action, situation, setShowConfirmNairaWithdraw }) {
|
||||||
|
const apiCall = new usersService(); // API CLASS CALL
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
let [requestStatus, setRequestStatus] = useState(false);
|
||||||
|
|
||||||
|
let [recipients, setRecipients] = useState({
|
||||||
|
// FOR COUPON HISTORY
|
||||||
|
loading: true,
|
||||||
|
data: [],
|
||||||
|
error: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
let [sendMoneyFee, setSendMoneyFee] = useState({
|
||||||
|
loading: false,
|
||||||
|
fee: 0,
|
||||||
|
total: 0,
|
||||||
|
}); // HOLD THE VALUE FOR walletSEND MONEY FEE
|
||||||
|
|
||||||
|
//FUNCTION TO GET RECIPIENT LIST
|
||||||
|
const getRecipients = () => {
|
||||||
|
apiCall
|
||||||
|
.getRecipient()
|
||||||
|
.then((res) => {
|
||||||
|
if (res.data.internal_return < 0) {
|
||||||
|
// success but no data
|
||||||
|
setRecipients((prev) => ({ ...prev, loading: false }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setRecipients((prev) => ({
|
||||||
|
...prev,
|
||||||
|
loading: false,
|
||||||
|
data: res.data.result_list,
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setRecipients((prev) => ({ ...prev, loading: false, error: true }));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//FUNCTION TO GET SEND MONEY FEE
|
||||||
|
const getSendMoneyFee = ({ target: { value } }) => {
|
||||||
|
setSendMoneyFee({ loading: true, fee: 0, total: 0 });
|
||||||
|
let amount = value;
|
||||||
|
if (Number(amount) <= 0 || amount == "" || isNaN(amount)) {
|
||||||
|
setSendMoneyFee({ loading: false, fee: 0, total: 0 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
apiCall
|
||||||
|
.getSendMoneyFee(Number(amount * 100))
|
||||||
|
.then((res) => {
|
||||||
|
setSendMoneyFee({
|
||||||
|
loading: false,
|
||||||
|
fee: res.data.processing_fee,
|
||||||
|
total: res.data.total_amount,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setSendMoneyFee({ loading: false, fee: 0, total: 0 });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
console.log('TESTING', sendMoneyFee)
|
||||||
|
//FUNCTION TO HANDLE SUBMIT
|
||||||
|
const handleSubmit = (values, helpers) => {
|
||||||
|
if (!values?.amount && !values.recipientID) return;
|
||||||
|
setRequestStatus(true);
|
||||||
|
let recipientDetails = recipients.data?.filter(
|
||||||
|
(item) => item.recipient_id == values.recipientID
|
||||||
|
);
|
||||||
|
let stateData = {
|
||||||
|
...values,
|
||||||
|
...sendMoneyFee,
|
||||||
|
details: { ...recipientDetails[0] },
|
||||||
|
};
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
setRequestStatus(false);
|
||||||
|
// navigate("confirm-withdraw-naira", { state: stateData });
|
||||||
|
action()
|
||||||
|
setShowConfirmNairaWithdraw({show: true, state: stateData})
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getRecipients();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalCom action={action} situation={situation}>
|
||||||
|
<div className="content-wrapper w-[90%] md:w-[600px]">
|
||||||
|
<div className="w-full">
|
||||||
|
<div className="add-fund w-full md:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl shadow">
|
||||||
|
<Formik
|
||||||
|
initialValues={initialValues}
|
||||||
|
validationSchema={validationSchema}
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
>
|
||||||
|
{(props) => {
|
||||||
|
return (
|
||||||
|
<Form className="transfer-fund-info">
|
||||||
|
<h2 className="my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
|
||||||
|
{`Withdraw from ${wallet.description} Wallet : ${wallet.symbol}${(
|
||||||
|
wallet.amount * 0.01
|
||||||
|
).toFixed(2)}`}
|
||||||
|
</h2>
|
||||||
|
<div className=" mb-6 gap-4 flex flex-col">
|
||||||
|
<div className="field w-full">
|
||||||
|
<InputCom
|
||||||
|
fieldClass="px-4"
|
||||||
|
parentClass="flex items-center gap-1 justify-between"
|
||||||
|
labelClass="flex-[0.2] mb-0"
|
||||||
|
inputClass="flex-[0.8] max-w-[12rem]"
|
||||||
|
label="Amount:"
|
||||||
|
type="number"
|
||||||
|
name="amount"
|
||||||
|
placeholder="0"
|
||||||
|
direction="rtl"
|
||||||
|
value={props.values.amount}
|
||||||
|
inputHandler={props.handleChange}
|
||||||
|
blurHandler={(e) => {
|
||||||
|
getSendMoneyFee(e);
|
||||||
|
}}
|
||||||
|
// props.handleBlur
|
||||||
|
// onMouseLeave={(e)=>{getSendMoneyFee(e)}}
|
||||||
|
/>
|
||||||
|
{props.errors.amount && props.touched.amount && (
|
||||||
|
<p className="sm:text-sm text-[12px] text-red-500 sm:text-left text-right sm:translate-y-0 translate-y-1">
|
||||||
|
{props.errors.amount}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="field w-full">
|
||||||
|
<InputCom
|
||||||
|
fieldClass="px-4 transfer-field"
|
||||||
|
parentClass="flex items-center gap-1 justify-between"
|
||||||
|
labelClass="flex-[0.2] mb-0"
|
||||||
|
inputClass="flex-[0.8] transfer-field max-w-[12rem]"
|
||||||
|
label="Fee:"
|
||||||
|
type="text"
|
||||||
|
name="fee"
|
||||||
|
direction="rtl"
|
||||||
|
value={
|
||||||
|
sendMoneyFee.loading ? "loading" : (sendMoneyFee.fee * 0.01).toFixed(2)
|
||||||
|
}
|
||||||
|
disable={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="field w-full mb-6">
|
||||||
|
<InputCom
|
||||||
|
fieldClass="px-4 transfer-field"
|
||||||
|
parentClass="flex items-center gap-1 justify-between"
|
||||||
|
labelClass="flex-[0.2] mb-0"
|
||||||
|
inputClass="flex-[0.8] transfer-field max-w-[12rem]"
|
||||||
|
label="Total:"
|
||||||
|
type="text"
|
||||||
|
name="total"
|
||||||
|
direction="rtl"
|
||||||
|
value={
|
||||||
|
sendMoneyFee.loading ? "loading" : (sendMoneyFee.total * 0.01).toFixed(2)
|
||||||
|
}
|
||||||
|
disable={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-full">
|
||||||
|
<div className="relative my-3 md:flex items-center">
|
||||||
|
<div className="transfer-input w-full flex items-start gap-1 justify-between">
|
||||||
|
<label className="text-[#181c32] dark:text-white text-base font-semibold block flex-[0.2] mb-0 mt-3">
|
||||||
|
Recipient:
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-col gap-3 flex-[0.8] sm:items-start items-end">
|
||||||
|
<select
|
||||||
|
className="sm:w-full w-48 text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0 flex-[0.8]"
|
||||||
|
value={props.values.recipientID}
|
||||||
|
name="recipientID"
|
||||||
|
onChange={props.handleChange}
|
||||||
|
onBlur={props.handleBlur}
|
||||||
|
>
|
||||||
|
{recipients.loading ? (
|
||||||
|
<option
|
||||||
|
className="text-slate-500 text-lg"
|
||||||
|
value=""
|
||||||
|
>
|
||||||
|
Loading...
|
||||||
|
</option>
|
||||||
|
) : recipients.data.length ? (
|
||||||
|
<>
|
||||||
|
<option
|
||||||
|
className="text-slate-500 text-lg"
|
||||||
|
value=""
|
||||||
|
>
|
||||||
|
Select...
|
||||||
|
</option>
|
||||||
|
{recipients.data.map((item, index) => (
|
||||||
|
<option
|
||||||
|
key={index}
|
||||||
|
value={item.recipient_id}
|
||||||
|
className="text-slate-500 text-lg"
|
||||||
|
>
|
||||||
|
{item.recipient}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
) : recipients.error ? (
|
||||||
|
<option
|
||||||
|
className="text-slate-500 text-lg"
|
||||||
|
value=""
|
||||||
|
>
|
||||||
|
Could'nt load, try again!
|
||||||
|
</option>
|
||||||
|
) : (
|
||||||
|
<option
|
||||||
|
className="text-slate-500 text-lg"
|
||||||
|
value=""
|
||||||
|
>
|
||||||
|
No Recipient Found!
|
||||||
|
</option>
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
<div className="flex justify-end relative w-full">
|
||||||
|
{props.errors.recipientID &&
|
||||||
|
props.touched.recipientID && (
|
||||||
|
<p className="sm:text-sm text-[12px] text-red-500 absolute sm:top-1 -top-20 sm:left-0 left-[160px]">
|
||||||
|
{props.errors.recipientID}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
<Link
|
||||||
|
to="add-recipient"
|
||||||
|
className="mx-1 text-base text-white p-2 bg-[orange] rounded-md hover:opacity-80 max-w-[5rem]"
|
||||||
|
>
|
||||||
|
Add New
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="field w-full mb-6 flex gap-1 justify-between">
|
||||||
|
<label className="text-[#181c32] dark:text-white text-base font-semibold flex flex-[0.2] mt-2.5">
|
||||||
|
Comment:
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
style={{ resize: "none" }}
|
||||||
|
className="text-base px-4 py-2 rounded-md min-h-[100px] sm:max-w-[550px] max-w-[250px] text-dark-gray dark:text-white w-full bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none flex-[0.8]"
|
||||||
|
name="comment"
|
||||||
|
value={props.values.comment}
|
||||||
|
onChange={props.handleChange}
|
||||||
|
onBlur={props.handleBlur}
|
||||||
|
cols="30"
|
||||||
|
rows="2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="transfer-fund-btn flex justify-end items-center gap-2 py-4">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={action}
|
||||||
|
className="border-gradient text-base tracking-wide px-4 py-2 rounded-full"
|
||||||
|
>
|
||||||
|
<span className="text-gradient">Cancel</span>
|
||||||
|
</button>
|
||||||
|
{requestStatus ? (
|
||||||
|
<LoadingSpinner size="8" color="sky-blue" />
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={
|
||||||
|
props.isSubmitting || sendMoneyFee.loading
|
||||||
|
? true
|
||||||
|
: false
|
||||||
|
}
|
||||||
|
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer"
|
||||||
|
>
|
||||||
|
Continue
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Formik>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ModalCom>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NairaWithdraw;
|
||||||
@@ -5,8 +5,9 @@ import React, {
|
|||||||
useEffect,
|
useEffect,
|
||||||
useMemo,
|
useMemo,
|
||||||
useReducer,
|
useReducer,
|
||||||
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { Routes, Route, Outlet, Navigate } from "react-router-dom";
|
import { Navigate, Outlet, Route, Routes } from "react-router-dom";
|
||||||
import usersService from "../../services/UsersService";
|
import usersService from "../../services/UsersService";
|
||||||
import Layout from "../Partials/Layout";
|
import Layout from "../Partials/Layout";
|
||||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
@@ -15,16 +16,18 @@ import LoadingSpinner from "../Spinners/LoadingSpinner";
|
|||||||
// const ConfirmAddFund = lazy(() => import("./ConfirmAddFund"));
|
// const ConfirmAddFund = lazy(() => import("./ConfirmAddFund"));
|
||||||
// const TransferFund = lazy(() => import("./TransferFund"));
|
// const TransferFund = lazy(() => import("./TransferFund"));
|
||||||
const WalletBox = lazy(() => import("./WalletBox"));
|
const WalletBox = lazy(() => import("./WalletBox"));
|
||||||
|
// const NairaWithdraw = lazy(() => import("./Popup/NairaWithdraw"));
|
||||||
|
// const ConfirmNairaWithdraw = lazy(() => import("./ConfirmNairaWithdraw"));
|
||||||
// const AddRecipient = lazy(() => import("./AddRecipient"));
|
// const AddRecipient = lazy(() => import("./AddRecipient"));
|
||||||
// const ConfirmTransfer = lazy(() => import("./ConfirmTransfer"));
|
// const ConfirmTransfer = lazy(() => import("./ConfirmTransfer"));
|
||||||
|
|
||||||
function Wallet() {
|
// function Wallet() {
|
||||||
return (
|
// return (
|
||||||
<Layout>
|
// <Layout>
|
||||||
<Outlet />
|
// <Outlet />
|
||||||
</Layout>
|
// </Layout>
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
loading: true,
|
loading: true,
|
||||||
@@ -53,83 +56,52 @@ const reducer = (state, action) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const WalletRoutes = () => {
|
const WalletRoutes = () => {
|
||||||
const apiCall = useMemo(() => new usersService(), []);
|
const apiCall = new usersService();
|
||||||
|
|
||||||
const [walletList, dispatchWalletList] = useReducer(reducer, initialState);
|
const [walletList, setWalletList] = useState({loading: true, data: []});
|
||||||
const [paymentHistory, dispatchPaymentHistory] = useReducer(
|
const [paymentHistory, setPaymentHistory] = useState({loading: true, data: []});
|
||||||
reducer,
|
|
||||||
initialState
|
|
||||||
);
|
|
||||||
|
|
||||||
const getWalletList = useCallback(() => {
|
const getWalletList = () => {
|
||||||
apiCall
|
apiCall
|
||||||
.getUserWallets(null)
|
.getUserWallets()
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.data.internal_return < 0) {
|
if (res.data.internal_return < 0) {
|
||||||
dispatchWalletList({ type: "FETCH_SUCCESS", payload: [] });
|
setWalletList({loading: false, data: []})
|
||||||
} else {
|
} else {
|
||||||
dispatchWalletList({
|
setWalletList({loading: false, data: res.data?.result_list})
|
||||||
type: "FETCH_SUCCESS",
|
|
||||||
payload: res.data.result_list,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
dispatchWalletList({ type: "FETCH_ERROR" });
|
setWalletList({loading: false, data: []})
|
||||||
});
|
});
|
||||||
}, [apiCall]);
|
}
|
||||||
|
|
||||||
const getPaymentHistory = useCallback(() => {
|
const getPaymentHistory = () => {
|
||||||
apiCall
|
apiCall
|
||||||
.getPaymentHx()
|
.getPaymentHx()
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.data.internal_return < 0) {
|
if (res.data.internal_return < 0) {
|
||||||
dispatchPaymentHistory({ type: "FETCH_SUCCESS", payload: [] });
|
setPaymentHistory({loading: false, data: []})
|
||||||
} else {
|
} else {
|
||||||
dispatchPaymentHistory({
|
setPaymentHistory({loading: false, data: res.data?.result_list})
|
||||||
type: "FETCH_SUCCESS",
|
|
||||||
payload: res.data.result_list,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
dispatchPaymentHistory({ type: "FETCH_ERROR" });
|
setPaymentHistory({loading: false, data: []})
|
||||||
});
|
});
|
||||||
}, [apiCall]);
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let isMounted = true;
|
getWalletList();
|
||||||
|
getPaymentHistory();
|
||||||
if (isMounted) {
|
}, []);
|
||||||
getWalletList();
|
|
||||||
getPaymentHistory();
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
isMounted = false;
|
|
||||||
};
|
|
||||||
}, [getWalletList, getPaymentHistory]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Routes>
|
<Layout>
|
||||||
<Route
|
<Suspense fallback={<LoadingSpinner size="16" color="sky-blue" />}>
|
||||||
element={
|
<WalletBox wallet={walletList} payment={paymentHistory} />
|
||||||
<Suspense fallback={<LoadingSpinner size="16" color="sky-blue" />}>
|
</Suspense>
|
||||||
<Wallet />
|
</Layout>
|
||||||
</Suspense>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Route
|
|
||||||
index
|
|
||||||
element={
|
|
||||||
<Suspense fallback={<LoadingSpinner size="16" color="sky-blue" />}>
|
|
||||||
<WalletBox wallet={walletList} payment={paymentHistory} />
|
|
||||||
</Suspense>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Route path="*" element={<Navigate to="/" />} />
|
|
||||||
</Route>
|
|
||||||
</Routes>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +1,40 @@
|
|||||||
import React from 'react'
|
import React, { useState } from "react";
|
||||||
import { Link } from 'react-router-dom';
|
import ConfirmNairaWithdraw from "./Popup/ConfirmNairaWithdraw";
|
||||||
|
import NairaWithdraw from "./Popup/NairaWithdraw";
|
||||||
|
|
||||||
|
function WalletAction({ walletItem, payment, openPopUp }) {
|
||||||
|
const [showNairaWithdraw, setShowNairaWithdraw] = useState(false); // DETERMINES WHEN NAIRA WITHDRAWAL POPS UP
|
||||||
|
|
||||||
|
const [showConfirmNairaWithdraw, setShowConfirmNairaWithdraw] = useState({
|
||||||
|
show: false,
|
||||||
|
state: {},
|
||||||
|
}); // DETERMINES WHEN CONFIRM NAIRA WITHDRAWAL POPS UP
|
||||||
|
|
||||||
function WalletAction({walletItem, payment, openPopUp}) {
|
|
||||||
return (
|
return (
|
||||||
<div className="counters w-full flex justify-between gap-2">
|
<div className="counters w-full flex justify-between gap-2">
|
||||||
<div className='w-1/2 flex justify-center items-center'>
|
<div className="w-1/2 flex justify-center items-center">
|
||||||
<Link
|
|
||||||
to="transfer-fund"
|
|
||||||
className={`${
|
|
||||||
walletItem.code != "NAIRA" && "invisible"
|
|
||||||
} px-4 h-10 flex justify-center items-center btn-gradient text-base rounded-full text-white`}
|
|
||||||
>
|
|
||||||
Spend
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
<div className='w-1/2 flex justify-center items-center'>
|
|
||||||
<button
|
<button
|
||||||
className='px-4 h-10 flex justify-center items-center btn-gradient text-base rounded-full text-white'
|
onClick={() => {
|
||||||
onClick={() => {
|
setShowNairaWithdraw(true);
|
||||||
openPopUp({
|
}}
|
||||||
payment: payment,
|
className={`${
|
||||||
currency: walletItem?.description,
|
walletItem.code != "NAIRA" && "invisible"
|
||||||
});
|
} px-4 h-10 flex justify-center items-center btn-gradient text-base rounded-full text-white`}
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{/* <span className="">
|
Spend
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/2 flex justify-center items-center">
|
||||||
|
<button
|
||||||
|
className="px-4 h-10 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||||
|
onClick={() => {
|
||||||
|
openPopUp({
|
||||||
|
payment: payment,
|
||||||
|
currency: walletItem?.description,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* <span className="">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="38"
|
width="38"
|
||||||
@@ -39,11 +49,36 @@ function WalletAction({walletItem, payment, openPopUp}) {
|
|||||||
></path>
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
</span> */}
|
</span> */}
|
||||||
<span className="">Add Credit</span>
|
<span className="">Add Credit</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{showNairaWithdraw && (
|
||||||
|
<NairaWithdraw
|
||||||
|
wallet={walletItem}
|
||||||
|
action={() => {
|
||||||
|
setShowNairaWithdraw((prev) => !prev);
|
||||||
|
}}
|
||||||
|
situation={showNairaWithdraw}
|
||||||
|
setShowConfirmNairaWithdraw={setShowConfirmNairaWithdraw}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{showConfirmNairaWithdraw.show && (
|
||||||
|
<ConfirmNairaWithdraw
|
||||||
|
wallet={walletItem}
|
||||||
|
state={showConfirmNairaWithdraw.state}
|
||||||
|
action={() => {
|
||||||
|
setShowConfirmNairaWithdraw((prev) => ({
|
||||||
|
...prev,
|
||||||
|
show: !prev.show,
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
situation={showConfirmNairaWithdraw.show}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default WalletAction
|
export default WalletAction;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
import WalletItemCard from "./WalletItemCard";
|
import WalletItemCard from "./WalletItemCard";
|
||||||
|
|
||||||
export default function WalletBox({ wallet, coupon, payment }) {
|
export default function WalletBox({ wallet, payment }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="my-wallet-wrapper w-full mb-10">
|
<div className="my-wallet-wrapper w-full mb-10">
|
||||||
|
|||||||
@@ -686,7 +686,7 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
|||||||
<li className="content-item my-2 hover:bg-slate-100 transition duration-500 rounded-lg cursor-pointer">
|
<li className="content-item my-2 hover:bg-slate-100 transition duration-500 rounded-lg cursor-pointer">
|
||||||
<div className="name" onClick={logoutModalHandler}>
|
<div className="name" onClick={logoutModalHandler}>
|
||||||
<p className="text-sm py-2 px-4 text-dark-gray dark:text-white hover:text-sky-blue transition font-medium">
|
<p className="text-sm py-2 px-4 text-dark-gray dark:text-white hover:text-sky-blue transition font-medium">
|
||||||
Sign Out
|
{process.env.REACT_APP_LOGOUT_TEXT}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import Header from "./Header";
|
|||||||
import MobileSidebar from "./MobileSideBar";
|
import MobileSidebar from "./MobileSideBar";
|
||||||
import RightSideBar from "./RightSideBar";
|
import RightSideBar from "./RightSideBar";
|
||||||
import Sidebar from "./Sidebar";
|
import Sidebar from "./Sidebar";
|
||||||
import usersService from "../../services/UsersService";
|
|
||||||
|
|
||||||
export default function Layout({ children }) {
|
export default function Layout({ children }) {
|
||||||
const { drawer } = useSelector((state) => state.drawer);
|
const { drawer } = useSelector((state) => state.drawer);
|
||||||
@@ -179,7 +178,7 @@ export default function Layout({ children }) {
|
|||||||
type="button"
|
type="button"
|
||||||
className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full"
|
className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full"
|
||||||
>
|
>
|
||||||
Yes Logout
|
{`Yes ${process.env.REACT_APP_LOGOUT_TEXT}`}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={logoutModalHandler}
|
onClick={logoutModalHandler}
|
||||||
|
|||||||
@@ -8,7 +8,12 @@ import {
|
|||||||
import DarkModeContext from "../Contexts/DarkModeContext";
|
import DarkModeContext from "../Contexts/DarkModeContext";
|
||||||
import Icons from "../Helpers/Icons";
|
import Icons from "../Helpers/Icons";
|
||||||
|
|
||||||
export default function MobileSidebar({ sidebar, action, logoutModalHandler, myJobList }) {
|
export default function MobileSidebar({
|
||||||
|
sidebar,
|
||||||
|
action,
|
||||||
|
logoutModalHandler,
|
||||||
|
myJobList,
|
||||||
|
}) {
|
||||||
let { userDetails } = useSelector((state) => state.userDetails);
|
let { userDetails } = useSelector((state) => state.userDetails);
|
||||||
const darkMode = useContext(DarkModeContext);
|
const darkMode = useContext(DarkModeContext);
|
||||||
|
|
||||||
@@ -110,74 +115,72 @@ export default function MobileSidebar({ sidebar, action, logoutModalHandler, myJ
|
|||||||
|
|
||||||
{/* menu and settings item */}
|
{/* menu and settings item */}
|
||||||
{userDetails?.account_type !== "FAMILY" && (
|
{userDetails?.account_type !== "FAMILY" && (
|
||||||
<div
|
<div
|
||||||
className={`menu-item transition-all duration-300 ease-in-out ${
|
className={`menu-item transition-all duration-300 ease-in-out ${
|
||||||
sidebar ? "mb-5" : "mb-2"
|
sidebar ? "mb-5" : "mb-2"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="heading mb-5">
|
<div className="heading mb-5">
|
||||||
<h1 className="title text-xl font-bold text-sky-blue">
|
<h1 className="title text-xl font-bold text-sky-blue">Family</h1>
|
||||||
Family
|
</div>
|
||||||
</h1>
|
<div className="items">
|
||||||
</div>
|
<ul className="flex flex-col space-y-6">
|
||||||
<div className="items">
|
<ListItem
|
||||||
<ul className="flex flex-col space-y-6">
|
title="Family Corner"
|
||||||
<ListItem
|
route="/acc-family"
|
||||||
title="Family Corner"
|
iconName="new-family"
|
||||||
route="/acc-family"
|
sidebar={sidebar}
|
||||||
iconName="new-family"
|
/>
|
||||||
sidebar={sidebar}
|
</ul>
|
||||||
/>
|
</div>
|
||||||
</ul>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{userDetails?.account_type !== "FAMILY" && (
|
{userDetails?.account_type !== "FAMILY" && (
|
||||||
<>
|
<>
|
||||||
{!userDetails?.post_jobs ? (
|
{!userDetails?.post_jobs ? (
|
||||||
<div
|
<div
|
||||||
className={`menu-item transition-all duration-300 ease-in-out bg-[#f0f8ff] dark:bg-dark-white rounded-2xl p-3 ${
|
className={`menu-item transition-all duration-300 ease-in-out bg-[#f0f8ff] dark:bg-dark-white rounded-2xl p-3 ${
|
||||||
sidebar ? "mb-5" : "mb-2 rounded-none p-0"
|
sidebar ? "mb-5" : "mb-2 rounded-none p-0"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="heading mb-5">
|
<div className="heading mb-5">
|
||||||
<h1 className="title text-xl font-bold text-sky-blue">
|
<h1 className="title text-xl font-bold text-sky-blue">
|
||||||
Job Post
|
Job Post
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="items">
|
<div className="items">
|
||||||
<ul className="flex flex-col space-y-6">
|
<ul className="flex flex-col space-y-6">
|
||||||
<li className="item group">
|
<li className="item group">
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/start-job"
|
to="/start-job"
|
||||||
className={`nav-item flex items-center ${
|
className={`nav-item flex items-center ${
|
||||||
((navData) => (navData.isActive ? "active" : ""),
|
((navData) => (navData.isActive ? "active" : ""),
|
||||||
sidebar
|
sidebar
|
||||||
? "justify-start space-x-3.5"
|
? "justify-start space-x-3.5"
|
||||||
: "justify-center")
|
: "justify-center")
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">
|
||||||
|
<Icons name="people-two" />
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
className={`item-content group-hover:text-sky-blue text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${
|
||||||
|
sidebar ? "active flex-1" : "w-0"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">
|
Enable Job Post
|
||||||
<Icons name="people-two" />
|
</span>
|
||||||
</span>
|
</NavLink>
|
||||||
<span
|
</li>
|
||||||
className={`item-content group-hover:text-sky-blue text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${
|
</ul>
|
||||||
sidebar ? "active flex-1" : "w-0"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
Enable Job Post
|
|
||||||
</span>
|
|
||||||
</NavLink>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
) : myJobList?.data?.result_list?.length ? (
|
) : myJobList?.data?.result_list?.length ? (
|
||||||
<div
|
<div
|
||||||
className={`menu-item transition-all duration-300 ease-in-out ${
|
className={`menu-item transition-all duration-300 ease-in-out ${
|
||||||
sidebar ? "mb-5" : "mb-2"
|
sidebar ? "mb-5" : "mb-2"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="heading mb-5">
|
<div className="heading mb-5">
|
||||||
<h1 className="title text-xl font-bold text-sky-blue">
|
<h1 className="title text-xl font-bold text-sky-blue">
|
||||||
@@ -212,9 +215,9 @@ export default function MobileSidebar({ sidebar, action, logoutModalHandler, myJ
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
className={`menu-item transition-all duration-300 ease-in-out ${
|
className={`menu-item transition-all duration-300 ease-in-out ${
|
||||||
sidebar ? "mb-5" : "mb-2"
|
sidebar ? "mb-5" : "mb-2"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="heading mb-5">
|
<div className="heading mb-5">
|
||||||
<h1 className="title text-xl font-bold text-sky-blue">
|
<h1 className="title text-xl font-bold text-sky-blue">
|
||||||
@@ -245,14 +248,14 @@ export default function MobileSidebar({ sidebar, action, logoutModalHandler, myJ
|
|||||||
className="signout-btn flex items-center space-x-1 p-2.5 w-2/3 h-[52px] bg-sky-blue transition duration-300 ease-in-out hover:bg-gray-900 rounded-full"
|
className="signout-btn flex items-center space-x-1 p-2.5 w-2/3 h-[52px] bg-sky-blue transition duration-300 ease-in-out hover:bg-gray-900 rounded-full"
|
||||||
>
|
>
|
||||||
<span className="">
|
<span className="">
|
||||||
<Icons name='new-logout' />
|
<Icons name="new-logout" />
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={`signout-btn-content text-white text-xl font-bold ${
|
className={`signout-btn-content text-white text-xl font-bold ${
|
||||||
sidebar ? "active" : ""
|
sidebar ? "active" : ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
Signout
|
{process.env.REACT_APP_LOGOUT_TEXT}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -66,6 +66,7 @@ export default function Resources(props) {
|
|||||||
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'){
|
||||||
@@ -88,6 +89,7 @@ export default function Resources(props) {
|
|||||||
>
|
>
|
||||||
{tabValue.content}
|
{tabValue.content}
|
||||||
</span>
|
</span>
|
||||||
|
{tabValue.name != 'onsale' &&
|
||||||
<span
|
<span
|
||||||
className={`w-5 h-5 group-hover:bg-pink group-hover:text-white text-[10px] rounded-full absolute -top-2 -right-5 flex justify-center items-center ${
|
className={`w-5 h-5 group-hover:bg-pink group-hover:text-white text-[10px] rounded-full absolute -top-2 -right-5 flex justify-center items-center ${
|
||||||
isActive
|
isActive
|
||||||
@@ -95,9 +97,9 @@ 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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 rounded-2xl" 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>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -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"),
|
||||||
|
|||||||
Reference in New Issue
Block a user