Merge branch 'add-family-acc' of WrenchBoard/Users-Wrench into master
This commit is contained in:
@@ -1,17 +1,17 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Link, useNavigate } from 'react-router-dom';
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
import WrenchBoard from "../../../assets/images/wrenchboard.png"
|
import WrenchBoard from "../../../assets/images/wrenchboard.png";
|
||||||
|
import usersService from "../../../services/UsersService";
|
||||||
import InputCom from "../../Helpers/Inputs/InputCom";
|
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||||
import AuthLayout from "../AuthLayout";
|
import AuthLayout from "../AuthLayout";
|
||||||
import usersService from "../../../services/UsersService";
|
|
||||||
|
|
||||||
export default function ForgotPassword() {
|
export default function ForgotPassword() {
|
||||||
const [checked, setValue] = useState(false);
|
const [checked, setValue] = useState(false);
|
||||||
const [resetLoading, setResetLoading] = useState(false)
|
const [resetLoading, setResetLoading] = useState(false);
|
||||||
// email
|
// email
|
||||||
const [email, setMail] = useState("");
|
const [email, setMail] = useState("");
|
||||||
const [msgError, setMsgError] = useState('');
|
const [msgError, setMsgError] = useState("");
|
||||||
const [msgSuccess, setMsgSuccess] = useState(false)
|
const [msgSuccess, setMsgSuccess] = useState(false);
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const userApi = new usersService();
|
const userApi = new usersService();
|
||||||
@@ -21,52 +21,54 @@ export default function ForgotPassword() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const humanChecker = () => {
|
const humanChecker = () => {
|
||||||
setValue(!checked)
|
setValue(!checked);
|
||||||
}
|
};
|
||||||
|
|
||||||
const resetHandler = async () => {
|
const resetHandler = async () => {
|
||||||
if (email == '') {
|
if (email == "") {
|
||||||
setMsgError('An email is required')
|
setMsgError("An email is required");
|
||||||
} else if (!checked) {
|
} else if (!checked) {
|
||||||
setMsgError('Check if you are human')
|
setMsgError("Check if you are human");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (email !== '' && checked) {
|
if (email !== "" && checked) {
|
||||||
const reqData = { email }
|
const reqData = { email };
|
||||||
setResetLoading(true)
|
setResetLoading(true);
|
||||||
try {
|
try {
|
||||||
const res = await userApi.StartResetPassword(reqData)
|
const res = await userApi.StartResetPassword(reqData);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
setMsgSuccess(true)
|
setMsgSuccess(true);
|
||||||
setMail("")
|
setMail("");
|
||||||
setValue(false)
|
setValue(false);
|
||||||
setResetLoading(false)
|
setResetLoading(false);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setResetLoading(false)
|
setResetLoading(false);
|
||||||
setMail("")
|
setMail("");
|
||||||
setMsgError('An error occurred')
|
setMsgError("An error occurred");
|
||||||
throw new Error(error)
|
throw new Error(error);
|
||||||
} finally {
|
} finally {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setMsgError(null)
|
setMsgError(null);
|
||||||
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT)
|
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setMsgError(null)
|
setMsgError(null);
|
||||||
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT)
|
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AuthLayout
|
<AuthLayout slogan="Welcome to WrenchBoard">
|
||||||
slogan="Welcome to WrenchBoard"
|
|
||||||
>
|
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className='mb-12'>
|
<div className="mb-12">
|
||||||
<Link to='#'>
|
<Link to="#">
|
||||||
<img src={WrenchBoard} alt="wrenchboard" className="h-10 mx-auto" />
|
<img
|
||||||
|
src={WrenchBoard}
|
||||||
|
alt="wrenchboard"
|
||||||
|
className="h-10 mx-auto"
|
||||||
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5">
|
<div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5">
|
||||||
@@ -75,11 +77,14 @@ export default function ForgotPassword() {
|
|||||||
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
|
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
|
||||||
Forget Password
|
Forget Password
|
||||||
</h1>
|
</h1>
|
||||||
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">Enter your email to reset your password.</span>
|
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
|
||||||
|
Enter your email to reset your password.
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-area">
|
<div className="input-area">
|
||||||
<div className="input-item mb-10">
|
<div className="input-item mb-10">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
placeholder="Your Username/Email"
|
placeholder="Your Username/Email"
|
||||||
label="Email"
|
label="Email"
|
||||||
name="email"
|
name="email"
|
||||||
@@ -98,7 +103,14 @@ export default function ForgotPassword() {
|
|||||||
<div className="relative table top-0 h-full">
|
<div className="relative table top-0 h-full">
|
||||||
<div className="table-cell align-middle">
|
<div className="table-cell align-middle">
|
||||||
<div className="relative w-[30px] h-[30px] mx-[15px]">
|
<div className="relative w-[30px] h-[30px] mx-[15px]">
|
||||||
<input type="checkbox" name="human-checkbox" id="human-checkbox" className="w-[28px] h-[28px] border-[1px] rounded border-gray-400 checked:bg-white" checked={checked} onChange={humanChecker} />
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
name="human-checkbox"
|
||||||
|
id="human-checkbox"
|
||||||
|
className="w-[28px] h-[28px] border-[1px] rounded border-gray-400 checked:bg-white"
|
||||||
|
checked={checked}
|
||||||
|
onChange={humanChecker}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -106,7 +118,10 @@ export default function ForgotPassword() {
|
|||||||
<div className="h-full relative inline-block w-[170px]">
|
<div className="h-full relative inline-block w-[170px]">
|
||||||
<label className="relative table top-0 h-full">
|
<label className="relative table top-0 h-full">
|
||||||
<label className="table-cell align-middle">
|
<label className="table-cell align-middle">
|
||||||
<label className="text-800 text-sm" htmlFor="human-checkbox">
|
<label
|
||||||
|
className="text-800 text-sm"
|
||||||
|
htmlFor="human-checkbox"
|
||||||
|
>
|
||||||
I am human
|
I am human
|
||||||
</label>
|
</label>
|
||||||
</label>
|
</label>
|
||||||
@@ -116,8 +131,24 @@ export default function ForgotPassword() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{msgError && <div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">{msgError}</div>}
|
{msgError && (
|
||||||
{msgSuccess && <div className="relative p-4 text-[#44228c] bg-[#e3d7fb] border-[#d5c4f9] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">If we find your email, you will receive a link to reset your password. Please use or <Link to='/contact' className="text-[#4687ba] hover:text-[#009ef7]">contact form</Link> if you did not get our message after few minutes.</div>}
|
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">
|
||||||
|
{msgError}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{msgSuccess && (
|
||||||
|
<div className="relative p-4 text-[#44228c] bg-[#e3d7fb] border-[#d5c4f9] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">
|
||||||
|
If we find your email, you will receive a link to reset your
|
||||||
|
password. Please use or{" "}
|
||||||
|
<Link
|
||||||
|
to="/contact"
|
||||||
|
className="text-[#4687ba] hover:text-[#009ef7]"
|
||||||
|
>
|
||||||
|
contact form
|
||||||
|
</Link>{" "}
|
||||||
|
if you did not get our message after few minutes.
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="signin-area mb-3.5">
|
<div className="signin-area mb-3.5">
|
||||||
<div className="flex justify-center items-center gap-2">
|
<div className="flex justify-center items-center gap-2">
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useNavigate, Link } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
import { toast } from "react-toastify";
|
|
||||||
import googleLogo from "../../../assets/images/google-logo.svg";
|
|
||||||
import appleLogo from "../../../assets/images/apple-black.svg";
|
import appleLogo from "../../../assets/images/apple-black.svg";
|
||||||
import facebookLogo from "../../../assets/images/facebook-4.svg";
|
import facebookLogo from "../../../assets/images/facebook-4.svg";
|
||||||
|
import googleLogo from "../../../assets/images/google-logo.svg";
|
||||||
import WrenchBoard from "../../../assets/images/wrenchboard.png";
|
import WrenchBoard from "../../../assets/images/wrenchboard.png";
|
||||||
import usersService from "../../../services/UsersService";
|
import usersService from "../../../services/UsersService";
|
||||||
import InputCom from "../../Helpers/Inputs/InputCom";
|
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||||
import AuthLayout from "../AuthLayout";
|
import AuthLayout from "../AuthLayout";
|
||||||
|
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { updateUserDetails } from "../../../store/UserDetails";
|
import { updateUserDetails } from "../../../store/UserDetails";
|
||||||
|
|
||||||
export default function Login() {
|
export default function Login() {
|
||||||
@@ -73,7 +72,7 @@ export default function Login() {
|
|||||||
setLoginError(true);
|
setLoginError(true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setMsgError("Please fill in fields");
|
setMsgError("Please fill in the fields");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setMsgError("An error occurred");
|
setMsgError("An error occurred");
|
||||||
@@ -117,6 +116,7 @@ export default function Login() {
|
|||||||
<div className="input-area">
|
<div className="input-area">
|
||||||
<div className="input-item mb-5">
|
<div className="input-item mb-5">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
value={email}
|
value={email}
|
||||||
inputHandler={handleEmail}
|
inputHandler={handleEmail}
|
||||||
placeholder="support@mermsemr.com"
|
placeholder="support@mermsemr.com"
|
||||||
@@ -129,6 +129,7 @@ export default function Login() {
|
|||||||
|
|
||||||
<div className="input-item mb-5">
|
<div className="input-item mb-5">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
value={password}
|
value={password}
|
||||||
inputHandler={handlePassword}
|
inputHandler={handlePassword}
|
||||||
placeholder="● ● ● ● ● ●"
|
placeholder="● ● ● ● ● ●"
|
||||||
@@ -139,39 +140,6 @@ export default function Login() {
|
|||||||
forgotPassword
|
forgotPassword
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/* <div className="forgot-password-area flex justify-between items-center mb-7">
|
|
||||||
<div className="remember-checkbox flex items-center space-x-2.5">
|
|
||||||
<button
|
|
||||||
onClick={rememberMe}
|
|
||||||
type="button"
|
|
||||||
className="w-5 h-5 text-dark-gray dark:text-white flex justify-center items-center border border-light-gray"
|
|
||||||
>
|
|
||||||
{checked && (
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
className="h-5 w-5"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="currentColor"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
|
||||||
clipRule="evenodd"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
<span
|
|
||||||
onClick={rememberMe}
|
|
||||||
className="text-base text-dark-gray dark:text-white"
|
|
||||||
>
|
|
||||||
Remember Me
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<a href="/forgot-password" className="text-base text-purple">
|
|
||||||
Forgot Password
|
|
||||||
</a>
|
|
||||||
</div> */}
|
|
||||||
{loginError && (
|
{loginError && (
|
||||||
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-thin leading-[19.5px] text-[13px]">
|
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-thin leading-[19.5px] text-[13px]">
|
||||||
Invalid username or password- Please{" "}
|
Invalid username or password- Please{" "}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useCallback, useEffect, useState } from "react";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
import { useNavigate, Link } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
import facebookLogo from "../../../assets/images/facebook-4.svg";
|
import facebookLogo from "../../../assets/images/facebook-4.svg";
|
||||||
import WrenchBoard from "../../../assets/images/wrenchboard.png";
|
import WrenchBoard from "../../../assets/images/wrenchboard.png";
|
||||||
import usersService from "../../../services/UsersService";
|
import usersService from "../../../services/UsersService";
|
||||||
@@ -171,6 +171,7 @@ export default function SignUp() {
|
|||||||
<div className="input-fl-name mb-5 sm:flex w-full sm:space-x-6 ">
|
<div className="input-fl-name mb-5 sm:flex w-full sm:space-x-6 ">
|
||||||
<div className="input-item sm:w-1/2 w-full mb-5 sm:mb-0">
|
<div className="input-item sm:w-1/2 w-full mb-5 sm:mb-0">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
placeholder="Firstname"
|
placeholder="Firstname"
|
||||||
label="First Name"
|
label="First Name"
|
||||||
name="first_name"
|
name="first_name"
|
||||||
@@ -181,6 +182,7 @@ export default function SignUp() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="input-item flex-1">
|
<div className="input-item flex-1">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
placeholder="Lastname"
|
placeholder="Lastname"
|
||||||
label="Last Name"
|
label="Last Name"
|
||||||
name="last_name"
|
name="last_name"
|
||||||
@@ -192,6 +194,7 @@ export default function SignUp() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="input-item mb-5">
|
<div className="input-item mb-5">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
placeholder="support@mermsemr.com"
|
placeholder="support@mermsemr.com"
|
||||||
label="Email"
|
label="Email"
|
||||||
name="email"
|
name="email"
|
||||||
@@ -202,6 +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"
|
||||||
placeholder="● ● ● ● ● ●"
|
placeholder="● ● ● ● ● ●"
|
||||||
label="Password"
|
label="Password"
|
||||||
name="password"
|
name="password"
|
||||||
|
|||||||
@@ -16,9 +16,7 @@ export default function UpdatePassword() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AuthLayout
|
<AuthLayout slogan="Welcome to myFit">
|
||||||
slogan="Welcome to myFit"
|
|
||||||
>
|
|
||||||
{updated === false ? (
|
{updated === false ? (
|
||||||
<div className="content-wrapper update-password-section xl:bg-white dark:bg-dark-white w-full 2xl:h-[818px] xl:h-[600px] sm:w-auto sm:px-[70px] px-5 2xl:px-[100px] rounded-xl flex flex-col justify-center">
|
<div className="content-wrapper update-password-section xl:bg-white dark:bg-dark-white w-full 2xl:h-[818px] xl:h-[600px] sm:w-auto sm:px-[70px] px-5 2xl:px-[100px] rounded-xl flex flex-col justify-center">
|
||||||
<div>
|
<div>
|
||||||
@@ -34,6 +32,7 @@ export default function UpdatePassword() {
|
|||||||
<div className="input-area">
|
<div className="input-area">
|
||||||
<div className="input-item mb-5">
|
<div className="input-item mb-5">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
placeholder="*********"
|
placeholder="*********"
|
||||||
label="Old Password"
|
label="Old Password"
|
||||||
name="password"
|
name="password"
|
||||||
@@ -43,6 +42,7 @@ export default function UpdatePassword() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="input-item mb-5">
|
<div className="input-item mb-5">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
placeholder="*********"
|
placeholder="*********"
|
||||||
label="New Password"
|
label="New Password"
|
||||||
name="password"
|
name="password"
|
||||||
@@ -52,6 +52,7 @@ export default function UpdatePassword() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="input-item mb-5">
|
<div className="input-item mb-5">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
placeholder="*********"
|
placeholder="*********"
|
||||||
label="Re-enter Password"
|
label="Re-enter Password"
|
||||||
name="password"
|
name="password"
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { useState, useEffect, useCallback } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { useLocation, Link, useNavigate } from "react-router-dom";
|
import { Link, useLocation, useNavigate } from "react-router-dom";
|
||||||
import AuthLayout from "../AuthLayout";
|
|
||||||
import InputCom from "../../Helpers/Inputs/InputCom";
|
|
||||||
import usersService from "../../../services/UsersService";
|
|
||||||
import WrenchBoard from "../../../assets/images/wrenchboard.png";
|
import WrenchBoard from "../../../assets/images/wrenchboard.png";
|
||||||
import debounce from "../../../hooks/debounce";
|
import debounce from "../../../hooks/debounce";
|
||||||
|
import usersService from "../../../services/UsersService";
|
||||||
|
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||||
|
import AuthLayout from "../AuthLayout";
|
||||||
|
|
||||||
export default function VerifyLink() {
|
export default function VerifyLink() {
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
@@ -173,6 +173,7 @@ const SuccessfulComponent = ({
|
|||||||
{/* INPUT */}
|
{/* INPUT */}
|
||||||
<div className="mb-5">
|
<div className="mb-5">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
value={email}
|
value={email}
|
||||||
inputHandler={handleEmail}
|
inputHandler={handleEmail}
|
||||||
placeholder="support@mermsemr.com"
|
placeholder="support@mermsemr.com"
|
||||||
@@ -184,6 +185,7 @@ const SuccessfulComponent = ({
|
|||||||
</div>
|
</div>
|
||||||
<div className="mb-5">
|
<div className="mb-5">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
value={password}
|
value={password}
|
||||||
inputHandler={handlePassword}
|
inputHandler={handlePassword}
|
||||||
placeholder="● ● ● ● ● ●"
|
placeholder="● ● ● ● ● ●"
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { useState, useEffect, useCallback } from "react";
|
import { useState } from "react";
|
||||||
import { useLocation, Link, useNavigate } from "react-router-dom";
|
import { Link, useLocation, useNavigate } from "react-router-dom";
|
||||||
import AuthLayout from "../AuthLayout";
|
|
||||||
import InputCom from "../../Helpers/Inputs/InputCom";
|
|
||||||
import usersService from "../../../services/UsersService";
|
|
||||||
import WrenchBoard from "../../../assets/images/wrenchboard.png";
|
import WrenchBoard from "../../../assets/images/wrenchboard.png";
|
||||||
|
import usersService from "../../../services/UsersService";
|
||||||
|
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||||
|
import AuthLayout from "../AuthLayout";
|
||||||
|
|
||||||
const VerifyPassword = () => {
|
const VerifyPassword = () => {
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
@@ -158,6 +158,7 @@ const SuccessfulComponent = ({
|
|||||||
{/* INPUT */}
|
{/* INPUT */}
|
||||||
<div className="mb-5">
|
<div className="mb-5">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
value={password}
|
value={password}
|
||||||
inputHandler={handlePassword}
|
inputHandler={handlePassword}
|
||||||
placeholder="● ● ● ● ● ●"
|
placeholder="● ● ● ● ● ●"
|
||||||
@@ -165,13 +166,12 @@ const SuccessfulComponent = ({
|
|||||||
name="password"
|
name="password"
|
||||||
type={showPassword ? "text" : "password"}
|
type={showPassword ? "text" : "password"}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
passIcon={
|
passIcon={showPassword ? "show-password" : "hide-password"}
|
||||||
showPassword ? "show-password" : "hide-password"
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-5">
|
<div className="mb-5">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
value={confirmPassword}
|
value={confirmPassword}
|
||||||
inputHandler={handlePassword}
|
inputHandler={handlePassword}
|
||||||
placeholder="● ● ● ● ● ●"
|
placeholder="● ● ● ● ● ●"
|
||||||
|
|||||||
@@ -1,80 +1,71 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import dataImage1 from "../../assets/images/data-table-user-1.png";
|
import dataImage1 from "../../assets/images/data-table-user-1.png";
|
||||||
import dataImage2 from "../../assets/images/data-table-user-2.png";
|
|
||||||
import dataImage3 from "../../assets/images/data-table-user-3.png";
|
|
||||||
import dataImage4 from "../../assets/images/data-table-user-4.png";
|
|
||||||
import SelectBox from "../Helpers/SelectBox";
|
|
||||||
|
|
||||||
export default function FamilyTable({ className }) {
|
export default function FamilyTable({ className }) {
|
||||||
const filterCategories = ["All Categories", "Explore", "Featured"];
|
const filterCategories = ["All Categories", "Explore", "Featured"];
|
||||||
const [selectedCategory, setCategory] = useState(filterCategories[0]);
|
const [selectedCategory, setCategory] = useState(filterCategories[0]);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px] ${
|
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px] ${
|
||||||
className || ""
|
className || ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
|
<div className="relative w-full overflow-x-auto sm:rounded-lg">
|
||||||
|
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
|
||||||
|
<tbody>
|
||||||
|
<tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-b dark:border-[#5356fb29] ottom ">
|
||||||
|
<td className="py-4">Name</td>
|
||||||
|
<td className="py-4 text-center">Last Login</td>
|
||||||
|
<td className="py-4 text-center">No of Tasks</td>
|
||||||
|
<td className="py-4 text-right">Status</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
|
||||||
|
<td className=" py-4">
|
||||||
|
<div className="flex space-x-2 items-center">
|
||||||
|
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
|
||||||
|
<img
|
||||||
|
src={dataImage1}
|
||||||
|
alt="data"
|
||||||
|
className="w-full h-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<h1 className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
|
||||||
|
Firstname Lastname (age)
|
||||||
|
</h1>
|
||||||
|
<span className="text-sm text-thin-light-gray">
|
||||||
|
Added <span className="text-purple">10-10-2029</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="text-center py-4 px-2">
|
||||||
|
<div className="flex space-x-1 items-center justify-center">
|
||||||
|
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
|
||||||
|
10-10-2019
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="text-center py-4 px-2">
|
||||||
|
<div className="flex space-x-1 items-center justify-center">
|
||||||
|
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
|
||||||
|
100
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
<div className="relative w-full overflow-x-auto sm:rounded-lg">
|
<td className="text-right py-4 px-2">
|
||||||
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
|
<button
|
||||||
<tbody>
|
type="button"
|
||||||
<tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-b dark:border-[#5356fb29] ottom ">
|
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||||
<td className="py-4">Name</td>
|
>
|
||||||
<td className="py-4 text-center">Last Login</td>
|
Manage
|
||||||
<td className="py-4 text-center">No of Tasks</td>
|
</button>
|
||||||
<td className="py-4 text-right">Status</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
|
</tbody>
|
||||||
<td className=" py-4">
|
</table>
|
||||||
<div className="flex space-x-2 items-center">
|
</div>
|
||||||
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
|
</div>
|
||||||
<img
|
);
|
||||||
src={dataImage1}
|
|
||||||
alt="data"
|
|
||||||
className="w-full h-full"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col">
|
|
||||||
<h1 className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
|
|
||||||
Firstname Lastname (age)
|
|
||||||
</h1>
|
|
||||||
<span className="text-sm text-thin-light-gray">
|
|
||||||
Added <span className="text-purple">10-10-2029</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td className="text-center py-4 px-2">
|
|
||||||
<div className="flex space-x-1 items-center justify-center">
|
|
||||||
|
|
||||||
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
|
|
||||||
10-10-2019
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td className="text-center py-4 px-2">
|
|
||||||
<div className="flex space-x-1 items-center justify-center">
|
|
||||||
|
|
||||||
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
|
|
||||||
100
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td className="text-right py-4 px-2">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
|
||||||
>
|
|
||||||
Manage
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,212 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useId, useMemo, useState } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import CustomPopUp from "../Helpers/CustomPopUp";
|
||||||
|
import InputCom from "../Helpers/Inputs/InputCom";
|
||||||
import Layout from "../Partials/Layout";
|
import Layout from "../Partials/Layout";
|
||||||
import CommonHead from "../UserHeader/CommonHead";
|
|
||||||
import FamilyTable from "./FamilyTable";
|
import FamilyTable from "./FamilyTable";
|
||||||
|
import SiteService from "../../services/SiteService";
|
||||||
|
|
||||||
export default function FamilyAcc() {
|
export default function FamilyAcc() {
|
||||||
const [selectTab, setValue] = useState("today");
|
const [selectTab, setValue] = useState("today");
|
||||||
const filterHandler = (value) => {
|
const [selectedAge, setSelectedAge] = useState(undefined);
|
||||||
setValue(value);
|
const [loader, setLoader] = useState(false);
|
||||||
};
|
const [msgErr, setMsgErr] = useState("");
|
||||||
return (
|
const [formData, setFormData] = useState({
|
||||||
<Layout>
|
first_name: "",
|
||||||
{/*<CommonHead />*/}
|
last_name: "",
|
||||||
<div className="notification-page w-full mb-10">
|
});
|
||||||
<div className="notification-wrapper w-full">
|
|
||||||
{/* heading */}
|
const apiCall = useMemo(() => new SiteService(), []);
|
||||||
<div className="sm:flex justify-between items-center mb-6">
|
|
||||||
<div className="mb-5 sm:mb-0">
|
// tab handler
|
||||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
const filterHandler = (value) => {
|
||||||
|
setValue(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
let id = useId();
|
||||||
|
// For the age drop down
|
||||||
|
let startAge = 16;
|
||||||
|
let endAge = 70;
|
||||||
|
// creates an array of age values ranging from 16 to 70
|
||||||
|
const ageRange = Array.from(
|
||||||
|
{ length: endAge - startAge + 1 },
|
||||||
|
(_, index) => startAge + index
|
||||||
|
);
|
||||||
|
// age handler
|
||||||
|
const handleAgeSelect = (event) => {
|
||||||
|
setSelectedAge(parseInt(event.target.value));
|
||||||
|
};
|
||||||
|
// Input handler
|
||||||
|
const handleInputChange = (event) => {
|
||||||
|
const { name, value } = event?.target;
|
||||||
|
setFormData({ ...formData, [name]: value });
|
||||||
|
};
|
||||||
|
|
||||||
|
const addMember = async () => {
|
||||||
|
let { first_name, last_name } = formData;
|
||||||
|
setLoader(true);
|
||||||
|
try {
|
||||||
|
if (first_name !== "" && last_name !== "") {
|
||||||
|
const reqData = {
|
||||||
|
member_id: localStorage.getItem("member_id"),
|
||||||
|
uid: localStorage.getItem("uid"),
|
||||||
|
session_id: localStorage.getItem("session_token"),
|
||||||
|
firstname: first_name,
|
||||||
|
lastname: last_name,
|
||||||
|
age: selectedAge,
|
||||||
|
};
|
||||||
|
const res = await apiCall.addFamily(reqData);
|
||||||
|
const { data } = res;
|
||||||
|
if (data.internal_return > 0 && data.status == "OK") {
|
||||||
|
setLoader(false);
|
||||||
|
console.log(data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setLoader(false);
|
||||||
|
setMsgErr("Please fill in the fields");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
setLoader(false);
|
||||||
|
setMsgErr("An error occurred");
|
||||||
|
} finally {
|
||||||
|
setTimeout(() => {
|
||||||
|
setMsgErr(null);
|
||||||
|
}, Number(process.env.REACT_APP_LOGIN_ERROR_TIMEOUT));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
{/*<CommonHead />*/}
|
||||||
|
<div className="notification-page w-full mb-10">
|
||||||
|
<div className="notification-wrapper w-full">
|
||||||
|
{/* heading */}
|
||||||
|
<div className="sm:flex justify-between items-center mb-6">
|
||||||
|
<div className="mb-5 sm:mb-0">
|
||||||
|
<h1 className="text-26 font-bold inline-flex gap-2 text-dark-gray dark:text-white">
|
||||||
<span
|
<span
|
||||||
className={`${selectTab === "today" ? "block" : "hidden"}`}
|
className={`${selectTab === "today" ? "block" : "hidden"}`}
|
||||||
>
|
>
|
||||||
Family Accounts
|
Family Accounts
|
||||||
</span>
|
</span>
|
||||||
|
<CustomPopUp
|
||||||
</h1>
|
name="(Add)"
|
||||||
</div>
|
btn_class="text-purple"
|
||||||
<div className="slider-btns flex space-x-4">
|
key={id}
|
||||||
<div onClick={() => filterHandler("today")} className="relative">
|
title="Add members"
|
||||||
|
>
|
||||||
</div>
|
<FamilyForm
|
||||||
</div>
|
value={formData}
|
||||||
</div>
|
ageHandler={handleAgeSelect}
|
||||||
<FamilyTable />
|
ageRange={ageRange}
|
||||||
</div>
|
ageValue={selectedAge}
|
||||||
|
inputHandler={handleInputChange}
|
||||||
|
msgErr={msgErr}
|
||||||
|
onClick={addMember}
|
||||||
|
loader={loader}
|
||||||
|
/>
|
||||||
|
</CustomPopUp>
|
||||||
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
<div className="slider-btns flex space-x-4">
|
||||||
);
|
<div
|
||||||
|
onClick={() => filterHandler("today")}
|
||||||
|
className="relative"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<FamilyTable />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const FamilyForm = ({
|
||||||
|
value: { first_name, last_name },
|
||||||
|
ageValue,
|
||||||
|
inputHandler,
|
||||||
|
ageHandler,
|
||||||
|
ageRange,
|
||||||
|
msgErr,
|
||||||
|
loader,
|
||||||
|
onClick,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className="w-full relative block ">
|
||||||
|
<form className="flex flex-col gap-4">
|
||||||
|
<InputCom
|
||||||
|
placeholder="Firstname"
|
||||||
|
label="First Name:"
|
||||||
|
name="first_name"
|
||||||
|
type="text"
|
||||||
|
parentClass="flex items-center gap-1"
|
||||||
|
labelClass="flex-[0.2] mb-0"
|
||||||
|
inputClass="flex-[0.8]"
|
||||||
|
fieldClass="px-2"
|
||||||
|
value={first_name}
|
||||||
|
inputHandler={inputHandler}
|
||||||
|
/>
|
||||||
|
<InputCom
|
||||||
|
placeholder="Lastname"
|
||||||
|
label="Last Name:"
|
||||||
|
name="last_name"
|
||||||
|
type="text"
|
||||||
|
parentClass="flex items-center gap-1"
|
||||||
|
labelClass="flex-[0.2] mb-0"
|
||||||
|
inputClass="flex-[0.8]"
|
||||||
|
fieldClass="px-2"
|
||||||
|
value={last_name}
|
||||||
|
inputHandler={inputHandler}
|
||||||
|
/>
|
||||||
|
<div className="input-com mb-7 flex gap-1 items-center">
|
||||||
|
{/* Age dropdown */}
|
||||||
|
<div className="flex items-center justify-between flex-[0.3]">
|
||||||
|
<label
|
||||||
|
className="input-label text-[#181c32] dark:text-white text-[15px] font-semibold"
|
||||||
|
htmlFor="age-selection"
|
||||||
|
>
|
||||||
|
Select your age:
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className=" flex-[0.7]">
|
||||||
|
<select
|
||||||
|
name="age-selection"
|
||||||
|
id="age-selection"
|
||||||
|
className="input-wrapper border border-[#f5f8fa]] dark:border-[#5e6278] w-full rounded-[0.475rem] 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 focus-visible:border-transparent focus-visible:outline-0 focus-visible:ring-transparent px-2"
|
||||||
|
onChange={ageHandler}
|
||||||
|
value={ageValue}
|
||||||
|
>
|
||||||
|
<option value={""}>Select your age</option>
|
||||||
|
{ageRange?.length > 0 &&
|
||||||
|
ageRange?.map((age) => (
|
||||||
|
<option value={age} key={age}>
|
||||||
|
{age}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{msgErr && (
|
||||||
|
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px]">
|
||||||
|
{msgErr}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="signin-area">
|
||||||
|
<div className="flex justify-center">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={onClick}
|
||||||
|
className={`rounded-[0.475rem] text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center h-[42px] py-[0.8875rem] px-[1.81rem] text-[14.95px] btn-login`}
|
||||||
|
>
|
||||||
|
{loader ? (
|
||||||
|
<div className="signup btn-loader"></div>
|
||||||
|
) : (
|
||||||
|
<span>Add</span>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
|
||||||
|
const CustomPopUp = ({ name, btn_class, title, children }) => {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const handleOpen = () => {
|
||||||
|
setIsOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setIsOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button onClick={handleOpen} className={btn_class}>
|
||||||
|
{name}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{isOpen && (
|
||||||
|
<div className={`fixed inset-0 bg-gray-800 bg-opacity-75 flex items-center justify-center z-50 transition-opacity ${isOpen ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}`}>
|
||||||
|
<div className="bg-white rounded-md p-6 shadow-lg transform transition-all duration-300 ease-in-out lg:max-w-[400px] lg:min-h-[300px] max-w-[300px] min-h-[200px] w-full">
|
||||||
|
<div className="w-full flex justify-end">
|
||||||
|
<button onClick={handleClose}>
|
||||||
|
<CloseIcon />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{title && <h2 className="text-xl font-bold mb-2">{title}</h2>}
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomPopUp;
|
||||||
|
|
||||||
|
const CloseIcon = () => (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
stroke="currentColor"
|
||||||
|
className="w-6 h-6"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
d="M6 18L18 6M6 6l12 12"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
@@ -12,76 +12,153 @@ export default function InputCom({
|
|||||||
inputHandler,
|
inputHandler,
|
||||||
value,
|
value,
|
||||||
forgotPassword,
|
forgotPassword,
|
||||||
|
parentClass,
|
||||||
|
labelClass,
|
||||||
|
inputClass,
|
||||||
|
fieldClass,
|
||||||
onClick,
|
onClick,
|
||||||
disable,
|
disable,
|
||||||
blurHandler
|
blurHandler,
|
||||||
}) {
|
}) {
|
||||||
const inputRef = useRef(null)
|
const inputRef = useRef(null);
|
||||||
// Entry Validation
|
// Entry Validation
|
||||||
// for Min Length:
|
// for Min Length:
|
||||||
const minLengthValidation = () => {
|
const minLengthValidation = () => {
|
||||||
if (inputRef && inputRef?.current && inputRef?.current?.name === 'email') {
|
if (inputRef && inputRef?.current && inputRef?.current?.name === "email") {
|
||||||
return 7
|
return 7;
|
||||||
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'first_name') {
|
} else if (
|
||||||
return 3
|
inputRef &&
|
||||||
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'last_name') {
|
inputRef?.current &&
|
||||||
return 3
|
inputRef?.current?.name === "first_name"
|
||||||
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'address') {
|
) {
|
||||||
return 5
|
return 3;
|
||||||
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'password') {
|
} else if (
|
||||||
return 8
|
inputRef &&
|
||||||
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'state') {
|
inputRef?.current &&
|
||||||
return 3
|
inputRef?.current?.name === "last_name"
|
||||||
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'province') {
|
) {
|
||||||
return 3
|
return 3;
|
||||||
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'city') {
|
} else if (
|
||||||
return 3
|
inputRef &&
|
||||||
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'amount') {
|
inputRef?.current &&
|
||||||
return 1
|
inputRef?.current?.name === "address"
|
||||||
|
) {
|
||||||
|
return 5;
|
||||||
|
} else if (
|
||||||
|
inputRef &&
|
||||||
|
inputRef?.current &&
|
||||||
|
inputRef?.current?.name === "password"
|
||||||
|
) {
|
||||||
|
return 8;
|
||||||
|
} else if (
|
||||||
|
inputRef &&
|
||||||
|
inputRef?.current &&
|
||||||
|
inputRef?.current?.name === "state"
|
||||||
|
) {
|
||||||
|
return 3;
|
||||||
|
} else if (
|
||||||
|
inputRef &&
|
||||||
|
inputRef?.current &&
|
||||||
|
inputRef?.current?.name === "province"
|
||||||
|
) {
|
||||||
|
return 3;
|
||||||
|
} else if (
|
||||||
|
inputRef &&
|
||||||
|
inputRef?.current &&
|
||||||
|
inputRef?.current?.name === "city"
|
||||||
|
) {
|
||||||
|
return 3;
|
||||||
|
} else if (
|
||||||
|
inputRef &&
|
||||||
|
inputRef?.current &&
|
||||||
|
inputRef?.current?.name === "amount"
|
||||||
|
) {
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// for MaxLength
|
// for MaxLength
|
||||||
const maxLengthValidation = () => {
|
const maxLengthValidation = () => {
|
||||||
if (inputRef && inputRef?.current && inputRef?.current?.name === 'email') {
|
if (inputRef && inputRef?.current && inputRef?.current?.name === "email") {
|
||||||
return 35
|
return 35;
|
||||||
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'first_name') {
|
} else if (
|
||||||
return 25
|
inputRef &&
|
||||||
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'last_name') {
|
inputRef?.current &&
|
||||||
return 25
|
inputRef?.current?.name === "first_name"
|
||||||
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'address') {
|
) {
|
||||||
return 49
|
return 25;
|
||||||
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'password') {
|
} else if (
|
||||||
return 15
|
inputRef &&
|
||||||
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'state') {
|
inputRef?.current &&
|
||||||
return 25
|
inputRef?.current?.name === "last_name"
|
||||||
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'province') {
|
) {
|
||||||
return 25
|
return 25;
|
||||||
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'city') {
|
} else if (
|
||||||
return 25
|
inputRef &&
|
||||||
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'amount') {
|
inputRef?.current &&
|
||||||
return 9
|
inputRef?.current?.name === "address"
|
||||||
|
) {
|
||||||
|
return 49;
|
||||||
|
} else if (
|
||||||
|
inputRef &&
|
||||||
|
inputRef?.current &&
|
||||||
|
inputRef?.current?.name === "password"
|
||||||
|
) {
|
||||||
|
return 15;
|
||||||
|
} else if (
|
||||||
|
inputRef &&
|
||||||
|
inputRef?.current &&
|
||||||
|
inputRef?.current?.name === "state"
|
||||||
|
) {
|
||||||
|
return 25;
|
||||||
|
} else if (
|
||||||
|
inputRef &&
|
||||||
|
inputRef?.current &&
|
||||||
|
inputRef?.current?.name === "province"
|
||||||
|
) {
|
||||||
|
return 25;
|
||||||
|
} else if (
|
||||||
|
inputRef &&
|
||||||
|
inputRef?.current &&
|
||||||
|
inputRef?.current?.name === "city"
|
||||||
|
) {
|
||||||
|
return 25;
|
||||||
|
} else if (
|
||||||
|
inputRef &&
|
||||||
|
inputRef?.current &&
|
||||||
|
inputRef?.current?.name === "amount"
|
||||||
|
) {
|
||||||
|
return 9;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
return (
|
return (
|
||||||
<div className="input-com">
|
<div className={`input-com ${parentClass}`}>
|
||||||
<div className="flex items-center justify-between">
|
<div className={`flex items-center justify-between mb-2.5 ${labelClass}`}>
|
||||||
{label && (
|
{label && (
|
||||||
<label
|
<label
|
||||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block mb-2.5"
|
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
|
||||||
htmlFor={name}
|
htmlFor={name}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
{forgotPassword && <Link to="/forgot-password" className="text-[13.975px] leading-[20.9625px] text-[#019ef7] hover:text-[#009ef7]">Forgot Password?</Link>}
|
{forgotPassword && (
|
||||||
|
<Link
|
||||||
|
to="/forgot-password"
|
||||||
|
className="text-[13.975px] leading-[20.9625px] text-[#019ef7] hover:text-[#009ef7]"
|
||||||
|
>
|
||||||
|
Forgot Password?
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="input-wrapper border border-[#f5f8fa]] dark:border-[#5e6278] w-full rounded-[0.475rem] 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 ">
|
<div
|
||||||
|
className={`input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-[0.475rem] 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 ${inputClass}`}
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={inputHandler}
|
onChange={inputHandler}
|
||||||
className="input-field placeholder:text-base px-6 text-dark-gray dark:text-white w-full h-full bg-[#FAFAFA] dark:bg-[#11131F] focus:ring-0 focus:outline-none"
|
className={`input-field placeholder:text-base text-dark-gray dark:text-white w-full h-full bg-[#FAFAFA] dark:bg-[#11131F] focus:ring-0 focus:outline-none ${fieldClass}`}
|
||||||
type={type}
|
type={type}
|
||||||
id={name}
|
id={name}
|
||||||
name={name}
|
name={name}
|
||||||
@@ -97,7 +174,10 @@ export default function InputCom({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{passIcon && (
|
{passIcon && (
|
||||||
<div className="absolute right-6 bottom-[10px] z-10" onClick={onClick}>
|
<div
|
||||||
|
className="absolute right-6 bottom-[10px] z-10"
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
<Icons name={passIcon} />
|
<Icons name={passIcon} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,370 +1,499 @@
|
|||||||
import React, {useEffect, useState} from 'react'
|
import React, { useEffect, useState } from "react";
|
||||||
import { Link, useNavigate } from 'react-router-dom'
|
import { useNavigate } from "react-router-dom";
|
||||||
import Icons from '../Helpers/Icons'
|
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 { toast } from "react-toastify";
|
||||||
import {toast} from 'react-toastify'
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
|
|
||||||
import {Formik, Form} from 'formik'
|
|
||||||
import * as Yup from 'yup'
|
|
||||||
|
|
||||||
|
import { Form, Formik } from "formik";
|
||||||
|
import * as Yup from "yup";
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
firstname: Yup.string()
|
firstname: Yup.string()
|
||||||
.min(3, 'Minimum 3 characters')
|
.min(3, "Minimum 3 characters")
|
||||||
.max(25, 'Maximum 25 characters')
|
.max(25, "Maximum 25 characters")
|
||||||
.required('Firstname is required'),
|
.required("Firstname is required"),
|
||||||
lastname: Yup.string()
|
lastname: Yup.string()
|
||||||
.min(3, 'Minimum 3 characters')
|
.min(3, "Minimum 3 characters")
|
||||||
.max(25, 'Maximum 25 characters')
|
.max(25, "Maximum 25 characters")
|
||||||
.required('Lastname is required'),
|
.required("Lastname is required"),
|
||||||
country: Yup.string()
|
country: Yup.string()
|
||||||
.min(1, 'Minimum 1 characters')
|
.min(1, "Minimum 1 characters")
|
||||||
.max(25, 'Maximum 25 characters')
|
.max(25, "Maximum 25 characters")
|
||||||
.required('Country is required'),
|
.required("Country is required"),
|
||||||
bank: Yup.string()
|
bank: Yup.string()
|
||||||
.min(3, 'Minimum 3 characters')
|
.min(3, "Minimum 3 characters")
|
||||||
.max(25, 'Maximum 25 characters')
|
.max(25, "Maximum 25 characters")
|
||||||
.required('Bank name is required'),
|
.required("Bank name is required"),
|
||||||
accountNumber: Yup.string()
|
accountNumber: Yup.string()
|
||||||
.matches(/\d/, "must be a number")
|
.matches(/\d/, "must be a number")
|
||||||
.min(3, 'Minimum 3 characters')
|
.min(3, "Minimum 3 characters")
|
||||||
.max(25, 'Maximum 25 characters')
|
.max(25, "Maximum 25 characters")
|
||||||
.required('Account Number is required'),
|
.required("Account Number is required"),
|
||||||
repeatAccountNumber: Yup.string()
|
repeatAccountNumber: Yup.string()
|
||||||
.required('Repeat Account Number is required')
|
.required("Repeat Account Number is required")
|
||||||
.oneOf([Yup.ref('accountNumber'), null], 'Must match Account Number'),
|
.oneOf([Yup.ref("accountNumber"), null], "Must match Account Number"),
|
||||||
accountType: Yup.string()
|
accountType: Yup.string()
|
||||||
.min(1, 'Minimum 3 characters')
|
.min(1, "Minimum 3 characters")
|
||||||
.max(25, 'Maximum 25 characters')
|
.max(25, "Maximum 25 characters")
|
||||||
.required('Account Type is required'),
|
.required("Account Type is required"),
|
||||||
city: Yup.string()
|
city: Yup.string()
|
||||||
.min(3, 'Minimum 3 characters')
|
.min(3, "Minimum 3 characters")
|
||||||
.max(25, 'Maximum 25 characters')
|
.max(25, "Maximum 25 characters")
|
||||||
.required('City is required'),
|
.required("City is required"),
|
||||||
state: Yup.string()
|
state: Yup.string()
|
||||||
.min(3, 'Minimum 3 characters')
|
.min(3, "Minimum 3 characters")
|
||||||
.max(25, 'Maximum 25 characters')
|
.max(25, "Maximum 25 characters")
|
||||||
.required('State is required'),
|
.required("State is required"),
|
||||||
})
|
});
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
firstname: '',
|
firstname: "",
|
||||||
lastname: '',
|
lastname: "",
|
||||||
country: '',
|
country: "",
|
||||||
bank: '',
|
bank: "",
|
||||||
accountNumber: '',
|
accountNumber: "",
|
||||||
repeatAccountNumber: '',
|
repeatAccountNumber: "",
|
||||||
accountType: '',
|
accountType: "",
|
||||||
state: '',
|
state: "",
|
||||||
city: ''
|
city: "",
|
||||||
}
|
};
|
||||||
|
|
||||||
function AddRecipient() {
|
function AddRecipient() {
|
||||||
|
const apiURL = new usersService();
|
||||||
|
|
||||||
const apiURL = new usersService()
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const navigate = useNavigate()
|
let [requestStatus, setRequestStatus] = useState({
|
||||||
|
message: "",
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
});
|
||||||
|
|
||||||
let [requestStatus, setRequestStatus] = useState({message: '', loading: false, status: false})
|
let [allCountries, setAllCountries] = useState({
|
||||||
|
// STATE TO HOLD LIST OF COUNTRIES
|
||||||
|
loading: true,
|
||||||
|
data: [],
|
||||||
|
});
|
||||||
|
|
||||||
let [allCountries, setAllCountries] = useState({ // STATE TO HOLD LIST OF COUNTRIES
|
let [bankName, setBankName] = useState({
|
||||||
loading: true,
|
// STATE TO HOLD LIST OF BANK NAME
|
||||||
data: []
|
loading: true,
|
||||||
})
|
data: [],
|
||||||
|
});
|
||||||
|
|
||||||
let [bankName, setBankName] = useState({ // STATE TO HOLD LIST OF BANK NAME
|
let [accType, setAccType] = useState({
|
||||||
loading: true,
|
// STATE TO HOLD LIST ACCOUNT TYPE
|
||||||
data: []
|
loading: true,
|
||||||
})
|
data: [],
|
||||||
|
});
|
||||||
|
|
||||||
let [accType, setAccType] = useState({ // STATE TO HOLD LIST ACCOUNT TYPE
|
//FUNCTION TO HANDLE ADD RECIPIENT SUBMIT
|
||||||
loading: true,
|
const handleSubmit = (values, helpers) => {
|
||||||
data: []
|
setRequestStatus({ message: "", loading: true, status: false });
|
||||||
})
|
|
||||||
|
|
||||||
//FUNCTION TO HANDLE ADD RECIPIENT SUBMIT
|
let reqData = {
|
||||||
const handleSubmit = (values, helpers) => {
|
//REQUEST DATA FOR API CALL
|
||||||
setRequestStatus({message: '', loading: true, status: false})
|
firstname: values.firstname,
|
||||||
|
lastname: values.lastname,
|
||||||
|
bank_code: values.bank,
|
||||||
|
account_no: values.accountNumber,
|
||||||
|
account_type: values.accountType,
|
||||||
|
country: values.country,
|
||||||
|
state: values.state,
|
||||||
|
city: values.city,
|
||||||
|
};
|
||||||
|
|
||||||
let reqData = { //REQUEST DATA FOR API CALL
|
//CALL TO ADD RECIPIENT API
|
||||||
firstname: values.firstname,
|
apiURL
|
||||||
lastname: values.lastname,
|
.addRecipient(reqData)
|
||||||
bank_code: values.bank,
|
.then((res) => {
|
||||||
account_no: values.accountNumber,
|
if (res.data.internal_return < 0) {
|
||||||
account_type: values.accountType,
|
setRequestStatus({
|
||||||
country: values.country,
|
message: "could not add recipient, try again!",
|
||||||
state: values.state,
|
loading: false,
|
||||||
city: values.city
|
status: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
// setRequestStatus({message: 'Recipient Added Successfully!', loading: false, status: true})
|
||||||
|
toast.success("Recipient Added Successfully!");
|
||||||
|
setTimeout(() => {
|
||||||
|
navigate("/my-wallet/transfer-fund", { replace: true });
|
||||||
|
}, 1000);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setRequestStatus({
|
||||||
|
message: "Opps! an error occured! Try again later",
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
//CALL TO ADD RECIPIENT API
|
// FUNCTION TO GET COUNTRIES
|
||||||
apiURL.addRecipient(reqData).then((res)=>{
|
const getCountry = () => {
|
||||||
if(res.data.internal_return < 0){
|
apiURL
|
||||||
setRequestStatus({message: 'could not add recipient, try again!', loading: false, status: true})
|
.getSignupCountryData()
|
||||||
return
|
.then((res) => {
|
||||||
}
|
if (res.data.internal_return < 0) {
|
||||||
// setRequestStatus({message: 'Recipient Added Successfully!', loading: false, status: true})
|
setAllCountries((prev) => ({ loading: false, data: [] }));
|
||||||
toast.success("Recipient Added Successfully!");
|
return;
|
||||||
setTimeout(()=>{navigate('/my-wallet/transfer-fund',{replace:true})},1000)
|
}
|
||||||
}).catch((error)=>{
|
setAllCountries((prev) => ({
|
||||||
setRequestStatus({message: 'Opps! an error occured! Try again later', loading: false, status: false})
|
loading: false,
|
||||||
})
|
data: res.data.signup_country,
|
||||||
}
|
}));
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setAllCountries((prev) => ({ loading: false, data: [] }));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// END OF FUNCTION TO GET COUNTRIES
|
||||||
|
|
||||||
|
// FUNCTION TO GET COUNTRY BANK
|
||||||
|
const getCountryBank = () => {
|
||||||
|
apiURL
|
||||||
|
.getCountryBank()
|
||||||
|
.then((res) => {
|
||||||
|
if (res.data.internal_return < 0) {
|
||||||
|
setBankName((prev) => ({ loading: false, data: [] }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setBankName((prev) => ({ loading: false, data: res.data.result_list }));
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setBankName((prev) => ({ loading: false, data: [] }));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// END OF FUNCTION TO GET COUNTRY BANK
|
||||||
|
|
||||||
// FUNCTION TO GET COUNTRIES
|
// FUNCTION TO GET ACCOUNT TYPES
|
||||||
const getCountry = ()=> {
|
const getAccountTypes = () => {
|
||||||
apiURL.getSignupCountryData().then((res)=>{
|
apiURL
|
||||||
if(res.data.internal_return < 0){
|
.getAccountTypes()
|
||||||
setAllCountries(prev => ({loading: false, data: []}))
|
.then((res) => {
|
||||||
return
|
if (res.data.internal_return < 0) {
|
||||||
}
|
setAccType((prev) => ({ loading: false, data: [] }));
|
||||||
setAllCountries(prev => ({loading: false, data:res.data.signup_country}))
|
return;
|
||||||
}).catch((error)=>{
|
}
|
||||||
setAllCountries(prev => ({loading: false, data: []}))
|
setAccType((prev) => ({ loading: false, data: res.data.result_list }));
|
||||||
})
|
})
|
||||||
}
|
.catch((error) => {
|
||||||
// END OF FUNCTION TO GET COUNTRIES
|
setAccType((prev) => ({ loading: false, data: [] }));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// END OF FUNCTION TO GET ACCOUNT TYPES
|
||||||
|
|
||||||
// FUNCTION TO GET COUNTRY BANK
|
useEffect(() => {
|
||||||
const getCountryBank = ()=> {
|
getCountry(); // TO LOAD LIST COUNTRY
|
||||||
apiURL.getCountryBank().then((res)=>{
|
getCountryBank(); // TO LOAD LIST COUNTRY BANK
|
||||||
if(res.data.internal_return < 0){
|
getAccountTypes(); // TO LOAD LIST ACCOUNT TYPES
|
||||||
setBankName(prev => ({loading: false, data: []}))
|
}, []);
|
||||||
return
|
|
||||||
}
|
|
||||||
setBankName(prev => ({loading: false, data:res.data.result_list}))
|
|
||||||
}).catch((error)=>{
|
|
||||||
setBankName(prev => ({loading: false, data: []}))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// END OF FUNCTION TO GET COUNTRY BANK
|
|
||||||
|
|
||||||
// FUNCTION TO GET ACCOUNT TYPES
|
return (
|
||||||
const getAccountTypes = ()=> {
|
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
|
||||||
apiURL.getAccountTypes().then((res)=>{
|
<div className="w-full mb-10 lg:mb-0">
|
||||||
if(res.data.internal_return < 0){
|
<div className="w-full md:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl shadow">
|
||||||
setAccType(prev => ({loading: false, data: []}))
|
<h2 className="my-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-semibold">
|
||||||
return
|
ADD BANK ACCOUNT
|
||||||
}
|
</h2>
|
||||||
setAccType(prev => ({loading: false, data:res.data.result_list}))
|
<Formik
|
||||||
}).catch((error)=>{
|
initialValues={initialValues}
|
||||||
setAccType(prev => ({loading: false, data: []}))
|
validationSchema={validationSchema}
|
||||||
})
|
onSubmit={handleSubmit}
|
||||||
}
|
>
|
||||||
// END OF FUNCTION TO GET ACCOUNT TYPES
|
{(props) => (
|
||||||
|
<Form className="add-recipient-info px-1 md:px-[50px] lg:px-[100px]">
|
||||||
|
{/* inputs starts here */}
|
||||||
|
{/* firstname */}
|
||||||
|
<div className="xl:flex xl:space-x-7 mb-6">
|
||||||
|
<div className="field w-full mb-6 xl:mb-0">
|
||||||
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
|
label="Firstname"
|
||||||
|
type="text"
|
||||||
|
name="firstname"
|
||||||
|
placeholder="Account Firstname"
|
||||||
|
value={props.values.firstname}
|
||||||
|
inputHandler={props.handleChange}
|
||||||
|
blurHandler={props.handleBlur}
|
||||||
|
/>
|
||||||
|
{props.errors.firstname && props.touched.firstname && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{props.errors.firstname}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
useEffect(()=>{
|
{/* lastname */}
|
||||||
getCountry() // TO LOAD LIST COUNTRY
|
<div className="field w-full">
|
||||||
getCountryBank() // TO LOAD LIST COUNTRY BANK
|
<InputCom
|
||||||
getAccountTypes() // TO LOAD LIST ACCOUNT TYPES
|
fieldClass="px-6"
|
||||||
},[])
|
label="Lastname"
|
||||||
|
type="text"
|
||||||
return (
|
name="lastname"
|
||||||
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
|
placeholder="Account Lastname"
|
||||||
<div className="w-full mb-10 lg:mb-0">
|
value={props.values.lastname}
|
||||||
<div className="w-full md:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl shadow">
|
inputHandler={props.handleChange}
|
||||||
<h2 className='my-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-semibold'>ADD BANK ACCOUNT</h2>
|
blurHandler={props.handleBlur}
|
||||||
<Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={handleSubmit}>
|
/>
|
||||||
{(props)=>(
|
{props.errors.lastname && props.touched.lastname && (
|
||||||
<Form className='add-recipient-info px-1 md:px-[50px] lg:px-[100px]'>
|
<p className="text-sm text-red-500">
|
||||||
|
{props.errors.lastname}
|
||||||
{/* inputs starts here */}
|
</p>
|
||||||
{/* firstname */}
|
)}
|
||||||
<div className="xl:flex xl:space-x-7 mb-6">
|
</div>
|
||||||
<div className="field w-full mb-6 xl:mb-0">
|
|
||||||
<InputCom
|
|
||||||
label="Firstname"
|
|
||||||
type="text"
|
|
||||||
name="firstname"
|
|
||||||
placeholder="Account Firstname"
|
|
||||||
value={props.values.firstname}
|
|
||||||
inputHandler={props.handleChange}
|
|
||||||
blurHandler={props.handleBlur}
|
|
||||||
/>
|
|
||||||
{(props.errors.firstname && props.touched.firstname) && <p className="text-sm text-red-500">{props.errors.firstname}</p>}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* lastname */}
|
|
||||||
<div className="field w-full">
|
|
||||||
<InputCom
|
|
||||||
label="Lastname"
|
|
||||||
type="text"
|
|
||||||
name="lastname"
|
|
||||||
placeholder="Account Lastname"
|
|
||||||
value={props.values.lastname}
|
|
||||||
inputHandler={props.handleChange}
|
|
||||||
blurHandler={props.handleBlur}
|
|
||||||
/>
|
|
||||||
{(props.errors.lastname && props.touched.lastname) && <p className="text-sm text-red-500">{props.errors.lastname}</p>}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div className="xl:flex xl:space-x-7 mb-6">
|
|
||||||
{/* country */}
|
|
||||||
<div className='add-recipient w-full mb-6 xl:mb-0'>
|
|
||||||
<label className='input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Country <span className='text-red-500'>*</span></label>
|
|
||||||
<select className='w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0' name='country'
|
|
||||||
value={props.values.country}
|
|
||||||
onChange={props.handleChange}
|
|
||||||
onBlur={props.handleBlur}
|
|
||||||
>
|
|
||||||
{allCountries.loading ?
|
|
||||||
<option className='text-slate-500 text-lg' value="">Loading...</option>
|
|
||||||
:
|
|
||||||
allCountries.data.length ?
|
|
||||||
<>
|
|
||||||
<option className='text-slate-500 text-lg' value="">Select...</option>
|
|
||||||
{allCountries.data.map((item, index)=>(
|
|
||||||
<option key={index} className='text-slate-500 text-lg' value={item[0]}>{item[1]}</option>
|
|
||||||
))}
|
|
||||||
</>
|
|
||||||
:
|
|
||||||
<option className='text-slate-500 text-lg' value="">No Options Found! Try Again</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
{(props.errors.country && props.touched.country) && <p className="text-sm text-red-500">{props.errors.country}</p>}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* bank name */}
|
|
||||||
<div className='add-recipient w-full'>
|
|
||||||
<label className='input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Bank Name <span className='text-red-500'>*</span></label>
|
|
||||||
<select className='w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0' name='bank'
|
|
||||||
value={props.values.bank}
|
|
||||||
onChange={props.handleChange}
|
|
||||||
onBlur={props.handleBlur}
|
|
||||||
>
|
|
||||||
{bankName.loading ?
|
|
||||||
<option className='text-slate-500 text-lg' value="">Loading...</option>
|
|
||||||
:
|
|
||||||
bankName.data.length ?
|
|
||||||
<>
|
|
||||||
<option className='text-slate-500 text-lg' value="">Select...</option>
|
|
||||||
{bankName.data.map((item, index)=>(
|
|
||||||
<option key={index} className='text-slate-500 text-lg' value={item.code}>{item.name}</option>
|
|
||||||
))}
|
|
||||||
</>
|
|
||||||
:
|
|
||||||
<option className='text-slate-500 text-lg' value="">No Options Found! Try Again</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
{(props.errors.bank && props.touched.bank) && <p className="text-sm text-red-500">{props.errors.bank}</p>}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* ACCOUNT NUMBER */}
|
|
||||||
<div className="xl:flex xl:space-x-7 mb-6">
|
|
||||||
<div className="field w-full mb-6 xl:mb-0">
|
|
||||||
<InputCom
|
|
||||||
label="Account Number"
|
|
||||||
type="text"
|
|
||||||
name="accountNumber"
|
|
||||||
placeholder="Account No"
|
|
||||||
value={props.values.accountNumber}
|
|
||||||
inputHandler={props.handleChange}
|
|
||||||
blurHandler={props.handleBlur}
|
|
||||||
/>
|
|
||||||
{(props.errors.accountNumber && props.touched.accountNumber) && <p className="text-sm text-red-500">{props.errors.accountNumber}</p>}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* REPEAT ACCT. NUMBER */}
|
|
||||||
<div className="field w-full">
|
|
||||||
<InputCom
|
|
||||||
label="Repeat Account Number"
|
|
||||||
type="text"
|
|
||||||
name="repeatAccountNumber"
|
|
||||||
placeholder="Repeat Account Number"
|
|
||||||
value={props.values.repeatAccountNumber}
|
|
||||||
inputHandler={props.handleChange}
|
|
||||||
blurHandler={props.handleBlur}
|
|
||||||
/>
|
|
||||||
{(props.errors.repeatAccountNumber && props.touched.repeatAccountNumber) && <p className="text-sm text-red-500">{props.errors.repeatAccountNumber}</p>}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="xl:flex xl:space-x-7 mb-6">
|
|
||||||
{/* Account Type */}
|
|
||||||
<div className='add-recipient w-full'>
|
|
||||||
<label className='input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Account Type <span className='text-red-500'>*</span></label>
|
|
||||||
<select className='w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0' name='accountType'
|
|
||||||
value={props.values.accountType}
|
|
||||||
onChange={props.handleChange}
|
|
||||||
onBlur={props.handleBlur}
|
|
||||||
>
|
|
||||||
{accType.loading ?
|
|
||||||
<option className='text-slate-500 text-lg' value="">Loading...</option>
|
|
||||||
:
|
|
||||||
accType.data.length ?
|
|
||||||
<>
|
|
||||||
<option className='text-slate-500 text-lg' value="">Select...</option>
|
|
||||||
{accType.data.map((item, index)=>(
|
|
||||||
<option key={index} className='text-slate-500 text-lg' value={item.value}>{item.name}</option>
|
|
||||||
))}
|
|
||||||
</>
|
|
||||||
:
|
|
||||||
<option className='text-slate-500 text-lg' value="">No Options Found! Try Again</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
{(props.errors.accountType && props.touched.accountType) && <p className="text-sm text-red-500">{props.errors.accountType}</p>}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* state */}
|
|
||||||
<div className="xl:flex xl:space-x-7 mb-6">
|
|
||||||
<div className="field w-full mb-6 xl:mb-0">
|
|
||||||
<InputCom
|
|
||||||
label="State"
|
|
||||||
type="text"
|
|
||||||
name="state"
|
|
||||||
placeholder="State/Province"
|
|
||||||
value={props.values.state}
|
|
||||||
inputHandler={props.handleChange}
|
|
||||||
blurHandler={props.handleBlur}
|
|
||||||
/>
|
|
||||||
{(props.errors.state && props.touched.state) && <p className="text-sm text-red-500">{props.errors.state}</p>}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* city */}
|
|
||||||
<div className="field w-full">
|
|
||||||
<InputCom
|
|
||||||
label="City"
|
|
||||||
type="text"
|
|
||||||
name="city"
|
|
||||||
placeholder="City"
|
|
||||||
value={props.values.city}
|
|
||||||
inputHandler={props.handleChange}
|
|
||||||
blurHandler={props.handleBlur}
|
|
||||||
/>
|
|
||||||
{(props.errors.city && props.touched.city) && <p className="text-sm text-red-500">{props.errors.city}</p>}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* end of inputs starts here */}
|
|
||||||
|
|
||||||
{/* REQUEST ERROR DISPLAY */}
|
|
||||||
{requestStatus.message && <p className='text-sm text-red-500'>{requestStatus.message}</p>}
|
|
||||||
|
|
||||||
<div className='add-recipient-btn flex justify-end items-center py-4'>
|
|
||||||
{requestStatus.loading ?
|
|
||||||
<LoadingSpinner size={6} color='sky-blue' />
|
|
||||||
:
|
|
||||||
<button type='submit' className='text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md flex items-center space-x-1'>
|
|
||||||
<span className='pr-2'>ADD RECIPIENT</span>
|
|
||||||
<Icons name="arrows" />
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</Form>
|
|
||||||
)}
|
|
||||||
</Formik>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<div className="xl:flex xl:space-x-7 mb-6">
|
||||||
|
{/* country */}
|
||||||
|
<div className="add-recipient w-full mb-6 xl:mb-0">
|
||||||
|
<label className="input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5">
|
||||||
|
Country <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
className="w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0"
|
||||||
|
name="country"
|
||||||
|
value={props.values.country}
|
||||||
|
onChange={props.handleChange}
|
||||||
|
onBlur={props.handleBlur}
|
||||||
|
>
|
||||||
|
{allCountries.loading ? (
|
||||||
|
<option className="text-slate-500 text-lg" value="">
|
||||||
|
Loading...
|
||||||
|
</option>
|
||||||
|
) : allCountries.data.length ? (
|
||||||
|
<>
|
||||||
|
<option className="text-slate-500 text-lg" value="">
|
||||||
|
Select...
|
||||||
|
</option>
|
||||||
|
{allCountries.data.map((item, index) => (
|
||||||
|
<option
|
||||||
|
key={index}
|
||||||
|
className="text-slate-500 text-lg"
|
||||||
|
value={item[0]}
|
||||||
|
>
|
||||||
|
{item[1]}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<option className="text-slate-500 text-lg" value="">
|
||||||
|
No Options Found! Try Again
|
||||||
|
</option>
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
{props.errors.country && props.touched.country && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{props.errors.country}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* bank name */}
|
||||||
|
<div className="add-recipient w-full">
|
||||||
|
<label className="input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5">
|
||||||
|
Bank Name <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
className="w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0"
|
||||||
|
name="bank"
|
||||||
|
value={props.values.bank}
|
||||||
|
onChange={props.handleChange}
|
||||||
|
onBlur={props.handleBlur}
|
||||||
|
>
|
||||||
|
{bankName.loading ? (
|
||||||
|
<option className="text-slate-500 text-lg" value="">
|
||||||
|
Loading...
|
||||||
|
</option>
|
||||||
|
) : bankName.data.length ? (
|
||||||
|
<>
|
||||||
|
<option className="text-slate-500 text-lg" value="">
|
||||||
|
Select...
|
||||||
|
</option>
|
||||||
|
{bankName.data.map((item, index) => (
|
||||||
|
<option
|
||||||
|
key={index}
|
||||||
|
className="text-slate-500 text-lg"
|
||||||
|
value={item.code}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<option className="text-slate-500 text-lg" value="">
|
||||||
|
No Options Found! Try Again
|
||||||
|
</option>
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
{props.errors.bank && props.touched.bank && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{props.errors.bank}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* ACCOUNT NUMBER */}
|
||||||
|
<div className="xl:flex xl:space-x-7 mb-6">
|
||||||
|
<div className="field w-full mb-6 xl:mb-0">
|
||||||
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
|
label="Account Number"
|
||||||
|
type="text"
|
||||||
|
name="accountNumber"
|
||||||
|
placeholder="Account No"
|
||||||
|
value={props.values.accountNumber}
|
||||||
|
inputHandler={props.handleChange}
|
||||||
|
blurHandler={props.handleBlur}
|
||||||
|
/>
|
||||||
|
{props.errors.accountNumber &&
|
||||||
|
props.touched.accountNumber && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{props.errors.accountNumber}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* REPEAT ACCT. NUMBER */}
|
||||||
|
<div className="field w-full">
|
||||||
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
|
label="Repeat Account Number"
|
||||||
|
type="text"
|
||||||
|
name="repeatAccountNumber"
|
||||||
|
placeholder="Repeat Account Number"
|
||||||
|
value={props.values.repeatAccountNumber}
|
||||||
|
inputHandler={props.handleChange}
|
||||||
|
blurHandler={props.handleBlur}
|
||||||
|
/>
|
||||||
|
{props.errors.repeatAccountNumber &&
|
||||||
|
props.touched.repeatAccountNumber && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{props.errors.repeatAccountNumber}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="xl:flex xl:space-x-7 mb-6">
|
||||||
|
{/* Account Type */}
|
||||||
|
<div className="add-recipient w-full">
|
||||||
|
<label className="input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5">
|
||||||
|
Account Type <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
className="w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0"
|
||||||
|
name="accountType"
|
||||||
|
value={props.values.accountType}
|
||||||
|
onChange={props.handleChange}
|
||||||
|
onBlur={props.handleBlur}
|
||||||
|
>
|
||||||
|
{accType.loading ? (
|
||||||
|
<option className="text-slate-500 text-lg" value="">
|
||||||
|
Loading...
|
||||||
|
</option>
|
||||||
|
) : accType.data.length ? (
|
||||||
|
<>
|
||||||
|
<option className="text-slate-500 text-lg" value="">
|
||||||
|
Select...
|
||||||
|
</option>
|
||||||
|
{accType.data.map((item, index) => (
|
||||||
|
<option
|
||||||
|
key={index}
|
||||||
|
className="text-slate-500 text-lg"
|
||||||
|
value={item.value}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<option className="text-slate-500 text-lg" value="">
|
||||||
|
No Options Found! Try Again
|
||||||
|
</option>
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
{props.errors.accountType && props.touched.accountType && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{props.errors.accountType}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* state */}
|
||||||
|
<div className="xl:flex xl:space-x-7 mb-6">
|
||||||
|
<div className="field w-full mb-6 xl:mb-0">
|
||||||
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
|
label="State"
|
||||||
|
type="text"
|
||||||
|
name="state"
|
||||||
|
placeholder="State/Province"
|
||||||
|
value={props.values.state}
|
||||||
|
inputHandler={props.handleChange}
|
||||||
|
blurHandler={props.handleBlur}
|
||||||
|
/>
|
||||||
|
{props.errors.state && props.touched.state && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{props.errors.state}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* city */}
|
||||||
|
<div className="field w-full">
|
||||||
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
|
label="City"
|
||||||
|
type="text"
|
||||||
|
name="city"
|
||||||
|
placeholder="City"
|
||||||
|
value={props.values.city}
|
||||||
|
inputHandler={props.handleChange}
|
||||||
|
blurHandler={props.handleBlur}
|
||||||
|
/>
|
||||||
|
{props.errors.city && props.touched.city && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{props.errors.city}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* end of inputs starts here */}
|
||||||
|
|
||||||
|
{/* REQUEST ERROR DISPLAY */}
|
||||||
|
{requestStatus.message && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{requestStatus.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="add-recipient-btn flex justify-end items-center py-4">
|
||||||
|
{requestStatus.loading ? (
|
||||||
|
<LoadingSpinner size={6} color="sky-blue" />
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md flex items-center space-x-1"
|
||||||
|
>
|
||||||
|
<span className="pr-2">ADD RECIPIENT</span>
|
||||||
|
<Icons name="arrows" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
</div>
|
</div>
|
||||||
)
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AddRecipient
|
export default AddRecipient;
|
||||||
|
|||||||
@@ -1,132 +1,156 @@
|
|||||||
import React, {useState, useEffect} from 'react'
|
import React, { useEffect, useState } from "react";
|
||||||
import RecentActivityTable from './WalletComponent/RecentActivityTable'
|
import { useSelector } from "react-redux";
|
||||||
import LoadingSpinner from '../Spinners/LoadingSpinner'
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import InputCom from '../Helpers/Inputs/InputCom'
|
import { toast } from "react-toastify";
|
||||||
import {toast} from 'react-toastify'
|
import InputCom from "../Helpers/Inputs/InputCom";
|
||||||
import { useLocation, useNavigate } from 'react-router-dom'
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
import { useSelector } from 'react-redux'
|
import RecentActivityTable from "./WalletComponent/RecentActivityTable";
|
||||||
|
|
||||||
import usersService from '../../services/UsersService'
|
import usersService from "../../services/UsersService";
|
||||||
|
|
||||||
import { FlutterWaveButton, closePaymentModal } from 'flutterwave-react-v3'
|
import { FlutterWaveButton, closePaymentModal } from "flutterwave-react-v3";
|
||||||
|
|
||||||
|
function ConfirmAddFund({ payment }) {
|
||||||
|
let { userDetails } = useSelector((state) => state.userDetails); // TO GET LOGGEDIN USER DETAILS
|
||||||
|
|
||||||
function ConfirmAddFund({payment}) {
|
let [pageLoading, setPageLoading] = useState(true);
|
||||||
|
|
||||||
let {userDetails} = useSelector(state => state.userDetails) // TO GET LOGGEDIN USER DETAILS
|
let [requestStatus, setRequestStatus] = useState({
|
||||||
|
message: "",
|
||||||
let [pageLoading, setPageLoading] = useState(true)
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
}); // STATE FOR API REQUEST
|
||||||
|
|
||||||
let [requestStatus, setRequestStatus] = useState({message: '', loading: false, status: false}) // STATE FOR API REQUEST
|
const apiURL = new usersService();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const apiURL = new usersService()
|
let { state } = useLocation();
|
||||||
const navigate = useNavigate()
|
|
||||||
|
|
||||||
let {state} = useLocation()
|
//FUNCTION TO HANDLE SUBMIT
|
||||||
|
const onSuccessPayment = () => {
|
||||||
|
setRequestStatus({ message: "", loading: true, status: false });
|
||||||
//FUNCTION TO HANDLE SUBMIT
|
let reqData = { amount: state?.account, currency: "NGN" };
|
||||||
const onSuccessPayment = () => {
|
apiURL
|
||||||
setRequestStatus({message: '', loading: true, status: false})
|
.startTopUp(reqData)
|
||||||
let reqData = {amount: state?.account, currency: 'NGN'}
|
.then((res) => {
|
||||||
apiURL.startTopUp(reqData).then((res)=>{
|
if (res.data.internal_return < 0) {
|
||||||
if(res.data.internal_return < 0){
|
setRequestStatus({
|
||||||
setRequestStatus({message: 'Could not finish transaction', loading: false, status: false})
|
message: "Could not finish transaction",
|
||||||
toast.success('Opps! something went wrong')
|
loading: false,
|
||||||
}
|
status: false,
|
||||||
// do something
|
});
|
||||||
setRequestStatus({message: 'Topup successful', loading: false, status: true})
|
toast.success("Opps! something went wrong");
|
||||||
toast.success('Account Topup was sucessful')
|
|
||||||
setTimeout(()=>{
|
|
||||||
navigate('/my-wallet', {replace: true})
|
|
||||||
window.location.reload(true)
|
|
||||||
}, 1000)
|
|
||||||
}).catch(err => {
|
|
||||||
// do something
|
|
||||||
setRequestStatus({message: 'Opps! An Error Occured', loading: false, status: false})
|
|
||||||
toast.success('Opps! something went wrong')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
public_key: process.env.REACT_APP_FLUTTERWAVE_APIKEY,
|
|
||||||
tx_ref: Date.now(),
|
|
||||||
amount: state?.amount,
|
|
||||||
currency: 'NGN',
|
|
||||||
payment_options: 'card,mobilemoney,ussd',
|
|
||||||
customer: {
|
|
||||||
email: `${userDetails.email}`,
|
|
||||||
phone_number: userDetails.phone,
|
|
||||||
name: `${userDetails.lastname} ${userDetails.firstname}`
|
|
||||||
},
|
|
||||||
customizations: {
|
|
||||||
title: 'WrenchBoard',
|
|
||||||
description: 'Topup Payment',
|
|
||||||
logo: 'https://st2.depositphotos.com/4403291/7418/v/450/depositphotos_74189661-stock-illustration-online-shop-log.jpg',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const fwConfig = {
|
|
||||||
...config,
|
|
||||||
text: 'Proceed',
|
|
||||||
callback: (response) => {
|
|
||||||
onSuccessPayment()
|
|
||||||
closePaymentModal() // this will close the modal programmatically
|
|
||||||
},
|
|
||||||
onClose: () => {},
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
// what happens if not state redirect user
|
|
||||||
if(!state){
|
|
||||||
navigate('/my-wallet/add-fund',{replace: true})
|
|
||||||
}else{
|
|
||||||
setPageLoading(false)
|
|
||||||
}
|
}
|
||||||
},[])
|
// do something
|
||||||
|
setRequestStatus({
|
||||||
|
message: "Topup successful",
|
||||||
|
loading: false,
|
||||||
|
status: true,
|
||||||
|
});
|
||||||
|
toast.success("Account Topup was sucessful");
|
||||||
|
setTimeout(() => {
|
||||||
|
navigate("/my-wallet", { replace: true });
|
||||||
|
window.location.reload(true);
|
||||||
|
}, 1000);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
// do something
|
||||||
|
setRequestStatus({
|
||||||
|
message: "Opps! An Error Occured",
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
});
|
||||||
|
toast.success("Opps! something went wrong");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
const config = {
|
||||||
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
|
public_key: process.env.REACT_APP_FLUTTERWAVE_APIKEY,
|
||||||
{pageLoading ?
|
tx_ref: Date.now(),
|
||||||
<LoadingSpinner size='8' color='sky-blue' />
|
amount: state?.amount,
|
||||||
:
|
currency: "NGN",
|
||||||
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
|
payment_options: "card,mobilemoney,ussd",
|
||||||
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl shadow">
|
customer: {
|
||||||
<h2 className='md:p-8 p-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Confirm Add Fund To Account</h2>
|
email: `${userDetails.email}`,
|
||||||
<hr />
|
phone_number: userDetails.phone,
|
||||||
<div className='px-4 md:px-8 py-4 add-fund-info'>
|
name: `${userDetails.lastname} ${userDetails.firstname}`,
|
||||||
<div className="field w-full mb-3">
|
},
|
||||||
<InputCom
|
customizations: {
|
||||||
label="Amount (Naira):"
|
title: "WrenchBoard",
|
||||||
type="text"
|
description: "Topup Payment",
|
||||||
name="amount"
|
logo: "https://st2.depositphotos.com/4403291/7418/v/450/depositphotos_74189661-stock-illustration-online-shop-log.jpg",
|
||||||
value={state.amount || ''}
|
},
|
||||||
disable={true}
|
};
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr />
|
const fwConfig = {
|
||||||
<div className='md:p-8 p-4 add-fund-btn flex justify-end items-center py-4'>
|
...config,
|
||||||
<FlutterWaveButton {...fwConfig} className='text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md' />
|
text: "Proceed",
|
||||||
</div>
|
callback: (response) => {
|
||||||
</div>
|
onSuccessPayment();
|
||||||
|
closePaymentModal(); // this will close the modal programmatically
|
||||||
|
},
|
||||||
|
onClose: () => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// what happens if not state redirect user
|
||||||
|
if (!state) {
|
||||||
|
navigate("/my-wallet/add-fund", { replace: true });
|
||||||
|
} else {
|
||||||
|
setPageLoading(false);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
|
||||||
|
{pageLoading ? (
|
||||||
|
<LoadingSpinner size="8" color="sky-blue" />
|
||||||
|
) : (
|
||||||
|
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
|
||||||
|
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl shadow">
|
||||||
|
<h2 className="md:p-8 p-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
|
||||||
|
Confirm Add Fund To Account
|
||||||
|
</h2>
|
||||||
|
<hr />
|
||||||
|
<div className="px-4 md:px-8 py-4 add-fund-info">
|
||||||
|
<div className="field w-full mb-3">
|
||||||
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
|
label="Amount (Naira):"
|
||||||
|
type="text"
|
||||||
|
name="amount"
|
||||||
|
value={state.amount || ""}
|
||||||
|
disable={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
|
||||||
|
<hr />
|
||||||
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
|
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4">
|
||||||
<div className="wallet w-full md:p-8 p-4 h-full max-h-[600px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
|
<FlutterWaveButton
|
||||||
<h2 className='text-gray-900 dark:text-white text-xl lg:text-2xl font-medium'>Recent Activity</h2>
|
{...fwConfig}
|
||||||
{/* <p className='text-base text-gray-600 dark:text-white'>Activity Report</p> */}
|
className="text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md"
|
||||||
{payment.loading ?
|
/>
|
||||||
<LoadingSpinner size='16' color='sky-blue' />
|
|
||||||
:
|
|
||||||
<RecentActivityTable payment={payment}/>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)}
|
||||||
|
|
||||||
|
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
|
||||||
|
<div className="wallet w-full md:p-8 p-4 h-full max-h-[600px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
|
||||||
|
<h2 className="text-gray-900 dark:text-white text-xl lg:text-2xl font-medium">
|
||||||
|
Recent Activity
|
||||||
|
</h2>
|
||||||
|
{/* <p className='text-base text-gray-600 dark:text-white'>Activity Report</p> */}
|
||||||
|
{payment.loading ? (
|
||||||
|
<LoadingSpinner size="16" color="sky-blue" />
|
||||||
|
) : (
|
||||||
|
<RecentActivityTable payment={payment} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ConfirmAddFund
|
export default ConfirmAddFund;
|
||||||
|
|||||||
@@ -1,168 +1,210 @@
|
|||||||
import React, {useState, useEffect} from 'react'
|
import React, { useEffect, useState } from "react";
|
||||||
import {useLocation, useNavigate} from 'react-router-dom'
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import RecentActivityTable from './WalletComponent/RecentActivityTable'
|
import { toast } from "react-toastify";
|
||||||
import LoadingSpinner from '../Spinners/LoadingSpinner'
|
import InputCom from "../Helpers/Inputs/InputCom";
|
||||||
import InputCom from '../Helpers/Inputs/InputCom'
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
import {toast} from 'react-toastify'
|
import RecentActivityTable from "./WalletComponent/RecentActivityTable";
|
||||||
|
|
||||||
import usersService from '../../services/UsersService'
|
import usersService from "../../services/UsersService";
|
||||||
|
|
||||||
function ConfirmTransfer({payment, wallet}) {
|
function ConfirmTransfer({ payment, wallet }) {
|
||||||
const apiURL = new usersService()
|
const apiURL = new usersService();
|
||||||
|
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate();
|
||||||
|
|
||||||
let {state} = useLocation()
|
|
||||||
|
|
||||||
|
|
||||||
let [requestStatus, setRequestStatus] = useState({message: '', loading: false, status: false})
|
let { state } = useLocation();
|
||||||
let [pageLoading, setPageLoading] = useState(true)
|
|
||||||
|
|
||||||
//FUNCTION TO HANDLE SUBMIT
|
let [requestStatus, setRequestStatus] = useState({
|
||||||
const handleSubmit = () => {
|
message: "",
|
||||||
setRequestStatus({message: '', loading: true, status: false})
|
loading: false,
|
||||||
let reqData = {
|
status: false,
|
||||||
amount: Number(state.amount),
|
});
|
||||||
Fee: Number(state.fee),
|
let [pageLoading, setPageLoading] = useState(true);
|
||||||
recipientid: Number(state.recipientID)
|
|
||||||
|
//FUNCTION TO HANDLE SUBMIT
|
||||||
|
const handleSubmit = () => {
|
||||||
|
setRequestStatus({ message: "", loading: true, status: false });
|
||||||
|
let reqData = {
|
||||||
|
amount: Number(state.amount),
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
apiURL.sendMoney(reqData).then((res)=>{
|
setRequestStatus({
|
||||||
if(res.data.internal_return < 0){
|
message: "transfer successful",
|
||||||
setRequestStatus({message: 'Could not perform transaction', loading: false, status: false})
|
loading: false,
|
||||||
return
|
status: true,
|
||||||
}
|
});
|
||||||
setRequestStatus({message: 'transfer successful', loading: false, status: true})
|
toast.success("Transfer sucessful");
|
||||||
toast.success('Transfer sucessful')
|
setTimeout(() => {
|
||||||
setTimeout(()=>{
|
navigate("/my-wallet", { replace: true });
|
||||||
navigate('/my-wallet', {replace: true})
|
window.location.reload(true);
|
||||||
window.location.reload(true)
|
}, 1000);
|
||||||
}, 1000)
|
})
|
||||||
}).catch(error=>{
|
.catch((error) => {
|
||||||
setRequestStatus({message: 'Opps! something went wrong! Try Again', loading: false, status: false})
|
setRequestStatus({
|
||||||
})
|
message: "Opps! something went wrong! Try Again",
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// what happens if not state redirect user
|
||||||
|
if (!state) {
|
||||||
|
navigate("/my-wallet/transfer-fund", { replace: true });
|
||||||
|
} else {
|
||||||
|
setPageLoading(false);
|
||||||
}
|
}
|
||||||
|
}, []);
|
||||||
useEffect(()=>{
|
return (
|
||||||
// what happens if not state redirect user
|
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
|
||||||
if(!state){
|
{pageLoading ? (
|
||||||
navigate('/my-wallet/transfer-fund',{replace: true})
|
<LoadingSpinner size="8" color="sky-blue" />
|
||||||
}else{
|
) : (
|
||||||
setPageLoading(false)
|
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
|
||||||
}
|
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl shadow">
|
||||||
},[])
|
<div className="px-4 md:px-8 py-4">
|
||||||
return (
|
{wallet.loading ? (
|
||||||
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
|
<LoadingSpinner size="8" color="sky-blue" />
|
||||||
{pageLoading ?
|
) : wallet.data.length ? (
|
||||||
<LoadingSpinner size='8' color='sky-blue' />
|
<h2 className="my-4 text-slate-500 dark:text-white text-sm xl:text-xl font-medium">
|
||||||
:
|
{wallet.data.map((item) => {
|
||||||
(
|
if (item.description == "Naira") {
|
||||||
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
|
return `Withdraw from Naira Wallet : ${item.symbol}${(
|
||||||
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl shadow">
|
item.amount * 0.01
|
||||||
<div className='px-4 md:px-8 py-4'>
|
).toFixed(2)}`;
|
||||||
{wallet.loading ?
|
|
||||||
<LoadingSpinner size='8' color='sky-blue' />
|
|
||||||
:
|
|
||||||
wallet.data.length ?
|
|
||||||
<h2 className='my-4 text-slate-500 dark:text-white text-sm xl:text-xl font-medium'>
|
|
||||||
{wallet.data.map(item => {
|
|
||||||
if(item.description == 'Naira'){
|
|
||||||
return `Withdraw from Naira Wallet : ${item.symbol}${(item.amount*0.01).toFixed(2)}`
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
</h2>
|
|
||||||
:
|
|
||||||
wallet.error ?
|
|
||||||
<h2 className='my-4 text-slate-500 dark:text-white text-sm xl:text-xl font-medium'>Opps! An Error Occured</h2>
|
|
||||||
:
|
|
||||||
<h2 className='my-4 text-slate-500 dark:text-white text-sm xl:text-xl font-medium'>No Wallet Information Found!</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
|
|
||||||
label="Amount:"
|
|
||||||
type="text"
|
|
||||||
name="amount"
|
|
||||||
value={state?.amount || ''}
|
|
||||||
disable={true}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* RECIPIENT ACC: */}
|
|
||||||
<div className="field w-full mb-3">
|
|
||||||
<InputCom
|
|
||||||
label="Recipient Acc:"
|
|
||||||
type="text"
|
|
||||||
name="recipient"
|
|
||||||
value={state?.details.recipient || ''}
|
|
||||||
disable={true}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* PROCESSING FEE: */}
|
|
||||||
<div className="field w-full mb-3">
|
|
||||||
<InputCom
|
|
||||||
label="Processing Fee:"
|
|
||||||
type="text"
|
|
||||||
name="processingFee"
|
|
||||||
value={state?.fee || ''}
|
|
||||||
disable={true}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* TOTAL */}
|
|
||||||
<div className="field w-full mb-3">
|
|
||||||
<InputCom
|
|
||||||
label="Total"
|
|
||||||
type="text"
|
|
||||||
name="total"
|
|
||||||
value={state?.total || ''}
|
|
||||||
disable={true}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* COMMENT/NOTE */}
|
|
||||||
<div className="field w-full mb-3">
|
|
||||||
<InputCom
|
|
||||||
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'>
|
|
||||||
{requestStatus.loading ?
|
|
||||||
<LoadingSpinner size='8' color='sky-blue' />
|
|
||||||
:
|
|
||||||
<button onClick={handleSubmit} className='text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md'>Transfer</button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
|
|
||||||
<div className="wallet w-full px-4 md:px-8 py-4 h-full max-h-[700px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
|
|
||||||
<h2 className='text-gray-900 dark:text-white text-xl lg:text-2xl font-medium'>Recent Activity</h2>
|
|
||||||
{/* <p className='text-base text-gray-600 dark:text-white'>Activity Report</p> */}
|
|
||||||
{payment.loading ?
|
|
||||||
<LoadingSpinner size='16' color='sky-blue' />
|
|
||||||
:
|
|
||||||
<RecentActivityTable payment={payment}/>
|
|
||||||
}
|
}
|
||||||
</div>
|
})}
|
||||||
|
</h2>
|
||||||
|
) : wallet.error ? (
|
||||||
|
<h2 className="my-4 text-slate-500 dark:text-white text-sm xl:text-xl font-medium">
|
||||||
|
Opps! An Error Occured
|
||||||
|
</h2>
|
||||||
|
) : (
|
||||||
|
<h2 className="my-4 text-slate-500 dark:text-white text-sm xl:text-xl font-medium">
|
||||||
|
No Wallet Information Found!
|
||||||
|
</h2>
|
||||||
|
)}
|
||||||
</div>
|
</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 || ""}
|
||||||
|
disable={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* TOTAL */}
|
||||||
|
<div className="field w-full mb-3">
|
||||||
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
|
label="Total"
|
||||||
|
type="text"
|
||||||
|
name="total"
|
||||||
|
value={state?.total || ""}
|
||||||
|
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">
|
||||||
|
{requestStatus.loading ? (
|
||||||
|
<LoadingSpinner size="8" color="sky-blue" />
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
onClick={handleSubmit}
|
||||||
|
className="text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md"
|
||||||
|
>
|
||||||
|
Transfer
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)}
|
||||||
|
|
||||||
|
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
|
||||||
|
<div className="wallet w-full px-4 md:px-8 py-4 h-full max-h-[700px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
|
||||||
|
<h2 className="text-gray-900 dark:text-white text-xl lg:text-2xl font-medium">
|
||||||
|
Recent Activity
|
||||||
|
</h2>
|
||||||
|
{/* <p className='text-base text-gray-600 dark:text-white'>Activity Report</p> */}
|
||||||
|
{payment.loading ? (
|
||||||
|
<LoadingSpinner size="16" color="sky-blue" />
|
||||||
|
) : (
|
||||||
|
<RecentActivityTable payment={payment} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ConfirmTransfer
|
export default ConfirmTransfer;
|
||||||
|
|||||||
@@ -1,240 +1,326 @@
|
|||||||
import React, {useEffect, useState} from 'react'
|
import React, { useEffect, useState } from "react";
|
||||||
import { Link, useNavigate } from 'react-router-dom'
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
import RecentActivityTable from './WalletComponent/RecentActivityTable'
|
import InputCom from "../Helpers/Inputs/InputCom";
|
||||||
import LoadingSpinner from '../Spinners/LoadingSpinner'
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
import InputCom from '../Helpers/Inputs/InputCom'
|
import RecentActivityTable from "./WalletComponent/RecentActivityTable";
|
||||||
|
|
||||||
import usersService from '../../services/UsersService'
|
import usersService from "../../services/UsersService";
|
||||||
|
|
||||||
import {toast} from 'react-toastify'
|
import { Form, Formik } from "formik";
|
||||||
|
import * as Yup from "yup";
|
||||||
import {Formik, Form} from 'formik'
|
|
||||||
import * as Yup from 'yup'
|
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
amount: Yup.number()
|
amount: Yup.number()
|
||||||
.typeError("you must specify a number")
|
.typeError("you must specify a number")
|
||||||
.min(1, 'Amount must be greater than 0')
|
.min(1, "Amount must be greater than 0")
|
||||||
.required('Amount is required'),
|
.required("Amount is required"),
|
||||||
recipientID: Yup.string()
|
recipientID: Yup.string()
|
||||||
.min(1, 'Minimum 1 characters')
|
.min(1, "Minimum 1 characters")
|
||||||
.max(50, 'Maximum 50 characters')
|
.max(50, "Maximum 50 characters")
|
||||||
.required('Recipient is required'),
|
.required("Recipient is required"),
|
||||||
})
|
});
|
||||||
|
|
||||||
const initialValues = {
|
|
||||||
amount: '',
|
|
||||||
recipientID: '',
|
|
||||||
comment: '',
|
|
||||||
}
|
|
||||||
|
|
||||||
function TransferFund({payment, wallet}) {
|
const initialValues = {
|
||||||
const apiCall = new usersService() // API CLASS CALL
|
amount: "",
|
||||||
|
recipientID: "",
|
||||||
|
comment: "",
|
||||||
|
};
|
||||||
|
|
||||||
const navigate = useNavigate()
|
function TransferFund({ payment, wallet }) {
|
||||||
|
const apiCall = new usersService(); // API CLASS CALL
|
||||||
|
|
||||||
let [requestStatus, setRequestStatus] = useState(false)
|
const navigate = useNavigate();
|
||||||
|
|
||||||
let [recipients, setRecipients] = useState({ // FOR COUPON HISTORY
|
let [requestStatus, setRequestStatus] = useState(false);
|
||||||
loading: true,
|
|
||||||
data: [],
|
|
||||||
error: false
|
|
||||||
})
|
|
||||||
|
|
||||||
let [sendMoneyFee, setSendMoneyFee] = useState({loading: false, fee: 0, total: 0}) // HOLD THE VALUE FOR SEND MONEY FEE
|
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 SEND MONEY FEE
|
||||||
|
|
||||||
//FUNCTION TO GET RECIPIENT LIST
|
//FUNCTION TO GET RECIPIENT LIST
|
||||||
const getRecipients = ()=>{
|
const getRecipients = () => {
|
||||||
apiCall.getRecipient().then((res)=>{
|
apiCall
|
||||||
if(res.data.internal_return < 0){ // success but no data
|
.getRecipient()
|
||||||
setRecipients(prev => ({...prev, loading: false}))
|
.then((res) => {
|
||||||
return
|
if (res.data.internal_return < 0) {
|
||||||
}
|
// success but no data
|
||||||
setRecipients(prev => ({...prev, loading: false, data: res.data.result_list}))
|
setRecipients((prev) => ({ ...prev, loading: false }));
|
||||||
}).catch((error)=>{
|
return;
|
||||||
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)).then((res)=>{
|
setRecipients((prev) => ({
|
||||||
setSendMoneyFee({loading: false, fee: res.data.processing_fee, total: res.data.total_amount})
|
...prev,
|
||||||
}).catch((error)=>{
|
loading: false,
|
||||||
setSendMoneyFee({loading: false, fee: 0, total: 0})
|
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))
|
||||||
|
.then((res) => {
|
||||||
|
setSendMoneyFee({
|
||||||
|
loading: false,
|
||||||
|
fee: res.data.processing_fee,
|
||||||
|
total: res.data.total_amount,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setSendMoneyFee({ loading: false, fee: 0, total: 0 });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//FUNCTION TO HANDLE SUBMIT
|
||||||
|
const handleSubmit = (values, helpers) => {
|
||||||
|
setRequestStatus(true);
|
||||||
|
let recipientDetails = recipients.data?.filter(
|
||||||
|
(item) => item.recipient_id == values.recipientID
|
||||||
|
);
|
||||||
|
let stateData = {
|
||||||
|
...values,
|
||||||
|
...sendMoneyFee,
|
||||||
|
details: { ...recipientDetails[0] },
|
||||||
|
};
|
||||||
|
|
||||||
//FUNCTION TO HANDLE SUBMIT
|
setTimeout(() => {
|
||||||
const handleSubmit = (values, helpers) => {
|
setRequestStatus(false);
|
||||||
setRequestStatus(true)
|
navigate("confirm-transfer", { state: stateData });
|
||||||
let recipientDetails = recipients.data?.filter(item => item.recipient_id == values.recipientID)
|
}, 1000);
|
||||||
let stateData = {...values, ...sendMoneyFee, details:{...recipientDetails[0]}}
|
};
|
||||||
|
|
||||||
setTimeout(()=>{
|
useEffect(() => {
|
||||||
setRequestStatus(false)
|
getRecipients();
|
||||||
navigate('confirm-transfer', {state: stateData})
|
}, []);
|
||||||
}, 1000)
|
return (
|
||||||
}
|
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
|
||||||
|
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
|
||||||
|
<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">
|
||||||
|
{wallet.loading ? (
|
||||||
|
<LoadingSpinner size="8" color="sky-blue" />
|
||||||
|
) : wallet.data.length ? (
|
||||||
|
<h2 className="my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
|
||||||
|
{wallet.data.map((item) => {
|
||||||
|
if (item.description == "Naira") {
|
||||||
|
return `Withdraw from Naira Wallet : ${item.symbol}${(
|
||||||
|
item.amount * 0.01
|
||||||
|
).toFixed(2)}`;
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</h2>
|
||||||
|
) : wallet.error ? (
|
||||||
|
<h2 className="my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
|
||||||
|
Opps! An Error Occured
|
||||||
|
</h2>
|
||||||
|
) : (
|
||||||
|
<h2 className="my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
|
||||||
|
No Wallet Information Found!
|
||||||
|
</h2>
|
||||||
|
)}
|
||||||
|
<div className="xl:flex xl:space-x-7 mb-6">
|
||||||
|
<div className="field w-full mb-6 xl:mb-0">
|
||||||
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
|
label="Amount"
|
||||||
|
type="text"
|
||||||
|
name="amount"
|
||||||
|
placeholder="0"
|
||||||
|
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="text-sm text-red-500">
|
||||||
|
{props.errors.amount}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
useEffect(()=>{
|
<div className="field w-full">
|
||||||
getRecipients()
|
<InputCom
|
||||||
},[])
|
fieldClass="px-6"
|
||||||
return (
|
label="Fee"
|
||||||
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
|
type="text"
|
||||||
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
|
name="fee"
|
||||||
<div className="add-fund w-full md:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl shadow">
|
value={
|
||||||
<Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={handleSubmit}>
|
sendMoneyFee.loading ? "loading" : sendMoneyFee.fee
|
||||||
{(props)=>{
|
}
|
||||||
return (
|
disable={true}
|
||||||
<Form className='transfer-fund-info'>
|
/>
|
||||||
{wallet.loading ?
|
</div>
|
||||||
<LoadingSpinner size='8' color='sky-blue' />
|
</div>
|
||||||
:
|
|
||||||
wallet.data.length ?
|
|
||||||
<h2 className='my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>
|
|
||||||
{wallet.data.map(item => {
|
|
||||||
if(item.description == 'Naira'){
|
|
||||||
return `Withdraw from Naira Wallet : ${item.symbol}${(item.amount*0.01).toFixed(2)}`
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
</h2>
|
|
||||||
:
|
|
||||||
wallet.error ?
|
|
||||||
<h2 className='my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Opps! An Error Occured</h2>
|
|
||||||
:
|
|
||||||
<h2 className='my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>No Wallet Information Found!</h2>
|
|
||||||
}
|
|
||||||
<div className="xl:flex xl:space-x-7 mb-6">
|
|
||||||
|
|
||||||
<div className="field w-full mb-6 xl:mb-0">
|
<div className="md:flex items-center justify-end">
|
||||||
<InputCom
|
<div className="field w-full lg:w-1/2 mb-6">
|
||||||
label="Amount"
|
<InputCom
|
||||||
type="text"
|
fieldClass="px-6"
|
||||||
name="amount"
|
label="Total"
|
||||||
placeholder='0'
|
type="text"
|
||||||
value={props.values.amount}
|
name="total"
|
||||||
inputHandler={props.handleChange}
|
value={
|
||||||
blurHandler={(e)=>{
|
sendMoneyFee.loading ? "loading" : sendMoneyFee.total
|
||||||
getSendMoneyFee(e)
|
}
|
||||||
}}
|
disable={true}
|
||||||
// props.handleBlur
|
/>
|
||||||
// onMouseLeave={(e)=>{getSendMoneyFee(e)}}
|
</div>
|
||||||
/>
|
</div>
|
||||||
{(props.errors.amount && props.touched.amount) && <p className="text-sm text-red-500">{props.errors.amount}</p>}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="field w-full">
|
|
||||||
<InputCom
|
|
||||||
label="Fee"
|
|
||||||
type="text"
|
|
||||||
name="fee"
|
|
||||||
value={sendMoneyFee.loading ? 'loading' : sendMoneyFee.fee}
|
|
||||||
disable={true}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='md:flex items-center justify-end'>
|
<div className="w-full">
|
||||||
<div className="field w-full lg:w-1/2 mb-6">
|
<div className="relative my-3 md:flex items-center">
|
||||||
<InputCom
|
<div className="transfer-input w-full">
|
||||||
label="Total"
|
<div className="flex items-center justify-start py-2">
|
||||||
type="text"
|
<label className="text-[#181c32] dark:text-white text-base font-semibold block mb-2.5">
|
||||||
name="total"
|
Recipient
|
||||||
value={sendMoneyFee.loading ? 'loading' : sendMoneyFee.total}
|
<span className="text-red-500 mx-2">*</span>
|
||||||
disable={true}
|
<span
|
||||||
/>
|
title="Transfer Recipient"
|
||||||
</div>
|
className={`text-white text-sm bg-slate-500 w-1 h-1 rounded-full px-3 py-1 cursor-pointer`}
|
||||||
</div>
|
>
|
||||||
|
!
|
||||||
<div className='w-full'>
|
</span>
|
||||||
<div className='relative my-3 md:flex items-center'>
|
</label>
|
||||||
<div className='transfer-input w-full'>
|
<Link
|
||||||
<div className='flex items-center justify-start py-2'>
|
to="add-recipient"
|
||||||
<label className='text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Recipient
|
className="mx-1 text-base text-white p-2 bg-[orange] rounded-md hover:opacity-80"
|
||||||
<span className='text-red-500 mx-2'>*</span>
|
>
|
||||||
<span title='Transfer Recipient' className={`text-white text-sm bg-slate-500 w-1 h-1 rounded-full px-3 py-1 cursor-pointer`}>!</span>
|
Add New
|
||||||
</label>
|
</Link>
|
||||||
<Link to='add-recipient' className='mx-1 text-base text-white p-2 bg-[orange] rounded-md hover:opacity-80'>Add New</Link>
|
</div>
|
||||||
</div>
|
<select
|
||||||
<select className='w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0' value={props.values.recipientID} name='recipientID' onChange={props.handleChange} onBlur={props.handleBlur}>
|
className="w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0"
|
||||||
{recipients.loading ?
|
value={props.values.recipientID}
|
||||||
<option className='text-slate-500 text-lg' value="">Loading...</option>
|
name="recipientID"
|
||||||
:
|
onChange={props.handleChange}
|
||||||
recipients.data.length ?
|
onBlur={props.handleBlur}
|
||||||
<>
|
>
|
||||||
<option className='text-slate-500 text-lg' value="">Select...</option>
|
{recipients.loading ? (
|
||||||
{recipients.data.map((item, index)=>(
|
<option className="text-slate-500 text-lg" value="">
|
||||||
<option key={index} value={item.recipient_id} className='text-slate-500 text-lg'>{item.recipient}</option>
|
Loading...
|
||||||
))}
|
</option>
|
||||||
</>
|
) : recipients.data.length ? (
|
||||||
:
|
<>
|
||||||
recipients.error ?
|
<option
|
||||||
<option className='text-slate-500 text-lg' value="">Could'nt Load, try again!</option>
|
className="text-slate-500 text-lg"
|
||||||
:
|
value=""
|
||||||
<option className='text-slate-500 text-lg' value="">No Recipient Found! Click Add to Add</option>
|
>
|
||||||
}
|
Select...
|
||||||
</select>
|
</option>
|
||||||
</div>
|
{recipients.data.map((item, index) => (
|
||||||
</div>
|
<option
|
||||||
{(props.errors.recipientID && props.touched.recipientID) && <p className="text-sm text-red-500">{props.errors.recipientID}</p>}
|
key={index}
|
||||||
</div>
|
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! Click Add to Add
|
||||||
|
</option>
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{props.errors.recipientID && props.touched.recipientID && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{props.errors.recipientID}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="field w-full mb-6">
|
<div className="field w-full mb-6">
|
||||||
{/* <InputCom
|
{/* <InputCom fieldClass="px-6"
|
||||||
label="Comment"
|
label="Comment"
|
||||||
type="text"
|
type="text"
|
||||||
name="comment"
|
name="comment"
|
||||||
value={inputs.comment}
|
value={inputs.comment}
|
||||||
inputHandler={handleChange}
|
inputHandler={handleChange}
|
||||||
/> */}
|
/> */}
|
||||||
<label className='text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Comment</label>
|
<label className="text-[#181c32] dark:text-white text-base font-semibold block mb-2.5">
|
||||||
<textarea style={{resize: 'none'}}
|
Comment
|
||||||
className='text-base px-6 text-dark-gray dark:text-white w-full bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none'
|
</label>
|
||||||
name="comment"
|
<textarea
|
||||||
value={props.values.comment}
|
style={{ resize: "none" }}
|
||||||
onChange={props.handleChange}
|
className="text-base px-6 text-dark-gray dark:text-white w-full bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none"
|
||||||
onBlur={props.handleBlur}
|
name="comment"
|
||||||
cols="30"
|
value={props.values.comment}
|
||||||
rows="2"
|
onChange={props.handleChange}
|
||||||
/>
|
onBlur={props.handleBlur}
|
||||||
</div>
|
cols="30"
|
||||||
|
rows="2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className='transfer-fund-btn flex justify-end items-center py-4'>
|
<div className="transfer-fund-btn flex justify-end items-center py-4">
|
||||||
{requestStatus ?
|
{requestStatus ? (
|
||||||
<LoadingSpinner size='8' color='sky-blue' />
|
<LoadingSpinner size="8" color="sky-blue" />
|
||||||
:
|
) : (
|
||||||
<button type='submit' className='text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md'>Continue</button>
|
<button
|
||||||
}
|
type="submit"
|
||||||
</div>
|
className="text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md"
|
||||||
</Form>
|
>
|
||||||
)
|
Continue
|
||||||
}}
|
</button>
|
||||||
</Formik>
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Form>
|
||||||
|
);
|
||||||
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
|
}}
|
||||||
<div className="wallet w-full md:p-8 p-4 h-full max-h-[650px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
|
</Formik>
|
||||||
<h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Recent Activity</h2>
|
|
||||||
{/* <p className='text-base text-slate-500 dark:text-white'>Activity Report</p> */}
|
|
||||||
{payment.loading ?
|
|
||||||
<LoadingSpinner size='16' color='sky-blue' />
|
|
||||||
:
|
|
||||||
<RecentActivityTable payment={payment}/>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
</div>
|
||||||
|
|
||||||
|
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
|
||||||
|
<div className="wallet w-full md:p-8 p-4 h-full max-h-[650px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
|
||||||
|
<h2 className="text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
|
||||||
|
Recent Activity
|
||||||
|
</h2>
|
||||||
|
{/* <p className='text-base text-slate-500 dark:text-white'>Activity Report</p> */}
|
||||||
|
{payment.loading ? (
|
||||||
|
<LoadingSpinner size="16" color="sky-blue" />
|
||||||
|
) : (
|
||||||
|
<RecentActivityTable payment={payment} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TransferFund
|
export default TransferFund;
|
||||||
|
|||||||
@@ -1,182 +1,224 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from "react";
|
||||||
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 InputCom from '../Helpers/Inputs/InputCom';
|
import InputCom from "../Helpers/Inputs/InputCom";
|
||||||
import LoadingSpinner from '../Spinners/LoadingSpinner';
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
|
|
||||||
import {Formik, Form} from 'formik'
|
import { Form, Formik } from "formik";
|
||||||
import * as Yup from 'yup'
|
import * as Yup from "yup";
|
||||||
import ReferralTable from '../MyWallet/WalletComponent/ReferralTable';
|
import ReferralTable from "../MyWallet/WalletComponent/ReferralTable";
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
email: Yup.string()
|
email: Yup.string()
|
||||||
.email('Wrong email format')
|
.email("Wrong email format")
|
||||||
.min(3, 'Minimum 3 characters')
|
.min(3, "Minimum 3 characters")
|
||||||
.max(50, 'Maximum 50 characters')
|
.max(50, "Maximum 50 characters")
|
||||||
.required('Email is required'),
|
.required("Email is required"),
|
||||||
firstname: Yup.string()
|
firstname: Yup.string()
|
||||||
.min(3, 'Minimum 3 characters')
|
.min(3, "Minimum 3 characters")
|
||||||
.max(25, 'Maximum 25 characters')
|
.max(25, "Maximum 25 characters")
|
||||||
.required('Firstname is required'),
|
.required("Firstname is required"),
|
||||||
lastname: Yup.string()
|
lastname: Yup.string()
|
||||||
.min(3, 'Minimum 3 characters')
|
.min(3, "Minimum 3 characters")
|
||||||
.max(25, 'Maximum 25 characters')
|
.max(25, "Maximum 25 characters")
|
||||||
.required('Lastname is required'),
|
.required("Lastname is required"),
|
||||||
})
|
});
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
firstname: '',
|
firstname: "",
|
||||||
lastname: '',
|
lastname: "",
|
||||||
email: ''
|
email: "",
|
||||||
}
|
};
|
||||||
|
|
||||||
function ReferralDisplay() {
|
function ReferralDisplay() {
|
||||||
const apiCall = new usersService() // GET API CALL
|
const apiCall = new usersService(); // GET API CALL
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate();
|
||||||
|
|
||||||
let [refHistoryReload, setRefHistoryReload] = useState(false) // Determines when referral history reloads
|
let [refHistoryReload, setRefHistoryReload] = useState(false); // Determines when referral history reloads
|
||||||
|
|
||||||
// STATE TO HOLD REFERRAL HISTORY
|
// STATE TO HOLD REFERRAL HISTORY
|
||||||
let [referralList, setReferralList] = useState({
|
let [referralList, setReferralList] = useState({
|
||||||
loading: true,
|
loading: true,
|
||||||
error: false,
|
error: false,
|
||||||
data: []
|
data: [],
|
||||||
})
|
});
|
||||||
|
|
||||||
let [error, setError] = useState({message: '', loading: false, status: false}) // for displaying error message on the page
|
let [error, setError] = useState({
|
||||||
|
message: "",
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
}); // for displaying error message on the page
|
||||||
|
|
||||||
//function to call referral history API
|
//function to call referral history API
|
||||||
const allReferrals = () => {
|
const allReferrals = () => {
|
||||||
setReferralList({
|
setReferralList({
|
||||||
loading: true,
|
loading: true,
|
||||||
error: false,
|
error: false,
|
||||||
data: []
|
data: [],
|
||||||
})
|
});
|
||||||
apiCall.getReferralHx().then((res)=>{
|
apiCall
|
||||||
setReferralList((prev)=>{
|
.getReferralHx()
|
||||||
return {...prev, loading: false, data:[...res.data.result_list]}
|
.then((res) => {
|
||||||
})
|
setReferralList((prev) => {
|
||||||
}).catch((error)=>{
|
return { ...prev, loading: false, data: [...res.data.result_list] };
|
||||||
setReferralList(prev => ({...prev, loading: false, error: true}))
|
});
|
||||||
})
|
})
|
||||||
}
|
.catch((error) => {
|
||||||
|
setReferralList((prev) => ({ ...prev, loading: false, error: true }));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
//FUNCTION TO SEND REFERRAL MESSAGE
|
//FUNCTION TO SEND REFERRAL MESSAGE
|
||||||
const sendReferralMsg = (postData) => {
|
const sendReferralMsg = (postData) => {
|
||||||
apiCall.sendReferralMsg(postData).then((res)=>{
|
apiCall
|
||||||
if(res.data.internal_return < 0){
|
.sendReferralMsg(postData)
|
||||||
setError({message:'Email already referred', loading: false, status: false})
|
.then((res) => {
|
||||||
return
|
if (res.data.internal_return < 0) {
|
||||||
}else{
|
setError({
|
||||||
toast.success("Message Sent");
|
message: "Email already referred",
|
||||||
setError({message:'', loading: false, status: true})
|
loading: false,
|
||||||
setRefHistoryReload(prev => !prev)
|
status: false,
|
||||||
}
|
});
|
||||||
}).catch((error)=>{
|
return;
|
||||||
setError({message:'Opps! an error occured, try again later', loading: false, status: false})
|
} else {
|
||||||
})
|
toast.success("Message Sent");
|
||||||
}
|
setError({ message: "", loading: false, status: true });
|
||||||
|
setRefHistoryReload((prev) => !prev);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setError({
|
||||||
|
message: "Opps! an error occured, try again later",
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
//FUNCTION TO HANDLE SUBMIT
|
//FUNCTION TO HANDLE SUBMIT
|
||||||
const handleSubmit = (values, helpers) => {
|
const handleSubmit = (values, helpers) => {
|
||||||
setError({message: '', loading: true, status: false})
|
setError({ message: "", loading: true, status: false });
|
||||||
|
|
||||||
var postData = {
|
var postData = {
|
||||||
uid: localStorage.getItem("uid"),
|
uid: localStorage.getItem("uid"),
|
||||||
member_id: localStorage.getItem("member_id"),
|
member_id: localStorage.getItem("member_id"),
|
||||||
sessionid: localStorage.getItem("session_token"),
|
sessionid: localStorage.getItem("session_token"),
|
||||||
action: 11032,
|
action: 11032,
|
||||||
...values
|
...values,
|
||||||
};
|
};
|
||||||
|
|
||||||
sendReferralMsg(postData) // FUNCTION TO SEND REFERRAL MESSAGE
|
sendReferralMsg(postData); // FUNCTION TO SEND REFERRAL MESSAGE
|
||||||
}
|
};
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(() => {
|
||||||
allReferrals()
|
allReferrals();
|
||||||
}, [refHistoryReload])
|
}, [refHistoryReload]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
|
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
|
||||||
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
|
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
|
||||||
<div className="referral w-full md:p-8 p-4 h-full bg-white dark:bg-dark-white rounded-2xl shadow">
|
<div className="referral w-full md:p-8 p-4 h-full bg-white dark:bg-dark-white rounded-2xl shadow">
|
||||||
<h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Send Referral</h2>
|
<h2 className="text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
|
||||||
<Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={handleSubmit}>
|
Send Referral
|
||||||
{(props)=>(
|
</h2>
|
||||||
<Form className='referral-info'>
|
<Formik
|
||||||
{/* Firstname */}
|
initialValues={initialValues}
|
||||||
<div className="field w-full mb-6">
|
validationSchema={validationSchema}
|
||||||
<InputCom
|
onSubmit={handleSubmit}
|
||||||
label="Firstname"
|
>
|
||||||
type="text"
|
{(props) => (
|
||||||
name="firstname"
|
<Form className="referral-info">
|
||||||
placeholder="Firstname"
|
{/* Firstname */}
|
||||||
value={props.values.firstname}
|
<div className="field w-full mb-6">
|
||||||
inputHandler={props.handleChange}
|
<InputCom
|
||||||
blurHandler={props.handleBlur}
|
fieldClass="px-6"
|
||||||
/>
|
label="Firstname"
|
||||||
{(props.errors.firstname && props.touched.firstname) && <p className="text-sm text-red-500">{props.errors.firstname}</p>}
|
type="text"
|
||||||
</div>
|
name="firstname"
|
||||||
|
placeholder="Firstname"
|
||||||
|
value={props.values.firstname}
|
||||||
|
inputHandler={props.handleChange}
|
||||||
|
blurHandler={props.handleBlur}
|
||||||
|
/>
|
||||||
|
{props.errors.firstname && props.touched.firstname && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{props.errors.firstname}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Lastname */}
|
{/* Lastname */}
|
||||||
<div className="field w-full mb-6">
|
<div className="field w-full mb-6">
|
||||||
<InputCom
|
<InputCom
|
||||||
label="Lastname"
|
fieldClass="px-6"
|
||||||
type="text"
|
label="Lastname"
|
||||||
name="lastname"
|
type="text"
|
||||||
placeholder="Lastname"
|
name="lastname"
|
||||||
value={props.values.lastname}
|
placeholder="Lastname"
|
||||||
inputHandler={props.handleChange}
|
value={props.values.lastname}
|
||||||
blurHandler={props.handleBlur}
|
inputHandler={props.handleChange}
|
||||||
/>
|
blurHandler={props.handleBlur}
|
||||||
{(props.errors.lastname && props.touched.lastname) && <p className="text-sm text-red-500">{props.errors.lastname}</p>}
|
/>
|
||||||
</div>
|
{props.errors.lastname && props.touched.lastname && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{props.errors.lastname}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="field w-full mb-6">
|
<div className="field w-full mb-6">
|
||||||
<InputCom
|
<InputCom
|
||||||
label="Email"
|
fieldClass="px-6"
|
||||||
type="text"
|
label="Email"
|
||||||
name="email"
|
type="text"
|
||||||
placeholder="Email"
|
name="email"
|
||||||
value={props.values.email}
|
placeholder="Email"
|
||||||
inputHandler={props.handleChange}
|
value={props.values.email}
|
||||||
blurHandler={props.handleBlur}
|
inputHandler={props.handleChange}
|
||||||
/>
|
blurHandler={props.handleBlur}
|
||||||
{(props.errors.email && props.touched.email) && <p className="text-sm text-red-500">{props.errors.email}</p>}
|
/>
|
||||||
</div>
|
{props.errors.email && props.touched.email && (
|
||||||
|
<p className="text-sm text-red-500">{props.errors.email}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
{error.message != '' && <p className='text-base text-red-500 py-2'>{error.message}</p>}
|
{error.message != "" && (
|
||||||
<div className='referral-btn flex justify-end items-center py-4 border-b-4'>
|
<p className="text-base text-red-500 py-2">{error.message}</p>
|
||||||
{error.loading ?
|
)}
|
||||||
<LoadingSpinner size='6' color='sky-blue' />
|
<div className="referral-btn flex justify-end items-center py-4 border-b-4">
|
||||||
:
|
{error.loading ? (
|
||||||
<button type='submit' className='text-lg text-white bg-sky-blue p-2 hover:opacity-90 rounded-md'>Send Message</button>
|
<LoadingSpinner size="6" color="sky-blue" />
|
||||||
}
|
) : (
|
||||||
</div>
|
<button
|
||||||
</Form>
|
type="submit"
|
||||||
)}
|
className="text-lg text-white bg-sky-blue p-2 hover:opacity-90 rounded-md"
|
||||||
</Formik>
|
>
|
||||||
</div>
|
Send Message
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
|
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
|
||||||
<div className="referral w-full md:p-8 p-4 h-full max-h-[700px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
|
<div className="referral w-full md:p-8 p-4 h-full max-h-[700px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
|
||||||
<h2 className='mb-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Referral List</h2>
|
<h2 className="mb-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
|
||||||
{referralList.loading ?
|
Referral List
|
||||||
(
|
</h2>
|
||||||
<LoadingSpinner size='32' color='sky-blue' />
|
{referralList.loading ? (
|
||||||
)
|
<LoadingSpinner size="32" color="sky-blue" />
|
||||||
:
|
) : (
|
||||||
(
|
<ReferralTable history={referralList} />
|
||||||
<ReferralTable history={referralList} />
|
)}
|
||||||
)
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ReferralDisplay
|
export default ReferralDisplay;
|
||||||
|
|||||||
@@ -1,39 +1,39 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
|
import usersService from "../../../services/UsersService";
|
||||||
import Icons from "../../Helpers/Icons";
|
import Icons from "../../Helpers/Icons";
|
||||||
import InputCom from "../../Helpers/Inputs/InputCom";
|
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||||
import {Link, useNavigate} from 'react-router-dom'
|
|
||||||
import usersService from "../../../services/UsersService";
|
|
||||||
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||||
import { useSelector } from "react-redux";
|
|
||||||
|
|
||||||
import {toast} from 'react-toastify'
|
import { toast } from "react-toastify";
|
||||||
|
|
||||||
import {Formik, Form} from 'formik'
|
import { Form, Formik } from "formik";
|
||||||
import * as Yup from 'yup'
|
import * as Yup from "yup";
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
email: Yup.string()
|
email: Yup.string()
|
||||||
.email('Wrong email format')
|
.email("Wrong email format")
|
||||||
.min(3, 'Minimum 3 characters')
|
.min(3, "Minimum 3 characters")
|
||||||
.max(50, 'Maximum 50 characters')
|
.max(50, "Maximum 50 characters")
|
||||||
.required('Email is required'),
|
.required("Email is required"),
|
||||||
firstname: Yup.string()
|
firstname: Yup.string()
|
||||||
.min(3, 'Minimum 3 characters')
|
.min(3, "Minimum 3 characters")
|
||||||
.max(25, 'Maximum 25 characters')
|
.max(25, "Maximum 25 characters")
|
||||||
.required('Firstname is required'),
|
.required("Firstname is required"),
|
||||||
lastname: Yup.string()
|
lastname: Yup.string()
|
||||||
.min(3, 'Minimum 3 characters')
|
.min(3, "Minimum 3 characters")
|
||||||
.max(25, 'Maximum 25 characters')
|
.max(25, "Maximum 25 characters")
|
||||||
.required('Lastname is required'),
|
.required("Lastname is required"),
|
||||||
city: Yup.string()
|
city: Yup.string()
|
||||||
.min(3, 'Minimum 3 characters')
|
.min(3, "Minimum 3 characters")
|
||||||
.max(25, 'Maximum 25 characters')
|
.max(25, "Maximum 25 characters")
|
||||||
.required('City is required'),
|
.required("City is required"),
|
||||||
state: Yup.string()
|
state: Yup.string()
|
||||||
.min(3, 'Minimum 3 characters')
|
.min(3, "Minimum 3 characters")
|
||||||
.max(25, 'Maximum 25 characters')
|
.max(25, "Maximum 25 characters")
|
||||||
.required('State is required'),
|
.required("State is required"),
|
||||||
})
|
});
|
||||||
|
|
||||||
export default function PersonalInfoTab({
|
export default function PersonalInfoTab({
|
||||||
datas,
|
datas,
|
||||||
@@ -49,72 +49,86 @@ export default function PersonalInfoTab({
|
|||||||
browseCoverImg,
|
browseCoverImg,
|
||||||
coverImgChangHandler,
|
coverImgChangHandler,
|
||||||
}) {
|
}) {
|
||||||
|
let { userDetails } = useSelector((state) => state.userDetails);
|
||||||
|
|
||||||
let {userDetails} = useSelector((state) => state.userDetails)
|
const apiCall = new usersService();
|
||||||
|
|
||||||
const apiCall = new usersService()
|
|
||||||
|
|
||||||
let navigate = useNavigate()
|
let navigate = useNavigate();
|
||||||
|
|
||||||
let [togglePromotion, setTogglePromotion] = useState(false)
|
let [togglePromotion, setTogglePromotion] = useState(false);
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
firstname: userDetails?.firstname,
|
firstname: userDetails?.firstname,
|
||||||
lastname: userDetails?.lastname,
|
lastname: userDetails?.lastname,
|
||||||
state: userDetails?.state,
|
state: userDetails?.state,
|
||||||
city: userDetails?.city,
|
city: userDetails?.city,
|
||||||
email: userDetails?.email
|
email: userDetails?.email,
|
||||||
}
|
};
|
||||||
|
|
||||||
let [profile, setProfile] = useState({ // state for requesting from load profile API
|
let [profile, setProfile] = useState({
|
||||||
|
// state for requesting from load profile API
|
||||||
loading: true,
|
loading: true,
|
||||||
status: false
|
status: false,
|
||||||
})
|
});
|
||||||
|
|
||||||
let [requestStatus, setRequestState] = useState({ // state for requesting from update api
|
let [requestStatus, setRequestState] = useState({
|
||||||
message: '',
|
// state for requesting from update api
|
||||||
|
message: "",
|
||||||
loading: false,
|
loading: false,
|
||||||
status: false
|
status: false,
|
||||||
})
|
});
|
||||||
|
|
||||||
const handleUpdateUser = (values, helpers)=> {
|
const handleUpdateUser = (values, helpers) => {
|
||||||
setRequestState({message: '', loading: true, status: false})
|
setRequestState({ message: "", loading: true, status: false });
|
||||||
|
|
||||||
apiCall.updateProfile(values).then((res)=>{ // API CALL TO UPDATE USER DETAILS
|
|
||||||
if(res.data.internal_return < 0){
|
|
||||||
setRequestState({message: 'Profile Was unable to update', loading: false, status: false})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// setRequestState({message: 'Profile update successfully', loading: false, status: true})
|
|
||||||
toast.success("Update Successful");
|
|
||||||
setTimeout(()=>{
|
|
||||||
navigate('/',{replace:true})
|
|
||||||
window.location.reload(true)
|
|
||||||
},1000)
|
|
||||||
}).catch(error => {
|
|
||||||
setRequestState({message: 'Opps! an error occurred. Try Agian', loading: false, status: false})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(()=>{
|
apiCall
|
||||||
setProfile({loading: false, status: true})
|
.updateProfile(values)
|
||||||
},[])
|
.then((res) => {
|
||||||
|
// API CALL TO UPDATE USER DETAILS
|
||||||
|
if (res.data.internal_return < 0) {
|
||||||
|
setRequestState({
|
||||||
|
message: "Profile Was unable to update",
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// setRequestState({message: 'Profile update successfully', loading: false, status: true})
|
||||||
|
toast.success("Update Successful");
|
||||||
|
setTimeout(() => {
|
||||||
|
navigate("/", { replace: true });
|
||||||
|
window.location.reload(true);
|
||||||
|
}, 1000);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setRequestState({
|
||||||
|
message: "Opps! an error occurred. Try Agian",
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
useEffect(() => {
|
||||||
|
setProfile({ loading: false, status: true });
|
||||||
|
}, []);
|
||||||
|
|
||||||
profile.loading ?
|
return profile.loading ? (
|
||||||
<div className="personal-info-tab w-full flex flex-col justify-between">
|
<div className="personal-info-tab w-full flex flex-col justify-between">
|
||||||
<div className="p-3">
|
<div className="p-3">
|
||||||
<LoadingSpinner size='32' color='sky-blue' />
|
<LoadingSpinner size="32" color="sky-blue" />
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
:
|
</div>
|
||||||
<div className="personal-info-tab w-full flex flex-col justify-between">
|
) : (
|
||||||
<Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={handleUpdateUser}>
|
<div className="personal-info-tab w-full flex flex-col justify-between">
|
||||||
{(props => {
|
<Formik
|
||||||
return (
|
initialValues={initialValues}
|
||||||
|
validationSchema={validationSchema}
|
||||||
|
onSubmit={handleUpdateUser}
|
||||||
|
>
|
||||||
|
{(props) => {
|
||||||
|
return (
|
||||||
<Form>
|
<Form>
|
||||||
|
|
||||||
<div className="flex flex-col-reverse sm:flex-row">
|
<div className="flex flex-col-reverse sm:flex-row">
|
||||||
<div className="flex-1 sm:mr-10">
|
<div className="flex-1 sm:mr-10">
|
||||||
<div className="fields w-full">
|
<div className="fields w-full">
|
||||||
@@ -122,6 +136,7 @@ export default function PersonalInfoTab({
|
|||||||
{/* username */}
|
{/* username */}
|
||||||
<div className="field w-full mb-6">
|
<div className="field w-full mb-6">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
label="User Name"
|
label="User Name"
|
||||||
type="text"
|
type="text"
|
||||||
name="username"
|
name="username"
|
||||||
@@ -134,6 +149,7 @@ export default function PersonalInfoTab({
|
|||||||
{/* Email */}
|
{/* Email */}
|
||||||
<div className="field w-full mb-6">
|
<div className="field w-full mb-6">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
label="Email"
|
label="Email"
|
||||||
type="text"
|
type="text"
|
||||||
name="email"
|
name="email"
|
||||||
@@ -142,12 +158,17 @@ export default function PersonalInfoTab({
|
|||||||
inputHandler={props.handleChange}
|
inputHandler={props.handleChange}
|
||||||
blurHandler={props.handleBlur}
|
blurHandler={props.handleBlur}
|
||||||
/>
|
/>
|
||||||
{(props.errors.email && props.touched.email) && <p className="text-sm text-red-500">{props.errors.email}</p>}
|
{props.errors.email && props.touched.email && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{props.errors.email}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{/* first name and last name */}
|
{/* first name and last name */}
|
||||||
<div className="xl:flex xl:space-x-7 mb-6">
|
<div className="xl:flex xl:space-x-7 mb-6">
|
||||||
<div className="field w-full mb-6 xl:mb-0">
|
<div className="field w-full mb-6 xl:mb-0">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
label="First Name"
|
label="First Name"
|
||||||
type="text"
|
type="text"
|
||||||
name="firstname"
|
name="firstname"
|
||||||
@@ -156,10 +177,15 @@ export default function PersonalInfoTab({
|
|||||||
inputHandler={props.handleChange}
|
inputHandler={props.handleChange}
|
||||||
blurHandler={props.handleBlur}
|
blurHandler={props.handleBlur}
|
||||||
/>
|
/>
|
||||||
{(props.errors.firstname && props.touched.firstname) && <p className="text-sm text-red-500">{props.errors.firstname}</p>}
|
{props.errors.firstname && props.touched.firstname && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{props.errors.firstname}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="field w-full">
|
<div className="field w-full">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
label="Last Name"
|
label="Last Name"
|
||||||
type="text"
|
type="text"
|
||||||
name="lastname"
|
name="lastname"
|
||||||
@@ -168,13 +194,18 @@ export default function PersonalInfoTab({
|
|||||||
inputHandler={props.handleChange}
|
inputHandler={props.handleChange}
|
||||||
blurHandler={props.handleBlur}
|
blurHandler={props.handleBlur}
|
||||||
/>
|
/>
|
||||||
{(props.errors.lastname && props.touched.lastname) && <p className="text-sm text-red-500">{props.errors.lastname}</p>}
|
{props.errors.lastname && props.touched.lastname && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{props.errors.lastname}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Country */}
|
{/* Country */}
|
||||||
<div className="field w-full mb-6">
|
<div className="field w-full mb-6">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
label="Country"
|
label="Country"
|
||||||
type="text"
|
type="text"
|
||||||
name="country"
|
name="country"
|
||||||
@@ -186,6 +217,7 @@ export default function PersonalInfoTab({
|
|||||||
{/* State/Province */}
|
{/* State/Province */}
|
||||||
<div className="field w-full mb-6">
|
<div className="field w-full mb-6">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
label="State/Province"
|
label="State/Province"
|
||||||
type="text"
|
type="text"
|
||||||
name="state"
|
name="state"
|
||||||
@@ -194,12 +226,17 @@ export default function PersonalInfoTab({
|
|||||||
inputHandler={props.handleChange}
|
inputHandler={props.handleChange}
|
||||||
blurHandler={props.handleBlur}
|
blurHandler={props.handleBlur}
|
||||||
/>
|
/>
|
||||||
{(props.errors.state && props.touched.state) && <p className="text-sm text-red-500">{props.errors.state}</p>}
|
{props.errors.state && props.touched.state && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{props.errors.state}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* City */}
|
{/* City */}
|
||||||
<div className="field w-full mb-6">
|
<div className="field w-full mb-6">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
label="City"
|
label="City"
|
||||||
type="text"
|
type="text"
|
||||||
name="city"
|
name="city"
|
||||||
@@ -208,34 +245,65 @@ export default function PersonalInfoTab({
|
|||||||
inputHandler={props.handleChange}
|
inputHandler={props.handleChange}
|
||||||
blurHandler={props.handleBlur}
|
blurHandler={props.handleBlur}
|
||||||
/>
|
/>
|
||||||
{(props.errors.city && props.touched.city) && <p className="text-sm text-red-500">{props.errors.city}</p>}
|
{props.errors.city && props.touched.city && (
|
||||||
|
<p className="text-sm text-red-500">
|
||||||
|
{props.errors.city}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Preferred Communication*/}
|
{/* Preferred Communication*/}
|
||||||
<div className='field w-full mb-6 md:flex items-center space-x-4'>
|
<div className="field w-full mb-6 md:flex items-center space-x-4">
|
||||||
<label className='input-label text-[#181c32] dark:text-white text-base font-semibold'>Pref. Communication</label>
|
<label className="input-label text-[#181c32] dark:text-white text-base font-semibold">
|
||||||
<div className="check-box">
|
Pref. Communication
|
||||||
<div className="flex items-center justify-start">
|
</label>
|
||||||
<div className="check-input flex items-center mr-1">
|
<div className="check-box">
|
||||||
<input className="w-4 h-4 cursor-pointer" type="checkbox" name="prefcomm1" id="" />
|
<div className="flex items-center justify-start">
|
||||||
<span className="mx-2 text-base text-dark-gray dark:text-white">Email</span>
|
<div className="check-input flex items-center mr-1">
|
||||||
</div>
|
<input
|
||||||
<div className="check-input flex items-center">
|
className="w-4 h-4 cursor-pointer"
|
||||||
<input className="w-4 h-4 cursor-pointer" type="checkbox" name="prefcomm2" id="" />
|
type="checkbox"
|
||||||
<span className="mx-2 text-base text-dark-gray dark:text-white">Phone</span>
|
name="prefcomm1"
|
||||||
</div>
|
id=""
|
||||||
|
/>
|
||||||
|
<span className="mx-2 text-base text-dark-gray dark:text-white">
|
||||||
|
Email
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="check-input flex items-center">
|
||||||
|
<input
|
||||||
|
className="w-4 h-4 cursor-pointer"
|
||||||
|
type="checkbox"
|
||||||
|
name="prefcomm2"
|
||||||
|
id=""
|
||||||
|
/>
|
||||||
|
<span className="mx-2 text-base text-dark-gray dark:text-white">
|
||||||
|
Phone
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Allow Promotions */}
|
{/* Allow Promotions */}
|
||||||
<div className='field w-full mb-6 flex items-center space-x-4'>
|
<div className="field w-full mb-6 flex items-center space-x-4">
|
||||||
<label className='input-label text-[#181c32] dark:text-white text-base font-semibold'>Allow Promotions</label>
|
<label className="input-label text-[#181c32] dark:text-white text-base font-semibold">
|
||||||
<div className="cursor-pointer flex items-center" onClick={()=>setTogglePromotion(prev => !prev)}>
|
Allow Promotions
|
||||||
<div className={`h-6 w-8 mr-1 p-1 ${togglePromotion ? 'bg-sky-blue flex justify-end items-center': 'bg-slate-200'} rounded-full transition`}>
|
</label>
|
||||||
<div className="w-4 h-full bg-white rounded-full"></div>
|
<div
|
||||||
</div>
|
className="cursor-pointer flex items-center"
|
||||||
|
onClick={() => setTogglePromotion((prev) => !prev)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={`h-6 w-8 mr-1 p-1 ${
|
||||||
|
togglePromotion
|
||||||
|
? "bg-sky-blue flex justify-end items-center"
|
||||||
|
: "bg-slate-200"
|
||||||
|
} rounded-full transition`}
|
||||||
|
>
|
||||||
|
<div className="w-4 h-full bg-white rounded-full"></div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* inputs ends here */}
|
{/* inputs ends here */}
|
||||||
</div>
|
</div>
|
||||||
@@ -300,11 +368,19 @@ export default function PersonalInfoTab({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="content-footer w-full">
|
<div className="content-footer w-full">
|
||||||
{requestStatus.message != '' && <p className={`text-center text-base ${requestStatus.status ? 'text-green-800' : 'text-red-600'}`}>{requestStatus.message}</p>}
|
{requestStatus.message != "" && (
|
||||||
|
<p
|
||||||
|
className={`text-center text-base ${
|
||||||
|
requestStatus.status ? "text-green-800" : "text-red-600"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{requestStatus.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
<div className="w-full h-[120px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
|
<div className="w-full h-[120px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
|
||||||
<div className="flex items-center space-x-4 mr-9">
|
<div className="flex items-center space-x-4 mr-9">
|
||||||
<Link
|
<Link
|
||||||
to='/'
|
to="/"
|
||||||
className="text-18 text-light-red tracking-wide "
|
className="text-18 text-light-red tracking-wide "
|
||||||
>
|
>
|
||||||
<span className="border-b dark:border-[#5356fb29] border-light-red">
|
<span className="border-b dark:border-[#5356fb29] border-light-red">
|
||||||
@@ -313,23 +389,23 @@ export default function PersonalInfoTab({
|
|||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
{requestStatus.loading ?
|
{requestStatus.loading ? (
|
||||||
<LoadingSpinner size='8' color='sky-blue' />
|
<LoadingSpinner size="8" color="sky-blue" />
|
||||||
:
|
) : (
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="w-[152px] h-[46px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
className="w-[152px] h-[46px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||||
>
|
>
|
||||||
Update Profile
|
Update Profile
|
||||||
</button>
|
</button>
|
||||||
}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
)
|
);
|
||||||
})}
|
}}
|
||||||
</Formik>
|
</Formik>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ export default function ProductUploadField({
|
|||||||
<h1 className="field-title">Item Name </h1>
|
<h1 className="field-title">Item Name </h1>
|
||||||
<div className="input-field mt-2">
|
<div className="input-field mt-2">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
type="text"
|
type="text"
|
||||||
name="name"
|
name="name"
|
||||||
placeholder="RaidParty Fighters"
|
placeholder="RaidParty Fighters"
|
||||||
@@ -164,6 +165,7 @@ export default function ProductUploadField({
|
|||||||
<h1 className="field-title">Exter link </h1>
|
<h1 className="field-title">Exter link </h1>
|
||||||
<div className="input-field mt-2">
|
<div className="input-field mt-2">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
type="text"
|
type="text"
|
||||||
name="link"
|
name="link"
|
||||||
inputHandler={linkh}
|
inputHandler={linkh}
|
||||||
@@ -200,7 +202,9 @@ export default function ProductUploadField({
|
|||||||
<div className="w-[1px] h-[33px] bg-light-purple dark:bg-dark-light-purple "></div>
|
<div className="w-[1px] h-[33px] bg-light-purple dark:bg-dark-light-purple "></div>
|
||||||
<div className="flex-1 flex h-full justify-center items-center bg-[#FAFAFA] dark:bg-[#11131F] ">
|
<div className="flex-1 flex h-full justify-center items-center bg-[#FAFAFA] dark:bg-[#11131F] ">
|
||||||
<div className="flex space-x-1 items-center">
|
<div className="flex space-x-1 items-center">
|
||||||
<span className="text-dark-gray dark:text-white text-base">ETH</span>
|
<span className="text-dark-gray dark:text-white text-base">
|
||||||
|
ETH
|
||||||
|
</span>
|
||||||
<span>
|
<span>
|
||||||
<svg
|
<svg
|
||||||
width="13"
|
width="13"
|
||||||
@@ -235,6 +239,7 @@ export default function ProductUploadField({
|
|||||||
<div className="input-field my-2">
|
<div className="input-field my-2">
|
||||||
<div className="mb-2">
|
<div className="mb-2">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
type="text"
|
type="text"
|
||||||
name="link"
|
name="link"
|
||||||
inputHandler={roltsHndlr}
|
inputHandler={roltsHndlr}
|
||||||
@@ -260,6 +265,7 @@ export default function ProductUploadField({
|
|||||||
<div className="sm:flex sm:space-x-8">
|
<div className="sm:flex sm:space-x-8">
|
||||||
<div className="sm:w-1/2 w-full mb-2 sm:mb-0">
|
<div className="sm:w-1/2 w-full mb-2 sm:mb-0">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
type="text"
|
type="text"
|
||||||
name="link"
|
name="link"
|
||||||
inputHandler={keyHndlr}
|
inputHandler={keyHndlr}
|
||||||
@@ -269,6 +275,7 @@ export default function ProductUploadField({
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<InputCom
|
<InputCom
|
||||||
|
fieldClass="px-6"
|
||||||
type="text"
|
type="text"
|
||||||
name="link"
|
name="link"
|
||||||
inputHandler={valueHndlr}
|
inputHandler={valueHndlr}
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ class SiteService {
|
|||||||
return this.getAuxEnd("/pricing", null);
|
return this.getAuxEnd("/pricing", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addFamily(reqData) {
|
||||||
|
return this.postAuxEnd('/familyadd', reqData)
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------- -----
|
//---------------------------------------- -----
|
||||||
//---------------------------------------- -----
|
//---------------------------------------- -----
|
||||||
// Unified call below
|
// Unified call below
|
||||||
|
|||||||
@@ -1,28 +1,9 @@
|
|||||||
import React, { useContext,useState, useEffect } from "react";
|
|
||||||
import usersService from "../services/UsersService";
|
|
||||||
import FamilyAcc from "../components/FamilyAcc";
|
import FamilyAcc from "../components/FamilyAcc";
|
||||||
|
|
||||||
export default function FamilyAccPage() {
|
export default function FamilyAccPage() {
|
||||||
|
|
||||||
const [MyActiveJobList, setMyActiveJobList] = useState([]);
|
|
||||||
const api = new usersService();
|
|
||||||
|
|
||||||
const getMyActiveJobList = async () => {
|
|
||||||
try {
|
|
||||||
const res = await api.getMyActiveJobList();
|
|
||||||
setMyActiveJobList(res.data);
|
|
||||||
} catch (error) {
|
|
||||||
console.log("Error getting mode");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
useEffect(() => {
|
|
||||||
getMyActiveJobList();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
//debugger;
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<FamilyAcc ActiveJobList={MyActiveJobList}/>
|
<FamilyAcc />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user