Compare commits

..

80 Commits

Author SHA1 Message Date
victorAnumudu 24545baad5 wallet clean up 2023-07-13 10:27:03 +01:00
ameye d2166d9578 Merge branch 'icons-size' of WrenchBoard/Users-Wrench into master 2023-07-12 21:20:53 +00:00
victorAnumudu c4872f522b icon color and size changed 2023-07-12 21:31:09 +01:00
ameye 0aef8c5e1e Merge branch 'wallet-icons' of WrenchBoard/Users-Wrench into master 2023-07-12 19:27:48 +00:00
ameye 767b5c1b32 Merge branch 'wallet-dropdown-icons' of WrenchBoard/Users-Wrench into master 2023-07-12 19:27:43 +00:00
ameye 6fed51443d Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-12 19:27:33 +00:00
victorAnumudu 017ba7bd2f wallet icon added and wallet layout changed 2023-07-12 20:00:17 +01:00
victorAnumudu 86d876b013 wallet dropdown icons added 2023-07-12 19:09:04 +01:00
Ebube fcd8898439 . 2023-07-12 19:05:06 +01:00
Ebube 690f496807 Add New Card Layout 2023-07-12 19:01:27 +01:00
ameye f804e13b56 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-12 16:19:58 +00:00
Ebube 5e248bc108 Restored layout and tiny modifications 2023-07-12 17:14:13 +01:00
ameye 26647b088f Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-12 15:04:53 +00:00
Ebube ae8ada33f4 Increased font 2023-07-12 15:54:57 +01:00
Ebube c31dab92e7 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-12 15:51:27 +01:00
Ebube c16764269e Added name to Add new fund 2023-07-12 15:48:57 +01:00
CHIEFSOFT\ameye afe6a1afcb currencies 2023-07-12 10:32:57 -04:00
Ebube e98929627f Compi! 2023-07-12 15:20:39 +01:00
Ebube 3919a2bc4b Layout Readjusting 2023-07-12 15:12:50 +01:00
ameye 93e89f996c Merge branch 'my-facebook-ID' of WrenchBoard/Users-Wrench into master 2023-07-12 13:47:25 +00:00
victorAnumudu 7ede9883ba facebook redirect page 2023-07-12 14:22:51 +01:00
victorAnumudu 7edc7b08e5 added my default facebook client ID 2023-07-12 14:07:07 +01:00
Ebube 7990959e9f Passed values to confirm add fund 2023-07-12 10:08:26 +01:00
CHIEFSOFT\ameye 6ead632c79 facebook 2023-07-11 17:31:52 -04:00
ameye 9c575716cd Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-11 19:13:15 +00:00
CHIEFSOFT\ameye cc93d5980d facebook login added 2023-07-11 14:59:16 -04:00
Ebube e899e5eb2a Convert ConfirmAddFund to Popup 2023-07-11 19:47:04 +01:00
ameye c53ee2833f Merge branch 'apple-login-init' of WrenchBoard/Users-Wrench into master 2023-07-11 14:23:27 +00:00
victorAnumudu 9475961c2d apple login initialization 2023-07-11 15:15:58 +01:00
CHIEFSOFT\ameye 97ae9dd136 env update 2023-07-11 06:43:18 -04:00
ameye ded088c70f Merge branch 'facebook-login-init' of WrenchBoard/Users-Wrench into master 2023-07-11 09:01:06 +00:00
ameye 4dacee11e8 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-11 09:00:52 +00:00
victorAnumudu 960579384c facebook login initiated 2023-07-11 07:56:45 +01:00
Ebube bcca701a6b Family Account Items Icons 2023-07-11 03:30:47 +01:00
ameye 6c29f37a60 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-10 23:29:30 +00:00
Ebube cc22e1a458 Completed conversion to popup 2023-07-10 23:21:59 +01:00
ameye d274a5c56a Merge branch 'family-login-bug-fixed' of WrenchBoard/Users-Wrench into master 2023-07-10 20:13:15 +00:00
victorAnumudu dfe90fbdc2 family login fixed 2023-07-10 20:40:52 +01:00
ameye a2f3c95671 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-10 19:10:14 +00:00
Ebube 6daa4d6d43 Fixed the prop drill 2023-07-10 19:22:03 +01:00
Ebube 2e25b33110 Wallet modifications and Intro to Credit Popup 2023-07-10 17:47:39 +01:00
ameye a216ab1098 Merge branch 'login-payload' of WrenchBoard/Users-Wrench into master 2023-07-10 15:14:51 +00:00
victorAnumudu 8b01139b93 validated email on user login page 2023-07-10 15:45:38 +01:00
CHIEFSOFT\ameye 8511db6961 favicon 2023-07-10 10:42:47 -04:00
ameye 99c81fd4ee Merge branch 'profile-update' of WrenchBoard/Users-Wrench into master 2023-07-10 13:55:41 +00:00
victorAnumudu ef545c9714 validated email 2023-07-10 13:48:23 +01:00
ameye 029a7327a8 Merge branch 'google-login-fix' of WrenchBoard/Users-Wrench into master 2023-07-10 11:22:19 +00:00
victorAnumudu 5a5d933b24 google login fix 2023-07-10 12:18:43 +01:00
ameye 9f19c930b7 Merge branch 'suggested-task-page' of WrenchBoard/Users-Wrench into master 2023-07-10 08:46:47 +00:00
Ebube 84d7fabae7 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into suggested-task-page 2023-07-10 09:14:54 +01:00
Ebube b245f87556 Optimizations and underlying fixes done yesterday 2023-07-10 09:14:30 +01:00
CHIEFSOFT\ameye bed5303fa4 wallet 2023-07-09 20:42:00 -04:00
ameye a5af8ed722 Merge branch 'home-hero-min-height' of WrenchBoard/Users-Wrench into master 2023-07-09 23:26:57 +00:00
victorAnumudu ec97d118b2 AuthLayout added to redirect page 2023-07-09 23:55:35 +01:00
ameye 85213c31a1 Merge branch 'home-hero-min-height' of WrenchBoard/Users-Wrench into master 2023-07-09 22:55:28 +00:00
victorAnumudu f9b6c68f99 added min height to home page hero section 2023-07-09 23:34:39 +01:00
ameye 2a4b77c9a0 Merge branch 'home-page-hero-adjustment' of WrenchBoard/Users-Wrench into master 2023-07-09 22:28:43 +00:00
victorAnumudu 97aa5dba21 Merge 'master' into home-page-hero-adjustment 2023-07-09 23:19:30 +01:00
victorAnumudu 58a10ca6be home page hero section adjusted and google login success redirect implemented 2023-07-09 23:14:07 +01:00
CHIEFSOFT\ameye f3edf1d90b home banner 2023-07-09 17:57:05 -04:00
CHIEFSOFT\ameye 1f7b310b6f google login 2023-07-09 15:41:49 -04:00
ameye aecb06ca96 Merge branch 'verify-link' of WrenchBoard/Users-Wrench into master 2023-07-09 10:54:08 +00:00
CHIEFSOFT\ameye d89194f18e sty 2023-07-09 00:39:38 -04:00
CHIEFSOFT\ameye 03866d666b banner bg 2023-07-09 00:17:20 -04:00
CHIEFSOFT\ameye 4224be46bc banner issues 2023-07-08 23:19:23 -04:00
victorAnumudu 5dad00096a check for all necessary variables from API to determine verify link success 2023-07-09 03:42:01 +01:00
CHIEFSOFT\ameye 72da5c707a wallet adjust 2023-07-08 21:44:45 -04:00
tolik 625928e34b Message fix 2023-07-09 09:31:45 +08:00
tolik 6fd92600b4 Specify login channel 2023-07-09 08:47:00 +08:00
tolik 133f500849 Specify login channel 2023-07-09 08:19:17 +08:00
tolik b1f1b34924 API calls for authstart and authlogin; Call authlogin with code and redirect URI to do the token exchange on the backend 2023-07-09 07:58:31 +08:00
ameye e80c3528db Merge branch 'suggested-task-page' of WrenchBoard/Users-Wrench into master 2023-07-08 22:38:35 +00:00
Ebube 3eb6960cc7 Fixed underlying bugs 2023-07-08 23:27:10 +01:00
Ebube eb01e35c75 Continue Suggested Task 2023-07-08 22:52:36 +01:00
ameye 0cc70d66b3 Merge branch 'family-account-icon' of WrenchBoard/Users-Wrench into master 2023-07-08 18:34:33 +00:00
victorAnumudu 7111e81f11 added family account login input icon 2023-07-08 19:22:00 +01:00
CHIEFSOFT\ameye 1c64771dcd Job action area 2023-07-08 11:27:21 -04:00
CHIEFSOFT\ameye ac1a4f895a container max with for 4k screens 2023-07-08 11:05:20 -04:00
CHIEFSOFT\ameye 22f5bd01d2 log in error 2023-07-08 10:53:58 -04:00
ameye 467528835a Merge branch 'valid-email-pattern' of WrenchBoard/Users-Wrench into master 2023-07-08 14:36:10 +00:00
69 changed files with 2500 additions and 1072 deletions
+22 -3
View File
@@ -42,9 +42,28 @@ REACT_APP_GOOGLE_CLIENT_SECRET=aozK_2G8UjaCmLgPPkv9abIm
REACT_APP_GOOGLE_CLIENT_SCOPE="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
REACT_APP_GOOGLE_REDIRECT_URL=http://localhost:9082/login/auth/
REACT_APP_FACEBOOK_CLIENT_ID=390204307987009
REACT_APP_FACEBOOK_CLIENT_SECRET=19f778e312f2ab96d147bacb612910c2
REACT_APP_FACEBOOK_CLIENT_SCOPE="email, public_profile"
#Real Account
REACT_APP_FACEBOOK_CLIENT_ID2=390204307987009
REACT_APP_FACEBOOK_CLIENT_SECRET2=19f778e312f2ab96d147bacb612910c2
#developenet Account
REACT_APP_FACEBOOK_CLIENT_ID=677857427521030
REACT_APP_FACEBOOK_CLIENT_SECRET=4801375f22072d8a75f64483fdd89829
#my Account
REACT_APP_FACEBOOK_CLIENT_ID3=1598725580610908
REACT_APP_FACEBOOK_CLIENT_SCOPE="email,public_profile"
REACT_APP_FACEBOOK_REDIRECT_URL="http://localhost:9082/login/auth/flogin"
REACT_APP_APPLE_CLIENT_ID='com.wrenchboard.users.client'
REACT_APP_APPLE_REDIRECT_URL='http://localhost:9082/login/auth/apple'
# /* 'client_id' => */ 'com.wrenchboard.users.client',
# /* 'client_secret' => */ 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6Ilc1V1RXQzlEVEoifQ.eyJpc3MiOiJKUjM2M0ZFWThSIiwiaWF0IjoxNjU0MDgzODQxLCJleHAiOjE2NTkyNjc4NDEsImF1ZCI6Imh0dHBzOi8vYXBwbGVpZC5hcHBsZS5jb20iLCJzdWIiOiJjb20ud3JlbmNoYm9hcmQudXNlcnMuY2xpZW50In0.TIPMwjS2MgSysqEuw3yu1nrOcrH-6omzerDhx0CadjWn2yCO8wZhQiAlhIFs7F-WPektIJ6h-2BT62yGrILiTA',
# /* 'redirect_uri' => */ site_url('login/auth/apple')
REACT_APP_MAX_FILE_SIZE=1000000
REACT_APP_TOTAL_NUM_FILE=4
+5
View File
@@ -40,6 +40,11 @@ REACT_APP_GOOGLE_CLIENT_SECRET=aozK_2G8UjaCmLgPPkv9abIm
REACT_APP_GOOGLE_CLIENT_SCOPE="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
REACT_APP_GOOGLE_REDIRECT_URL=https://users.wrenchboard.com/login/auth/
REACT_APP_FACEBOOK_CLIENT_ID2=390204307987009
REACT_APP_FACEBOOK_CLIENT_SECRET2=19f778e312f2ab96d147bacb612910c2
REACT_APP_FACEBOOK_CLIENT_SCOPE="email,public_profile"
REACT_APP_FACEBOOK_REDIRECT_URL="https://users.wrenchboard.com/login/auth/flogin"
DISABLE_ESLINT_PLUGIN=true
REACT_APP_MAX_FILE_SIZE=1000000
+1
View File
@@ -17,6 +17,7 @@
"flutterwave-react-v3": "^1.3.0",
"formik": "^2.2.9",
"react": "^18.2.0",
"react-apple-login": "^1.1.6",
"react-chartjs-2": "^4.1.0",
"react-countup": "^6.2.0",
"react-dom": "^18.2.0",
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 713 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 15 KiB

