Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 960579384c | |||
| 6c29f37a60 | |||
| cc22e1a458 | |||
| d274a5c56a | |||
| dfe90fbdc2 | |||
| a2f3c95671 | |||
| 6daa4d6d43 | |||
| 2e25b33110 | |||
| a216ab1098 | |||
| 8b01139b93 | |||
| 8511db6961 | |||
| 99c81fd4ee | |||
| ef545c9714 | |||
| 029a7327a8 | |||
| 5a5d933b24 | |||
| 9f19c930b7 | |||
| 84d7fabae7 | |||
| b245f87556 | |||
| bed5303fa4 | |||
| a5af8ed722 | |||
| ec97d118b2 | |||
| 85213c31a1 | |||
| f9b6c68f99 | |||
| 2a4b77c9a0 | |||
| 97aa5dba21 | |||
| 58a10ca6be | |||
| f3edf1d90b | |||
| 1f7b310b6f | |||
| aecb06ca96 | |||
| d89194f18e | |||
| 03866d666b | |||
| 4224be46bc | |||
| 5dad00096a | |||
| 72da5c707a | |||
| 625928e34b | |||
| 6fd92600b4 | |||
| 133f500849 | |||
| b1f1b34924 | |||
| e80c3528db | |||
| 3eb6960cc7 | |||
| eb01e35c75 | |||
| 0cc70d66b3 | |||
| 7111e81f11 | |||
| 1c64771dcd | |||
| ac1a4f895a | |||
| 22f5bd01d2 | |||
| 467528835a |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 713 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 15 KiB |
@@ -47,6 +47,7 @@ import OffersInterestPage from "./views/OffersInterestPage";
|
||||
import ManageInterestOfferPage from './views/ManageInterestOfferPage'
|
||||
import MyWaitingJobsPage from "./views/MyWaitingJobsPage";
|
||||
import FamilyMarketPage from "./views/FamilyMarketPage";
|
||||
import FacebookRedirect from "./views/FacebookRedirect";
|
||||
|
||||
export default function Routers() {
|
||||
return (
|
||||
@@ -56,6 +57,7 @@ export default function Routers() {
|
||||
<Route exact path="/login" element={<LoginPage />} />
|
||||
<Route exact path="/signup" element={<SignupPage />} />
|
||||
<Route exact path="/login/auth" element={<AuthRedirect />} />
|
||||
<Route exact path="/login/auth/flogin" element={<FacebookRedirect />} />
|
||||
<Route
|
||||
exact
|
||||
path="/forgot-password"
|
||||
|
||||
|
After Width: | Height: | Size: 6.2 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="identificationcard"><path fill="#4687ba" d="M0 6v13c0 1.103.897 2 2 2h20c1.103 0 2-.897 2-2V6" class="color2d98d4 svgShape"></path><path fill="#ff6699" d="M22 3H2a2 2 0 0 0-2 2v2h24V5a2 2 0 0 0-2-2z" class="color0377be svgShape"></path><path fill="#e6e7f9" d="M22 3H2C.897 3 0 3.897 0 5v.25c0-1.103.897-2 2-2h20c1.103 0 2 .897 2 2V5c0-1.103-.897-2-2-2z" opacity=".2" class="colorffffff svgShape"></path><path fill="#4687ba" d="M22 20.75H2c-1.103 0-2-.897-2-2V19c0 1.103.897 2 2 2h20c1.103 0 2-.897 2-2v-.25c0 1.103-.897 2-2 2z" opacity=".1" class="color010101 svgShape"></path><path fill="#e6e7f9" d="M13 17h8v1h-8zM13 14h8v1h-8zM13 11h8v1h-8z" class="colorffffff svgShape"></path><circle cx="7" cy="12" r="2" fill="#e6e7f9" class="colorffffff svgShape"></circle><path fill="#e6e7f9" d="M9.987 15.237C9.288 14.9 8.203 14.5 7 14.5s-2.288.4-2.987.737c-.625.3-1.013.9-1.013 1.566V18h8v-1.197c0-.665-.388-1.265-1.013-1.566z" class="colorffffff svgShape"></path><circle cx="17" cy="5" r="1" fill="#ff6699" class="color0a70b9 svgShape"></circle><path fill="#4687ba" d="M17 4.25a.99.99 0 0 1 .975.875C17.98 5.082 18 5.045 18 5a1 1 0 0 0-2 0c0 .044.02.082.025.125A.99.99 0 0 1 17 4.25z" opacity=".1" class="color010101 svgShape"></path><linearGradient id="a" x1="6.973" x2="21.55" y1="1.973" y2="16.55" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#010101" stop-opacity=".1" class="stopColor010101 svgShape"></stop><stop offset="1" stop-color="#010101" stop-opacity="0" class="stopColor010101 svgShape"></stop></linearGradient><path fill="url(#a)" d="M22 21c1.103 0 2-.897 2-2V7H0l14 14h8z"></path><circle cx="7" cy="5" r="1" fill="#ff6699" class="color0a70b9 svgShape"></circle><path fill="#4687ba" d="M7 4.25a.99.99 0 0 1 .975.875C7.98 5.082 8 5.045 8 5a1 1 0 0 0-2 0c0 .044.02.082.025.125A.99.99 0 0 1 7 4.25z" opacity=".1" class="color010101 svgShape"></path><linearGradient id="b" x1="-.708" x2="24.708" y1="6.074" y2="17.925" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ffffff" stop-opacity=".2" class="stopColorffffff svgShape"></stop><stop offset="1" stop-color="#ffffff" stop-opacity="0" class="stopColorffffff svgShape"></stop></linearGradient><path fill="url(#b)" d="M22 3H2a2 2 0 0 0-2 2v14c0 1.103.897 2 2 2h20c1.103 0 2-.897 2-2V5a2 2 0 0 0-2-2z"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 128 128" viewBox="0 0 128 128" id="Pin"><path fill="#4687ba" d="M106,13.8L91.7,4.6C86.2,1,78.9,2,74.5,7L41.9,46.9c-9.1,0.4-17.9,3.3-25.4,8.7c-0.7,0.5-0.7,1.6,0.1,2.1
|
||||
l10.2,6.6l0,0L46.4,77l-24,41.4c-1.2,2.1-0.7,4.9,1.4,6.3c2.2,1.6,5.2,1.1,6.7-1.1l28-38.8L78,97.5l0,0l10.2,6.6
|
||||
c0.7,0.5,1.7,0.1,1.9-0.8c1.8-9,0.9-18.3-2.5-26.8l23.1-46C113.6,24.5,111.5,17.4,106,13.8z" class="color2d3e50 svgShape"></path></svg>
|
||||
|
After Width: | Height: | Size: 482 B |
@@ -0,0 +1,69 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import usersService from '../../../services/UsersService';
|
||||
import {updateUserDetails} from "../../../store/UserDetails";
|
||||
import { useDispatch } from "react-redux";
|
||||
import AuthLayout from "../AuthLayout";
|
||||
|
||||
function FbookRedirect() {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const userApi = new usersService();
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const queryParams = new URLSearchParams(location?.search);
|
||||
const codeResponse = queryParams.get("code");
|
||||
|
||||
useEffect(()=>{
|
||||
if(!codeResponse){
|
||||
navigate('/login', {state: {error: true}})
|
||||
return
|
||||
}
|
||||
console.log(codeResponse);
|
||||
|
||||
setTimeout(()=>{ // remove LATER
|
||||
navigate('/login', {state: {error: true}})
|
||||
},2000)
|
||||
|
||||
/*
|
||||
POST /token HTTP/1.1
|
||||
Host: oauth2.googleapis.com
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
|
||||
client_id=your_client_id&
|
||||
client_secret=your_client_secret&
|
||||
redirect_uri=https%3A//oauth2.example.com/code&
|
||||
grant_type=authorization_code
|
||||
*/
|
||||
var reqData = {
|
||||
auth_type: "GOOGLE",
|
||||
code: codeResponse,
|
||||
redirect_uri: process.env.REACT_APP_GOOGLE_REDIRECT_URL,
|
||||
};
|
||||
// userApi
|
||||
// .authStart(reqData)
|
||||
// .then((res) => {
|
||||
// if (res.status == 200 && res.data.internal_return >= 0 && res.data.member_id && res.data.uid && res.data.session) {
|
||||
// localStorage.setItem("member_id", `${res.data.member_id}`);
|
||||
// localStorage.setItem("uid", `${res.data.uid}`);
|
||||
// localStorage.setItem("session_token", `${res.data.session}`);
|
||||
// dispatch(updateUserDetails({...res.data}));
|
||||
// navigate('/', {replace: true})
|
||||
// return
|
||||
// }
|
||||
// navigate('/login', {state: {error: true}})
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// navigate('/login', {state: {error: true}})
|
||||
// console.log(error);
|
||||
// });
|
||||
},[])
|
||||
return (
|
||||
<AuthLayout>
|
||||
<div className='min-h-[70vh]'>Redirecting ... </div>
|
||||
</AuthLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default FbookRedirect
|
||||
@@ -1,23 +1,64 @@
|
||||
import React, {useState, useEffect} from 'react'
|
||||
import { useLocation, useNavigate } from 'react-router-dom'
|
||||
import React, { useEffect } from 'react';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import usersService from '../../../services/UsersService';
|
||||
import {updateUserDetails} from "../../../store/UserDetails";
|
||||
import { useDispatch } from "react-redux";
|
||||
import AuthLayout from "../AuthLayout";
|
||||
|
||||
function Redirect() {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const userApi = new usersService();
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const queryParams = new URLSearchParams(location?.search);
|
||||
const codeResponse = queryParams.get("code");
|
||||
|
||||
useEffect(()=>{
|
||||
if(!codeResponse){
|
||||
navigate('/login', {replace: true})
|
||||
if(!codeResponse){
|
||||
navigate('/login', {state: {error: true}})
|
||||
return
|
||||
}
|
||||
console.log(codeResponse);
|
||||
/*
|
||||
POST /token HTTP/1.1
|
||||
Host: oauth2.googleapis.com
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
|
||||
client_id=your_client_id&
|
||||
client_secret=your_client_secret&
|
||||
redirect_uri=https%3A//oauth2.example.com/code&
|
||||
grant_type=authorization_code
|
||||
*/
|
||||
var reqData = {
|
||||
auth_type: "GOOGLE",
|
||||
code: codeResponse,
|
||||
redirect_uri: process.env.REACT_APP_GOOGLE_REDIRECT_URL,
|
||||
};
|
||||
userApi
|
||||
.authStart(reqData)
|
||||
.then((res) => {
|
||||
if (res.status == 200 && res.data.internal_return >= 0 && res.data.member_id && res.data.uid && res.data.session) {
|
||||
localStorage.setItem("member_id", `${res.data.member_id}`);
|
||||
localStorage.setItem("uid", `${res.data.uid}`);
|
||||
localStorage.setItem("session_token", `${res.data.session}`);
|
||||
dispatch(updateUserDetails({...res.data}));
|
||||
navigate('/', {replace: true})
|
||||
return
|
||||
}
|
||||
console.log(codeResponse)
|
||||
}
|
||||
navigate('/login', {state: {error: true}})
|
||||
})
|
||||
.catch((error) => {
|
||||
navigate('/login', {state: {error: true}})
|
||||
console.log(error);
|
||||
});
|
||||
},[])
|
||||
return (
|
||||
<div>Redirecting ... </div>
|
||||
<AuthLayout>
|
||||
<div className='min-h-[70vh]'>Redirecting ... </div>
|
||||
</AuthLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default Redirect
|
||||
export default Redirect
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useLayoutEffect, useState } from "react";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { Link, useNavigate, useLocation } from "react-router-dom";
|
||||
import linkedInLogo from "../../../assets/images/Linkedin.png";
|
||||
import appleLogo from "../../../assets/images/apple-black.svg";
|
||||
import facebookLogo from "../../../assets/images/facebook-4.svg";
|
||||
@@ -16,12 +16,15 @@ import { updateUserDetails } from "../../../store/UserDetails";
|
||||
|
||||
export default function Login() {
|
||||
const dispatch = useDispatch();
|
||||
const {state} = useLocation()
|
||||
|
||||
let [loginType, setLoginType] = useState('');
|
||||
|
||||
const [checked, setValue] = useState(false);
|
||||
const [loginLoading, setLoginLoading] = useState(false);
|
||||
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
|
||||
//login error state
|
||||
const [loginError, setLoginError] = useState(false);
|
||||
// for the catch error
|
||||
@@ -31,6 +34,11 @@ export default function Login() {
|
||||
setValue(!checked);
|
||||
};
|
||||
|
||||
// To Show and Hide Password
|
||||
const togglePasswordVisibility = () => {
|
||||
setShowPassword(!showPassword);
|
||||
};
|
||||
|
||||
//FUNCTION TO DETERMINE/CHANGE LOGIN COMPONENT
|
||||
const handleLoginType = ({ target: { name } }) => {
|
||||
setLoginType(name);
|
||||
@@ -70,6 +78,13 @@ export default function Login() {
|
||||
}
|
||||
|
||||
if (name == "full") {
|
||||
//checks if email is a valid email address
|
||||
let regEx = /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/;
|
||||
if (regEx.test(email) == false) {
|
||||
setLoginLoading(false);
|
||||
setMsgError("Invalid Email");
|
||||
return setTimeout(()=>{setMsgError("");},3000)
|
||||
}
|
||||
// Post Data Info for normal Login
|
||||
postData = {
|
||||
username: email,
|
||||
@@ -98,7 +113,7 @@ export default function Login() {
|
||||
userApi
|
||||
.logInUser(postData)
|
||||
.then((res) => {
|
||||
if (res.status != 200 || res.data.internal_return < 0) {
|
||||
if (res.status != 200 || res.data.internal_return < 0 || !res.data.member_id || !res.data.uid || !res.data.session) {
|
||||
// setMsgError("Wrong, email/password");
|
||||
setLoginError(true);
|
||||
setLoginLoading(false);
|
||||
@@ -108,7 +123,7 @@ export default function Login() {
|
||||
localStorage.setItem("uid", `${res.data.uid}`);
|
||||
localStorage.setItem("session_token", `${res.data.session}`);
|
||||
// localStorage.setItem("session", `${res.data.session}`);
|
||||
dispatch(updateUserDetails({...res.data, loggedIn:true}));
|
||||
dispatch(updateUserDetails({...res.data}));
|
||||
setTimeout(() => {
|
||||
navigate("/", { replace: true });
|
||||
setLoginLoading(false);
|
||||
@@ -168,6 +183,14 @@ export default function Login() {
|
||||
}
|
||||
let loginValue = readCookie('loginType')
|
||||
setLoginType(loginValue)
|
||||
|
||||
if(state?.error){ //check if the login path has an error state indicating any social handle login with error
|
||||
setMsgError("Unexpected Error, Please try again soon.");
|
||||
setTimeout(()=>{
|
||||
setMsgError("");
|
||||
navigate('/login', {replace: true})
|
||||
},4000)
|
||||
}
|
||||
},[])
|
||||
|
||||
|
||||
@@ -189,7 +212,7 @@ export default function Login() {
|
||||
/>
|
||||
</Link>
|
||||
</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-[530px] 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="w-full">
|
||||
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
||||
{/* <h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
|
||||
@@ -211,7 +234,7 @@ export default function Login() {
|
||||
<button
|
||||
name="full"
|
||||
className={`login-type-btn px-4 py-1 rounded-t-2xl ${
|
||||
loginType=='full' ? "bg-white text-[#000] border-t-[2px]" : "bg-[#4687ba] border-[2px] border-[#4687ba] text-white"
|
||||
loginType=='full' ? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white" : "bg-white text-[#000] border-t-[2px]"
|
||||
}`}
|
||||
onClick={handleLoginType}
|
||||
>
|
||||
@@ -220,7 +243,7 @@ export default function Login() {
|
||||
<button
|
||||
name="family"
|
||||
className={`login-type-btn px-4 py-1 rounded-t-2xl ${
|
||||
loginType=='family' ? "bg-white text-[#000] border-t-[2px]" : "bg-[#4687ba] border-[2px] border-[#4687ba] text-white"
|
||||
loginType=='family' ? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white" : "bg-white text-[#000] border-t-[2px]"
|
||||
}`}
|
||||
onClick={handleLoginType}
|
||||
>
|
||||
@@ -234,7 +257,7 @@ export default function Login() {
|
||||
{
|
||||
loginType == 'full' ? (
|
||||
//user login component
|
||||
<div className="p-2 input-area login-area border-2 border-[#4687ba] rounded-2xl">
|
||||
<div className="p-6 input-area login-area border-2 border-[#4687ba] rounded-2xl">
|
||||
<div className="input-item mb-5">
|
||||
<InputCom
|
||||
labelClass="tracking-wider"
|
||||
@@ -258,8 +281,9 @@ export default function Login() {
|
||||
placeholder="● ● ● ● ● ●"
|
||||
label="Password"
|
||||
name="password"
|
||||
type="password"
|
||||
iconName="password"
|
||||
type={showPassword ? "text" : "password"}
|
||||
onClick={togglePasswordVisibility}
|
||||
passIcon={showPassword ? "password" : "password"}
|
||||
forgotPassword
|
||||
/>
|
||||
</div>
|
||||
@@ -297,32 +321,39 @@ export default function Login() {
|
||||
</button>
|
||||
</div>
|
||||
<div className="sm:flex sm:justify-between sm:items-center sm:space-x-2">
|
||||
<BrandBtn
|
||||
link="#"
|
||||
imgSrc={googleLogo}
|
||||
brand="Google"
|
||||
onClick={googleLogin}
|
||||
/>
|
||||
<BrandBtn link="#" imgSrc={appleLogo} brand="Apple" />
|
||||
<BrandBtn
|
||||
link="#"
|
||||
imgSrc={googleLogo}
|
||||
brand="Google"
|
||||
onClick={googleLogin}
|
||||
/>
|
||||
<BrandBtn
|
||||
// link="https://appleid.apple.com/auth/authorize?response_type=code&response_mode=form_post&client_id=com.wrenchboard.users.client&redirect_uri=https%3A%2F%2Fwork.wrenchboard.com%2Flogin%2Fauth%2Fapple&state=4b2c4456b7&scope=name+email"
|
||||
imgSrc={appleLogo}
|
||||
brand="Apple"
|
||||
isAnchor={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="sm:flex sm:justify-between sm:items-center sm:space-x-2">
|
||||
<BrandBtn
|
||||
link="#"
|
||||
imgSrc={facebookLogo}
|
||||
brand="Facebook"
|
||||
/>
|
||||
<BrandBtn
|
||||
link="#"
|
||||
imgSrc={linkedInLogo}
|
||||
brand="LinkedIn"
|
||||
/>
|
||||
<BrandBtn
|
||||
link={`https://www.facebook.com/v14.0/dialog/oauth?client_id=${'1287693041832191'}&redirect_uri=http://localhost:9082/login/auth/flogin&scope=${process.env.REACT_APP_FACEBOOK_CLIENT_SCOPE}`}
|
||||
imgSrc={facebookLogo}
|
||||
brand="Facebook"
|
||||
isAnchor={true}
|
||||
/>
|
||||
<BrandBtn
|
||||
// link="https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&scope=comma-separated-list-of-scopes&state=YOUR_STATE_VALUE"
|
||||
imgSrc={linkedInLogo}
|
||||
brand="LinkedIn"
|
||||
isAnchor={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
// END of user login compoenent
|
||||
// family login compoenent
|
||||
<div className="p-2 input-area login-area border-2 border-[#4687ba] rounded-2xl">
|
||||
<div className="p-6 input-area login-area border-2 border-[#4687ba] rounded-2xl">
|
||||
<div className="input-item mb-5">
|
||||
<InputCom
|
||||
labelClass="tracking-wider"
|
||||
@@ -333,7 +364,7 @@ export default function Login() {
|
||||
label="Username"
|
||||
name="email"
|
||||
type="email"
|
||||
iconName="message"
|
||||
iconName="family-id"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -346,9 +377,9 @@ export default function Login() {
|
||||
placeholder="● ● ● ● ● ●"
|
||||
label="Pin"
|
||||
name="password"
|
||||
type="password"
|
||||
iconName="password"
|
||||
// forgotPassword
|
||||
type={showPassword ? "text" : "password"}
|
||||
onClick={togglePasswordVisibility}
|
||||
passIcon={showPassword ? "family-pin" : "family-pin"}
|
||||
/>
|
||||
</div>
|
||||
{loginError && (
|
||||
@@ -403,7 +434,7 @@ export default function Login() {
|
||||
);
|
||||
}
|
||||
|
||||
const BrandBtn = ({ link, imgSrc, brand, onClick }) => {
|
||||
const BrandBtn = ({ link, imgSrc, brand, onClick, isAnchor=false }) => {
|
||||
// const doGoogle = async () => {
|
||||
// alert("start google");
|
||||
// };
|
||||
@@ -422,10 +453,23 @@ const BrandBtn = ({ link, imgSrc, brand, onClick }) => {
|
||||
// const doFacebook = async () => {
|
||||
// alert("start facebook");
|
||||
// };
|
||||
|
||||
return (
|
||||
<div className="w-full sm:w-1/2 flex justify-center bottomMargin">
|
||||
<button
|
||||
{isAnchor ?
|
||||
(
|
||||
<a
|
||||
href={link}
|
||||
className="w-full border border-light-purple dark:border-[#5356fb29] rounded-[0.475rem] h-[48px] flex justify-center bg-[#FAFAFA] hover:bg-[#eff2f5] hover:text-[#7e8299] transition duration-300 dark:bg-[#11131F] items-center font-medium cursor-pointer"
|
||||
>
|
||||
<img className="mr-3 h-6" src={imgSrc} alt="logo-icon(s)" />
|
||||
<span className="text-lg text-thin-light-gray font-normal text-[15px]">
|
||||
Continue with {brand}
|
||||
</span>
|
||||
</a>
|
||||
)
|
||||
:
|
||||
(
|
||||
<button
|
||||
onClick={onClick}
|
||||
// href="#dd"
|
||||
className="w-full border border-light-purple dark:border-[#5356fb29] rounded-[0.475rem] h-[48px] flex justify-center bg-[#FAFAFA] hover:bg-[#eff2f5] hover:text-[#7e8299] transition duration-300 dark:bg-[#11131F] items-center font-medium cursor-pointer"
|
||||
@@ -435,6 +479,9 @@ const BrandBtn = ({ link, imgSrc, brand, onClick }) => {
|
||||
Continue with {brand}
|
||||
</span>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
)
|
||||
};
|
||||
|
||||
|
||||
@@ -72,6 +72,12 @@ export default function SignUp() {
|
||||
return setTimeout(()=>{setMsgError("");},3000)
|
||||
}
|
||||
|
||||
//checks if terms and condition is checked
|
||||
if (!checked) {
|
||||
setMsgError("Terms and condition required");
|
||||
return setTimeout(()=>{setMsgError("");},3000)
|
||||
}
|
||||
|
||||
setSignUpLoading(true);
|
||||
const reqData = {
|
||||
country: country,
|
||||
@@ -89,7 +95,7 @@ export default function SignUp() {
|
||||
if (res.status === 200) {
|
||||
const { data } = res;
|
||||
if (data && data.acc === "DULPICATE") {
|
||||
setMsgError("This account has been already created");
|
||||
setMsgError("Unable to use this username. Please try another username.");
|
||||
setSignUpLoading(false);
|
||||
}
|
||||
if (data && data.status === "1") {
|
||||
@@ -131,7 +137,7 @@ export default function SignUp() {
|
||||
/>
|
||||
</Link>
|
||||
</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 mb-0">
|
||||
<div className="content-wrapper login relative shadow-md w-full lg:max-w-[530px] 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 mb-0">
|
||||
<div>
|
||||
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
||||
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
|
||||
@@ -213,7 +219,7 @@ export default function SignUp() {
|
||||
/>
|
||||
</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]">
|
||||
<div className="p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px]">
|
||||
{msgError}
|
||||
</div>
|
||||
)}
|
||||
@@ -298,7 +304,7 @@ const SelectOption = ({
|
||||
<select
|
||||
name={name}
|
||||
id={name}
|
||||
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 "
|
||||
className="input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base focus-visible:border-transparent focus-visible:outline-0 focus-visible:ring-transparent "
|
||||
onChange={inputHandler}
|
||||
value={value}
|
||||
>
|
||||
|
||||
@@ -86,10 +86,14 @@ export default function VerifyLink() {
|
||||
const verifyRes = await userApi.verifyEmail(code);
|
||||
if (verifyRes.status === 200) {
|
||||
let { data } = verifyRes;
|
||||
|
||||
console.log('TESTING VERIFY',data)
|
||||
if (
|
||||
data &&
|
||||
data.internal_return >= 0 &&
|
||||
data.internal_return >= 0 &&
|
||||
data.status == 0 &&
|
||||
data.pending_id != '' &&
|
||||
data.pending_uid != '' &&
|
||||
data.username != '' &&
|
||||
data.status_text === "Link Verified"
|
||||
) {
|
||||
setPageLoader(false);
|
||||
|
||||
@@ -21,7 +21,8 @@ export default function FamilyActiveJobsCard({ datas, hidden = false }) {
|
||||
toast.warn("Remove to Favorite List");
|
||||
}
|
||||
};
|
||||
|
||||
//debugger;
|
||||
const bannerName = datas.banner == null ?'default.jpg':datas.banner;
|
||||
return (
|
||||
<div className="card-style-one flex flex-col justify-between w-full h-[387px] bg-white dark:bg-dark-white p-3 pb rounded-2xl">
|
||||
<div className="content">
|
||||
@@ -32,7 +33,7 @@ export default function FamilyActiveJobsCard({ datas, hidden = false }) {
|
||||
className="thumbnail w-full h-full rounded-xl overflow-hidden px-4 pt-4"
|
||||
style={{
|
||||
background: `url(${localImgLoad(
|
||||
`images/taskbanners/${datas.banner}`
|
||||
`images/taskbanners/${bannerName}`
|
||||
)}) center / contain no-repeat`,
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -17,21 +17,21 @@ export default function HomeBannerOffersCard(props) {
|
||||
return (
|
||||
<Link
|
||||
to={link_result}
|
||||
className="item w-full block group banner-630-340 bg-cover bg-center"
|
||||
className="item p-2 w-full flex items-center min-h-[340px] bg-alice-blue bg-cover bg-center"
|
||||
style={{
|
||||
backgroundImage: `url('${imageUrl}')`,
|
||||
}}
|
||||
>
|
||||
<div className="flex flex-col justify-between h-full">
|
||||
<div className="w-[80%] h-full mx-auto flex flex-col justify-between">
|
||||
<div className="content flex justify-between items-center">
|
||||
<div className="siderCardHeader">
|
||||
<h1 className="text-2xl font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
<div className="mb-2">
|
||||
<h1 className="text-2xl lg:text-4xl font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
<span className="heroSilderTitle">{props.itemData.title}</span>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col justify-around items-center flex-1">
|
||||
<div className="siderCardDescription">
|
||||
<div className="siderCardDescription mb-2">
|
||||
{props.itemData.description}
|
||||
</div>
|
||||
<button className="w-[150px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
import React, {
|
||||
Suspense,
|
||||
lazy,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
useTransition,
|
||||
} from "react";
|
||||
import { useReactToPrint } from "react-to-print";
|
||||
import profile from "../../assets/images/profile-info-profile.png";
|
||||
import usersService from "../../services/UsersService";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import AssignTaskPopout from "./FamilyPopout/AssignTaskPopout";
|
||||
import {
|
||||
FamilyWaitlist,
|
||||
FamilyAccount,
|
||||
FamilyProfile,
|
||||
FamilyTasks,
|
||||
ProfileInfo,
|
||||
FamilyPending,
|
||||
} from "./Tabs";
|
||||
import localImgLoad from "../../lib/localImgLoad";
|
||||
|
||||
// Lazy Imports for components
|
||||
const FamilyWaitlist = lazy(() => import("./Tabs/FamilyWaitlist"));
|
||||
const FamilyAccount = lazy(() => import("./Tabs/FamilyAccount"));
|
||||
const FamilyProfile = lazy(() => import("./Tabs/FamilyProfile"));
|
||||
const FamilyTasks = lazy(() => import("./Tabs/FamilyTasks"));
|
||||
const ProfileInfo = lazy(() => import("./Tabs/ProfileInfo"));
|
||||
const FamilyPending = lazy(() => import("./Tabs/FamilyPending"));
|
||||
|
||||
export default function FamilyManageTabs({
|
||||
className,
|
||||
accountDetails,
|
||||
@@ -35,14 +37,15 @@ export default function FamilyManageTabs({
|
||||
});
|
||||
const [errMsg, setErrMsg] = useState("");
|
||||
const [familyTaskPopout, setFamilyTaskPopout] = useState(false);
|
||||
const [profileImg, setProfileImg] = useState(profile);
|
||||
const profileImgInput = useRef(null);
|
||||
const [isPending, startTransition] = useTransition();
|
||||
const apiCall = useMemo(() => new usersService(), []);
|
||||
|
||||
const familyPopUpHandler = () => {
|
||||
setFamilyTaskPopout((prev) => !prev);
|
||||
};
|
||||
|
||||
const [profileImg, setProfileImg] = useState(profile);
|
||||
const profileImgInput = useRef(null);
|
||||
|
||||
const browseProfileImg = () => {
|
||||
profileImgInput.current.click();
|
||||
};
|
||||
@@ -57,16 +60,15 @@ export default function FamilyManageTabs({
|
||||
}
|
||||
};
|
||||
|
||||
const apiCall = useMemo(() => new usersService(), []);
|
||||
|
||||
const manageFamily = useCallback(async () => {
|
||||
try {
|
||||
setDetails({
|
||||
setDetails((prevDetails) => ({
|
||||
...prevDetails,
|
||||
familyDetails: { loading: true },
|
||||
familyTasks: { loading: true },
|
||||
familyWaitList: { loading: true },
|
||||
familyPending: { loading: true },
|
||||
});
|
||||
}));
|
||||
|
||||
const { family_uid } = accountDetails;
|
||||
const reqData = { family_uid };
|
||||
@@ -89,22 +91,26 @@ export default function FamilyManageTabs({
|
||||
tasksData?.internal_return < 0 ||
|
||||
familyWaitData?.internal_return < 0 ||
|
||||
familyPendingData?.internal_return < 0
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
setDetails({
|
||||
familyDetails: { loading: false, data: familyData },
|
||||
familyTasks: { loading: false, data: tasksData },
|
||||
familyWaitList: { loading: false, data: familyWaitData },
|
||||
familyPending: { loading: false, data: familyPendingData },
|
||||
startTransition(() => {
|
||||
setDetails({
|
||||
familyDetails: { loading: false, data: familyData },
|
||||
familyTasks: { loading: false, data: tasksData },
|
||||
familyWaitList: { loading: false, data: familyWaitData },
|
||||
familyPending: { loading: false, data: familyPendingData },
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
setDetails({
|
||||
setDetails((prevDetails) => ({
|
||||
...prevDetails,
|
||||
familyDetails: { loading: false },
|
||||
familyTasks: { loading: false },
|
||||
familyWaitList: { loading: false },
|
||||
familyPending: { loading: false },
|
||||
});
|
||||
}));
|
||||
setErrMsg("An error occurred");
|
||||
throw new Error(error);
|
||||
}
|
||||
@@ -119,13 +125,15 @@ export default function FamilyManageTabs({
|
||||
const tabs = [
|
||||
{ id: 1, name: "Tasks" },
|
||||
{ id: 2, name: "Waiting" },
|
||||
{ id: 3, name: "Pending" }
|
||||
{ id: 3, name: "Pending" },
|
||||
];
|
||||
|
||||
const [tab, setTab] = useState(tabs[0].name);
|
||||
|
||||
const tabHandler = (value) => {
|
||||
setTab(value);
|
||||
startTransition(() => {
|
||||
setTab(value);
|
||||
});
|
||||
};
|
||||
|
||||
const tabComponents = {
|
||||
@@ -174,7 +182,13 @@ export default function FamilyManageTabs({
|
||||
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
|
||||
|
||||
useEffect(() => {
|
||||
manageFamily();
|
||||
let __manageFamily = true;
|
||||
if (__manageFamily) {
|
||||
manageFamily();
|
||||
}
|
||||
return () => {
|
||||
__manageFamily = false;
|
||||
};
|
||||
}, [tab, manageFamily]);
|
||||
|
||||
return (
|
||||
@@ -202,15 +216,25 @@ export default function FamilyManageTabs({
|
||||
/>
|
||||
<div className="mt-4 flex justify-center items-center gap-2">
|
||||
<button
|
||||
onClick={() => tabHandler('Account')}
|
||||
className="family-icon p-2 border-2 border-sky-blue rounded-2xl flex flex-col justify-between items-center">
|
||||
<img src={localImgLoad('images/icons/account.svg')} className="w-[70px] h-[70px]" alt='Settings-Icon' />
|
||||
onClick={() => tabHandler("Account")}
|
||||
className="family-icon p-2 border-2 border-sky-blue rounded-2xl flex flex-col justify-between items-center"
|
||||
>
|
||||
<img
|
||||
src={localImgLoad("images/icons/account.svg")}
|
||||
className="w-[70px] h-[70px]"
|
||||
alt="Settings-Icon"
|
||||
/>
|
||||
<p className="mt-2 text-lg text-sky-blue">Account</p>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => tabHandler('Profile')}
|
||||
className="family-icon p-2 border-2 border-sky-blue rounded-2xl flex flex-col justify-between items-center">
|
||||
<img src={localImgLoad('images/icons/profile.svg')} className="w-[70px] h-[70px]" alt='Settings-Icon' />
|
||||
onClick={() => tabHandler("Profile")}
|
||||
className="family-icon p-2 border-2 border-sky-blue rounded-2xl flex flex-col justify-between items-center"
|
||||
>
|
||||
<img
|
||||
src={localImgLoad("images/icons/profile.svg")}
|
||||
className="w-[70px] h-[70px]"
|
||||
alt="Settings-Icon"
|
||||
/>
|
||||
<p className="mt-2 text-lg text-sky-blue">Profile</p>
|
||||
</button>
|
||||
</div>
|
||||
@@ -243,7 +267,11 @@ export default function FamilyManageTabs({
|
||||
</div>
|
||||
<div className="flex-[0.9] lg:min-h-[450px] h-full">
|
||||
<div className="h-full p-4 border border-[#dbd9d9] relative overflow-y-auto">
|
||||
{selectedTabComponent}
|
||||
<Suspense
|
||||
fallback={<LoadingSpinner size="16" color="sky-blue" />}
|
||||
>
|
||||
{selectedTabComponent}
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useTransition } from "react";
|
||||
import ModalCom from "../../Helpers/ModalCom";
|
||||
import Detail from "../../jobPopout/popoutcomponent/Detail";
|
||||
import usersService from "../../../services/UsersService";
|
||||
@@ -6,7 +6,7 @@ import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||
import { PriceFormatter } from "../../Helpers/PriceFormatter";
|
||||
import { NewTasks } from "./forms";
|
||||
|
||||
function AssignTaskPopout({ action, situation, familyDetails }) {
|
||||
const AssignTaskPopout = React.memo(({ action, details, situation, familyDetails }) => {
|
||||
const apiCall = new usersService();
|
||||
|
||||
let [requestStatus, setRequestStatus] = useState({
|
||||
@@ -15,9 +15,9 @@ function AssignTaskPopout({ action, situation, familyDetails }) {
|
||||
message: "",
|
||||
}); // HOLDS RESPONSE FOR SENDING API REQUEST
|
||||
|
||||
let [familyTask, setFamilyTask] = useState({ loading: true, data: [] });
|
||||
let [familyTask, setFamilyTask] = useState({ loading: false, data: [] });
|
||||
|
||||
let [taskType, setTaskType] = useState("select"); // SWITCHES BTW SELECT TASK AND NEW TASK
|
||||
let [taskType, setTaskType] = useState(details ? "new" : "select"); // SWITCHES BTW SELECT TASK AND NEW TASK
|
||||
|
||||
let [activeTask, setActiveTask] = useState({ id: 0, data: {} }); // HOLDS SELECTED TASK
|
||||
|
||||
@@ -34,14 +34,14 @@ function AssignTaskPopout({ action, situation, familyDetails }) {
|
||||
// New Task
|
||||
const [formState, setFormState] = useState({
|
||||
// Initialize form state with desired fields
|
||||
banner: "" || "default.jpg",
|
||||
country: "" || "",
|
||||
price: "" || "",
|
||||
title: "" || "",
|
||||
description: "" || "",
|
||||
job_detail: "" || "",
|
||||
timeline_days: "" || "",
|
||||
category: [] || "",
|
||||
banner: details?.banner || "default.jpg",
|
||||
country: details?.country || "",
|
||||
price: details?.price || "",
|
||||
title: details?.title || "",
|
||||
description: details?.description || "",
|
||||
job_detail: details?.job_detail || "",
|
||||
timeline_days: details?.timeline_days || "",
|
||||
category: details?.category || "",
|
||||
});
|
||||
|
||||
const assignFamilyTask = () => {
|
||||
@@ -81,30 +81,29 @@ function AssignTaskPopout({ action, situation, familyDetails }) {
|
||||
title,
|
||||
} = formState;
|
||||
|
||||
const requiredFields = [
|
||||
const requiredFields = {
|
||||
banner,
|
||||
category,
|
||||
// category,
|
||||
country,
|
||||
description,
|
||||
job_detail,
|
||||
price,
|
||||
timeline_days,
|
||||
title,
|
||||
];
|
||||
};
|
||||
|
||||
if (requiredFields.some((field) => !field)) {
|
||||
const emptyField = requiredFields.find((field) => !field);
|
||||
setRequestStatus({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: `${emptyField} Empty`,
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
setRequestStatus({ loading: false, status: false, message: "" });
|
||||
}, 3000);
|
||||
|
||||
return;
|
||||
for (let field in requiredFields) {
|
||||
if (requiredFields[field] == "") {
|
||||
// let currencyErrMsg = field == "country" && "currency"
|
||||
setRequestStatus({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: `${field} is empty`,
|
||||
});
|
||||
return setTimeout(() => {
|
||||
setRequestStatus({ loading: false, status: false, message: "" });
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
reqData = {
|
||||
@@ -117,7 +116,7 @@ function AssignTaskPopout({ action, situation, familyDetails }) {
|
||||
timeline_days,
|
||||
title,
|
||||
assign_mode: 110055,
|
||||
family_uid: familyDetails.uid,
|
||||
family_uid: details?.family_uid || familyDetails?.uid,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -157,37 +156,48 @@ function AssignTaskPopout({ action, situation, familyDetails }) {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let checkFamilyTask = true;
|
||||
const reqData = {
|
||||
limit: 30,
|
||||
offset: 0,
|
||||
job_type: "FAMILY",
|
||||
action: 13005,
|
||||
};
|
||||
|
||||
apiCall
|
||||
.getMyJobList(reqData)
|
||||
.then((res) => {
|
||||
setFamilyTask({ loading: false, data: res?.data?.result_list });
|
||||
if (res?.data?.result_list?.length) {
|
||||
setActiveTask((prev) => ({
|
||||
...prev,
|
||||
data: res?.data?.result_list[0],
|
||||
}));
|
||||
if (checkFamilyTask) {
|
||||
setFamilyTask({ loading: false, data: res?.data?.result_list });
|
||||
if (res?.data?.result_list?.length) {
|
||||
setActiveTask((prev) => ({
|
||||
...prev,
|
||||
data: res?.data?.result_list[0],
|
||||
}));
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
setFamilyTask({ loading: false, data: [] });
|
||||
console.log("Error", err);
|
||||
});
|
||||
|
||||
return () => {
|
||||
checkFamilyTask = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
console.log("Trying to see form data >>", formState);
|
||||
return (
|
||||
<>
|
||||
<ModalCom action={action} situation={situation} className="assign-task-popup">
|
||||
<ModalCom
|
||||
action={action}
|
||||
situation={situation}
|
||||
className="assign-task-popup"
|
||||
>
|
||||
<div className="w-full h-full lg:w-[700px] lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
|
||||
<div className="w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
Assign task to {familyDetails?.firstname}
|
||||
Assign task to {familyDetails?.firstname || details.firstName}
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
@@ -362,55 +372,62 @@ function AssignTaskPopout({ action, situation, familyDetails }) {
|
||||
</div>
|
||||
|
||||
{/* BTN */}
|
||||
<div className="p-2 border-t-2 flex justify-end items-center gap-3">
|
||||
<div className="py-2 px-4 border-t-2 flex justify-between items-center">
|
||||
{/* error or success display */}
|
||||
{requestStatus.message != "" &&
|
||||
(!requestStatus.status ? (
|
||||
<div
|
||||
className={`relative p-2 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
|
||||
>
|
||||
{requestStatus.message}
|
||||
</div>
|
||||
) : (
|
||||
requestStatus.status && (
|
||||
<div className="w-auto h-auto flex items-center">
|
||||
{requestStatus.message != "" &&
|
||||
(!requestStatus.status ? (
|
||||
<div
|
||||
className={`relative p-2 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
|
||||
className={`relative p-2 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px] self-start`}
|
||||
>
|
||||
{requestStatus.message}
|
||||
</div>
|
||||
)
|
||||
))}
|
||||
) : (
|
||||
requestStatus.status && (
|
||||
<div
|
||||
className={`relative p-2 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
|
||||
>
|
||||
{requestStatus.message}
|
||||
</div>
|
||||
)
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* End of error or success display */}
|
||||
<button
|
||||
disabled={requestStatus.loading}
|
||||
onClick={action}
|
||||
type="button"
|
||||
className="w-20 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white cursor-pointer"
|
||||
>
|
||||
<span className="text-gradient">Close</span>
|
||||
</button>
|
||||
<div className="">
|
||||
{requestStatus.loading ? (
|
||||
<LoadingSpinner color="sky-blue" size="8" />
|
||||
) : taskType == "select" ? (
|
||||
<button
|
||||
type="button"
|
||||
disabled={requestStatus.loading}
|
||||
onClick={assignFamilyTask}
|
||||
className="px-1 w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white cursor-pointer"
|
||||
>
|
||||
Assign
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
disabled={requestStatus.loading}
|
||||
onClick={assignFamilyTask}
|
||||
className="px-1 w-40 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white cursor-pointer"
|
||||
>
|
||||
{`Assign to ${familyDetails?.firstname}`}
|
||||
</button>
|
||||
)}
|
||||
<div className="w-auto h-auto flex items-center gap-3">
|
||||
<button
|
||||
disabled={requestStatus.loading}
|
||||
onClick={action}
|
||||
type="button"
|
||||
className="w-20 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white cursor-pointer"
|
||||
>
|
||||
<span className="text-gradient">Close</span>
|
||||
</button>
|
||||
<div className="">
|
||||
{requestStatus.loading ? (
|
||||
<LoadingSpinner color="sky-blue" size="8" />
|
||||
) : taskType == "select" ? (
|
||||
<button
|
||||
type="button"
|
||||
disabled={requestStatus.loading}
|
||||
onClick={assignFamilyTask}
|
||||
className="px-1 w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white cursor-pointer"
|
||||
>
|
||||
Assign
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
disabled={requestStatus.loading}
|
||||
onClick={assignFamilyTask}
|
||||
className="px-1 w-40 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white cursor-pointer"
|
||||
>
|
||||
{`Assign to ${
|
||||
familyDetails?.firstname || details?.firstName
|
||||
}`}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
@@ -419,6 +436,6 @@ function AssignTaskPopout({ action, situation, familyDetails }) {
|
||||
</ModalCom>
|
||||
</>
|
||||
);
|
||||
}
|
||||
})
|
||||
|
||||
export default AssignTaskPopout;
|
||||
export default AssignTaskPopout;
|
||||
@@ -1,9 +1,7 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import usersService from "../../../../services/UsersService";
|
||||
import InputCom from "../../../Helpers/Inputs/InputCom";
|
||||
import debounce from "../../../../hooks/debounce";
|
||||
|
||||
const DEFAULT_IMAGE = require("../../../../assets/images/taskbanners/default.jpg");
|
||||
export default function NewTasks({ formState, setFormState }) {
|
||||
let [currency, setCurrency] = useState({
|
||||
loading: true,
|
||||
@@ -11,6 +9,9 @@ export default function NewTasks({ formState, setFormState }) {
|
||||
data: null,
|
||||
});
|
||||
|
||||
const selectImage = require(`../../../../assets/images/taskbanners/${
|
||||
formState.banner || "default.jpg"
|
||||
}`);
|
||||
const ApiCall = new usersService();
|
||||
|
||||
// FUNCTION TO GET Currency
|
||||
@@ -47,7 +48,7 @@ export default function NewTasks({ formState, setFormState }) {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<form className="w-full flex justify-between items-center">
|
||||
<form className="w-full flex justify-between items-start">
|
||||
<div className="flex flex-col gap-3 max-w-[77%]">
|
||||
{/* inputs starts here */}
|
||||
<div className="grid md:grid-cols-3 grid-cols-1 gap-6 mb-[5px]">
|
||||
@@ -207,7 +208,7 @@ export default function NewTasks({ formState, setFormState }) {
|
||||
<div className="max-w-[20%] w-full">
|
||||
<div className="h-32 w-full">
|
||||
<img
|
||||
src={DEFAULT_IMAGE}
|
||||
src={selectImage}
|
||||
alt="task_banner_img"
|
||||
className="w-full h-full object-contain"
|
||||
/>
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import React, { useState } from "react";
|
||||
import dataImage1 from "../../assets/images/data-table-user-1.png";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import { useNavigate, useLocation, Link } from "react-router-dom";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { handlePagingFunc } from "../Pagination/HandlePagination";
|
||||
import PaginatedList from "../Pagination/PaginatedList";
|
||||
|
||||
import familyImage from '../../assets/images/no-family-side.png'
|
||||
|
||||
export default function FamilyTable({ className, familyList, loader, popUpHandler }) {
|
||||
const filterCategories = ["All Categories", "Explore", "Featured"];
|
||||
const [selectedCategory, setCategory] = useState(filterCategories[0]);
|
||||
const navigate = useNavigate();
|
||||
// let location = useLocation();
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const indexOfFirstItem = Number(currentPage);
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
import { forwardRef } from 'react'
|
||||
import QRCode from 'react-qr-code';
|
||||
import { forwardRef } from "react";
|
||||
import QRCode from "react-qr-code";
|
||||
|
||||
const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint }, ref) => {
|
||||
return (
|
||||
<div
|
||||
className="w-full lg:min-h-[500px] h-full flex flex-col items-center justify-center"
|
||||
ref={myRef}
|
||||
>
|
||||
<div className="update-table w-full lg:min-h-[450px] h-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow ">
|
||||
<div className="flex items-center justify-around h-[380px]">
|
||||
<div className="flex flex-col">
|
||||
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
|
||||
Username:{" "}
|
||||
<span className="ml-2 normal-case">
|
||||
{familyData?.username ? familyData?.username : "please wait..."}
|
||||
</span>
|
||||
</h2>
|
||||
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
|
||||
Pin:{" "}
|
||||
<span className="ml-2 normal-case">
|
||||
{familyData?.pin ? familyData?.pin : "please wait..."}
|
||||
</span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<span className="text-5xl text-gray-400 opacity-20 font-bold">
|
||||
or
|
||||
</span>
|
||||
|
||||
<div className="max-w-[200px]">
|
||||
<p className="text-xl tracking-wide mb-[15px] text-center font-bold text-dark-gray dark:text-white">
|
||||
Scan the code from mobile app
|
||||
</p>
|
||||
<QRCode
|
||||
size={256}
|
||||
style={{ height: "auto", maxWidth: "100%", width: "100%" }}
|
||||
value={`https://www.google.com`}
|
||||
viewBox={`0 0 256 256`}
|
||||
/>
|
||||
</div>
|
||||
return (
|
||||
<div
|
||||
className="w-full lg:min-h-[500px] h-full flex flex-col items-center justify-center"
|
||||
ref={myRef}
|
||||
>
|
||||
<div className="update-table w-full lg:min-h-[450px] h-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow ">
|
||||
<div className="flex items-center justify-around h-[380px]">
|
||||
<div className="flex flex-col">
|
||||
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
|
||||
Username:{" "}
|
||||
<span className="ml-2 normal-case">
|
||||
{familyData?.username ? familyData?.username : "please wait..."}
|
||||
</span>
|
||||
</h2>
|
||||
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
|
||||
Pin:{" "}
|
||||
<span className="ml-2 normal-case">
|
||||
{familyData?.pin ? familyData?.pin : "please wait..."}
|
||||
</span>
|
||||
</h2>
|
||||
</div>
|
||||
<div className="h-[50px] w-full flex justify-center items-center">
|
||||
<button
|
||||
className="btn-shine w-[116px] h-[46px] text-white rounded-full text-base bg-pink flex justify-center items-center"
|
||||
onClick={handlePrint}
|
||||
>
|
||||
Print
|
||||
</button>
|
||||
|
||||
<span className="text-5xl text-gray-400 opacity-20 font-bold">
|
||||
or
|
||||
</span>
|
||||
|
||||
<div className="max-w-[200px]">
|
||||
<p className="text-xl tracking-wide mb-[15px] text-center font-bold text-dark-gray dark:text-white">
|
||||
Scan the code from mobile app
|
||||
</p>
|
||||
<QRCode
|
||||
size={256}
|
||||
style={{ height: "auto", maxWidth: "100%", width: "100%" }}
|
||||
value={`https://www.google.com`}
|
||||
viewBox={`0 0 256 256`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="h-[50px] w-full flex justify-center items-center">
|
||||
<button
|
||||
className="btn-shine w-[116px] h-[46px] text-white rounded-full text-base bg-pink flex justify-center items-center"
|
||||
onClick={handlePrint}
|
||||
>
|
||||
Print
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export default FamilyAccount
|
||||
export default FamilyAccount;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { PaginatedList, handlePagingFunc } from "../../Pagination";
|
||||
import { PriceFormatter } from "../../Helpers/PriceFormatter";
|
||||
import dataImage2 from "../../../assets/images/data-table-user-2.png";
|
||||
@@ -13,8 +13,12 @@ export default function FamilyPending({
|
||||
}) {
|
||||
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
|
||||
|
||||
let filteredFamilyData = familyData?.result_list?.filter(
|
||||
(data) => data?.family_uid === accountDetails?.family_uid
|
||||
let filteredFamilyData = useMemo(
|
||||
() =>
|
||||
familyData?.result_list?.filter(
|
||||
(data) => data?.family_uid === accountDetails?.family_uid
|
||||
),
|
||||
[accountDetails?.family_uid, familyData?.result_list]
|
||||
);
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
@@ -51,7 +55,7 @@ export default function FamilyPending({
|
||||
value?.currency_code,
|
||||
value?.currency
|
||||
);
|
||||
let image = value.banner ? value.banner : 'default.jpg'
|
||||
let image = value.banner ? value.banner : "default.jpg";
|
||||
return (
|
||||
<tr
|
||||
key={index}
|
||||
@@ -61,7 +65,9 @@ export default function FamilyPending({
|
||||
<div className="flex space-x-2 items-center w-full">
|
||||
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
|
||||
<img
|
||||
src={localImgLoad(`images/taskbanners/${image}`)}
|
||||
src={localImgLoad(
|
||||
`images/taskbanners/${image}`
|
||||
)}
|
||||
alt="data"
|
||||
className="w-full h-full rounded-full"
|
||||
/>
|
||||
|
||||
@@ -1,26 +1,50 @@
|
||||
import { useState } from "react";
|
||||
import { useState, useMemo, memo } from "react";
|
||||
import { handlePagingFunc, PaginatedList } from "../../Pagination";
|
||||
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||
import SuggestTask from "../../FamilyPopup/SuggestTask";
|
||||
import AssignTaskPopout from "../FamilyPopout/AssignTaskPopout";
|
||||
|
||||
const FamilyWaitlist = ({ familyData, className, accountDetails, loader }) => {
|
||||
const FamilyWaitlist = memo(({ familyData, className, accountDetails, loader }) => {
|
||||
const [popUp, setPopUp] = useState({ show: false, data: {} });
|
||||
|
||||
let filteredFamilyData = familyData?.result_list?.filter(
|
||||
(data) => data?.family_uid === accountDetails?.family_uid
|
||||
const [continueTaskPopup, setContinueTaskPopup] = useState({
|
||||
show: false,
|
||||
data: {},
|
||||
});
|
||||
const filteredFamilyData = useMemo(
|
||||
() =>
|
||||
familyData?.result_list?.filter(
|
||||
(data) => data?.family_uid === accountDetails?.family_uid
|
||||
),
|
||||
[familyData, accountDetails]
|
||||
);
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const itemsPerPage = Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
||||
const indexOfFirstItem = currentPage;
|
||||
const indexOfLastItem = currentPage + itemsPerPage;
|
||||
const currentTask = filteredFamilyData?.slice(
|
||||
indexOfFirstItem,
|
||||
indexOfLastItem
|
||||
const currentTask = useMemo(
|
||||
() => filteredFamilyData?.slice(indexOfFirstItem, indexOfLastItem),
|
||||
[filteredFamilyData, indexOfFirstItem, indexOfLastItem]
|
||||
);
|
||||
|
||||
const handlePagination = (e) => handlePagingFunc(e, setCurrentPage);
|
||||
|
||||
const openPopUp = (value) => {
|
||||
setPopUp({ show: true, data: { ...value } });
|
||||
};
|
||||
|
||||
const closePopUp = () => {
|
||||
setPopUp({ show: false, data: {} });
|
||||
};
|
||||
|
||||
const openContinueTaskPopup = (value) => {
|
||||
setContinueTaskPopup({ show: true, data: { ...value } });
|
||||
};
|
||||
|
||||
const closeContinueTaskPopup = () => {
|
||||
setContinueTaskPopup({ show: false, data: {} });
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`update-table w-full bg-white dark:bg-dark-white h-full lg:min-h-[450px] overflow-hidden rounded-2xl section-shadow ${
|
||||
@@ -78,12 +102,7 @@ const FamilyWaitlist = ({ familyData, className, accountDetails, loader }) => {
|
||||
</td>
|
||||
<td className="text-right py-4 px-2">
|
||||
<button
|
||||
onClick={() =>
|
||||
setPopUp({
|
||||
show: true,
|
||||
data: { ...value, selectedImage },
|
||||
})
|
||||
}
|
||||
onClick={() => openPopUp(value)}
|
||||
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
View
|
||||
@@ -109,14 +128,21 @@ const FamilyWaitlist = ({ familyData, className, accountDetails, loader }) => {
|
||||
{popUp.show && (
|
||||
<SuggestTask
|
||||
details={popUp.data}
|
||||
onClose={() => {
|
||||
setPopUp({ show: false, data: {} });
|
||||
}}
|
||||
onClose={closePopUp}
|
||||
continuePopupData={openContinueTaskPopup}
|
||||
situation={popUp.show}
|
||||
/>
|
||||
)}
|
||||
|
||||
{continueTaskPopup.show && (
|
||||
<AssignTaskPopout
|
||||
details={continueTaskPopup.data}
|
||||
action={closeContinueTaskPopup}
|
||||
situation={continueTaskPopup.show}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export default FamilyWaitlist;
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import React, {
|
||||
Suspense,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from "react";
|
||||
import InputCom from "../Helpers/Inputs/InputCom";
|
||||
import Layout from "../Partials/Layout";
|
||||
import FamilyTable from "./FamilyTable";
|
||||
import SiteService from "../../services/SiteService";
|
||||
import ModalCom from "../Helpers/ModalCom";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
|
||||
export default function FamilyAcc() {
|
||||
const [selectTab, setValue] = useState("today");
|
||||
@@ -20,60 +27,50 @@ export default function FamilyAcc() {
|
||||
|
||||
const apiCall = useMemo(() => new SiteService(), []);
|
||||
|
||||
// This is to make sure it's called once and used everywhere
|
||||
let memberId = localStorage.getItem("member_id");
|
||||
let uid = localStorage.getItem("uid");
|
||||
let sessionId = localStorage.getItem("session_token");
|
||||
|
||||
const popUpHandler = () => {
|
||||
setPopUp((prev) => !prev);
|
||||
};
|
||||
|
||||
// tab handler
|
||||
const filterHandler = (value) => {
|
||||
setValue(value);
|
||||
};
|
||||
|
||||
// For the age drop down
|
||||
let startAge = 5;
|
||||
let endAge = 16;
|
||||
// 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 ageRange = useMemo(() => {
|
||||
const startAge = 5;
|
||||
const endAge = 16;
|
||||
return Array.from(
|
||||
{ length: endAge - startAge + 1 },
|
||||
(_, index) => startAge + index
|
||||
);
|
||||
}, []);
|
||||
|
||||
const handleAgeSelect = (event) => {
|
||||
setSelectedAge(parseInt(event.target.value));
|
||||
};
|
||||
// Input handler
|
||||
|
||||
const handleInputChange = (event) => {
|
||||
const { name, value } = event?.target;
|
||||
setFormData({ ...formData, [name]: value });
|
||||
setFormData((prevFormData) => ({ ...prevFormData, [name]: value }));
|
||||
};
|
||||
|
||||
// Add member
|
||||
const addMember = async () => {
|
||||
const { first_name, last_name } = formData;
|
||||
setLoader(true);
|
||||
try {
|
||||
if (first_name !== "" && last_name !== "") {
|
||||
let reqData = {
|
||||
member_id: memberId,
|
||||
uid: uid,
|
||||
session_id: sessionId,
|
||||
const reqData = {
|
||||
firstname: first_name,
|
||||
lastname: last_name,
|
||||
age: selectedAge,
|
||||
};
|
||||
|
||||
let res = await apiCall.addFamily(reqData);
|
||||
const res = await apiCall.addFamily(reqData);
|
||||
const { data } = res;
|
||||
|
||||
if (data?.internal_return > 0 && data?.status == "OK") {
|
||||
if (data?.internal_return > 0 && data?.status === "OK") {
|
||||
setLoader(false);
|
||||
setListReload((prev) => !prev);
|
||||
popUpHandler()
|
||||
popUpHandler();
|
||||
} else {
|
||||
setLoader(false);
|
||||
setMsgErr("Sorry, something went wrong");
|
||||
@@ -94,38 +91,42 @@ export default function FamilyAcc() {
|
||||
first_name: "",
|
||||
last_name: "",
|
||||
});
|
||||
setSelectedAge("")
|
||||
setSelectedAge("");
|
||||
}
|
||||
};
|
||||
|
||||
// member listing
|
||||
const memberList = useCallback(async () => {
|
||||
setLoader(true);
|
||||
try {
|
||||
let reqData = {
|
||||
member_id: memberId,
|
||||
uid: uid,
|
||||
session_id: sessionId,
|
||||
const reqData = {
|
||||
limit: 20,
|
||||
offset: 0,
|
||||
action: 22010,
|
||||
};
|
||||
|
||||
let res = await apiCall.familyListings(reqData);
|
||||
const res = await apiCall.familyListings(reqData);
|
||||
const { data } = res;
|
||||
if (data?.internal_return >= 0 && data?.status == "OK") {
|
||||
let { result_list } = data;
|
||||
if (data?.internal_return >= 0 && data?.status === "OK") {
|
||||
const { result_list } = data;
|
||||
setFamilyList(result_list);
|
||||
setLoader(false);
|
||||
} else return;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
setLoader(false);
|
||||
throw new Error(error);
|
||||
}
|
||||
}, [apiCall, memberId, sessionId, uid]);
|
||||
}, [apiCall]);
|
||||
|
||||
useEffect(() => {
|
||||
memberList();
|
||||
let checkMemberList = true;
|
||||
if (checkMemberList) {
|
||||
memberList();
|
||||
}
|
||||
return () => {
|
||||
checkMemberList = false;
|
||||
};
|
||||
}, [listReload, memberList]);
|
||||
|
||||
return (
|
||||
@@ -158,7 +159,13 @@ export default function FamilyAcc() {
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<FamilyTable familyList={familyList} loader={loader} popUpHandler={popUpHandler} />
|
||||
<Suspense fallback={<LoadingSpinner color="sky-blue" size="16" />}>
|
||||
<FamilyTable
|
||||
familyList={familyList}
|
||||
loader={loader}
|
||||
popUpHandler={popUpHandler}
|
||||
/>
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
{popUp && (
|
||||
|
||||
@@ -7,7 +7,7 @@ import usersService from "../../services/UsersService";
|
||||
import Icons from "../Helpers/Icons";
|
||||
|
||||
const DEFAULT_IMAGE = require("../../assets/images/family/default.jpg");
|
||||
const SuggestTask = ({ details, onClose, situation }) => {
|
||||
const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
const { pathname, state } = useLocation();
|
||||
const [submitTask, setSubmitTask] = useState({
|
||||
loading: false,
|
||||
@@ -16,7 +16,7 @@ const SuggestTask = ({ details, onClose, situation }) => {
|
||||
});
|
||||
const [suggestedNextStep, setSuggestedNextStep] = useState("Send Task");
|
||||
|
||||
const switchNextStep = (value) => {
|
||||
const switchNextStep = ({ target: value }) => {
|
||||
setSuggestedNextStep(value);
|
||||
};
|
||||
|
||||
@@ -29,8 +29,9 @@ const SuggestTask = ({ details, onClose, situation }) => {
|
||||
|
||||
const apiCall = new usersService();
|
||||
|
||||
const handleSubmit = async (values) => {
|
||||
const handleSuggestedTask = async (values) => {
|
||||
if (!values.title && !values.description) return;
|
||||
|
||||
try {
|
||||
setSubmitTask({ loading: true });
|
||||
const reqData = { ...values };
|
||||
@@ -49,7 +50,15 @@ const SuggestTask = ({ details, onClose, situation }) => {
|
||||
}
|
||||
};
|
||||
|
||||
// console.log("state >-->>", state);
|
||||
const handleParentSuggestion = (values) => {
|
||||
if (suggestedNextStep == "Send Task") {
|
||||
let firstName = state?.firstname;
|
||||
let family_uid = state?.family_uid;
|
||||
continuePopupData({ ...details, firstName, family_uid });
|
||||
}
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalCom action={onClose} situation={situation}>
|
||||
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
||||
@@ -87,7 +96,11 @@ const SuggestTask = ({ details, onClose, situation }) => {
|
||||
</div>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
onSubmit={pathname !== "/manage-family" && handleSubmit}
|
||||
onSubmit={
|
||||
pathname !== "/manage-family"
|
||||
? handleSuggestedTask
|
||||
: handleParentSuggestion
|
||||
}
|
||||
>
|
||||
{(props) => {
|
||||
return (
|
||||
@@ -164,7 +177,7 @@ const SuggestTask = ({ details, onClose, situation }) => {
|
||||
</div>
|
||||
|
||||
{/* Radio buttons for family */}
|
||||
{pathname === "/manage-family" && (
|
||||
{pathname === "/manage-family" ? (
|
||||
<div className="h-[20px] w-full border-t dark:border-[#5356fb29] border-light-purple relative">
|
||||
<div id="my-radio-group" className="sr-only">
|
||||
Parent suggested next step
|
||||
@@ -182,18 +195,22 @@ const SuggestTask = ({ details, onClose, situation }) => {
|
||||
<label
|
||||
role="group"
|
||||
key={idx}
|
||||
htmlFor="parent-suggested"
|
||||
htmlFor={`parent-suggested-${idx}`}
|
||||
className={`transition duration-150 ease-in-out parent-suggest group cursor-pointer`}
|
||||
onClick={() => setSuggestedNextStep(title)}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
name="parent-suggested"
|
||||
value={title}
|
||||
checked={title == suggestedNextStep}
|
||||
checked={suggestedNextStep === title}
|
||||
onChange={switchNextStep}
|
||||
className={`transition duration-150 ease-in-out parent-suggest`}
|
||||
className={`transition duration-150 ease-in-out parent-suggest pointer-events-none`}
|
||||
/>
|
||||
<span
|
||||
onClick={switchNextStep}
|
||||
onClick={() => setSuggestedNextStep(title)}
|
||||
id={`parent-suggested-${idx}`}
|
||||
name="parent-suggested"
|
||||
className={`ml-1 ${
|
||||
title == "Not Now"
|
||||
? "text-red-500"
|
||||
@@ -208,9 +225,10 @@ const SuggestTask = ({ details, onClose, situation }) => {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full h-[70px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
|
||||
<div className="flex items-center space-x-4 mr-9">
|
||||
<button
|
||||
@@ -220,31 +238,33 @@ const SuggestTask = ({ details, onClose, situation }) => {
|
||||
>
|
||||
<span className="text-gradient"> Cancel</span>
|
||||
</button>
|
||||
{pathname !== "/manage-family" ? (
|
||||
<button
|
||||
type="submit"
|
||||
disabled={props.isSubmitting}
|
||||
className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full transition duration-150 ease-in-out"
|
||||
>
|
||||
{submitTask.loading
|
||||
? "Submitting Task"
|
||||
: submitTask.state == "success"
|
||||
? "Task Submitted"
|
||||
: submitTask.state == "bad"
|
||||
? "An Error Occurred"
|
||||
: "Send to Parents"}
|
||||
</button>
|
||||
) : (
|
||||
<button className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full flex items-center transition duration-150 ease-in-out">
|
||||
{suggestedNextStep == "Send Task" ? (
|
||||
<>
|
||||
Continue <Icons name="chevron-right" />
|
||||
</>
|
||||
) : (
|
||||
"Complete"
|
||||
)}
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
type="submit"
|
||||
disabled={props.isSubmitting}
|
||||
className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full transition duration-150 ease-in-out flex items-center"
|
||||
>
|
||||
{pathname !== "/manage-family" ? (
|
||||
<>
|
||||
{submitTask.loading
|
||||
? "Submitting Task"
|
||||
: submitTask.state == "success"
|
||||
? "Task Submitted"
|
||||
: submitTask.state == "bad"
|
||||
? "An Error Occurred"
|
||||
: "Send to Parents"}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{suggestedNextStep == "Send Task" ? (
|
||||
<>
|
||||
Continue <Icons name="chevron-right" />
|
||||
</>
|
||||
) : (
|
||||
"Complete"
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
|
||||
@@ -519,7 +519,11 @@ export default function Icons({ name }) {
|
||||
<img className="w-[17px] h-[17px]" src={localImgLoad('images/icons/market.svg')} alt="market" />
|
||||
) : name === "new-mytask" ? (
|
||||
<img className="w-[17px] h-[17px]" src={localImgLoad('images/icons/my-task.svg')} alt="task" />
|
||||
) : (
|
||||
) : name === "family-id" ? (
|
||||
<img className="w-[20px] h-[20px]" src={localImgLoad('images/icons/family-id.svg')} alt="family-id" />
|
||||
) : name === "family-pin" ? (
|
||||
<img className="w-[20px] h-[20px]" src={localImgLoad('images/icons/family-pin.svg')} alt="family-pin" />
|
||||
): (
|
||||
""
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -20,7 +20,8 @@ import React from "react";
|
||||
export const PriceFormatter = (
|
||||
price = "00",
|
||||
currency = "",
|
||||
currencyName = ""
|
||||
currencyName = "",
|
||||
priceClass
|
||||
) => {
|
||||
// Convert the number to a string
|
||||
let numStr = String(price);
|
||||
@@ -44,7 +45,7 @@ export const PriceFormatter = (
|
||||
return (
|
||||
<span className="text-sm flex items-center">
|
||||
<sup>{currency || currencyName || ""}</sup>
|
||||
<span className="px-1 font-bold text-lg">{formattedInteger || ""}</span>
|
||||
<span className={`px-1 font-bold ${priceClass ? priceClass : "text-lg"}`}>{formattedInteger || ""}</span>
|
||||
<sup>{formattedDecimal || ""}</sup>
|
||||
</span>
|
||||
);
|
||||
|
||||
@@ -11,12 +11,6 @@ import HomeActivities from "./HomeActivities";
|
||||
|
||||
export default function FullAccountDash(props) {
|
||||
console.log("PROPS IN HOME->", props);
|
||||
|
||||
const trending = datas.datas;
|
||||
const jobData = datas.datas; // api calls or cache
|
||||
|
||||
const userApi = new usersService();
|
||||
|
||||
const { userDetails } = useSelector((state) => state?.userDetails);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { toast } from "react-toastify";
|
||||
import heroBg from "../../assets/images/hero-bg.svg";
|
||||
import heroBg from "../../assets/images/bg-sky-blue.jpg"; //hero-bg.svg";
|
||||
import heroUser from "../../assets/images/hero-user.png";
|
||||
import CountDown from "../Helpers/CountDown";
|
||||
import HomeSliders from "./HomeSliders";
|
||||
@@ -24,7 +24,7 @@ export default function Hero({ className, bannerList, nextDueTask }) {
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`w-full lg:h-[444px] h-full lg:flex lg:p-8 p-4 justify-between items-center lg:space-x-28 rounded-2xl overflow-hidden ${
|
||||
className={`w-full min-h-[400px] md:grid grid-cols-2 lg:p-8 p-4 justify-between items-center gap-2 rounded-2xl overflow-hidden ${
|
||||
className || ""
|
||||
}`}
|
||||
style={{
|
||||
@@ -33,7 +33,7 @@ export default function Hero({ className, bannerList, nextDueTask }) {
|
||||
backgroundSize: "cover",
|
||||
}}
|
||||
>
|
||||
<div className="flex-1 h-[330px] lg:h-full flex flex-col justify-between mb-5 lg:mb-0">
|
||||
<div className="h-full flex flex-col justify-between mb-5 lg:mb-0">
|
||||
{/* heading */}
|
||||
<div>
|
||||
<h1 className="lg:text-2xl text-xl font-medium text-white tracking-wide">
|
||||
@@ -57,7 +57,7 @@ export default function Hero({ className, bannerList, nextDueTask }) {
|
||||
</div>
|
||||
{/* countdown */}
|
||||
{nextDueTask?.next_due && Object.keys(nextDueTask.next_due)?.length != 0 && (
|
||||
<div className="w-full h-32 flex justify-evenly items-center sm:p-6 p-1 rounded-2xl border border-white-opacity">
|
||||
<div className="w-full h-32 flex justify-evenly items-center sm:p-6 p-1 rounded-2xl border back-dark1 border-white-opacity">
|
||||
<div className="flex flex-col justify-between">
|
||||
<p className="text-base text-white tracking-wide">Current Task</p>
|
||||
<p className="lg:text-2xl text-lg font-bold tracking-wide text-white">
|
||||
@@ -84,7 +84,7 @@ export default function Hero({ className, bannerList, nextDueTask }) {
|
||||
)}
|
||||
{/* action */}
|
||||
<div className="flex lg:space-x-3 space-x-1 items-center">
|
||||
<Link to="/mytask" className="text-white text-base sm:block hidden">
|
||||
<Link to="/mytask" className="text-white text-base">
|
||||
<span className=" border-b dark:border-[#5356fb29] border-white">
|
||||
{" "}
|
||||
View All Task(s)
|
||||
|
||||
@@ -6,7 +6,7 @@ export default function HomeSliders(props) {
|
||||
// debugger;
|
||||
return (
|
||||
<>
|
||||
<div className="hero-slider relative 2xl:w-[600px] xl:w-[400px] lg:w-[420px] w-full mb-2 lg:mb-0 ">
|
||||
<div className="hero-slider relative h-full w-full mb-2 lg:mb-0">
|
||||
<div className="w-full">
|
||||
<SliderCom settings={props.settings}>
|
||||
{props.bannerList?.length <= 0 && (
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react'
|
||||
|
||||
function CurrentJobAction() {
|
||||
return (
|
||||
<div className='job-action bg-white dark:bg-black'>
|
||||
<div className='job-action dark:bg-black'>
|
||||
<p className="my-3 py-1 text-base active-owner">
|
||||
<table className="w-full text-sm text-left text-gray-500">
|
||||
<tbody>
|
||||
|
||||
@@ -60,7 +60,7 @@ function CurrentTaskAction({jobDetails}) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='job-action bg-white dark:bg-black'>
|
||||
<div className='job-action dark:bg-black'>
|
||||
|
||||
<table className="w-full text-sm text-left text-gray-500 active-worker">
|
||||
<tbody>
|
||||
|
||||
@@ -101,7 +101,7 @@ function PastDueJobAction({jobDetails}) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='job-action bg-white dark:bg-black'>
|
||||
<div className='job-action dark:bg-black'>
|
||||
|
||||
<table className="w-full text-sm text-left text-gray-500 owner-pastdue">
|
||||
<tbody>
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react'
|
||||
|
||||
function PastDueTaskAction() {
|
||||
return (
|
||||
<div className='job-action bg-white dark:bg-black'>
|
||||
<div className='job-action dark:bg-black'>
|
||||
|
||||
<table className="w-full text-sm text-left text-gray-500 worker-pastdue">
|
||||
<tbody>
|
||||
|
||||
@@ -90,7 +90,7 @@ function ReviewJobAction({jobDetails}) {
|
||||
})
|
||||
}
|
||||
return (
|
||||
<div className='job-action bg-white dark:bg-black'>
|
||||
<div className='job-action dark:bg-black'>
|
||||
<div className="my-3 py-1 text-base">
|
||||
<table className="w-full text-sm text-left text-gray-500 review-owner">
|
||||
<tbody>
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react'
|
||||
|
||||
function ReviewTaskAction() {
|
||||
return (
|
||||
<div className='job-action bg-white dark:bg-black'>
|
||||
<div className='job-action dark:bg-black'>
|
||||
<p className="my-3 py-1 text-base text-dark-gray dark:text-white">
|
||||
Waiting for the completion message from the client before you can approve. Worker True & Review Job
|
||||
</p>
|
||||
|
||||
@@ -42,7 +42,7 @@ function AddFund({payment}) {
|
||||
return (
|
||||
<div>
|
||||
{/* heading */}
|
||||
<div className="sm:flex justify-between items-center mb-6">
|
||||
{/* <div className="sm:flex justify-between items-center mb-6">
|
||||
<div className="w-full flex justify-start space-x-3 items-center">
|
||||
<button
|
||||
type="button"
|
||||
@@ -71,7 +71,7 @@ function AddFund({payment}) {
|
||||
className="relative"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
|
||||
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
|
||||
<div className="lg:w-2/2 w-full mb-10 lg:mb-0">
|
||||
|
||||
@@ -1,402 +1,472 @@
|
||||
import React,{useEffect, useState} from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import InputCom from '../Helpers/Inputs/InputCom';
|
||||
import PaginatedList from '../Pagination/PaginatedList';
|
||||
import { handlePagingFunc } from '../Pagination/HandlePagination';
|
||||
import LoadingSpinner from '../Spinners/LoadingSpinner';
|
||||
import usersService from '../../services/UsersService';
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import usersService from "../../services/UsersService";
|
||||
import InputCom from "../Helpers/Inputs/InputCom";
|
||||
import { handlePagingFunc } from "../Pagination/HandlePagination";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
|
||||
import { Form, Formik } from "formik";
|
||||
import * as Yup from "yup";
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
name: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(50, "Maximum 50 characters")
|
||||
.required("Name is required"),
|
||||
cardNum: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(25, "Maximum 25 characters")
|
||||
.required("Card Number is required"),
|
||||
code: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(25, "Maximum 25 characters")
|
||||
.required("Postal Code is required"),
|
||||
state: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(25, "Maximum 25 characters")
|
||||
.required("State is required"),
|
||||
address: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(50, "Maximum 50 characters")
|
||||
.required("Address is required"),
|
||||
expirationYear: Yup.string()
|
||||
.min(4, "Minimum 4 characters")
|
||||
.max(4, "Maximum 4 characters")
|
||||
.required("Expiration Year is required"),
|
||||
expirationMonth: Yup.string()
|
||||
.min(1, "Minimum 1 characters")
|
||||
.max(2, "Maximum 2 characters")
|
||||
.required("Expiration Month is required"),
|
||||
cvv: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(4, "Maximum 4 characters")
|
||||
.required("CVV Year is required"),
|
||||
name: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(50, "Maximum 50 characters")
|
||||
.required("Name is required"),
|
||||
cardNum: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(25, "Maximum 25 characters")
|
||||
.required("Card Number is required"),
|
||||
code: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(25, "Maximum 25 characters")
|
||||
.required("Postal Code is required"),
|
||||
state: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(25, "Maximum 25 characters")
|
||||
.required("State is required"),
|
||||
address: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(50, "Maximum 50 characters")
|
||||
.required("Address is required"),
|
||||
expirationYear: Yup.string()
|
||||
.min(4, "Minimum 4 characters")
|
||||
.max(4, "Maximum 4 characters")
|
||||
.required("Expiration Year is required"),
|
||||
expirationMonth: Yup.string()
|
||||
.min(1, "Minimum 1 characters")
|
||||
.max(2, "Maximum 2 characters")
|
||||
.required("Expiration Month is required"),
|
||||
cvv: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(4, "Maximum 4 characters")
|
||||
.required("CVV Year is required"),
|
||||
});
|
||||
|
||||
const initialValues = {
|
||||
name: '',
|
||||
cardNum: '',
|
||||
code: '',
|
||||
state: '',
|
||||
address: '',
|
||||
expirationYear: '',
|
||||
expirationMonth: '',
|
||||
cvv: ''
|
||||
};
|
||||
|
||||
name: "",
|
||||
cardNum: "",
|
||||
code: "",
|
||||
state: "",
|
||||
address: "",
|
||||
expirationYear: "",
|
||||
expirationMonth: "",
|
||||
cvv: "",
|
||||
};
|
||||
|
||||
function AddFundDollars(props) {
|
||||
const navigate = useNavigate()
|
||||
let apiCall = new usersService()
|
||||
const navigate = useNavigate();
|
||||
let apiCall = new usersService();
|
||||
|
||||
let [tab, setTab] = useState("previous"); //STATE FOR SWITCHING BETWEEN TABS
|
||||
let [tab, setTab] = useState("previous"); //STATE FOR SWITCHING BETWEEN TABS
|
||||
|
||||
let [prevCardDetails, setPrevCardDetails] = useState(null) // STATE TO HOLD PREVIOUS CARD SELECTED
|
||||
let [prevCardDetails, setPrevCardDetails] = useState(null); // STATE TO HOLD PREVIOUS CARD SELECTED
|
||||
|
||||
let [payListCard, setPayListCard] = useState({loading: true, data:[]}) //USER PREVIOUS CARDS
|
||||
let [payListCard, setPayListCard] = useState({ loading: true, data: [] }); //USER PREVIOUS CARDS
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const indexOfFirstItem = Number(currentPage);
|
||||
const indexOfLastItem = Number(indexOfFirstItem)+Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
||||
const currentPreviousCards = payListCard?.data?.slice(indexOfFirstItem, indexOfLastItem);
|
||||
|
||||
const handlePagination = (e) => {
|
||||
handlePagingFunc(e,setCurrentPage)
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const indexOfFirstItem = Number(currentPage);
|
||||
const indexOfLastItem =
|
||||
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
||||
const currentPreviousCards = payListCard?.data?.slice(
|
||||
indexOfFirstItem,
|
||||
indexOfLastItem
|
||||
);
|
||||
|
||||
const handlePagination = (e) => {
|
||||
handlePagingFunc(e, setCurrentPage);
|
||||
};
|
||||
|
||||
// FUNCTION TO SUBMIT
|
||||
const handleSubmit = (values, helpers) => {
|
||||
props.setInputError("");
|
||||
if (!props.input || props.input == "0") {
|
||||
props.setInputError("Please Enter Amount");
|
||||
return setTimeout(() => {
|
||||
props.setInputError("");
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
// FUNCTION TO SUBMIT
|
||||
const handleSubmit = (values, helpers) => {
|
||||
props.setInputError('')
|
||||
if(!props.input || props.input == '0'){
|
||||
props.setInputError('Please Enter Amount')
|
||||
return setTimeout(()=>{props.setInputError('')}, 5000)
|
||||
}
|
||||
|
||||
if(isNaN(props.input)){
|
||||
props.setInputError('Amount must be a Number')
|
||||
return setTimeout(()=>{props.setInputError('')}, 5000)
|
||||
}
|
||||
if(tab == 'previous'){
|
||||
const stateData = {amount: Number(props.input), currency: 'dollars'}
|
||||
navigate('confirm-add-fund', {state: stateData}) // State will change later dummy for now
|
||||
}
|
||||
if(tab == 'new'){
|
||||
const stateData = {amount: Number(props.input), currency: 'dollars', ...values}
|
||||
navigate('confirm-add-fund', {state: stateData}) // State will change later dummy for now
|
||||
}
|
||||
props.setInput('')
|
||||
if (isNaN(props.input)) {
|
||||
props.setInputError("Amount must be a Number");
|
||||
return setTimeout(() => {
|
||||
props.setInputError("");
|
||||
}, 5000);
|
||||
}
|
||||
if (tab == "previous") {
|
||||
const stateData = { amount: Number(props.input), currency: "dollars" };
|
||||
navigate("confirm-add-fund", { state: stateData }); // State will change later dummy for now
|
||||
}
|
||||
if (tab == "new") {
|
||||
const stateData = {
|
||||
amount: Number(props.input),
|
||||
currency: "dollars",
|
||||
...values,
|
||||
};
|
||||
navigate("confirm-add-fund", { state: stateData }); // State will change later dummy for now
|
||||
}
|
||||
props.setInput("");
|
||||
};
|
||||
|
||||
useEffect(()=>{
|
||||
apiCall.payListCard().then(res => {
|
||||
setPayListCard({loading: false, data: res.data.result_list})
|
||||
}).catch(err => {
|
||||
console.log('PAYCARDLIST ERROR', err)
|
||||
setPayListCard({loading: false, data: []})
|
||||
})
|
||||
}, [])
|
||||
useEffect(() => {
|
||||
apiCall
|
||||
.payListCard()
|
||||
.then((res) => {
|
||||
setPayListCard({ loading: false, data: res.data.result_list });
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log("PAYCARDLIST ERROR", err);
|
||||
setPayListCard({ loading: false, data: [] });
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1 className='mb-2 text-xl font-bold text-dark-gray dark:text-white'>Payment Method</h1>
|
||||
<div className="w-full">
|
||||
{/* switch button */}
|
||||
<div className="my-1 flex items-center border-b border-slate-300">
|
||||
<button
|
||||
name="previous"
|
||||
onClick={(e) => setTab(e.target.name)}
|
||||
className={`p-2 text-lg font-bold text-slate-600 dark:text-white border ${
|
||||
tab == "previous" ? "border-sky-blue" : "border-slate-300"
|
||||
} tracking-wide transition duration-200`}
|
||||
>
|
||||
Previous Cards
|
||||
</button>
|
||||
<button
|
||||
name="new"
|
||||
onClick={(e) => setTab(e.target.name)}
|
||||
className={`p-2 text-lg font-bold text-slate-600 dark:text-white border ${
|
||||
tab == "new" ? "border-sky-blue" : "border-slate-300"
|
||||
} tracking-wide transition duration-200`}
|
||||
>
|
||||
Add New Card
|
||||
</button>
|
||||
</div>
|
||||
{/* END OF switch button */}
|
||||
<div className="w-full">
|
||||
{/* switch button */}
|
||||
<div className="my-1 flex items-center gap-2">
|
||||
<label
|
||||
onClick={() => setTab("previous")}
|
||||
htmlFor="previous"
|
||||
className="cursor-pointer flex items-center gap-1"
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
id="previous"
|
||||
name="card-option"
|
||||
checked={tab === "previous"}
|
||||
className={`p-2 text-lg font-bold text-slate-600 dark:text-white border pointer-events-none w-7 h-7 ${
|
||||
tab == "previous" ? "" : ""
|
||||
} tracking-wide transition duration-200`}
|
||||
/>
|
||||
Previous Cards
|
||||
</label>
|
||||
<label
|
||||
onClick={() => setTab("new")}
|
||||
htmlFor="new"
|
||||
className="cursor-pointer flex items-center gap-1"
|
||||
>
|
||||
<input
|
||||
id="new"
|
||||
type="radio"
|
||||
name="card-option"
|
||||
checked={tab === "new"}
|
||||
className={`p-2 text-lg font-bold text-slate-600 dark:text-white border pointer-events-none w-7 h-7 ${
|
||||
tab == "new" ? "" : ""
|
||||
} tracking-wide transition duration-200`}
|
||||
/>
|
||||
Add New Card
|
||||
</label>
|
||||
</div>
|
||||
{/* END OF switch button */}
|
||||
|
||||
{/* previous tab */}
|
||||
{tab == 'previous' ?
|
||||
<div className="p-4 previous-details w-full border min-h-[300px] flex flex-col justify-between items-center">
|
||||
{ payListCard.loading ?
|
||||
<LoadingSpinner size='10' color='sky-blue' />
|
||||
:
|
||||
payListCard?.data?.length ?
|
||||
<table className="my-3 w-full">
|
||||
<tbody>
|
||||
{currentPreviousCards.map((item, index)=>(
|
||||
<tr key={index} className={index != 0 && 'border-t-2'}>
|
||||
<td>
|
||||
<div className='my-2 flex items-center gap-5'>
|
||||
<input type="radio" className='w-8 h-8' name='card' value='value' />
|
||||
<div className='card-details'>
|
||||
<h1 className='text-lg font-bold text-dark-gray dark:text-white tracking-wide'>{item.description} Card</h1>
|
||||
<p className='text-base font-bold text-dark-gray dark:text-white tracking-wide'>Bank **************{item.digits}</p>
|
||||
<div className='w-full sm:flex items-center gap-5'>
|
||||
<p className='text-base font-bold text-dark-gray dark:text-white tracking-wide'>{item.added}</p>
|
||||
<p className='text-sm font-bold text-green-700 dark:text-white tracking-wide'>Verified</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
// onClick={handleSubmit}
|
||||
type="button"
|
||||
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
<span className="text-white">Manage</span>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
:
|
||||
<div className='w-full flex flex-col items-center'>
|
||||
<p className='my-5 text-base font-bold text-dark-gray dark:text-white tracking-wide'>No Previous Card Found!</p>
|
||||
<button
|
||||
onClick={()=> setTab('new')}
|
||||
type="button"
|
||||
className="my-5 px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
<span className="text-white">Add Card</span>
|
||||
</button>
|
||||
</div>
|
||||
{/* previous tab */}
|
||||
{tab == "previous" ? (
|
||||
<div className="p-4 previous-details w-full min-h-[177px] flex flex-col justify-between items-center">
|
||||
{payListCard.loading ? (
|
||||
<LoadingSpinner size="10" color="sky-blue" />
|
||||
) : payListCard?.data?.length ? (
|
||||
<select className="my-3 w-full rounded-full p-4 outline-none border-none">
|
||||
<option value="">Select a card</option>
|
||||
{currentPreviousCards.map((item, index) => (
|
||||
<option key={index} className={index != 0 && "border-t-2"}>
|
||||
<div className="my-2 flex items-center gap-5">
|
||||
{/* <input
|
||||
type="radio"
|
||||
className="w-8 h-8"
|
||||
name="card"
|
||||
value="value"
|
||||
/> */}
|
||||
<div className="card-details">
|
||||
<h1 className="text-lg font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
{item.description} Card
|
||||
</h1>
|
||||
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
Bank **************{item.digits}
|
||||
</p>
|
||||
{/* <div className="w-full sm:flex items-center gap-5">
|
||||
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
{item.added}
|
||||
</p>
|
||||
<p className="text-sm font-bold text-green-700 dark:text-white tracking-wide">
|
||||
Verified
|
||||
</p>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
{/* <td>
|
||||
<button
|
||||
// onClick={handleSubmit}
|
||||
type="button"
|
||||
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
<span className="text-white">Manage</span>
|
||||
</button>
|
||||
</td> */}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
) : (
|
||||
<div className="w-full flex flex-col items-center">
|
||||
<p className="my-5 text-base font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
No Previous Card Found!
|
||||
</p>
|
||||
<button
|
||||
onClick={() => setTab("new")}
|
||||
type="button"
|
||||
className="my-5 px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
<span className="text-white">Add Card</span>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{/* PAGINATION BUTTON */}
|
||||
{/* <div className="w-full">
|
||||
<PaginatedList
|
||||
onClick={handlePagination}
|
||||
prev={currentPage == 0 ? true : false}
|
||||
next={
|
||||
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
|
||||
payListCard?.data?.length
|
||||
? true
|
||||
: false
|
||||
}
|
||||
{/* PAGINATION BUTTON */}
|
||||
<div className='w-full'>
|
||||
<PaginatedList onClick={handlePagination} prev={currentPage == 0 ? true : false} next={currentPage+Number(process.env.REACT_APP_ITEM_PER_PAGE) >= payListCard?.data?.length ? true : false} data={payListCard?.data} start={indexOfFirstItem} stop={indexOfLastItem} />
|
||||
</div>
|
||||
{/* END OF PAGINATION BUTTON */}
|
||||
</div>
|
||||
:
|
||||
<div className="new-details w-full min-h-[300px] border-t">
|
||||
<div className="w-full flex flex-col justify-between">
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{(props) => {
|
||||
return (
|
||||
<Form>
|
||||
<div className="flex flex-col-reverse sm:flex-row">
|
||||
<div className="flex-1 sm:mr-10">
|
||||
<div className="fields w-full">
|
||||
{/* inputs starts here */}
|
||||
{/* Name */}
|
||||
<div className="field w-full my-6">
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
spanTag='*'
|
||||
label="Name on Card"
|
||||
type="text"
|
||||
name="name"
|
||||
placeholder="DUMMY NAME"
|
||||
value={props.values.name}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{props.errors.name && props.touched.name && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.name}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* CARD NUMBER */}
|
||||
<div className="field w-full mb-6">
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
spanTag='*'
|
||||
iconName='master-card visa-card atm-card'
|
||||
label="Card Number"
|
||||
type="text"
|
||||
name="cardNum"
|
||||
placeholder="Enter Card Number"
|
||||
value={props.values.cardNum}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{props.errors.cardNum && props.touched.cardNum && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.cardNum}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
{/* EXPIRE YEAR, YEAR AND CVV */}
|
||||
<div className="sm:grid gap-5 grid-cols-3 mb-6">
|
||||
<div className="field w-full mb-6 xl:mb-0 col-span-1">
|
||||
<div className="select-option">
|
||||
<div className={`flex items-center justify-between mb-2.5`}>
|
||||
<label
|
||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
|
||||
htmlFor='expiration'
|
||||
>Expiration Month <span className="text-red-700 text-sm tracking-wide">*</span></label>
|
||||
</div>
|
||||
<div
|
||||
className={`input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base`}
|
||||
>
|
||||
<select
|
||||
className={`input-field placeholder:text-base text-dark-gray w-full h-full tracking-wide dark:bg-[#11131F] bg-[#f5f8fa] focus:ring-0 focus:outline-none`}
|
||||
value={props.values.expirationMonth}
|
||||
onChange={props.handleChange}
|
||||
onBlur={props.handleBlur}
|
||||
name='expirationMonth'
|
||||
>
|
||||
<option value=''>Select...</option>
|
||||
{expireMonth?.length &&
|
||||
expireMonth.map((item, index) => (
|
||||
<option key={index} value={item.value}>{item.name}</option>
|
||||
))
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{props.errors.expirationMonth && props.touched.expirationMonth && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.expirationMonth}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="field w-full mb-6 xl:mb-0 col-span-1">
|
||||
<div className="select-option">
|
||||
<div className={`flex items-center justify-between mb-2.5`}>
|
||||
<label
|
||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
|
||||
htmlFor='expiration'
|
||||
>Expiration Year <span className="text-red-700 text-sm tracking-wide">*</span>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
className={`input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base`}
|
||||
>
|
||||
<select
|
||||
className={`input-field placeholder:text-base text-dark-gray w-full h-full tracking-wide dark:bg-[#11131F] bg-[#f5f8fa] focus:ring-0 focus:outline-none`}
|
||||
value={props.values.expirationYear}
|
||||
onChange={props.handleChange}
|
||||
onBlur={props.handleBlur}
|
||||
name='expirationYear'
|
||||
>
|
||||
<option value=''>Select...</option>
|
||||
{expireYear?.length &&
|
||||
expireYear.map((item, index) => (
|
||||
<option key={index} value={item}>{item}</option>
|
||||
))
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{props.errors.expirationYear && props.touched.expirationYear && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.expirationYear}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="field w-full col-span-1">
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
spanTag='*'
|
||||
iconName='atm-card'
|
||||
label="CVV"
|
||||
type="text"
|
||||
name="cvv"
|
||||
placeholder="CVV"
|
||||
value={props.values.cvv}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{props.errors.cvv && props.touched.cvv && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.cvv}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* Address */}
|
||||
<div className="field w-full my-6">
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
spanTag='*'
|
||||
label="Billing Address"
|
||||
type="text"
|
||||
name="address"
|
||||
placeholder="Billing Address"
|
||||
value={props.values.Address}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{props.errors.address && props.touched.address && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.address}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
{/* postal code and state */}
|
||||
<div className="sm:grid gap-5 grid-cols-3 mb-6">
|
||||
<div className="field w-full mb-6 xl:mb-0 col-span-1">
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
spanTag='*'
|
||||
label="Postal Code"
|
||||
type="text"
|
||||
name="code"
|
||||
placeholder="Postal Code"
|
||||
value={props.values.code}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{props.errors.code && props.touched.code && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.code}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="field w-full col-span-1">
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
spanTag='*'
|
||||
label="State"
|
||||
type="text"
|
||||
name="state"
|
||||
placeholder="State"
|
||||
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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
data={payListCard?.data}
|
||||
start={indexOfFirstItem}
|
||||
stop={indexOfLastItem}
|
||||
/>
|
||||
</div> */}
|
||||
{/* END OF PAGINATION BUTTON */}
|
||||
</div>
|
||||
) : (
|
||||
<div className="new-details w-full max-h-[19.063rem] overflow-y-scroll">
|
||||
<div className="w-full flex flex-col justify-between">
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{(props) => {
|
||||
return (
|
||||
<Form>
|
||||
<div className="flex flex-col-reverse sm:flex-row">
|
||||
<div className="flex-1 sm:mr-10">
|
||||
<div className="fields w-full">
|
||||
{/* inputs starts here */}
|
||||
{/* Name */}
|
||||
<div className="field w-full my-6">
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
spanTag="*"
|
||||
label="Name on Card"
|
||||
type="text"
|
||||
name="name"
|
||||
placeholder="DUMMY NAME"
|
||||
value={props.values.name}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{props.errors.name && props.touched.name && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.name}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* <div className="w-full">
|
||||
{/* CARD NUMBER */}
|
||||
<div className="field w-full mb-6">
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
spanTag="*"
|
||||
iconName="master-card visa-card atm-card"
|
||||
label="Card Number"
|
||||
type="text"
|
||||
name="cardNum"
|
||||
placeholder="Enter Card Number"
|
||||
value={props.values.cardNum}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{props.errors.cardNum &&
|
||||
props.touched.cardNum && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.cardNum}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
{/* EXPIRE YEAR, YEAR AND CVV */}
|
||||
<div className="sm:grid gap-5 grid-cols-3 mb-6">
|
||||
<div className="field w-full mb-6 xl:mb-0 col-span-1">
|
||||
<div className="select-option">
|
||||
<div
|
||||
className={`flex items-center justify-between mb-2.5`}
|
||||
>
|
||||
<label
|
||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
|
||||
htmlFor="expiration"
|
||||
>
|
||||
Expiration Month{" "}
|
||||
<span className="text-red-700 text-sm tracking-wide">
|
||||
*
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
className={`input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base`}
|
||||
>
|
||||
<select
|
||||
className={`input-field placeholder:text-base text-dark-gray w-full h-full tracking-wide dark:bg-[#11131F] bg-[#f5f8fa] focus:ring-0 focus:outline-none`}
|
||||
value={props.values.expirationMonth}
|
||||
onChange={props.handleChange}
|
||||
onBlur={props.handleBlur}
|
||||
name="expirationMonth"
|
||||
>
|
||||
<option value="">Select...</option>
|
||||
{expireMonth?.length &&
|
||||
expireMonth.map((item, index) => (
|
||||
<option
|
||||
key={index}
|
||||
value={item.value}
|
||||
>
|
||||
{item.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{props.errors.expirationMonth &&
|
||||
props.touched.expirationMonth && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.expirationMonth}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="field w-full mb-6 xl:mb-0 col-span-1">
|
||||
<div className="select-option">
|
||||
<div
|
||||
className={`flex items-center justify-between mb-2.5`}
|
||||
>
|
||||
<label
|
||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
|
||||
htmlFor="expiration"
|
||||
>
|
||||
Expiration Year{" "}
|
||||
<span className="text-red-700 text-sm tracking-wide">
|
||||
*
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
className={`input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base`}
|
||||
>
|
||||
<select
|
||||
className={`input-field placeholder:text-base text-dark-gray w-full h-full tracking-wide dark:bg-[#11131F] bg-[#f5f8fa] focus:ring-0 focus:outline-none`}
|
||||
value={props.values.expirationYear}
|
||||
onChange={props.handleChange}
|
||||
onBlur={props.handleBlur}
|
||||
name="expirationYear"
|
||||
>
|
||||
<option value="">Select...</option>
|
||||
{expireYear?.length &&
|
||||
expireYear.map((item, index) => (
|
||||
<option key={index} value={item}>
|
||||
{item}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{props.errors.expirationYear &&
|
||||
props.touched.expirationYear && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.expirationYear}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="field w-full col-span-1">
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
spanTag="*"
|
||||
iconName="atm-card"
|
||||
label="CVV"
|
||||
type="text"
|
||||
name="cvv"
|
||||
placeholder="CVV"
|
||||
value={props.values.cvv}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{props.errors.cvv && props.touched.cvv && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.cvv}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* Address */}
|
||||
<div className="field w-full my-6">
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
spanTag="*"
|
||||
label="Billing Address"
|
||||
type="text"
|
||||
name="address"
|
||||
placeholder="Billing Address"
|
||||
value={props.values.Address}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{props.errors.address &&
|
||||
props.touched.address && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.address}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
{/* postal code and state */}
|
||||
<div className="sm:grid gap-5 grid-cols-3 mb-6">
|
||||
<div className="field w-full mb-6 xl:mb-0 col-span-1">
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
spanTag="*"
|
||||
label="Postal Code"
|
||||
type="text"
|
||||
name="code"
|
||||
placeholder="Postal Code"
|
||||
value={props.values.code}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{props.errors.code && props.touched.code && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.code}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="field w-full col-span-1">
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
spanTag="*"
|
||||
label="State"
|
||||
type="text"
|
||||
name="state"
|
||||
placeholder="State"
|
||||
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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* <div className="w-full">
|
||||
{requestStatus.message != "" && (
|
||||
<p
|
||||
className={`text-center text-base ${
|
||||
@@ -431,50 +501,62 @@ function AddFundDollars(props) {
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
<div className='md:p-8 p-4 add-fund-btn flex justify-end items-center py-4'>
|
||||
<button
|
||||
type="submit"
|
||||
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
<span className="text-white">Continue</span>
|
||||
</button>
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
}}
|
||||
</Formik>
|
||||
</div>
|
||||
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4">
|
||||
<button
|
||||
type="submit"
|
||||
className="py-1 px-4 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
<span className="text-white">Continue</span>
|
||||
</button>
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
}}
|
||||
</Formik>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{tab == "previous" && (
|
||||
<div className="md:py-8 px-[38px] add-fund-btn flex justify-end items-center py-4">
|
||||
<button
|
||||
onClick={handleSubmit}
|
||||
type="button"
|
||||
className="px-4 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
<span className="text-white">Continue</span>
|
||||
</button>
|
||||
</div>
|
||||
{ tab == 'previous' &&
|
||||
<div className='md:p-8 p-4 add-fund-btn flex justify-end items-center py-4'>
|
||||
<button
|
||||
onClick={handleSubmit}
|
||||
type="button"
|
||||
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
<span className="text-white">Continue</span>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
)}
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default AddFundDollars
|
||||
|
||||
export default AddFundDollars;
|
||||
|
||||
// FORMS ARRAY OF EXPIRATION YEAR FOR CARD
|
||||
const expireYear = []
|
||||
let currentYear = new Date().getFullYear()
|
||||
for(let i=0; i<=6; i++){
|
||||
expireYear.push(currentYear + i)
|
||||
const expireYear = [];
|
||||
let currentYear = new Date().getFullYear();
|
||||
for (let i = 0; i <= 6; i++) {
|
||||
expireYear.push(currentYear + i);
|
||||
}
|
||||
|
||||
// FORMS ARRAY OF EXPIRATION MONTH FOR CARD
|
||||
let month = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
|
||||
const expireMonth = []
|
||||
for(let i=0; i<month.length; i++){
|
||||
expireMonth.push({name:month[i], value:i+1})
|
||||
}
|
||||
let month = [
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July",
|
||||
"August",
|
||||
"September",
|
||||
"October",
|
||||
"November",
|
||||
"December",
|
||||
];
|
||||
const expireMonth = [];
|
||||
for (let i = 0; i < month.length; i++) {
|
||||
expireMonth.push({ name: month[i], value: i + 1 });
|
||||
}
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
import React, { useState } from "react";
|
||||
import RecentActivityTable from "./WalletComponent/RecentActivityTable";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import InputCom from "../Helpers/Inputs/InputCom";
|
||||
|
||||
import AddFundDollars from "./AddFundDollars";
|
||||
|
||||
function AddFundPop({ _payment }) {
|
||||
const navigate = useNavigate();
|
||||
// const { currency } = useLocation()?.state; //GETS THE USER CURRENCY FOR ADD FUND
|
||||
|
||||
let { payment, currency } = _payment;
|
||||
|
||||
//STATE FOR CONTROLLED INPUT
|
||||
let [input, setInput] = useState("");
|
||||
|
||||
let [inputError, setInputError] = useState("");
|
||||
|
||||
// FUNCTION TO HANDLE INPUT CHANGE
|
||||
const handleChange = ({ target: { name, value } }) => {
|
||||
setInput(value);
|
||||
};
|
||||
|
||||
//FUNCTION TO HANDLE SUBMIT
|
||||
const handleSubmit = () => {
|
||||
setInputError("");
|
||||
if (!input || input == "0") {
|
||||
setInputError("Please Enter Amount");
|
||||
return setTimeout(() => {
|
||||
setInputError("");
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
if (isNaN(input)) {
|
||||
setInputError("Amount must be a Number");
|
||||
return setTimeout(() => {
|
||||
setInputError("");
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
const stateData = { amount: Number(input), currency: "naira" };
|
||||
navigate("confirm-add-fund", { state: stateData });
|
||||
|
||||
setInput("");
|
||||
};
|
||||
|
||||
console.log("walletItem details >>", payment, currency);
|
||||
|
||||
return (
|
||||
<div className="h-[36rem] w-full">
|
||||
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
|
||||
<div className="lg:w-2/2 w-full mb-10 lg:mb-0">
|
||||
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl">
|
||||
{/*<h2 className='md:p-8 p-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Add Credit with Account Deposit</h2>*/}
|
||||
{/*<hr />*/}
|
||||
<form className="md:p-8 p-4 add-fund-info">
|
||||
<div className="field w-full">
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
label={
|
||||
currency == "US Dollars" ? "Amount (USD)" : "Amount (Naira)"
|
||||
}
|
||||
type="text"
|
||||
name="amount"
|
||||
placeholder="0"
|
||||
value={input}
|
||||
inputHandler={handleChange}
|
||||
/>
|
||||
{inputError && (
|
||||
<p className="text-base text-red-500">{inputError}</p>
|
||||
)}
|
||||
</div>
|
||||
</form>
|
||||
{currency == "US Dollars" && (
|
||||
<h1 className="mb-2 text-xl font-bold text-dark-gray dark:text-white px-4">
|
||||
Payment Method
|
||||
</h1>
|
||||
)}
|
||||
<hr />
|
||||
|
||||
{/* SHOWS THIS IF USER CURRENCY IS DOLLARS */}
|
||||
{currency == "US Dollars" && (
|
||||
<div className="w-full md:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl">
|
||||
<AddFundDollars
|
||||
setInputError={setInputError}
|
||||
input={input}
|
||||
setInput={setInput}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* HIDES THIS BUTTON IF CURENCY IS NAIRA */}
|
||||
{currency != "US Dollars" && (
|
||||
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4">
|
||||
<button
|
||||
onClick={handleSubmit}
|
||||
type="button"
|
||||
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
<span className="text-white">Continue</span>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* HIDES THIS SECTION IF CURENCY IS NAIRA */}
|
||||
{currency != "US Dollars" &&
|
||||
// <div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
|
||||
// <div className="lg:w-2/2 w-full mb-10 lg:mb-0">
|
||||
// <div className="wallet w-full md:p-8 p-4 h-full min-h-[590px] bg-white dark:bg-dark-white 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>
|
||||
null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default AddFundPop;
|
||||
@@ -0,0 +1,81 @@
|
||||
import { useState } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
// import ModalCom from "../Helpers/ModalCom";
|
||||
import { Form, Formik } from "formik";
|
||||
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||
import usersService from "../../../services/UsersService";
|
||||
import Icons from "../../Helpers/Icons";
|
||||
import AddFund from "../AddFund";
|
||||
import ModalCom from "../../Helpers/ModalCom";
|
||||
import AddFundPop from "../AddFundPop";
|
||||
|
||||
const CreditPopup = ({ details, onClose, situation }) => {
|
||||
const { pathname, state } = useLocation();
|
||||
const [submitTask, setSubmitTask] = useState({
|
||||
loading: false,
|
||||
msg: "",
|
||||
state: "",
|
||||
});
|
||||
const [suggestedNextStep, setSuggestedNextStep] = useState("Send Task");
|
||||
|
||||
const switchNextStep = ({ target: value }) => {
|
||||
setSuggestedNextStep(value);
|
||||
};
|
||||
|
||||
const apiCall = new usersService();
|
||||
|
||||
const handleParentSuggestion = (values) => {
|
||||
if (suggestedNextStep == "Send Task") {
|
||||
let firstName = state?.firstname;
|
||||
let family_uid = state?.family_uid;
|
||||
// continuePopupData({ ...details, firstName, family_uid });
|
||||
}
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalCom
|
||||
action={onClose}
|
||||
situation={situation}
|
||||
className="assign-task-popup"
|
||||
>
|
||||
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
||||
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
Add Credit
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
className="text-[#374557] dark:text-red-500"
|
||||
onClick={onClose}
|
||||
>
|
||||
<svg
|
||||
width="36"
|
||||
height="36"
|
||||
viewBox="0 0 36 36"
|
||||
fill="none"
|
||||
className="fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z"
|
||||
fill=""
|
||||
fillOpacity="0.6"
|
||||
/>
|
||||
<path
|
||||
d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z"
|
||||
fill="#"
|
||||
fillOpacity="0.6"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div className="logout-modal-body w-full flex flex-col items-center">
|
||||
<AddFundPop _payment={details} />
|
||||
</div>
|
||||
</div>
|
||||
</ModalCom>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreditPopup;
|
||||
@@ -91,6 +91,7 @@ function TransferFund({ payment, wallet }) {
|
||||
|
||||
//FUNCTION TO HANDLE SUBMIT
|
||||
const handleSubmit = (values, helpers) => {
|
||||
if(!values?.amount && !values.recipientID) return
|
||||
setRequestStatus(true);
|
||||
let recipientDetails = recipients.data?.filter(
|
||||
(item) => item.recipient_id == values.recipientID
|
||||
@@ -302,6 +303,7 @@ function TransferFund({ payment, wallet }) {
|
||||
) : (
|
||||
<button
|
||||
type="submit"
|
||||
disabled={props.isSubmitting}
|
||||
className="text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md"
|
||||
>
|
||||
Continue
|
||||
|
||||
@@ -1,83 +1,177 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import {Routes, Route, Outlet, Navigate} from 'react-router-dom'
|
||||
import usersService from '../../services/UsersService'
|
||||
import React, {
|
||||
Suspense,
|
||||
lazy,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useReducer,
|
||||
} from "react";
|
||||
import { Routes, Route, Outlet, Navigate } from "react-router-dom";
|
||||
import usersService from "../../services/UsersService";
|
||||
import Layout from "../Partials/Layout";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
|
||||
import Layout from '../Partials/Layout'
|
||||
|
||||
import Balance from './Balance'
|
||||
import TransferFund from './TransferFund'
|
||||
import AddFund from './AddFund'
|
||||
import AddRecipient from './AddRecipient'
|
||||
import ConfirmTransfer from './ConfirmTransfer'
|
||||
import ConfirmAddFund from './ConfirmAddFund'
|
||||
const AddFund = lazy(() => import("./AddFund"));
|
||||
const ConfirmAddFund = lazy(() => import("./ConfirmAddFund"));
|
||||
const TransferFund = lazy(() => import("./TransferFund"));
|
||||
const WalletBox = lazy(() => import("./WalletBox"));
|
||||
const AddRecipient = lazy(() => import("./AddRecipient"));
|
||||
const ConfirmTransfer = lazy(() => import("./ConfirmTransfer"));
|
||||
|
||||
function Wallet() {
|
||||
return (
|
||||
<Layout>
|
||||
<Outlet />
|
||||
<Outlet />
|
||||
</Layout>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const initialState = {
|
||||
loading: true,
|
||||
data: [],
|
||||
error: false,
|
||||
};
|
||||
|
||||
// Currently learning better about useReducer, so I converted this since it seemed like something complex
|
||||
const reducer = (state, action) => {
|
||||
switch (action.type) {
|
||||
case "FETCH_SUCCESS":
|
||||
return {
|
||||
...state,
|
||||
loading: false,
|
||||
data: action.payload,
|
||||
};
|
||||
case "FETCH_ERROR":
|
||||
return {
|
||||
...state,
|
||||
loading: false,
|
||||
error: true,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
const WalletRoutes = () => {
|
||||
const apiCall = new usersService()
|
||||
const apiCall = useMemo(() => new usersService(), []);
|
||||
|
||||
let [walletList, setWalletList] = useState({ // FOR WALLET LIST
|
||||
loading: true,
|
||||
data: [],
|
||||
error: false
|
||||
})
|
||||
const [walletList, dispatchWalletList] = useReducer(reducer, initialState);
|
||||
const [paymentHistory, dispatchPaymentHistory] = useReducer(
|
||||
reducer,
|
||||
initialState
|
||||
);
|
||||
|
||||
let [paymentHistory, setPaymentHistory] = useState({ // FOR PAYMENT HISTORY
|
||||
loading: true,
|
||||
data: [],
|
||||
error: false
|
||||
})
|
||||
const getWalletList = useCallback(() => {
|
||||
apiCall
|
||||
.getUserWallets(null)
|
||||
.then((res) => {
|
||||
if (res.data.internal_return < 0) {
|
||||
dispatchWalletList({ type: "FETCH_SUCCESS", payload: [] });
|
||||
} else {
|
||||
dispatchWalletList({
|
||||
type: "FETCH_SUCCESS",
|
||||
payload: res.data.result_list,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
dispatchWalletList({ type: "FETCH_ERROR" });
|
||||
});
|
||||
}, [apiCall]);
|
||||
|
||||
//FUNCTION TO GET WALLET LIST
|
||||
const getWalletList = ()=>{
|
||||
apiCall.getUserWallets(null).then((res)=>{
|
||||
if(res.data.internal_return < 0){ // success but no data
|
||||
setWalletList(prev => ({...prev, loading: false}))
|
||||
return
|
||||
}
|
||||
setWalletList(prev => ({...prev, loading: false, data: res.data.result_list}))
|
||||
}).catch((error)=>{
|
||||
setWalletList(prev => ({...prev, loading: false, error: true}))
|
||||
})
|
||||
const getPaymentHistory = useCallback(() => {
|
||||
apiCall
|
||||
.getPaymentHx()
|
||||
.then((res) => {
|
||||
if (res.data.internal_return < 0) {
|
||||
dispatchPaymentHistory({ type: "FETCH_SUCCESS", payload: [] });
|
||||
} else {
|
||||
dispatchPaymentHistory({
|
||||
type: "FETCH_SUCCESS",
|
||||
payload: res.data.result_list,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
dispatchPaymentHistory({ type: "FETCH_ERROR" });
|
||||
});
|
||||
}, [apiCall]);
|
||||
|
||||
useEffect(() => {
|
||||
let isMounted = true;
|
||||
|
||||
if (isMounted) {
|
||||
getWalletList();
|
||||
getPaymentHistory();
|
||||
}
|
||||
|
||||
//FUNCTION TO GET PAYMENT HISTORY
|
||||
const getPaymentHistory = ()=>{
|
||||
apiCall.getPaymentHx().then((res)=>{
|
||||
if(res.data.internal_return < 0){ // success but no data
|
||||
setPaymentHistory(prev => ({...prev, loading: false}))
|
||||
return
|
||||
}
|
||||
setPaymentHistory(prev => ({...prev, loading: false, data: res.data.result_list}))
|
||||
}).catch((error)=>{
|
||||
setPaymentHistory(prev => ({...prev, loading: false, error: true}))
|
||||
})
|
||||
}
|
||||
return () => {
|
||||
isMounted = false;
|
||||
};
|
||||
}, [getWalletList, getPaymentHistory]);
|
||||
|
||||
useEffect(()=>{
|
||||
getWalletList()
|
||||
getPaymentHistory()
|
||||
}, [])
|
||||
return (
|
||||
<Routes>
|
||||
<Route element={<Wallet />}>
|
||||
<Route path='add-fund' element={<AddFund payment={paymentHistory} />} />
|
||||
<Route path='add-fund/confirm-add-fund' element={<ConfirmAddFund payment={paymentHistory} />} />
|
||||
<Route path='transfer-fund' element={<TransferFund payment={paymentHistory} wallet={walletList} />} />
|
||||
<Route index element={<Balance wallet={walletList} />} />
|
||||
<Route path='transfer-fund/add-recipient' element={<AddRecipient />} />
|
||||
<Route path='transfer-fund/confirm-transfer' element={<ConfirmTransfer payment={paymentHistory} wallet={walletList} />} />
|
||||
<Route path='*' element={<Navigate to='/' />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Routes>
|
||||
<Route
|
||||
element={
|
||||
<Suspense fallback={<LoadingSpinner size="16" color="sky-blue" />}>
|
||||
<Wallet />
|
||||
</Suspense>
|
||||
}
|
||||
>
|
||||
<Route
|
||||
path="add-fund"
|
||||
element={
|
||||
<Suspense fallback={<LoadingSpinner size="16" color="sky-blue" />}>
|
||||
<AddFund payment={paymentHistory} />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="add-fund/confirm-add-fund"
|
||||
element={
|
||||
<Suspense fallback={<LoadingSpinner size="16" color="sky-blue" />}>
|
||||
<ConfirmAddFund payment={paymentHistory} />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="transfer-fund"
|
||||
element={
|
||||
<Suspense fallback={<LoadingSpinner size="16" color="sky-blue" />}>
|
||||
<TransferFund payment={paymentHistory} wallet={walletList} />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
{/*<Route index element={<Balance wallet={walletList} />} />*/}
|
||||
<Route
|
||||
index
|
||||
element={
|
||||
<Suspense fallback={<LoadingSpinner size="16" color="sky-blue" />}>
|
||||
<WalletBox wallet={walletList} payment={paymentHistory} />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="transfer-fund/add-recipient"
|
||||
element={
|
||||
<Suspense fallback={<LoadingSpinner size="16" color="sky-blue" />}>
|
||||
<AddRecipient />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="transfer-fund/confirm-transfer"
|
||||
element={
|
||||
<Suspense fallback={<LoadingSpinner size="16" color="sky-blue" />}>
|
||||
<ConfirmTransfer payment={paymentHistory} wallet={walletList} />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
<Route path="*" element={<Navigate to="/" />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
);
|
||||
};
|
||||
|
||||
export default WalletRoutes
|
||||
export default WalletRoutes;
|
||||
|
||||
@@ -0,0 +1,266 @@
|
||||
import CurrencyStaticsSection from "./CurrencyStaticsSection";
|
||||
import CurrentBalanceWidget from "./CurrentBalanceWidget";
|
||||
import InvestmentSection from "./InvestmentSection";
|
||||
import RecentTransactionWidget from "./RecentTransactionWidget";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import WalletItemCard from "./WalletItemCard";
|
||||
|
||||
export default function WalletBox({ wallet, coupon, payment }) {
|
||||
return (
|
||||
<>
|
||||
<div className="my-wallet-wrapper w-full mb-10">
|
||||
<div className="main-wrapper w-full">
|
||||
<div className="balance-inquery w-full lg:h-[436px] lg:flex lg:space-x-11 mb-11">
|
||||
{wallet.loading ? (
|
||||
<div className="w-full h-full flex items-center justify-center">
|
||||
<LoadingSpinner size="16" color="sky-blue" />
|
||||
</div>
|
||||
) : wallet.data.length ? (
|
||||
wallet.data.map((item, index) => (
|
||||
<div className="lg:w-1/2 h-full mb-10 lg:mb-0">
|
||||
<WalletItemCard walletItem={item} payment={payment} />
|
||||
</div>
|
||||
))
|
||||
) : null}
|
||||
|
||||
{/*<div className="flex-1">*/}
|
||||
{/* <CurrentBalanceWidget />*/}
|
||||
{/*</div>*/}
|
||||
{/* <div className="flex-1">*/}
|
||||
{/* <div className="my-wallets w-full h-full bg-white dark:bg-dark-white rounded-lg p-6">*/}
|
||||
{/* <div className="mb-4">*/}
|
||||
{/* <h1 className="text-xl font-bold tracking-wide text-dark-gray dark:text-white">*/}
|
||||
{/* My Wallet*/}
|
||||
{/* </h1>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="content-area">*/}
|
||||
{/* <div className="flex justify-between items-center mb-6">*/}
|
||||
{/* <div className="flex space-x-5 items-center">*/}
|
||||
{/* <div className="account-name flex space-x-4 items-center">*/}
|
||||
{/* <div className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
|
||||
{/* <img src={bank1} alt="" />*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="name">*/}
|
||||
{/* <p className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">*/}
|
||||
{/* MetaMask*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="flex space-x-5 items-center">*/}
|
||||
{/* <div>*/}
|
||||
{/* <p className="text-xl font-bold text-dark-gray dark:text-white text-right mb-3">*/}
|
||||
{/* $734.79*/}
|
||||
{/* </p>*/}
|
||||
{/* <p className="text-sm text-thin-light-gray">*/}
|
||||
{/* New Add*/}
|
||||
{/* <span className="text-light-green ml-1">*/}
|
||||
{/* +324.75*/}
|
||||
{/* </span>*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div>*/}
|
||||
{/*<span className="dark:text-thin-light-gray text-[#374557]">*/}
|
||||
{/* <svg*/}
|
||||
{/* width="6"*/}
|
||||
{/* height="26"*/}
|
||||
{/* viewBox="0 0 6 26"*/}
|
||||
{/* fill="none"*/}
|
||||
{/* className="fill-current"*/}
|
||||
{/* xmlns="http://www.w3.org/2000/svg"*/}
|
||||
{/* >*/}
|
||||
{/* <circle cx="3" cy="3" r="3" fillOpacity="0.6" />*/}
|
||||
{/* <circle*/}
|
||||
{/* cx="3"*/}
|
||||
{/* cy="12.75"*/}
|
||||
{/* r="3"*/}
|
||||
{/* fillOpacity="0.6"*/}
|
||||
{/* />*/}
|
||||
{/* <circle*/}
|
||||
{/* cx="3"*/}
|
||||
{/* cy="22.5"*/}
|
||||
{/* r="3"*/}
|
||||
{/* fillOpacity="0.6"*/}
|
||||
{/* />*/}
|
||||
{/* </svg>*/}
|
||||
{/*</span>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="flex justify-between items-center mb-6">*/}
|
||||
{/* <div className="flex space-x-5 items-center">*/}
|
||||
{/* <div className="account-name flex space-x-4 items-center">*/}
|
||||
{/* <div className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
|
||||
{/* <img src={bank2} alt="" />*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="name">*/}
|
||||
{/* <p className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">*/}
|
||||
{/* Coinbase Wallet*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="flex space-x-5 items-center">*/}
|
||||
{/* <div>*/}
|
||||
{/* <p className="text-xl font-bold text-dark-gray dark:text-white text-right mb-3">*/}
|
||||
{/* $734.79*/}
|
||||
{/* </p>*/}
|
||||
{/* <p className="text-sm text-thin-light-gray">*/}
|
||||
{/* New Add*/}
|
||||
{/* <span className="text-light-green ml-1">*/}
|
||||
{/* +324.75*/}
|
||||
{/* </span>*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div>*/}
|
||||
{/*<span className="dark:text-thin-light-gray text-[#374557]">*/}
|
||||
{/* <svg*/}
|
||||
{/* width="6"*/}
|
||||
{/* height="26"*/}
|
||||
{/* viewBox="0 0 6 26"*/}
|
||||
{/* fill="none"*/}
|
||||
{/* className="fill-current"*/}
|
||||
{/* xmlns="http://www.w3.org/2000/svg"*/}
|
||||
{/* >*/}
|
||||
{/* <circle cx="3" cy="3" r="3" fillOpacity="0.6" />*/}
|
||||
{/* <circle*/}
|
||||
{/* cx="3"*/}
|
||||
{/* cy="12.75"*/}
|
||||
{/* r="3"*/}
|
||||
{/* fillOpacity="0.6"*/}
|
||||
{/* />*/}
|
||||
{/* <circle*/}
|
||||
{/* cx="3"*/}
|
||||
{/* cy="22.5"*/}
|
||||
{/* r="3"*/}
|
||||
{/* fillOpacity="0.6"*/}
|
||||
{/* />*/}
|
||||
{/* </svg>*/}
|
||||
{/*</span>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="flex justify-between items-center mb-6">*/}
|
||||
{/* <div className="flex space-x-5 items-center">*/}
|
||||
{/* <div className="account-name flex space-x-4 items-center">*/}
|
||||
{/* <div className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
|
||||
{/* <img src={bank3} alt="" />*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="name">*/}
|
||||
{/* <p className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">*/}
|
||||
{/* Bitski*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="flex space-x-5 items-center">*/}
|
||||
{/* <div>*/}
|
||||
{/* <p className="text-xl font-bold text-dark-gray dark:text-white text-right mb-3">*/}
|
||||
{/* $734.79*/}
|
||||
{/* </p>*/}
|
||||
{/* <p className="text-sm text-thin-light-gray">*/}
|
||||
{/* New Add*/}
|
||||
{/* <span className="text-light-green ml-1">*/}
|
||||
{/* +324.75*/}
|
||||
{/* </span>*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div>*/}
|
||||
{/*<span className="dark:text-thin-light-gray text-[#374557]">*/}
|
||||
{/* <svg*/}
|
||||
{/* width="6"*/}
|
||||
{/* height="26"*/}
|
||||
{/* viewBox="0 0 6 26"*/}
|
||||
{/* fill="none"*/}
|
||||
{/* className="fill-current"*/}
|
||||
{/* xmlns="http://www.w3.org/2000/svg"*/}
|
||||
{/* >*/}
|
||||
{/* <circle cx="3" cy="3" r="3" fillOpacity="0.6" />*/}
|
||||
{/* <circle*/}
|
||||
{/* cx="3"*/}
|
||||
{/* cy="12.75"*/}
|
||||
{/* r="3"*/}
|
||||
{/* fillOpacity="0.6"*/}
|
||||
{/* />*/}
|
||||
{/* <circle*/}
|
||||
{/* cx="3"*/}
|
||||
{/* cy="22.5"*/}
|
||||
{/* r="3"*/}
|
||||
{/* fillOpacity="0.6"*/}
|
||||
{/* />*/}
|
||||
{/* </svg>*/}
|
||||
{/*</span>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="flex justify-between items-center mb-6">*/}
|
||||
{/* <div className="flex space-x-5 items-center">*/}
|
||||
{/* <div className="account-name flex space-x-4 items-center">*/}
|
||||
{/* <div className="icon w-14 h-14 transition duration-300 ease-in-out rounded-full flex justify-center items-center bg-light-purple dark:bg-dark-light-purple ">*/}
|
||||
{/* <img src={bank4} alt="" />*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="name">*/}
|
||||
{/* <p className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">*/}
|
||||
{/* WalletConnect*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="flex space-x-5 items-center">*/}
|
||||
{/* <div>*/}
|
||||
{/* <p className="text-xl font-bold text-dark-gray dark:text-white text-right mb-3">*/}
|
||||
{/* $734.79*/}
|
||||
{/* </p>*/}
|
||||
{/* <p className="text-sm text-thin-light-gray">*/}
|
||||
{/* New Add*/}
|
||||
{/* <span className="text-light-green ml-1">*/}
|
||||
{/* +324.75*/}
|
||||
{/* </span>*/}
|
||||
{/* </p>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div>*/}
|
||||
{/*<span className="dark:text-thin-light-gray text-[#374557]">*/}
|
||||
{/* <svg*/}
|
||||
{/* width="6"*/}
|
||||
{/* height="26"*/}
|
||||
{/* viewBox="0 0 6 26"*/}
|
||||
{/* fill="none"*/}
|
||||
{/* className="fill-current"*/}
|
||||
{/* xmlns="http://www.w3.org/2000/svg"*/}
|
||||
{/* >*/}
|
||||
{/* <circle cx="3" cy="3" r="3" fillOpacity="0.6" />*/}
|
||||
{/* <circle*/}
|
||||
{/* cx="3"*/}
|
||||
{/* cy="12.75"*/}
|
||||
{/* r="3"*/}
|
||||
{/* fillOpacity="0.6"*/}
|
||||
{/* />*/}
|
||||
{/* <circle*/}
|
||||
{/* cx="3"*/}
|
||||
{/* cy="22.5"*/}
|
||||
{/* r="3"*/}
|
||||
{/* fillOpacity="0.6"*/}
|
||||
{/* />*/}
|
||||
{/* </svg>*/}
|
||||
{/*</span>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
</div>
|
||||
{/* flex space-x-11 */}
|
||||
{/*<div className="recent-and-investment grid lg:grid-cols-2 grid-cols-1 2xl:gap-[40px] xl:gap-7 gap-4 lg:h-[416px] w-full justify-between">*/}
|
||||
{/* <div className=" h-full">*/}
|
||||
{/* <RecentTransactionWidget />*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className=" h-full">*/}
|
||||
{/* <InvestmentSection />*/}
|
||||
{/* </div>*/}
|
||||
{/*</div>*/}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,66 +1,87 @@
|
||||
import React, {useState} from 'react'
|
||||
import React, { useState } from "react";
|
||||
|
||||
import PaginatedList from '../../Pagination/PaginatedList';
|
||||
import {handlePagingFunc} from '../../Pagination/HandlePagination';
|
||||
import PaginatedList from "../../Pagination/PaginatedList";
|
||||
import { handlePagingFunc } from "../../Pagination/HandlePagination";
|
||||
|
||||
function RecentActivityTable({payment}) {
|
||||
function RecentActivityTable({ payment }) {
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const indexOfFirstItem = Number(currentPage);
|
||||
const indexOfLastItem =
|
||||
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
||||
const currentActivity = payment?.data?.slice(
|
||||
indexOfFirstItem,
|
||||
indexOfLastItem
|
||||
);
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const indexOfFirstItem = Number(currentPage);
|
||||
const indexOfLastItem = Number(indexOfFirstItem)+Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
||||
const currentActivity = payment?.data?.slice(indexOfFirstItem, indexOfLastItem);
|
||||
|
||||
const handlePagination = (e) => {
|
||||
handlePagingFunc(e,setCurrentPage)
|
||||
}
|
||||
const handlePagination = (e) => {
|
||||
handlePagingFunc(e, setCurrentPage);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='flex flex-col justify-between min-h-[500px]'>
|
||||
<table className="wallet-activity w-full table-auto border-collapse text-left">
|
||||
<thead className='border-b-2'>
|
||||
<tr className='text-slate-600'>
|
||||
<div className="flex flex-col justify-between overflow-y-auto">
|
||||
<table className="wallet-activity w-full table-auto border-collapse text-left">
|
||||
<thead className="border-b-2">
|
||||
<tr className="text-slate-600">
|
||||
<th className="p-2">Date</th>
|
||||
<th className="p-4">Trx.</th>
|
||||
<th className="p-4">Trx.</th>
|
||||
<th className="p-2">Amnt./Fee</th>
|
||||
<th className="p-2">Status</th>
|
||||
</tr>
|
||||
</tr>
|
||||
</thead>
|
||||
{payment.data.length ?
|
||||
(
|
||||
<tbody>
|
||||
{payment?.data?.length > 0 ? (
|
||||
<tbody>
|
||||
{currentActivity.map((item, index) => (
|
||||
<tr key={index} className='text-slate-500'>
|
||||
<tr key={index} className="text-slate-500">
|
||||
<td className="p-2">{item.trx_date}</td>
|
||||
<td className="p-4" dangerouslySetInnerHTML={{__html:item.recipient}}></td>
|
||||
<td className="p-2">{item.amount}<br />{item.fee}</td>
|
||||
<td
|
||||
className="p-4"
|
||||
dangerouslySetInnerHTML={{ __html: item.recipient }}
|
||||
></td>
|
||||
<td className="p-2">
|
||||
{item.amount}
|
||||
<br />
|
||||
{item.fee}
|
||||
</td>
|
||||
<td className="p-2">{item.status}</td>
|
||||
</tr>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
)
|
||||
:
|
||||
payment.error ?
|
||||
(
|
||||
<tbody>
|
||||
<tr className='text-slate-500'>
|
||||
<td className="p-2" colSpan={4}>Opps! an error occurred. Please try again!</td>
|
||||
</tbody>
|
||||
) : payment?.error ? (
|
||||
<tbody>
|
||||
<tr className="text-slate-500">
|
||||
<td className="p-2" colSpan={4}>
|
||||
Opps! an error occurred. Please try again!
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
)
|
||||
:
|
||||
<tbody>
|
||||
<tr className='text-slate-500'>
|
||||
<td className="p-2" colSpan={4}>No Payment History Found!</td>
|
||||
</tbody>
|
||||
) : (
|
||||
<tbody>
|
||||
<tr className="text-slate-500">
|
||||
<td className="p-2" colSpan={4}>
|
||||
No Payment History Found!
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
}
|
||||
</table>
|
||||
</tbody>
|
||||
)}
|
||||
</table>
|
||||
|
||||
{/* PAGINATION BUTTON */}
|
||||
<PaginatedList onClick={handlePagination} prev={currentPage == 0 ? true : false} next={currentPage+Number(process.env.REACT_APP_ITEM_PER_PAGE) >= payment?.data?.length ? true : false} data={payment?.data} start={indexOfFirstItem} stop={indexOfLastItem} />
|
||||
{/* END OF PAGINATION BUTTON */}
|
||||
{/* PAGINATION BUTTON */}
|
||||
<PaginatedList
|
||||
onClick={handlePagination}
|
||||
prev={currentPage == 0 ? true : false}
|
||||
next={
|
||||
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
|
||||
payment?.data?.length
|
||||
? true
|
||||
: false
|
||||
}
|
||||
data={payment?.data}
|
||||
start={indexOfFirstItem}
|
||||
stop={indexOfLastItem}
|
||||
/>
|
||||
{/* END OF PAGINATION BUTTON */}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default RecentActivityTable
|
||||
export default RecentActivityTable;
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
import React, { useState } from "react";
|
||||
import background from "../../assets/images/bg-sky-blue.jpg"; //shape/balance-bg.svg";
|
||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useSelector } from "react-redux";
|
||||
import CreditPopup from "./Popup/CreditPopup";
|
||||
|
||||
export default function WalletItemCard({ walletItem, payment }) {
|
||||
// const [eth] = useState(90);
|
||||
// const [btc] = useState(85);
|
||||
// const [ltc] = useState(20);
|
||||
|
||||
const { userDetails } = useSelector((state) => state?.userDetails);
|
||||
let accountType = userDetails?.account_type == "FAMILY";
|
||||
|
||||
// Credit popup
|
||||
const [creditPopup, setCreditPopup] = useState({ show: false, data: {} });
|
||||
|
||||
const openPopUp = (value) => {
|
||||
setCreditPopup({
|
||||
show: true,
|
||||
data: { ...value },
|
||||
});
|
||||
};
|
||||
|
||||
const closePopUp = () => {
|
||||
setCreditPopup({ show: false, data: {} });
|
||||
};
|
||||
|
||||
console.log("walletItem >>", walletItem, payment);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={`current-balance-widget w-full h-full rounded-2xl overflow-hidden flex flex-col ${
|
||||
accountType ? "justify-start" : "justify-between"
|
||||
} px-8 py-9`}
|
||||
style={{
|
||||
background: `url(${background}) 0% 0% / cover no-repeat`,
|
||||
}}
|
||||
>
|
||||
<div className="wallet flex justify-between">
|
||||
<div className="w-[100px] h-[100px] rounded-full bg-[#485199] flex justify-center items-center">
|
||||
<div>
|
||||
<p className="text-26 font-bold text-white tracking-wide text-center">
|
||||
.
|
||||
</p>
|
||||
<p className="text-lg text-white tracking-wide text-center">
|
||||
{walletItem.code}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div className="balance">
|
||||
<p className="text-lg text-white opacity-[70%] tracking-wide mb-6">
|
||||
Current Balance
|
||||
</p>
|
||||
<p className="text-[44px] font-bold text-white tracking-wide leading-10 mb-2">
|
||||
{PriceFormatter(
|
||||
walletItem.amount * 0.01,
|
||||
walletItem.code,
|
||||
undefined,
|
||||
"text-[2rem]"
|
||||
)}
|
||||
</p>
|
||||
<p className="text-lg text-white tracking-wide">
|
||||
HOLDINGS :{" "}
|
||||
<span className="mt-1">
|
||||
{PriceFormatter(
|
||||
walletItem.escrow * 0.01,
|
||||
walletItem.code,
|
||||
undefined,
|
||||
"text-[2rem]"
|
||||
)}
|
||||
</span>
|
||||
{/*<span className="text-light-green">(11.5%)</span>*/}
|
||||
</p>
|
||||
</div>
|
||||
{!accountType && (
|
||||
<div className="counters flex space-x-16">
|
||||
<div>
|
||||
<Link
|
||||
to="transfer-fund"
|
||||
className={`${
|
||||
walletItem.action_type != "AC_AD_FD_ONLY" && "invisible"
|
||||
} px-2 py-1 flex items-center gap-2 user-balance cursor-pointer h-[40px] rounded-full relative bg-purple lg:text-xl text-lg font-bold text-white`}
|
||||
>
|
||||
Transfer
|
||||
</Link>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
// state={{ currency: walletItem.description }}
|
||||
className="px-2 py-1 flex items-center gap-2 user-balance cursor-pointer h-[40px] rounded-full bg-white lg:text-xl text-lg font-bold text-black group relative transition duration-300 stroke-black fill-white"
|
||||
onClick={() => {
|
||||
openPopUp({
|
||||
payment: payment,
|
||||
currency: walletItem?.description,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<span className="">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="38"
|
||||
height="38"
|
||||
viewBox="0 0 42 42"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M21 0C16.8466 0 12.7865 1.23163 9.33303 3.53914C5.8796 5.84665 3.18798 9.1264 1.59854 12.9636C0.00909901 16.8009 -0.406771 21.0233 0.403518 25.0969C1.21381 29.1705 3.21386 32.9123 6.15077 35.8492C9.08767 38.7861 12.8295 40.7862 16.9031 41.5965C20.9767 42.4068 25.1991 41.9909 29.0364 40.4015C32.8736 38.812 36.1534 36.1204 38.4609 32.667C40.7684 29.2135 42 25.1534 42 21C41.994 15.4323 39.7796 10.0944 35.8426 6.15741C31.9056 2.22045 26.5677 0.00602189 21 0ZM28 22.75H22.75V28C22.75 28.4641 22.5656 28.9092 22.2374 29.2374C21.9093 29.5656 21.4641 29.75 21 29.75C20.5359 29.75 20.0908 29.5656 19.7626 29.2374C19.4344 28.9092 19.25 28.4641 19.25 28V22.75H14C13.5359 22.75 13.0908 22.5656 12.7626 22.2374C12.4344 21.9092 12.25 21.4641 12.25 21C12.25 20.5359 12.4344 20.0907 12.7626 19.7626C13.0908 19.4344 13.5359 19.25 14 19.25H19.25V14C19.25 13.5359 19.4344 13.0908 19.7626 12.7626C20.0908 12.4344 20.5359 12.25 21 12.25C21.4641 12.25 21.9093 12.4344 22.2374 12.7626C22.5656 13.0908 22.75 13.5359 22.75 14V19.25H28C28.4641 19.25 28.9093 19.4344 29.2374 19.7626C29.5656 20.0907 29.75 20.5359 29.75 21C29.75 21.4641 29.5656 21.9092 29.2374 22.2374C28.9093 22.5656 28.4641 22.75 28 22.75Z"
|
||||
// fill="white"
|
||||
className="stroke-black fill-white"
|
||||
></path>
|
||||
</svg>
|
||||
</span>
|
||||
<span className="">Add Credit</span>
|
||||
<span className="absolute inset-0 w-full h-full transition-all duration-300 ease-out bg-gray-300 group-hover:bg-gray-400 opacity-0"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{creditPopup.show && (
|
||||
<CreditPopup
|
||||
details={creditPopup.data}
|
||||
onClose={closePopUp}
|
||||
situation={openPopUp}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
const PaginatedList = ({ onClick, prev, next, data, start, stop }) => {
|
||||
if (data.length > process.env.REACT_APP_ITEM_PER_PAGE) {
|
||||
if (data?.length > process.env.REACT_APP_ITEM_PER_PAGE) {
|
||||
return (
|
||||
<div className="p-3 flex justify-center items-center min-h-[70px] space-x-2 border-t-2">
|
||||
{/* Render pagination buttons */}
|
||||
{!prev && (
|
||||
<button
|
||||
className={`p-2 border ${
|
||||
prev ? "border-black dark:border-white dark:text-white" : "border-transparent dark:text-white"
|
||||
prev
|
||||
? "border-black dark:border-white dark:text-white"
|
||||
: "border-transparent dark:text-white"
|
||||
} btn-shine rounded-full h-11 w-11`}
|
||||
name="prev"
|
||||
onClick={onClick}
|
||||
@@ -15,7 +17,7 @@ const PaginatedList = ({ onClick, prev, next, data, start, stop }) => {
|
||||
</button>
|
||||
)}
|
||||
|
||||
{data.map((item, index) => {
|
||||
{data?.map((item, index) => {
|
||||
if (
|
||||
index % process.env.REACT_APP_ITEM_PER_PAGE == 0 &&
|
||||
index >= start &&
|
||||
@@ -26,7 +28,9 @@ const PaginatedList = ({ onClick, prev, next, data, start, stop }) => {
|
||||
key={index}
|
||||
value={index}
|
||||
className={`p-2 border ${
|
||||
index === start ? "border-black dark:border-white dark:text-white" : "border-transparent dark:text-white"
|
||||
index === start
|
||||
? "border-black dark:border-white dark:text-white"
|
||||
: "border-transparent dark:text-white"
|
||||
} btn-shine rounded-full h-11 w-11`}
|
||||
onClick={onClick}
|
||||
name="page_num"
|
||||
@@ -43,7 +47,9 @@ const PaginatedList = ({ onClick, prev, next, data, start, stop }) => {
|
||||
{!next && (
|
||||
<button
|
||||
className={`p-2 border ${
|
||||
next ? "border-black dark:border-white dark:text-white" : "border-transparent dark:text-white"
|
||||
next
|
||||
? "border-black dark:border-white dark:text-white"
|
||||
: "border-transparent dark:text-white"
|
||||
} btn-shine rounded-full h-11 w-11`}
|
||||
name="next"
|
||||
onClick={onClick}
|
||||
|
||||
@@ -11,6 +11,11 @@ import ReferralTable from "../MyWallet/WalletComponent/ReferralTable";
|
||||
const validationSchema = Yup.object().shape({
|
||||
ref_email: Yup.string()
|
||||
.email("Wrong email format")
|
||||
.matches(
|
||||
// /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/,
|
||||
/^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/,
|
||||
"Invalid email format"
|
||||
)
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(50, "Maximum 50 characters")
|
||||
.required("Email is required"),
|
||||
|
||||
@@ -14,6 +14,11 @@ import * as Yup from "yup";
|
||||
const validationSchema = Yup.object().shape({
|
||||
email: Yup.string()
|
||||
.email("Wrong email format")
|
||||
.matches(
|
||||
// /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/,
|
||||
/^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/,
|
||||
"Invalid email format"
|
||||
)
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(50, "Maximum 50 characters")
|
||||
.required("Email is required"),
|
||||
@@ -96,7 +101,7 @@ export default function PersonalInfoTab({
|
||||
// setRequestState({message: 'Profile update successfully', loading: false, status: true})
|
||||
toast.success("Update Successful");
|
||||
setTimeout(() => {
|
||||
navigate("/", { replace: true });
|
||||
// navigate("/", { replace: true });
|
||||
window.location.reload(true);
|
||||
}, 1000);
|
||||
})
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
font-family: "Product Sans";
|
||||
src: url("./assets/fonts/Product Sans Regular.ttf");
|
||||
}
|
||||
|
||||
.nft-main-container{
|
||||
max-width: 1200px;
|
||||
}
|
||||
/* Bold Weight */
|
||||
@font-face {
|
||||
font-family: "Product Sans";
|
||||
@@ -25,14 +27,17 @@
|
||||
.heroSilderTitle{
|
||||
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;
|
||||
font-family: sans; color: white;
|
||||
font-size: 42px;
|
||||
font-family: Circular, Helvetica Neue, Helvetica, Roboto, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.back-dark1{
|
||||
background-color: #193F5F;
|
||||
min-width: 280px !important;
|
||||
}
|
||||
.job-action{
|
||||
background-color: lightgoldenrodyellow;
|
||||
background-color: aliceblue;
|
||||
height: 100px;
|
||||
border-radius: 15px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.msg_box{
|
||||
@@ -46,13 +51,7 @@
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
.siderCardHeader{
|
||||
margin: 40px 40px 10px 40px;
|
||||
font-size: 24px;
|
||||
font-weight: bolder;
|
||||
}
|
||||
.siderCardDescription{
|
||||
margin: 10px 45px 10px 45px;
|
||||
background-color: aliceblue;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
|
||||
@@ -18,7 +18,9 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||
|
||||
const { jobListTable } = useSelector((state) => state.tableReload);
|
||||
|
||||
const { userDetails:{loggedIn} } = useSelector((state) => state?.userDetails); // CHECKS IF LOGGEDIN IS TRUE
|
||||
const { userDetails:{username, uid} } = useSelector((state) => state?.userDetails); // CHECKS IF USER Details are avaliable, to determine if user is active
|
||||
|
||||
let loggedIn = username && uid ? true : false // variable to determine if user is logged in
|
||||
|
||||
useEffect(() => {
|
||||
//Removing Data stored at localStorage after session expires
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import Axios from "axios";
|
||||
|
||||
class usersService {
|
||||
@@ -11,6 +10,10 @@ class usersService {
|
||||
return this.postAuxEnd("/createuser", reqData);
|
||||
}
|
||||
|
||||
CompleteOauthLogin(reqData) {
|
||||
localStorage.setItem("session_token", ``);
|
||||
return this.postAuxEnd("/authlogin", reqData);
|
||||
}
|
||||
CompleteSignUp(reqData) {
|
||||
localStorage.setItem("session_token", ``);
|
||||
return this.postAuxEnd("/completesignuplink", reqData);
|
||||
@@ -26,10 +29,22 @@ class usersService {
|
||||
};
|
||||
return this.postAuxEnd("/dashdata", postData);
|
||||
}
|
||||
|
||||
logInUser(reqData) {
|
||||
localStorage.setItem("session_token", ``);
|
||||
return this.postAuxEnd("/userlogin", reqData);
|
||||
}
|
||||
|
||||
authStart(reqData) {
|
||||
localStorage.setItem("session_token", ``);
|
||||
return this.postAuxEnd("/authstart", reqData);
|
||||
}
|
||||
|
||||
authLogin(reqData) {
|
||||
localStorage.setItem("session_token", ``);
|
||||
return this.postAuxEnd("/authlogin", reqData);
|
||||
}
|
||||
|
||||
marketJobData(reqData) {
|
||||
var postData = {
|
||||
uuid: localStorage.getItem("uuid"),
|
||||
@@ -838,6 +853,27 @@ class usersService {
|
||||
return this.postAuxEnd("/offerinterestlistmsg", postData);
|
||||
}
|
||||
|
||||
// TO ADD FAMILY
|
||||
addFamily(reqData) {
|
||||
var postData = {
|
||||
uid: localStorage.getItem("uid"),
|
||||
member_id: localStorage.getItem("member_id"),
|
||||
sessionid: localStorage.getItem("session_token"),
|
||||
...reqData,
|
||||
};
|
||||
return this.postAuxEnd("/familyadd", postData);
|
||||
}
|
||||
|
||||
familyListings(reqData) {
|
||||
var postData = {
|
||||
uid: localStorage.getItem("uid"),
|
||||
member_id: localStorage.getItem("member_id"),
|
||||
sessionid: localStorage.getItem("session_token"),
|
||||
...reqData,
|
||||
};
|
||||
return this.postAuxEnd("/familylist", postData);
|
||||
}
|
||||
|
||||
// FUNCTION TO ASSIGN TASK TO FAMILY MEMBER
|
||||
assignFamilyTask(reqData) {
|
||||
var postData = {
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import React from 'react'
|
||||
|
||||
import FbookRedirect from '../components/AuthPages/AuthRedirect/FbookRedirect'
|
||||
|
||||
function FacebookRedirect() {
|
||||
return (
|
||||
<>
|
||||
<FbookRedirect />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default FacebookRedirect
|
||||
@@ -1,9 +1,9 @@
|
||||
import FamilyAcc from "../components/FamilyAcc";
|
||||
|
||||
export default function FamilyAccPage() {
|
||||
return (
|
||||
<>
|
||||
<FamilyAcc />
|
||||
</>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<FamilyAcc />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import React from "react";
|
||||
// import MyWallet from "../components/MyWallet";
|
||||
import WalletRoutes from "../components/MyWallet/Wallet";
|
||||
|
||||
export default function MyWalletPage() {
|
||||
|
||||