+4
View File
@@ -47,6 +47,8 @@ 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";
import AppleRedirectPage from "./views/AppleRedirectPage";
export default function Routers() {
return (
@@ -56,6 +58,8 @@ 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="/login/auth/apple" element={<AppleRedirectPage />} />
<Route
exact
path="/forgot-password"
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" id="naira"><path fill="#fff" d="M24,5A19,19,0,1,0,43,24,19,19,0,0,0,24,5Zm7,20a1,1,0,0,1,0,2H29v3A1.94,1.94,0,0,1,27.45,32a2,2,0,0,1-2.26-1.08L20,17.05l0,14a1,1,0,0,1-2,0V27H16a1,1,0,0,1,0-2h2V22H16a1,1,0,0,1,0-2h2V17a1.94,1.94,0,0,1,1.55-1.92,2,2,0,0,1,2.26,1.08L27,30,27,16a1,1,0,0,1,2,0v4h2a1,1,0,0,1,0,2H29v3Z" class="color3b3c3d svgShape"></path><path fill="#e3e3e3" d="M24,48A24,24,0,1,1,48,24,24,24,0,0,1,24,48ZM24,2A22,22,0,1,0,46,24,22,22,0,0,0,24,2Z" class="color3b3c3d svgShape"></path></svg>

After

Width:  |  Height:  |  Size: 563 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16.933 16.933" id="Coin"><path d="M8.452 281.052a7.487 7.487 0 0 0-7.483 7.482 7.485 7.485 0 0 0 7.483 7.48 7.484 7.484 0 0 0 7.48-7.48 7.486 7.486 0 0 0-7.48-7.482zm0 1.232a6.253 6.253 0 0 1 6.248 6.25 6.25 6.25 0 0 1-6.248 6.248c-3.449 0-6.25-2.8-6.25-6.248a6.254 6.254 0 0 1 6.25-6.25zm0 .53a5.717 5.717 0 0 0-5.721 5.72 5.715 5.715 0 0 0 5.72 5.719 5.713 5.713 0 0 0 5.72-5.719 5.715 5.715 0 0 0-5.72-5.72zm-.004 2.011a.265.265 0 0 1 .267.268v.596H9.74a.265.265 0 1 1 0 .529H8.715v2.05h.17c.856 0 1.551.697 1.551 1.555s-.696 1.555-1.549 1.555h-.172v.596a.265.265 0 1 1-.529 0v-.596H7.161a.265.265 0 1 1 0-.53h1.025v-2.05h-.172a1.552 1.552 0 0 1-1.547-1.555c0-.858.694-1.554 1.547-1.554h.172v-.596a.265.265 0 0 1 .262-.268zm-.434 1.393a1.01 1.01 0 0 0-1.018 1.025 1.01 1.01 0 0 0 1.018 1.026h.172v-2.051zm.701 2.58v2.05h.172c.57 0 1.02-.448 1.02-1.025s-.449-1.025-1.022-1.025z" color="#e3e3e3" font-family="sans-serif" font-weight="400" overflow="visible" transform="translate(0 -280.067)" style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;shape-padding:0;isolation:auto;mix-blend-mode:normal" fill="#fff" class="color000000 svgShape"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+1
View File
@@ -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

+3
View File
@@ -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 AppleRedirect() {
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: "APPLE",
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 AppleRedirect
@@ -0,0 +1,65 @@
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);
/*
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: "FACEBOOK",
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
+83 -35
View File
@@ -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,40 @@ 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=${process.env.REACT_APP_APPLE_CLIENT_ID}&redirect_uri=https%3A%2F%2Fwork.wrenchboard.com%2Flogin%2Fauth%2Fapple&state=4b2c4456b7&scope=name+email`}
link={`https://appleid.apple.com/auth/authorize?response_type=code&response_mode=form_post&client_id=${process.env.REACT_APP_APPLE_CLIENT_ID}&redirect_uri=${process.env.REACT_APP_APPLE_REDIRECT_URL}&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=${process.env.REACT_APP_FACEBOOK_CLIENT_ID}&redirect_uri=${process.env.REACT_APP_FACEBOOK_REDIRECT_URL}&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 +365,7 @@ export default function Login() {
label="Username"
name="email"
type="email"
iconName="message"
iconName="family-id"
/>
</div>
@@ -346,9 +378,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 +435,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 +454,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 +480,9 @@ const BrandBtn = ({ link, imgSrc, brand, onClick }) => {
Continue with {brand}
</span>
</button>
)
}
</div>
);
)
};
+10 -4
View File
@@ -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">
+64 -36
View File
@@ -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 (
@@ -200,18 +214,28 @@ export default function FamilyManageTabs({
browseProfileImg={browseProfileImg}
accountDetails={accountDetails}
/>
<div className="mt-4 flex justify-center items-center gap-2">
<div className="mt-4 flex justify-start 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' />
<p className="mt-2 text-lg text-sky-blue">Account</p>
onClick={() => tabHandler("Account")}
className="family-icon p-2 border-2 border-sky-blue rounded-2xl flex flex-col justify-between items-center max-w-[65px] w-full"
>
<img
src={localImgLoad("images/icons/account.svg")}
className="max-w-[30px] w-full"
alt="Settings-Icon"
/>
<p className="text-lg text-sky-blue">Acc.</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' />
<p className="mt-2 text-lg text-sky-blue">Profile</p>
onClick={() => tabHandler("Profile")}
className="family-icon p-2 border-2 border-sky-blue rounded-2xl flex flex-col justify-between items-center max-w-[65px] w-full"
>
<img
src={localImgLoad("images/icons/profile.svg")}
className="max-w-[30px] w-full"
alt="Settings-Icon"
/>
<p className="text-lg text-sky-blue">Profile</p>
</button>
</div>
</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 -4
View File
@@ -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);
+49 -49
View File
@@ -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"
/>
+139 -109
View File
@@ -1,122 +1,152 @@
import { useState } from "react";
import { handlePagingFunc, PaginatedList } from "../../Pagination";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import { memo, useMemo, useState } from "react";
import SuggestTask from "../../FamilyPopup/SuggestTask";
import { PaginatedList, handlePagingFunc } from "../../Pagination";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import AssignTaskPopout from "../FamilyPopout/AssignTaskPopout";
const FamilyWaitlist = ({ familyData, className, accountDetails, loader }) => {
const [popUp, setPopUp] = useState({ show: false, data: {} });
const FamilyWaitlist = memo(
({ familyData, className, accountDetails, loader }) => {
const [popUp, setPopUp] = useState({ show: false, data: {} });
const [continueTaskPopup, setContinueTaskPopup] = useState({
show: false,
data: {},
});
const filteredFamilyData = useMemo(
() =>
familyData?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
),
[familyData, accountDetails]
);
let filteredFamilyData = familyData?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
);
const [currentPage, setCurrentPage] = useState(0);
const itemsPerPage = Number(process.env.REACT_APP_ITEM_PER_PAGE);
const indexOfFirstItem = currentPage;
const indexOfLastItem = currentPage + itemsPerPage;
const currentTask = useMemo(
() => filteredFamilyData?.slice(indexOfFirstItem, indexOfLastItem),
[filteredFamilyData, indexOfFirstItem, indexOfLastItem]
);
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 handlePagination = (e) => handlePagingFunc(e, setCurrentPage);
const handlePagination = (e) => handlePagingFunc(e, setCurrentPage);
const openPopUp = (value) => {
setPopUp({ show: true, data: { ...value } });
};
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 ${
className || ""
}`}
>
{loader ? (
<div className="w-full h-full flex justify-center items-center lg:min-h-[470px]">
<LoadingSpinner size={16} color="sky-blue" />
</div>
) : (
<>
{filteredFamilyData && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{currentTask.map((value) => {
const addedDate = value?.added.split(" ")[0];
const selectedImage = require(`../../../assets/images/family/${
value?.banner || "default.jpg"
}`);
return (
<tr
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
key={value.uid}
>
<td className="py-4">
<div className="w-full flex justify-between items-center">
<div className="account-name flex space-x-4 items-center">
<div className="icon w-14 h-14 flex justify-center items-center">
<img
src={selectedImage}
alt="task_img"
className="w-full object-cover"
/>
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 ${
className || ""
}`}
>
{loader ? (
<div className="w-full h-full flex justify-center items-center lg:min-h-[470px]">
<LoadingSpinner size={16} color="sky-blue" />
</div>
) : (
<>
{filteredFamilyData && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{currentTask.map((value) => {
const addedDate = value?.added.split(" ")[0];
const selectedImage = require(`../../../assets/images/family/${
value?.banner || "default.jpg"
}`);
return (
<tr
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
key={value.uid}
>
<td className="py-4">
<div className="w-full flex justify-between items-center">
<div className="account-name flex space-x-4 items-center">
<div className="icon w-14 h-14 flex justify-center items-center">
<img
src={selectedImage}
alt="task_img"
className="w-full object-cover"
/>
</div>
<div className="">
<p className="text-xl font-bold text-dark-gray dark:text-white mb-2 capitalize line-clamp-1">
{value.title}
</p>
<p className="text-sm text-thin-light-gray font-medium">
{value.description}
</p>
</div>
</div>
<div className="">
<p className="text-xl font-bold text-dark-gray dark:text-white mb-2 capitalize line-clamp-1">
{value.title}
<div className="px-2 flex flex-col items-center justify-center">
<p className="text-sm font-bold text-dark-gray dark:text-white">
{addedDate}
</p>
<p className="text-sm text-thin-light-gray font-medium">
{value.description}
<p className="text-xs py-1.5 w-[70px] cursor-default tracking-wide rounded-full bg-gold text-white flex justify-center items-center">
{value.status_text}
</p>
</div>
</div>
<div className="px-2 flex flex-col items-center justify-center">
<p className="text-sm font-bold text-dark-gray dark:text-white">
{addedDate}
</p>
<p className="text-xs py-1.5 w-[70px] cursor-default tracking-wide rounded-full bg-gold text-white flex justify-center items-center">
{value.status_text}
</p>
</div>
</div>
</td>
<td className="text-right py-4 px-2">
<button
onClick={() =>
setPopUp({
show: true,
data: { ...value, selectedImage },
})
}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
</button>
</td>
</tr>
);
})}
</tbody>
</table>
<PaginatedList
onClick={handlePagination}
prev={currentPage === 0}
next={currentPage + itemsPerPage >= filteredFamilyData?.length}
data={filteredFamilyData}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
</div>
)}
</>
)}
{popUp.show && (
<SuggestTask
details={popUp.data}
onClose={() => {
setPopUp({ show: false, data: {} });
}}
situation={popUp.show}
/>
)}
</div>
);
};
</td>
<td className="text-right py-4 px-2">
<button
onClick={() => openPopUp(value)}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
</button>
</td>
</tr>
);
})}
</tbody>
</table>
<PaginatedList
onClick={handlePagination}
prev={currentPage === 0}
next={
currentPage + itemsPerPage >= filteredFamilyData?.length
}
data={filteredFamilyData}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
</div>
)}
</>
)}
{popUp.show && (
<SuggestTask
details={popUp.data}
onClose={closePopUp}
continuePopupData={openContinueTaskPopup}
situation={popUp.show}
/>
)}
{continueTaskPopup.show && (
<AssignTaskPopout
details={continueTaskPopup.data}
action={closeContinueTaskPopup}
situation={continueTaskPopup.show}
/>
)}
</div>
);
}
);
export default FamilyWaitlist;
@@ -8,13 +8,13 @@ export default function ProfileInfo({
accountDetails,
}) {
return (
<div className="flex flex-col items-center gap-6">
<div className="flex flex-col items-center gap-4">
<div className="flex justify-center">
<div className="w-full relative">
<img
src={profileImg}
alt=""
className="sm:w-[198px] sm:h-[198px] w-[120px] h-[120px] rounded-full overflow-hidden object-cover"
className="sm:w-[180px] sm:h-[180px] w-[120px] h-[120px] rounded-full overflow-hidden object-cover"
/>
<input
ref={profileImgInput}
+46 -39
View File
@@ -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 && (
+56 -36
View File
@@ -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>
+5 -1
View File
@@ -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" />
): (
""
)}
</>
@@ -97,7 +97,7 @@ export default function InputCom({
dir={direction}
/>
{iconName && (
<div className="absolute right-6 bottom-[10px] z-10 flex gap-2">
<div className="absolute right-6 bottom-3 z-10 flex gap-2">
{iconName.split(" ").map((item, index) => (
<Icons key={index} name={item} />
))}
@@ -105,7 +105,7 @@ export default function InputCom({
)}
{passIcon && (
<div
className="absolute right-6 bottom-[10px] z-10"
className="absolute right-6 bottom-3 z-10"
onClick={onClick}
>
<Icons name={passIcon} />
+3 -2
View File
@@ -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>
);
-6
View File
@@ -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 (
+5 -5
View File
@@ -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)
+1 -1
View File
@@ -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>
+2 -2
View File
@@ -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">
+525 -410
View File
@@ -1,402 +1,494 @@
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 LoadingSpinner from "../Spinners/LoadingSpinner";
import { Form, Formik } from "formik";
import { useSelector } from "react-redux";
import * as Yup from "yup";
import Icons from "../Helpers/Icons";
const validationSchema = Yup.object().shape({
name: Yup.string()
.min(3, "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
const [loader, setLoader] = useState(false);
const { userDetails } = useSelector((state) => state?.userDetails);
let { firstname, lastname } = userDetails;
let [prevCardDetails, setPrevCardDetails] = useState({}); // STATE TO HOLD PREVIOUS CARD SELECTED
let [payListCards, setPayListCards] = useState({ loading: true, data: [] }); //USER PREVIOUS CARDS
// const [payListCard, setPayListCard] = useState({ data: "" }); //USER PAYLIST
let [prevCardDetails, setPrevCardDetails] = useState(null) // STATE TO HOLD PREVIOUS CARD SELECTED
const handleInputChange = (event) => {
const { name, value } = event.target;
setPrevCardDetails((prevState) => ({
...prevState,
[name]: value,
}));
};
let [payListCard, setPayListCard] = useState({loading: true, data:[]}) //USER PREVIOUS CARDS
const indexOfFirstItem = 0;
const indexOfLastItem =
indexOfFirstItem + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentPreviousCards = payListCards?.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 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") {
if (!prevCardDetails) {
// return setTimeout(() => {
// props.setInputError("");
// }, 5000);
return;
}
setLoader(true);
const stateData = {
amount: Number(props.input),
currency: props.currency,
card: prevCardDetails["payment-card"],
};
useEffect(()=>{
apiCall.payListCard().then(res => {
setPayListCard({loading: false, data: res.data.result_list})
}).catch(err => {
console.log('PAYCARDLIST ERROR', err)
setPayListCard({loading: false, data: []})
})
}, [])
setTimeout(() => {
props.setConfirmCredit({ show: true, data: stateData });
setLoader(false);
}, 1500);
// navigate("confirm-add-fund", { state: stateData }); // State will change later dummy for now
}
if (tab == "new") {
const stateData = {
amount: Number(props.input),
currency: props.currency,
values,
};
// navigate("confirm-add-fund", { state: stateData }); // State will change later dummy for now
}
};
useEffect(() => {
apiCall
.payListCard()
.then((res) => {
setPayListCards({ loading: false, data: res.data.result_list });
})
.catch((err) => {
console.log("PAYCARDLIST ERROR", err);
setPayListCards({ 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`}
>
<div className="w-full">
{/* switch button */}
<div className="flex">
<form className="add-fund-info flex items-center gap-3">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{props.currency == "US Dollars" && "Payment Method"}
</h1>
<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
</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`}
>
</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>
</form>
</div>
<hr />
{/* END OF switch button */}
{/* previous tab */}
{tab == "previous" ? (
<div className="p-4 previous-details w-full min-h-[16rem] flex flex-col justify-between items-center">
{payListCards.loading ? (
<LoadingSpinner size="10" color="sky-blue" />
) : payListCards?.data?.length ? (
<select
className="my-3 w-full rounded-full p-4 outline-none border-none text-base text-black dark:text-gray-100 bg-[#dce2e6] dark:bg-[#5e6278] border"
value={prevCardDetails["payment-card"]?.card_uid}
id="payment-card"
name="payment-card"
onChange={handleInputChange}
>
<option value="">Select a card</option>
{currentPreviousCards.map((item, index) => (
<option
key={index}
className={index != 0 && "border-t-2"}
value={JSON.stringify(item)}
>
<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>
</div>
</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>
{/* 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>
}
{/* 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>
</div>
)}
</div>
) : (
<div className="new-details w-full max-h-[23rem] 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="flex items-center field w-full my-2 flex-[0.4] gap-3">
<label className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1">
Name:
</label>
<p className="input-label text-[#181c32] dark:text-white text-[16px] leading-[20.9625px] font-semibold flex items-center gap-1">{`${firstname} ${lastname}`}</p>
</div>
{/* <div className="w-full">
{/* <div className="field w-full my-2 flex-[0.4]">
<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="flex items-center flex-1 gap-3 my-3">
{/* CARD NUMBER */}
<div className="field w-full flex-[0.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 */}
<div className="sm:grid gap-5 grid-cols-2 flex-[0.4]">
<div className="field w-full mb-6 xl:mb-0 col-span-1">
<div className="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"
>
Exp 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-[#fafafa] focus:ring-0 focus:outline-none`}
value={props.values.expirationMonth}
onChange={props.handleChange}
onBlur={props.handleBlur}
name="expirationMonth"
>
<option
value=""
className="text-dark-gray"
>
Month
</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"
>
Exp 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-[#fafafa] focus:ring-0 focus:outline-none`}
value={props.values.expirationYear}
onChange={props.handleChange}
onBlur={props.handleBlur}
name="expirationYear"
>
<option value="" className="text-dark-gray">Year</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>
</div>
<div className="flex items-center flex-1 gap-3 my-3">
{/* Address AND CVV */}
<div className="field w-full col-span-1 flex-[0.4]">
<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 className="field w-full flex-[0.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>
</div>
{/* postal code and state */}
<div className="sm:grid gap-5 grid-cols-3 my-3">
<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 +523,73 @@ 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:px-8 md:pt-4 px-4 pt-2 add-fund-btn flex justify-end items-center">
<button
type="submit"
className="py-1 px-4 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white gap-1"
>
<span className="text-white">Continue</span>{" "}
<Icons name="chevron-right" />
</button>
</div>
</Form>
);
}}
</Formik>
</div>
}
</div>
)}
</div>
{tab == "previous" && (
<div className="md:py-8 px-[38px] add-fund-btn flex justify-end items-center gap-4 py-4">
<button
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center border-gradient text-base rounded-full"
onClick={props.onClose}
>
Cancel
</button>
<button
onClick={handleSubmit}
type="button"
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
{loader ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<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 });
}
+139
View File
@@ -0,0 +1,139 @@
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import InputCom from "../Helpers/Inputs/InputCom";
import AddFundDollars from "./AddFundDollars";
function AddFundPop({ _payment, input, setInput, onClose, setConfirmCredit }) {
const navigate = useNavigate();
// const { currency } = useLocation()?.state; //GETS THE USER CURRENCY FOR ADD FUND
let { payment, currency } = _payment;
//STATE FOR CONTROLLED INPUT
let [inputError, setInputError] = useState("");
// FUNCTION TO HANDLE INPUT CHANGE
const handleChange = ({ target: { name, value } }) => {
setInput(value);
};
//FUNCTION TO HANDLE SUBMIT
const handleSubmit = (e) => {
e.preventDefault();
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);
}
if (input) return;
// setTimeout(
// () =>
// setConfirmCredit({
// show: true,
// data: { amount: Number(input), currency: "naira" },
// }),
// 1500
// );
// const stateData = { amount: Number(input), currency: "naira" };
// navigate("confirm-add-fund", { state: stateData });
// setInput("");
};
return (
<div className="h-[33rem] 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:px-8 md:pt-4 px-4 pt-2 add-fund-info flex items-center gap-[2.1rem]">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{currency == "US Dollars" ? "Amount (USD)" : "Amount (Naira)"}
</h1>
<div className="field w-full max-w-[250px]">
<InputCom
fieldClass="px-6"
type="text"
name="amount"
placeholder="0"
value={input}
inputHandler={handleChange}
/>
<p className="text-base text-red-500 h-5">
{inputError && inputError}
</p>
</div>
</form>
{/* SHOWS THIS IF USER CURRENCY IS DOLLARS */}
{currency == "US Dollars" && (
<div className="w-full md:px-8 md:pt-4 px-4 pt-2 bg-white dark:bg-dark-white rounded-2xl">
<AddFundDollars
setInputError={setInputError}
input={input}
setInput={setInput}
currency={currency}
onClose={onClose}
setConfirmCredit={setConfirmCredit}
/>
</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 gap-4">
<button
className="px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
onClick={onClose}
>
Cancel
</button>
<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;
+99 -49
View File
@@ -1,16 +1,14 @@
import React, { useEffect, useState } from "react";
import React, { useState } from "react";
import { useSelector } from "react-redux";
import { useLocation, useNavigate } from "react-router-dom";
import { useNavigate } from "react-router-dom";
import { toast } from "react-toastify";
import InputCom from "../Helpers/Inputs/InputCom";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import RecentActivityTable from "./WalletComponent/RecentActivityTable";
import usersService from "../../services/UsersService";
import { FlutterWaveButton, closePaymentModal } from "flutterwave-react-v3";
function ConfirmAddFund({ payment }) {
function ConfirmAddFund({ confirmCredit, onClose, walletItem }) {
let { userDetails } = useSelector((state) => state.userDetails); // TO GET LOGGEDIN USER DETAILS
let [pageLoading, setPageLoading] = useState(true);
@@ -24,12 +22,10 @@ function ConfirmAddFund({ payment }) {
const apiURL = new usersService();
const navigate = useNavigate();
let { state } = useLocation();
//FUNCTION TO HANDLE SUBMIT
const onSuccessPayment = () => {
setRequestStatus({ message: "", loading: true, status: false });
let reqData = { amount: state?.account, currency: "NGN" };
let reqData = { amount: confirmCredit?.data?.account, currency: "NGN" };
apiURL
.startTopUp(reqData)
.then((res) => {
@@ -66,7 +62,7 @@ function ConfirmAddFund({ payment }) {
const config = {
public_key: process.env.REACT_APP_FLUTTERWAVE_APIKEY,
tx_ref: Date.now(),
amount: state?.amount,
amount: confirmCredit?.data?.amount,
currency: "NGN",
payment_options: "card,mobilemoney,ussd",
customer: {
@@ -91,73 +87,127 @@ function ConfirmAddFund({ payment }) {
onClose: () => {},
};
useEffect(() => {
// what happens if not state redirect user
if (!state) {
navigate("/my-wallet/add-fund", { replace: true });
} else {
setPageLoading(false);
}
}, []);
// useEffect(() => {
// // what happens if not data redirect user
// if (!data) {
// navigate("/my-wallet/add-fund", { replace: true });
// } else {
// setPageLoading(false);
// }
// }, []);
let __confirmCard = JSON.parse(confirmCredit?.data.card);
const ThePaymentText = ({ value }) => (
<div className="my-2 flex items-center gap-5">
<div className="card-details flex items-center gap-3">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{value.description} Card
</h1>
<p className="text-base font-bold text-dark-gray dark:text-white tracking-wide">
Bank **************{value.digits}
</p>
</div>
</div>
);
return (
<div className="content-wrapper w-full">
{pageLoading ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<div className="w-full mb-10">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl shadow">
<h2 className="md:p-8 p-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
<div className="content-wrapper w-full h-[32rem]">
<div className="w-full mb-10">
<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">
Confirm Add Fund To Account
</h2>
<hr />
<div className="px-4 md:px-8 py-4 add-fund-info">
<div className="field w-full mb-3">
<hr /> */}
<div className="px-4 md:p-8 py-4 add-fund-info">
<div className="field w-full mb-3 min-h-[45px]">
{confirmCredit?.show ? (
<div className="flex flex-col gap-4">
<div className="flex items-center gap-4">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{confirmCredit?.data?.currency == "naira"
? "Amount (Naira):"
: "Amount (Dollars):"}
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{`${walletItem?.symbol} ${
Number(confirmCredit?.data?.amount).toLocaleString() ||
""
}`}
</span>
</div>
<div className="flex items-center gap-4">
{/* <h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1"> */}
<label
htmlFor="payment"
className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1"
>
{confirmCredit?.data?.currency && "Payment Method:"}
</label>
<span className="text-[#181c32] dark:text-white ">
{__confirmCard && (
<ThePaymentText value={__confirmCard} />
)}
</span>
</div>
</div>
) : (
<InputCom
fieldClass="px-6"
label={state.currency == 'naira' ? "Amount (Naira):" : "Amount (Dollars):"}
label={
confirmCredit?.data?.currency == "naira"
? "Amount (Naira):"
: "Amount (Dollars):"
}
type="text"
name="amount"
value={state.amount || ""}
value={confirmCredit?.data?.amount || ""}
disable={true}
/>
</div>
)}
</div>
<hr />
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4">
{
state.currency == 'naira' ?
<FlutterWaveButton
{...fwConfig}
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
/>
:
<button
</div>
{/* <h1 className="mb-2 text-xl font-bold text-dark-gray dark:text-white px-4 h-5">
{confirmCredit?.data?.currency && "Payment Method"}
</h1> */}
{/* <hr /> */}
<div className="min-h-[220px]"></div>
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4 gap-4">
<button
className="px-4 h-11 flex justify-center items-center border-gradient text-base rounded-full"
onClick={onClose}
>
Cancel
</button>
{confirmCredit?.data?.currency == "naira" ? (
<FlutterWaveButton
{...fwConfig}
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
onClick={()=>console.log('WORKING')}
/>
) : (
<button
className="px-4 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
onClick={() => console.log("WORKING")}
>
Continue
</button>
}
</div>
)}
</div>
</div>
)}
</div>
<div className="w-full mb-10">
<div className="wallet w-full md:p-8 p-4 h-full min-h-[600px] bg-white dark:bg-dark-white rounded-2xl shadow">
{/* <div className="w-full mb-10">
<div className="wallet w-full md:p-8 p-4 h-full 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> */}
<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> */}
</div>
);
}
@@ -0,0 +1,112 @@
import { useState } from "react";
import { useLocation } from "react-router-dom";
import usersService from "../../../services/UsersService";
import ModalCom from "../../Helpers/ModalCom";
import AddFundPop from "../AddFundPop";
import ConfirmAddFund from "../ConfirmAddFund";
const CreditPopup = ({ details, onClose, situation, walletItem }) => {
const { pathname, state } = useLocation();
const [submitTask, setSubmitTask] = useState({
loading: false,
msg: "",
state: "",
});
const [suggestedNextStep, setSuggestedNextStep] = useState("Send Task");
let [input, setInput] = useState("");
const [confirmCredit, setConfirmCredit] = useState({
show: false,
data: {},
});
// const openConfirmCredit = (value) => {
// setConfirmCredit({ show: true, data: { ...value } });
// };
// const closeConfirmCredit = () => {
// setConfirmCredit({ show: false, data: {} });
// };
// const handleConfirmCredit = useMemo((input) => {
// if (input) {
// setConfirmCredit(true);
// } else setConfirmCredit(false);
// }, []);
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();
};
console.log("prop drills >> ", state);
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">
{!confirmCredit.show ? "Add Credit" : "Confirm Credit Add"}
</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">
{confirmCredit.show ? (
<ConfirmAddFund
confirmCredit={confirmCredit}
walletItem={walletItem}
onClose={onClose}
/>
) : (
<AddFundPop
_payment={details}
input={input}
setInput={setInput}
onClose={onClose}
confirmCredit={confirmCredit}
setConfirmCredit={setConfirmCredit}
/>
)}
</div>
</div>
</ModalCom>
);
};
export default CreditPopup;
+2
View File
@@ -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
+160 -66
View File
@@ -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;
+49
View File
@@ -0,0 +1,49 @@
import React from 'react'
import { Link } from 'react-router-dom';
function WalletAction({walletItem, payment, openPopUp}) {
return (
<div className="counters flex justify-between gap-2">
<div className='w-1/2 flex justify-center items-center'>
<Link
to="transfer-fund"
className={`${
walletItem.code != "NAIRA" && "invisible"
} px-4 h-10 flex justify-center items-center btn-gradient text-base rounded-full text-white`}
>
Spend
</Link>
</div>
<div className='w-1/2 flex justify-center items-center'>
<button
className='px-4 h-10 flex justify-center items-center btn-gradient text-base rounded-full text-white'
onClick={() => {
openPopUp({
payment: payment,
currency: walletItem?.description,
});
}}
>
{/* <span className="">
<svg
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>
</button>
</div>
</div>
)
}
export default WalletAction
+266
View File
@@ -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: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;
+30 -24
View File
@@ -1,11 +1,12 @@
import { Link, useLocation, useNavigate } from "react-router-dom";
import Icons from "../Helpers/Icons";
import bank1 from "../../assets/images/bank-1.png";
import bank2 from "../../assets/images/bank-2.png";
import bank3 from "../../assets/images/bank-3.png";
import bank4 from "../../assets/images/bank-4.png";
// import bank1 from "../../assets/images/bank-1.png";
// import bank2 from "../../assets/images/bank-2.png";
// import bank3 from "../../assets/images/bank-3.png";
// import bank4 from "../../assets/images/bank-4.png";
import Accordion from "../Helpers/Accordion";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import localImgLoad from "../../lib/localImgLoad";
export default function WalletHeader(props) {
// debugger;
@@ -41,30 +42,35 @@ export default function WalletHeader(props) {
<ul>
{props.myWalletList &&
props.myWalletList?.result_list?.length > 0 &&
props.myWalletList.result_list.map((value, index) => (
<li
key={index}
className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple"
>
<div className="sm:flex justify-between items-center">
<div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">
<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="" />
props.myWalletList.result_list.map((value, index) =>
{
let image = value.code ? `${value.code.toLocaleLowerCase()}.svg` : 'default.png'
return(
<li
key={index}
className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple"
>
<div className="sm:flex justify-between items-center">
<div className="account-name flex space-x-4 items-center mb-2 sm:mb-0">
<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={localImgLoad(`images/currency/${image}`)} className="w-14 h-14" alt="" />
</div>
<div className="name">
<p className="text-base text-dark-gray dark:text-white font-medium">
{value.description}
</p>
</div>
</div>
<div className="name">
<p className="text-base text-dark-gray dark:text-white font-medium">
{value.description}
<div>
<p className="eth text-xl font-bold text-purple">
{PriceFormatter(value.amount * 0.01, value.code)}
</p>
</div>
</div>
<div>
<p className="eth text-xl font-bold text-purple">
{PriceFormatter(value.amount * 0.01, value.code)}
</p>
</div>
</div>
</li>
))}
</li>
)
}
)}
{/*<li className="content-item py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple">*/}
{/* <div className="sm:flex justify-between items-center">*/}
+120
View File
@@ -0,0 +1,120 @@
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";
import localImgLoad from "../../lib/localImgLoad";
import WalletAction from "./WalletAction";
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);
let image = walletItem.code ? `${walletItem.code.toLocaleLowerCase()}.svg` : 'default.png' // HOLDS THE VALUE NAME PROPERTY FOR IMAGE ICON
return (
<>
<div
className={`current-balance-widget w-full h-full rounded-2xl overflow-hidden flex flex-col gap-2 px-8 py-9`}
style={{
background: `url(${background}) 0% 0% / cover no-repeat`,
}}
>
<div className="wallet xxs:flex justify-around items-start gap-3">
<div className="min-w-[100px] min-h-[100px] max-w-[100px] max-h-[100px] rounded-full bg-[#e3e3e3] flex justify-center items-center">
<img src={localImgLoad(`images/currency/${image}`)} className="w-full h-full" alt="curreny-icon" />
</div>
<div className="balance w-full">
<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="xxs:-ml-5 mt-10 text-lg text-white tracking-wide flex justify-start items-center gap-2">
HOLDINGS :{" "}
<span className="mt-1">
{PriceFormatter(
walletItem.escrow * 0.01,
walletItem.code,
undefined,
"text-[2rem]"
)}
</span>
</p>
</div>
</div>
{/* <div className="flex justify-center items-center">
<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>
</p>
</div>
</div> */}
{/* for white underline */}
<div className="my-2 w-full h-[1px] bg-white"></div>
{!accountType ? (
<WalletAction walletItem={walletItem} payment={payment} openPopUp={openPopUp} />
)
:
null
}
</div>
{creditPopup.show && (
<CreditPopup
details={creditPopup.data}
walletItem={walletItem}
onClose={closePopUp}
situation={openPopUp}
/>
)}
</>
);
}
+11 -5
View File
@@ -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);
})
+9 -10
View File
@@ -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;
+3 -1
View File
@@ -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
+37 -1
View File
@@ -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 = {
+13
View File
@@ -0,0 +1,13 @@
import React from 'react'
import AppleRedirect from '../components/AuthPages/AuthRedirect/AppleRedirect'
function AppleRedirectPage() {
return (
<>
<AppleRedirect />
</>
)
}
export default AppleRedirectPage
+13
View File
@@ -0,0 +1,13 @@
import React from 'react'
import FbookRedirect from '../components/AuthPages/AuthRedirect/FbookRedirect'
function FacebookRedirect() {
return (
<>
<FbookRedirect />
</>
)
}
export default FacebookRedirect
+5 -5
View File
@@ -1,9 +1,9 @@
import FamilyAcc from "../components/FamilyAcc";
export default function FamilyAccPage() {
return (
<>
<FamilyAcc />
</>
);
return (
<>
<FamilyAcc />
</>
);
}
-2
View File
@@ -1,5 +1,3 @@
import React from "react";
// import MyWallet from "../components/MyWallet";
import WalletRoutes from "../components/MyWallet/Wallet";
export default function MyWalletPage() {
+3
View File
@@ -20,6 +20,9 @@ module.exports = {
'sky-blue': '#3a8fc3',
'alice-blue': '#f0f8ff'
},
screens:{
xxs: '400px'
}
},
},
plugins: [require("@tailwindcss/line-clamp")],