Compare commits

...

71 Commits

Author SHA1 Message Date
victorAnumudu a50b9f0026 force page to reload after successful transaction 2023-05-04 12:09:18 +01:00
victorAnumudu fb4939946e loadprofile loop bug fixed 2023-05-03 23:49:56 +01:00
Olu Amey 1d18d8e6ac flutter wave added 2023-05-03 16:29:22 -04:00
ameye 81aff85dae Merge branch 'payment_test' of WrenchBoard/Users-Wrench into master 2023-05-03 15:22:27 +00:00
victorAnumudu 145b77dcf7 flutterwave payment integration 2023-05-03 02:40:47 +01:00
ameye fabf07f2d1 Merge branch 'authroute_bug_fix' of WrenchBoard/Users-Wrench into master 2023-05-02 11:17:15 +00:00
victorAnumudu adca9029ae made loading profile to load only when user login status is false 2023-05-02 09:02:09 +01:00
ameye 6ce51b5a7e Merge branch 'referral_page_validation' of WrenchBoard/Users-Wrench into master 2023-05-01 20:19:27 +00:00
victorAnumudu 032f0cabd8 made session expire checker 300000ms 2023-05-01 20:10:48 +01:00
victorAnumudu 230d49d49e referral page validation 2023-05-01 19:50:39 +01:00
ameye 32275ba40e Merge branch 'login-dash-test' of WrenchBoard/Users-Wrench into master 2023-05-01 11:41:46 +00:00
Ebube ddce27c65a Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into login-dash-test 2023-05-01 12:36:27 +01:00
Ebube 87d1615b73 added header 2023-05-01 12:33:27 +01:00
Ebube 9ef2084956 login dash 2023-05-01 12:21:35 +01:00
ameye 15e6ed3264 Merge branch 'transfer_page_bug' of WrenchBoard/Users-Wrench into master 2023-05-01 10:50:51 +00:00
victorAnumudu 804a9cf692 removed props.handleBlur from amount input box in transfer page 2023-05-01 11:46:39 +01:00
tolik b911f65535 Fix & conversion rules 2023-05-01 04:59:04 +08:00
tolik ebedcdafcf Fix 2023-05-01 04:50:05 +08:00
DESKTOP-GBA0BK8\Admin ddfbba02e4 Sie 2023-04-28 22:11:56 -04:00
DESKTOP-GBA0BK8\Admin 158fe344f6 side bar clean up 2023-04-28 20:40:57 -04:00
DESKTOP-GBA0BK8\Admin bd3aaa6c44 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench 2023-04-28 20:25:35 -04:00
DESKTOP-GBA0BK8\Admin 30f3662772 side menu 2023-04-28 20:25:10 -04:00
ameye bc3a77aa8e Merge branch 'added-auth-footer' of WrenchBoard/Users-Wrench into master 2023-04-28 16:39:36 +00:00
Ebube 6c8a087196 removed height checker 2023-04-28 16:42:34 +01:00
Ebube 80a3a4578b Added missed component 2023-04-28 16:40:44 +01:00
ameye 775607b619 Merge branch 'transfer_implementation' of WrenchBoard/Users-Wrench into master 2023-04-28 14:26:16 +00:00
victorAnumudu aa9482bb95 transfer fund implemented 2023-04-28 15:23:43 +01:00
ameye 67b639c64f Merge branch 'confirm_transfer' of WrenchBoard/Users-Wrench into master 2023-04-28 08:55:37 +00:00
victorAnumudu 0bac836eb8 confirm transfer page added 2023-04-28 09:52:23 +01:00
ameye 76621a87c5 Merge branch 'verify-signup' of WrenchBoard/Users-Wrench into master 2023-04-28 01:51:46 +00:00
Ebube 7c2be04fac Added intervals for the requests for the verification 2023-04-28 02:08:04 +01:00
Ebube d23408d0ab added complete signup handler 2023-04-27 22:54:27 +01:00
ameye e94655a2a7 Merge branch 'transfer_money_validation' of WrenchBoard/Users-Wrench into master 2023-04-27 16:04:59 +00:00
victorAnumudu 94ced78c82 tranfer fund input validation done 2023-04-27 17:01:30 +01:00
Ebube 63f2ee3e6c removed a field 2023-04-27 14:01:12 +01:00
ameye b3582be38c Merge branch 'adding_recipient' of WrenchBoard/Users-Wrench into master 2023-04-27 12:58:03 +00:00
ameye 73cc1ef485 Merge branch 'verify-signup' of WrenchBoard/Users-Wrench into master 2023-04-27 12:57:59 +00:00
Ebube fb1745b0ad changed queryParams name 2023-04-27 13:52:42 +01:00
victorAnumudu 39b3218545 merged master to branch 2023-04-27 13:52:21 +01:00
victorAnumudu e26330af9a handling adding recipient done 2023-04-27 13:49:19 +01:00
ameye ccc43bb55d Merge branch 'verify-signup' of WrenchBoard/Users-Wrench into master 2023-04-27 12:29:37 +00:00
Ebube 2b0d344dfa lest touch b4 pr 2023-04-27 13:11:56 +01:00
ameye 53b9db85a5 Merge branch 'recipient_account_num__match' of WrenchBoard/Users-Wrench into master 2023-04-27 10:10:38 +00:00
victorAnumudu ecdd8f9180 validates that account number is a number 2023-04-27 11:08:11 +01:00
victorAnumudu 25dcfecfaf made validates that account number matches retype account number 2023-04-27 10:47:05 +01:00
DESKTOP-GBA0BK8\Admin ed638f5c0f Honeofferc card 2023-04-27 05:24:18 -04:00
DESKTOP-GBA0BK8\Admin 033d87fdf6 My Jobs listimg 2023-04-27 05:09:35 -04:00
Ebube babed484b2 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into verify-signup 2023-04-27 10:07:52 +01:00
Ebube e2b4aaa105 added the rest 2023-04-27 10:07:10 +01:00
ameye ce01b2637b Merge branch 'add_recipient_validation' of WrenchBoard/Users-Wrench into master 2023-04-27 09:01:07 +00:00
Ebube d91241dad9 added verify emali endpoint 2023-04-27 08:34:07 +01:00
Ebube 1ad3b74610 added checkers 2023-04-27 08:31:25 +01:00
victorAnumudu d94ff616a9 added validation to add recipient page 2023-04-27 04:26:11 +01:00
DESKTOP-GBA0BK8\Admin f87dbcbe5e Jobs format 2023-04-26 22:40:15 -04:00
DESKTOP-GBA0BK8\Admin 4df1589222 my jobs list 2023-04-26 22:13:41 -04:00
Ebube 886b73ffa3 fixing signup 2023-04-27 02:44:09 +01:00
Ebube 6cb0871d34 added html validation 2023-04-27 02:37:04 +01:00
Ebube 3ed764e8f4 Added a check up email v 2023-04-27 02:28:59 +01:00
Ebube c87fc4f32d Added verify link 2023-04-27 02:25:03 +01:00
ameye 75015e84d2 Merge branch 'add_recipient_country' of WrenchBoard/Users-Wrench into master 2023-04-26 11:57:49 +00:00
tokslaw7 24a5b8e785 Attempt fix 2023-04-26 11:40:51 +00:00
tolik 03ca576e16 Fix build 2023-04-26 19:25:47 +08:00
victorAnumudu 8886544024 Merge branch 'master' into add_recipient_country 2023-04-26 12:06:39 +01:00
victorAnumudu cadd2aa4c4 added recipient country, bank name and account types from API 2023-04-26 12:03:33 +01:00
tolik 104cd15f64 Attempt to fix 2023-04-26 18:49:58 +08:00
tolik 3acdbfb6e0 Remove volume maps for node_modules & vendors 2023-04-26 18:29:41 +08:00
tolik f30600816b Map node_modules 2023-04-26 18:11:32 +08:00
tolik 627774c910 Dev/prod env support 2023-04-26 17:25:58 +08:00
DESKTOP-GBA0BK8\Admin ee59990d85 sntx error 2023-04-25 20:56:41 -04:00
DESKTOP-GBA0BK8\Admin 7f4d8f3ff0 Hero Top data parts 2023-04-25 20:45:25 -04:00
ameye b888e9f5df Merge branch 'profile_validation' of WrenchBoard/Users-Wrench into master 2023-04-25 19:08:01 +00:00
53 changed files with 17180 additions and 13234 deletions
+2
View File
@@ -23,6 +23,8 @@ REACT_APP_SESSION_EXPIRE_CHECKER=60000
REACT_APP_LOGIN_ERROR_TIMEOUT=7000 REACT_APP_LOGIN_ERROR_TIMEOUT=7000
REACT_APP_SIGNUP_ERROR_TIMEOUT=7000 REACT_APP_SIGNUP_ERROR_TIMEOUT=7000
REACT_APP_FLUTTERWAVE_APIKEY=FLWPUBK_TEST-54c90141b028789d671067bd72f781a9-X
# Had to change the error time to 3sec cause it took too long # Had to change the error time to 3sec cause it took too long
REACT_APP_RESET_START_ERROR_TIMEOUT=3000 REACT_APP_RESET_START_ERROR_TIMEOUT=3000
+32
View File
@@ -0,0 +1,32 @@
SKIP_PREFLIGHT_CHECK=true
REACT_APP_FACEBOOK="https://www.facebook.com/profile.php?id=100066498622246"
REACT_APP_TWITTER="https://twitter.com/fluxtra"
REACT_APP_APPSITE="https://myfitapp.mermsemr.com"
#REACT_APP_APPSITE="http://localhost:7012"
# REACT_APP_AUX_ENDPOINT="http://10.20.30.32:9083/svs/user"
# REACT_APP_USERS_ENDPOINT="http://10.20.30.32:9083/svs/user"
REACT_APP_AUX_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/svs/user"
REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/svs/user"
#REACT_APP_AUX_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
#REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
REACT_APP_SESSION_EXPIRE_MINUTES=300000
REACT_APP_SESSION_EXPIRE_CHECKER=60000
REACT_APP_LOGIN_ERROR_TIMEOUT=7000
REACT_APP_SIGNUP_ERROR_TIMEOUT=7000
REACT_APP_FLUTTERWAVE_APIKEY=FLWPUBK_TEST-54c90141b028789d671067bd72f781a9-X
# Had to change the error time to 3sec cause it took too long
REACT_APP_RESET_START_ERROR_TIMEOUT=3000
#apigate.lotus.g1.wrenchboard.com:76.209.103.227
#apigate.orion.g1.wrenchboard.com:76.209.103.227
+32
View File
@@ -0,0 +1,32 @@
SKIP_PREFLIGHT_CHECK=true
REACT_APP_FACEBOOK="https://www.facebook.com/profile.php?id=100066498622246"
REACT_APP_TWITTER="https://twitter.com/fluxtra"
REACT_APP_APPSITE="https://myfitapp.mermsemr.com"
#REACT_APP_APPSITE="http://localhost:7012"
# REACT_APP_AUX_ENDPOINT="http://10.20.30.32:9083/svs/user"
# REACT_APP_USERS_ENDPOINT="http://10.20.30.32:9083/svs/user"
REACT_APP_AUX_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/svs/user"
REACT_APP_USERS_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/svs/user"
#REACT_APP_AUX_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/en/wrench/api/v1"
#REACT_APP_USERS_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/en/wrench/api/v1"
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
REACT_APP_SESSION_EXPIRE_MINUTES=300000
REACT_APP_SESSION_EXPIRE_CHECKER=60000
REACT_APP_LOGIN_ERROR_TIMEOUT=7000
REACT_APP_SIGNUP_ERROR_TIMEOUT=7000
REACT_APP_FLUTTERWAVE_APIKEY=FLWPUBK_TEST-54c90141b028789d671067bd72f781a9-X
# Had to change the error time to 3sec cause it took too long
REACT_APP_RESET_START_ERROR_TIMEOUT=3000
#apigate.orion.g1.wrenchboard.com:76.209.103.227
#apigate.orion.g1.wrenchboard.com:76.209.103.227
-59
View File
@@ -1,59 +0,0 @@
{
"extends": [
"airbnb",
"airbnb/hooks",
"eslint:recommended",
"prettier",
"plugin:jsx-a11y/recommended"
],
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 8
},
"env": {
"browser": true,
"node": true,
"es6": true,
"jest": true
},
"rules": {
"no-plusplus": 0,
"import/no-dynamic-require": 0,
"global-require": 0,
"no-nested-ternary": 0,
"react/self-closing-comp": 0,
"react/no-unescaped-entities": 0,
"jsx-a11y/anchor-is-valid": 0,
"react/jsx-props-no-spreading": 0,
"jsx-eslint/eslint-plugin-jsx-a11y": 0,
"jsx-a11y/no-static-element-interactions": 0,
"jsx-a11y/label-has-associated-control": 0,
"jsx-a11y/no-noninteractive-element-interactions": 0,
"react/react-in-jsx-scope": 0,
"react-hooks/rules-of-hooks": "error",
"no-console": 0,
"react/state-in-constructor": 0,
"indent": 0,
"linebreak-style": 0,
"react/prop-types": 0,
"jsx-a11y/click-events-have-key-events": 0,
"react/jsx-filename-extension": [
1,
{
"extensions": [".js", ".jsx"]
}
]
// "prettier/prettier": [
// "error",
// {
// "trailingComma": "es5",
// "singleQuote": true,
// "printWidth": 100,
// "tabWidth": 4,
// "semi": true,
// "endOfLine": "auto"
// }
// ]
},
"plugins": ["prettier", "react", "react-hooks"]
}
+15
View File
@@ -0,0 +1,15 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.jsx text
*.js text
*.css text
# Declare files that will always have CRLF line endings on checkout.
*.md text eol=crlf
# Denote all files that are truly binary and should not be modified.
*.sh binary
+36
View File
@@ -0,0 +1,36 @@
# pull the base image
FROM node:alpine
# Build args
ARG NODE_ENV
# set the working direction
#WORKDIR /app
WORKDIR /usr/src/app
# add `/app/node_modules/.bin` to $PATH
# ENV PATH /app/node_modules/.bin:$PATH
ENV PATH /usr/src/app/node_modules/.bin:$PATH
ENV NODE_ENV=$NODE_ENV
# install nginx
RUN apk update
RUN apk add nginx
# install app dependencies
COPY package.json ./
COPY package-lock.json ./
COPY nginx.conf ./
COPY run.sh ./
RUN npm install --legacy-peer-deps
# add app
COPY . ./
# start app
CMD /bin/sh ./run.sh
+6 -3
View File
@@ -4,7 +4,9 @@ services:
image: registry.chiefsoft.net/wrenchboard-users-wrench:latest image: registry.chiefsoft.net/wrenchboard-users-wrench:latest
build: build:
context: . context: .
dockerfile: docker/Dockerfile dockerfile: Dockerfile
args:
- NODE_ENV=production
restart: unless-stopped restart: unless-stopped
ports: ports:
- 9082:3000 - 9082:3000
@@ -13,19 +15,20 @@ services:
working_dir: /usr/src/app working_dir: /usr/src/app
volumes: volumes:
- ./:/usr/src/app - ./:/usr/src/app
- /usr/src/app/node_modules
- ./src/:/usr/src/app/src - ./src/:/usr/src/app/src
- ./vendors/:/usr/src/app/vendors - ./run.sh:/usr/src/app/run.sh
extra_hosts: extra_hosts:
- backend.wrenchboard.api.live:10.10.33.15 - backend.wrenchboard.api.live:10.10.33.15
- backend.wrenchboard.api.test:10.10.33.15 - backend.wrenchboard.api.test:10.10.33.15
- apigate.lotus.g1.wrenchboard.com:10.10.33.15 - apigate.lotus.g1.wrenchboard.com:10.10.33.15
- apigate.orion.g1.wrenchboard.com:10.10.33.15
# #- backend.wrenchboard.api.live:172.31.4.27 # #- backend.wrenchboard.api.live:172.31.4.27
# #- backend.wrenchboard.api.test:10.20.30.27 # #- backend.wrenchboard.api.test:10.20.30.27
- apigateway.wrenchboard.app.dev.fluxtra.net:10.20.30.19 - apigateway.wrenchboard.app.dev.fluxtra.net:10.20.30.19
- apigateway.wrenchboard.app.lotus.fluxtra.net:172.31.4.19 - apigateway.wrenchboard.app.lotus.fluxtra.net:172.31.4.19
environment: environment:
- CHOKIDAR_USEPOLLING=true - CHOKIDAR_USEPOLLING=true
- NODE_ENV=${NODE_ENV:-production}
# volumes: # volumes:
# - ./:/app # - ./:/app
# - /app/node_modules # - /app/node_modules
+15 -1
View File
@@ -3,7 +3,15 @@
FROM alpine:3.15 FROM alpine:3.15
# Build args
ARG NODE_ENV
ENV NODE_VERSION 14.19.0 ENV NODE_VERSION 14.19.0
ENV NODE_ENV=$NODE_ENV
# install nginx
RUN apk update
RUN apk add nginx
RUN addgroup -g 1000 node \ RUN addgroup -g 1000 node \
&& adduser -u 1000 -G node -s /bin/sh -D node \ && adduser -u 1000 -G node -s /bin/sh -D node \
@@ -103,6 +111,10 @@ WORKDIR /usr/src/app
# ENV PATH /app/node_modules/.bin:$PATH # ENV PATH /app/node_modules/.bin:$PATH
ENV PATH /usr/src/app/node_modules/.bin:$PATH ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY nginx.conf ./
COPY run.sh ./
# install app dependencies # install app dependencies
COPY package.json ./ COPY package.json ./
RUN npm install RUN npm install
@@ -114,7 +126,9 @@ RUN npm install
COPY . ./ COPY . ./
# start app # start app
CMD ["npm","run", "start"] # CMD ["npm","run", "start"]
# CMD ["yarn", "start"] # CMD ["yarn", "start"]
# start app
CMD /bin/sh ./run.sh
+29
View File
@@ -0,0 +1,29 @@
worker_processes 1;
events {
worker_connections 1024;
}
http {
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
server {
gzip on;
listen 3000;
server_name localhost;
root /usr/src/app/build;
include /etc/nginx/mime.types;
location /nginx_status {
stub_status on;
access_log off;
}
location / {
try_files $uri $uri/ /index.html;
}
}
}
+10992 -6604
View File
File diff suppressed because it is too large Load Diff
+9 -25
View File
@@ -14,27 +14,26 @@
"cors": "^2.8.5", "cors": "^2.8.5",
"faker": "^6.6.6", "faker": "^6.6.6",
"formik": "^2.2.9", "formik": "^2.2.9",
"react": "^18.0.0",
"react-chartjs-2": "^4.1.0", "react-chartjs-2": "^4.1.0",
"react-countup": "^6.2.0", "react-countup": "^6.2.0",
"react-dom": "^18.0.0",
"react-lottie": "^1.2.3",
"react-redux": "^8.0.2",
"react-router-dom": "^6.0.2", "react-router-dom": "^6.0.2",
"react-scripts": "5.0.0",
"react-slick": "^0.29.0", "react-slick": "^0.29.0",
"react-toastify": "^9.0.1", "react-toastify": "^9.0.1",
"flutterwave-react-v3": "^1.3.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-redux": "^8.0.5",
"react-scripts": "5.0.1",
"redux": "^4.2.0", "redux": "^4.2.0",
"slick-carousel": "^1.8.1", "slick-carousel": "^1.8.1",
"web-vitals": "^1.0.1", "web-vitals": "^1.0.1",
"yup": "^1.1.1" "yup": "^1.1.1"
}, },
"scripts": { "scripts": {
"start": "react-scripts start", "start": "react-scripts start -e .env.development",
"build": "react-scripts build", "build": "react-scripts build -e .env.production",
"test": "react-scripts test", "test": "react-scripts test",
"eject": "react-scripts eject", "eject": "react-scripts eject"
"lint": "yarn add -D prettier@2.4.1 && yarn add -D eslint@7.11.0 && yarn add -D babel-eslint@10.1.0 && npx install-peerdeps --dev eslint-config-airbnb@18.2.1 && yarn add -D eslint-config-prettier@8.3.0 eslint-plugin-prettier@4.0.0"
}, },
"eslintConfig": { "eslintConfig": {
"extends": [ "extends": [
@@ -53,20 +52,5 @@
"last 1 firefox version", "last 1 firefox version",
"last 1 safari version" "last 1 safari version"
] ]
},
"devDependencies": {
"autoprefixer": "^10.4.5",
"babel-eslint": "10.1.0",
"eslint": "7.2.0",
"eslint-config-airbnb": "18.2.1",
"eslint-config-prettier": "8.3.0",
"eslint-plugin-import": "2.22.1",
"eslint-plugin-jsx-a11y": "6.4.1",
"eslint-plugin-prettier": "4.0.0",
"eslint-plugin-react": "^7.29.4",
"eslint-plugin-react-hooks": "1.7.0",
"postcss": "^8.4.12",
"prettier": "2.4.1",
"tailwindcss": "^3.0.24"
} }
} }
Executable
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/env sh
set -e
set -x
export NODE_ENV="${NODE_ENV:-development}"
if [ $NODE_ENV == "development" ]; then
# this runs webpack-dev-server with hot reloading
echo "Development build"
npm install --legacy-peer-deps
npm start
else
# build the app and serve it via nginx
echo "Production build"
npm install --legacy-peer-deps
npm run build
nginx -g 'daemon off;' -c /usr/src/app/nginx.conf
nginx -c /usr/src/app/nginx.conf
fi
+4 -1
View File
@@ -30,6 +30,7 @@ import ResourcePage from "./views/ResourcePage";
import MyTaskPage from "./views/MyTaskPage"; import MyTaskPage from "./views/MyTaskPage";
import MyJobsPage from "./views/MyJobsPage"; import MyJobsPage from "./views/MyJobsPage";
import ReferralPage from "./views/ReferralPage"; import ReferralPage from "./views/ReferralPage";
import VerifyLinkPages from "./views/VerifyLinkPages";
export default function Routers() { export default function Routers() {
return ( return (
@@ -48,7 +49,8 @@ export default function Routers() {
path="/update-password" path="/update-password"
element={<UpdatePasswordPages />} element={<UpdatePasswordPages />}
/> />
<Route exact path="/verify-you" element={<VerifyYouPages />} /> <Route path="/vemail" element={<VerifyLinkPages />} />
<Route exact path="/outmessage" element={<VerifyYouPages />} />
{/* private route */} {/* private route */}
<Route element={<AuthRoute />}> <Route element={<AuthRoute />}>
@@ -70,6 +72,7 @@ export default function Routers() {
<Route exact path="/notification" element={<Notification />} /> <Route exact path="/notification" element={<Notification />} />
<Route exact path="/mytask" element={<MyTaskPage />} /> <Route exact path="/mytask" element={<MyTaskPage />} />
<Route exact path="/myjobs" element={<MyJobsPage />} /> <Route exact path="/myjobs" element={<MyJobsPage />} />
<Route exact path="/my-active-jobs" element={<MyJobsPage />} />
<Route <Route
exact exact
path="/my-collection/collection-item" path="/my-collection/collection-item"
+25 -14
View File
@@ -1,24 +1,35 @@
import React from "react"; import React from "react";
import loginThumb from "../../assets/images/auth-thumb.svg"; import { Link } from "react-router-dom";
import logo from "../../assets/images/wrenchboard.png"; //logo-1.svg";
export default function LoginLayout({ slogan, children }) { export default function LoginLayout({ slogan, children }) {
const checkScreenHeight = window.screen.height;
let screen = "";
if (checkScreenHeight <= 950) {
screen = "h-screen";
// screen = "h-[950px]";
} else {
screen = "h-screen";
}
return ( return (
<div className="layout-wrapper login"> <div className={`layout-wrapper login`}>
<div className={`main-wrapper login-wrapper w-full ${screen}`}> <div className={`main-wrapper login-wrapper w-full h-screen overflow-y-auto sm:p-20 p-10`}>
<div className="flex w-full h-full"> <div className="w-full h-full">
<div className="flex-1 flex justify-center items-center"> <div className="flex-1 flex justify-center items-center">
{children && children} {children && children}
</div> </div>
<div className="flex-1 flex justify-center items-center p-10">
<div className="flex items-center">
<Link to="#" className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]">
About
</Link>
<Link to="#" className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]">
Services
</Link>
<Link to="#" className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]">
Contact Us
</Link>
</div>
</div>
<div className="flex-1 flex justify-center items-center p-10">
<p className="text-black text-[15px] px-2 font-medium flex items-center">
<span className="text-3xl mt-2 mr-1">©</span> 2023 - {" "}
<Link to="/" className="text-[#009ef7] ml-1">
WrenchBoard
</Link>{" "}
</p>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -11,6 +11,7 @@ export default function ForgotPassword() {
// email // email
const [email, setMail] = useState(""); const [email, setMail] = useState("");
const [msgError, setMsgError] = useState(''); const [msgError, setMsgError] = useState('');
const [msgSuccess, setMsgSuccess] = useState(false)
const navigate = useNavigate(); const navigate = useNavigate();
const userApi = new usersService(); const userApi = new usersService();
@@ -20,8 +21,8 @@ export default function ForgotPassword() {
}; };
const humanChecker = () => { const humanChecker = () => {
setValue(!checked); setValue(!checked)
}; }
const resetHandler = async () => { const resetHandler = async () => {
if (email == '') { if (email == '') {
@@ -30,24 +31,16 @@ export default function ForgotPassword() {
setMsgError('Check if you are human') setMsgError('Check if you are human')
} }
if (email != '' && checked) { if (email !== '' && checked) {
const reqData = { email } const reqData = { email }
setResetLoading(true) setResetLoading(true)
try { try {
const res = await userApi.StartResetPassword(reqData) const res = await userApi.StartResetPassword(reqData)
if (res.status === 200) { if (res.status === 200) {
const { data } = res setMsgSuccess(true)
if (data.status == -1) {
setMsgError('This is an incorrect or duplicate email')
setResetLoading(false)
} else if (data.status > 0) {
setResetLoading(false)
navigate("/verify-you", { replace: true })
} else{
setMsgError("reset was not successful")
setResetLoading(false)
}
setMail("") setMail("")
setValue(false)
setResetLoading(false)
} }
} catch (error) { } catch (error) {
setResetLoading(false) setResetLoading(false)
@@ -79,12 +72,10 @@ export default function ForgotPassword() {
<div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5"> <div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5">
<div className="flex flex-col justify-center w-full h-full px-5"> <div className="flex flex-col justify-center w-full h-full px-5">
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7"> <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" style={{ <h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
fontSize: 'calc(1rem + .6vw)'
}}>
Forget Password Forget Password
</h1> </h1>
<span className="text-gray-400 font-medium text-xl">Enter your email to reset your password.</span> <span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">Enter your email to reset your password.</span>
</div> </div>
<div className="input-area"> <div className="input-area">
<div className="input-item mb-10"> <div className="input-item mb-10">
@@ -98,7 +89,6 @@ export default function ForgotPassword() {
iconName="message" iconName="message"
/> />
</div> </div>
{msgError && <div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px]">{msgError}</div>}
{/* hCaptha clone for the time being */} {/* hCaptha clone for the time being */}
<div className="mb-10"> <div className="mb-10">
<div className="w-[303px] h-[78px] mx-auto overflow-hidden"> <div className="w-[303px] h-[78px] mx-auto overflow-hidden">
@@ -108,7 +98,7 @@ export default function ForgotPassword() {
<div className="relative table top-0 h-full"> <div className="relative table top-0 h-full">
<div className="table-cell align-middle"> <div className="table-cell align-middle">
<div className="relative w-[30px] h-[30px] mx-[15px]"> <div className="relative w-[30px] h-[30px] mx-[15px]">
<input type="checkbox" name="human-checkbox" id="human-checkbox" className="w-[28px] h-[28px] border-[1px] rounded border-gray-400 checked:bg-white" onClick={humanChecker} /> <input type="checkbox" name="human-checkbox" id="human-checkbox" className="w-[28px] h-[28px] border-[1px] rounded border-gray-400 checked:bg-white" checked={checked} onChange={humanChecker} />
</div> </div>
</div> </div>
</div> </div>
@@ -126,12 +116,15 @@ export default function ForgotPassword() {
</div> </div>
</div> </div>
</div> </div>
{msgError && <div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">{msgError}</div>}
{msgSuccess && <div className="relative p-4 text-[#44228c] bg-[#e3d7fb] border-[#d5c4f9] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">If we find your email, you will receive a link to reset your password. Please use or <Link to='/contact' className="text-[#4687ba] hover:text-[#009ef7]">contact form</Link> if you did not get our message after few minutes.</div>}
<div className="signin-area mb-3.5"> <div className="signin-area mb-3.5">
<div className="flex justify-center items-center gap-2"> <div className="flex justify-center items-center gap-2">
<button <button
type="button" type="button"
onClick={resetHandler} onClick={resetHandler}
className={`rounded-[0.475rem] mb-6 text-[1.15rem] font-semibold text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`} className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
> >
{resetLoading ? ( {resetLoading ? (
<div className="signup btn-loader"></div> <div className="signup btn-loader"></div>
@@ -142,7 +135,7 @@ export default function ForgotPassword() {
<button <button
type="button" type="button"
onClick={() => navigate("/login")} onClick={() => navigate("/login")}
className={`rounded-[0.475rem] mb-6 text-[1.15rem] font-semibold text-[#009ef7] hover:text-white flex justify-center bg-[#f1faff] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.8125rem] `} className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-[#009ef7] hover:text-white flex justify-center bg-[#f1faff] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.8125rem] `}
> >
Cancel Cancel
</button> </button>
+16 -21
View File
@@ -9,7 +9,13 @@ import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom"; import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout"; import AuthLayout from "../AuthLayout";
import { useDispatch, useSelector } from "react-redux";
import {updateUserDetails} from '../../../store/UserDetails'
export default function Login() { export default function Login() {
const dispatch = useDispatch()
const [checked, setValue] = useState(false); const [checked, setValue] = useState(false);
const [loginLoading, setLoginLoading] = useState(false); const [loginLoading, setLoginLoading] = useState(false);
@@ -51,23 +57,14 @@ export default function Login() {
//debugger; //debugger;
// if (email === "support@mermsemr.com") { // if (email === "support@mermsemr.com") {
if (loginResult.data.status > 0 && loginResult.data.internal_return == 100 && loginResult.data.session != '') { // just for a start if (loginResult.data.status > 0 && loginResult.data.internal_return == 100 && loginResult.data.session != '') { // just for a start
localStorage.setItem("email", `${loginResult.data.email}`);
localStorage.setItem("member_id", `${loginResult.data.member_id}`); localStorage.setItem("member_id", `${loginResult.data.member_id}`);
localStorage.setItem("uid", `${loginResult.data.uid}`); localStorage.setItem("uid", `${loginResult.data.uid}`);
localStorage.setItem("session_token", `${loginResult.data.session}`); localStorage.setItem("session_token", `${loginResult.data.session}`);
localStorage.setItem("added", `${loginResult.data.added}`);
localStorage.setItem("city", `${loginResult.data.city}`);
localStorage.setItem("country", `${loginResult.data.country}`);
localStorage.setItem("firstname", `${loginResult.data.firstname}`);
localStorage.setItem("last_login", `${loginResult.data.last_login}`);
localStorage.setItem("lastname", `${loginResult.data.lastname}`);
localStorage.setItem("state", `${loginResult.data.state}`);
localStorage.setItem("zip_code", `${loginResult.data.zip_code}`);
localStorage.setItem("session", `${loginResult.data.session}`); localStorage.setItem("session", `${loginResult.data.session}`);
setLoginLoading(true); setLoginLoading(true);
// userApi.getUserReminders(); //testing // userApi.getUserReminders(); //testing
dispatch(updateUserDetails(loginResult.data))
setTimeout(() => { setTimeout(() => {
toast.success("Login Successfully");
navigate("/", { replace: true }); navigate("/", { replace: true });
setLoginLoading(false); setLoginLoading(false);
}, 2000); }, 2000);
@@ -100,12 +97,10 @@ export default function Login() {
<div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5"> <div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5">
<div className="w-full"> <div className="w-full">
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7"> <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" style={{ <h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
fontSize: 'calc(1rem + .6vw)'
}}>
Sign In to WrenchBoard Sign In to WrenchBoard
</h1> </h1>
<span className="text-gray-400 font-medium text-xl">New Here? <Link to='/signup' className='font-semibold text-[#4687ba] hover:text-[#009ef7] transition'>Create an Account</Link></span> <span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">New Here? <Link to='/signup' className='font-semibold text-[#4687ba] hover:text-[#009ef7] transition'>Create an Account</Link></span>
</div> </div>
<div className="input-area"> <div className="input-area">
<div className="input-item mb-5"> <div className="input-item mb-5">
@@ -119,6 +114,7 @@ export default function Login() {
iconName="message" iconName="message"
/> />
</div> </div>
<div className="input-item mb-5"> <div className="input-item mb-5">
<InputCom <InputCom
value={password} value={password}
@@ -164,15 +160,14 @@ export default function Login() {
Forgot Password Forgot Password
</a> </a>
</div> */} </div> */}
{loginError && <div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-thin leading-[19.5px]">Invalid username or password- Please <Link to='/#' className='text-[#009ef7]'>reset your password</Link> or <Link to='/signup' className='text-[#009ef7]'>create a new account</Link></div>} {loginError && <div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-thin leading-[19.5px] text-[13px]">Invalid username or password- Please <Link to='/#' className='text-[#009ef7]'>reset your password</Link> or <Link to='/signup' className='text-[#009ef7]'>create a new account</Link></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]">{msgError}</div>} {msgError && <div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">{msgError}</div>}
<div className="signin-area mb-3.5"> <div className="signin-area mb-3.5">
<div className="flex justify-center"> <div className="flex justify-center">
<button <button
onClick={doLogin} onClick={doLogin}
type="button" type="button"
className={`btn-login rounded-[0.475rem] mb-6 text-xl text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center ${loginLoading ? "active" : "" className={`btn-login rounded-[0.475rem] mb-6 text-xl text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center text-[15px]`}
}`}
> >
{loginLoading ? ( {loginLoading ? (
<div className="signup btn-loader"></div> <div className="signup btn-loader"></div>
@@ -193,7 +188,7 @@ export default function Login() {
</a> </a>
</p> </p>
</div> */} </div> */}
<div className="pt-5 text-[#181c32] text-center font-semibold text-base">This site is protected by hCaptcha and the our Privacy Policy and Terms of Service apply.</div> <div className="pt-5 text-[#181c32] text-center font-semibold text-[13.975px] leading-[20.9625px]">This site is protected by hCaptcha and the our Privacy Policy and Terms of Service apply.</div>
</div> </div>
</div> </div>
</div> </div>
@@ -215,8 +210,8 @@ const BrandBtn = ({
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" 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)" /> <img className="mr-3 h-6" src={imgSrc} alt="logo-icon(s)" />
<span className="text-lg text-thin-light-gray font-normal"> <span className="text-lg text-thin-light-gray font-normal text-[15px]">
Sign In with {brand} Continue with {brand}
</span> </span>
</a> </a>
</div> </div>
+121 -74
View File
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
import { useNavigate, Link } from "react-router-dom"; import { useNavigate, Link } from "react-router-dom";
import facebookLogo from "../../../assets/images/facebook-4.svg"; import facebookLogo from "../../../assets/images/facebook-4.svg";
import WrenchBoard from "../../../assets/images/wrenchboard.png"; import WrenchBoard from "../../../assets/images/wrenchboard.png";
@@ -6,10 +6,10 @@ import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom"; import InputCom from "../../Helpers/Inputs/InputCom";
export default function SignUp() { export default function SignUp() {
const [signUpLoading, setSignUpLoading] = useState(false) const [signUpLoading, setSignUpLoading] = useState(false);
const [checked, setValue] = useState(false); const [checked, setValue] = useState(false);
// for the catch error // for the catch error
const [msgError, setMsgError] = useState(''); const [msgError, setMsgError] = useState("");
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);
const [countries, setCountries] = useState([]); const [countries, setCountries] = useState([]);
@@ -18,7 +18,7 @@ export default function SignUp() {
first_name: "", first_name: "",
last_name: "", last_name: "",
email: "", email: "",
password: "" password: "",
}); });
const handleInputChange = (event) => { const handleInputChange = (event) => {
@@ -37,32 +37,38 @@ export default function SignUp() {
const navigate = useNavigate(); const navigate = useNavigate();
const userApi = new usersService(); const userApi = new usersService();
// Get Country Api // Get Country Api
const getCountryList = async () => { const getCountryList = useCallback(async () => {
const res = await userApi.getSignupCountryData() const res = await userApi.getSignupCountryData();
try { try {
if (res.status === 200) { if (res.status === 200) {
const { signup_country } = await res.data const { signup_country } = await res.data;
setCountries(signup_country) setCountries(signup_country);
} else if (res.data.result != 100) { } else if (res.data.result !== 100) {
setCountries('Nothing see here!') setCountries("Nothing see here!");
} }
} catch (error) { } catch (error) {
throw new Error(error) throw new Error(error);
} }
} }, []);
const handleSignUp = async () => { const handleSignUp = async () => {
let { country, first_name, last_name, email, password } = formData let { country, first_name, last_name, email, password } = formData;
if (email == '' && password == '' && first_name == '') { if (email === "" && password === "" && first_name === "") {
setMsgError('Please fill in fields') setMsgError("Please fill in fields");
} }
try { try {
if (email !== '' && password !== '' && first_name !== '' && last_name !== '') { if (
email !== "" &&
password !== "" &&
first_name !== "" &&
last_name !== ""
) {
setSignUpLoading(true);
const reqData = { const reqData = {
country: country, country: country,
firstname: first_name, firstname: first_name,
@@ -71,50 +77,40 @@ export default function SignUp() {
username: email, username: email,
password: password, password: password,
terms: 1, terms: 1,
news: 1 news: 1,
} };
const res = await userApi.CreateUser(reqData) const res = await userApi.CreateUser(reqData);
setSignUpLoading(true)
if (res.status === 200) { if (res.status === 200) {
const { data } = res const { data } = res;
if (data.status == -1 && data.acc == 'DULPICATE') { if (data.status === -1 && data.acc === "DULPICATE") {
setMsgError('This account has been already created') setMsgError("This account has been already created");
setSignUpLoading(false) setSignUpLoading(false);
} }
if (data.status > 0 && data.internal_return == 100 && data.session != '') { if (data && data.status === "1") {
localStorage.setItem("email", `${data.email}`);
localStorage.setItem("country", `${data.country}`);
localStorage.setItem("firstname", `${data.firstname}`);
localStorage.setItem("lastname", `${data.lastname}`);
setTimeout(() => { setTimeout(() => {
navigate("/", { replace: true }); navigate("/outmessage", { replace: true });
setSignUpLoading(false) setSignUpLoading(false);
}, 2000) }, 2000);
} else {
setMsgError(data.status)
setSignUpLoading(false)
} }
} else {
setSignUpLoading(false);
setMsgError("An error occurred");
} }
} else {
setMsgError('This account does not exist')
setSignUpLoading(false)
} }
} catch (error) { } catch (error) {
throw new Error(error) throw new Error(error);
setMsgError('An error occurred')
} finally { } finally {
setTimeout(() => { setTimeout(() => {
setMsgError(null) setMsgError(null);
}, process.env.REACT_APP_SIGNUP_ERROR_TIMEOUT) }, process.env.REACT_APP_SIGNUP_ERROR_TIMEOUT);
} }
} };
useEffect(() => { useEffect(() => {
getCountryList() getCountryList();
}, []) });
return ( return (
<> <>
@@ -123,36 +119,52 @@ export default function SignUp() {
<div className=" h-full"> <div className=" h-full">
<div className="flex-1 flex justify-center items-center"> <div className="flex-1 flex justify-center items-center">
<div className="w-full"> <div className="w-full">
<div className='mb-12'> <div className="mb-12">
<Link to='#'> <Link to="#">
<img src={WrenchBoard} alt="wrenchboard" className="h-10 mx-auto" /> <img
src={WrenchBoard}
alt="wrenchboard"
className="h-10 mx-auto"
/>
</Link> </Link>
</div> </div>
<div className="content-wrapper login shadow-md w-full lg:max-w-[600px] 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-7"> <div className="content-wrapper login shadow-md w-full lg:max-w-[600px] 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-7">
<div> <div>
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7"> <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" style={{ <h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
fontSize: 'calc(1rem + .6vw)'
}}>
Create Account Create Account
</h1> </h1>
<span className="text-gray-400 font-medium text-xl">Already have an account? <Link to='/login' className='font-semibold text-[#4687ba] hover:text-[#009ef7] transition'>Sign in here</Link></span> <span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
Already have an account?{" "}
<Link
to="/login"
className="font-semibold text-[#4687ba] hover:text-[#009ef7] transition"
>
Sign in here
</Link>
</span>
</div> </div>
<button <button
type="button" type="button"
className={`rounded-[0.475rem] w-full mb-6 text-[1.15rem] h-[42px] font-semibold text-[#009ef7] hover:text-white flex justify-center bg-[#f1faff] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.8125rem]`} className={`rounded-[0.475rem] w-full mb-6 text-[15px] h-[42px] font-semibold text-[#009ef7] hover:text-white flex justify-center bg-[#f1faff] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.8125rem]`}
> >
<img className="mr-3 h-6" src={facebookLogo} alt="logo-icon(s)" /> <img
className="mr-3 h-6"
src={facebookLogo}
alt="logo-icon(s)"
/>
Sign in with Facebook Sign in with Facebook
</button> </button>
<div className="w-full flex items-center gap-2"> <div className="w-full flex items-center gap-2">
<div className="border-b border-[#eff2f5] max-w-[50%] w-full"></div> <div className="border-b border-[#eff2f5] max-w-[50%] w-full"></div>
<span className="text-[#b5b5c3] font-medium text-[0.7rem] w-[2%]">OR</span> <span className="text-[#b5b5c3] font-medium text-[0.7rem] w-[2%]">
OR
</span>
<div className="border-b border-[#eff2f5] max-w-[50%] w-full"></div> <div className="border-b border-[#eff2f5] max-w-[50%] w-full"></div>
</div> </div>
<div className="input-area"> <div className="input-area">
<SelectOption <SelectOption
label='Country' label="Country"
data={countries} data={countries}
name="country" name="country"
value={formData.country} value={formData.country}
@@ -195,14 +207,20 @@ export default function SignUp() {
placeholder="● ● ● ● ● ●" placeholder="● ● ● ● ● ●"
label="Password" label="Password"
name="password" name="password"
type={showPassword ? 'text' : 'password'} type={showPassword ? "text" : "password"}
onClick={togglePasswordVisibility} onClick={togglePasswordVisibility}
passIcon={showPassword ? "show-password" : "hide-password"} passIcon={
showPassword ? "show-password" : "hide-password"
}
value={formData.password} value={formData.password}
inputHandler={handleInputChange} inputHandler={handleInputChange}
/> />
</div> </div>
{msgError && <div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px]">{msgError}</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]">
{msgError}
</div>
)}
<div className="forgot-password-area flex justify-between items-center mb-6"> <div className="forgot-password-area flex justify-between items-center mb-6">
<div className="remember-checkbox flex items-center space-x-2.5"> <div className="remember-checkbox flex items-center space-x-2.5">
<button <button
@@ -227,15 +245,15 @@ export default function SignUp() {
</button> </button>
<span <span
onClick={rememberMe} onClick={rememberMe}
className="text-base cursor-default text-dark-gray dark:text-white" className="cursor-default text-dark-gray dark:text-white text-[15px]"
> >
I agree with all I agree with all
<a <Link
href="#" href="#"
className="text-base text-[#4687ba] hover:text-[#009ef7] mx-1 inline-block" className="text-base text-[#4687ba] hover:text-[#009ef7] mx-1 inline-block"
> >
terms and condition terms and condition
</a> </Link>
</span> </span>
</div> </div>
</div> </div>
@@ -244,8 +262,7 @@ export default function SignUp() {
<button <button
type="button" type="button"
onClick={handleSignUp} onClick={handleSignUp}
className={`rounded-[0.475rem] mb-6 text-xl text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center h-[42px] py-[0.8875rem] px-[1.81rem] ${signUpLoading ? "active" : "" className={`rounded-[0.475rem] mb-6 text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center h-[42px] py-[0.8875rem] px-[1.81rem] text-[14.95px]`}
}`}
> >
{signUpLoading ? ( {signUpLoading ? (
<div className="signup btn-loader"></div> <div className="signup btn-loader"></div>
@@ -260,6 +277,27 @@ export default function SignUp() {
</div> </div>
</div> </div>
</div> </div>
<div className="flex-1 flex justify-center items-center p-10">
<div className="flex items-center">
<Link to="#" className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]">
About
</Link>
<Link to="#" className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]">
Services
</Link>
<Link to="#" className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]">
Contact Us
</Link>
</div>
</div>
<div className="flex-1 flex justify-center items-center p-10">
<p className="text-black text-[15px] px-2 font-medium flex items-center">
<span className="text-3xl mt-2 mr-1">©</span> 2023 - {" "}
<Link to="/" className="text-[#009ef7] ml-1">
WrenchBoard
</Link>{" "}
</p>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -272,26 +310,35 @@ const SelectOption = ({
name, name,
inputHandler, inputHandler,
value, value,
data // passing the data from parent data, // passing the data from parent
}) => { }) => {
return ( return (
<div className="input-com mb-7"> <div className="input-com mb-7">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<label <label
className="input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5" className="input-label text-[#181c32] dark:text-white text-[15px] font-semibold block mb-2.5"
htmlFor={name} htmlFor={name}
> >
{label} {label}
</label> </label>
</div> </div>
<div> <div>
<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 " onChange={inputHandler} value={value}> <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 "
onChange={inputHandler}
value={value}
>
<option value={""}>Select your Country</option> <option value={""}>Select your Country</option>
{data?.length > 0 && data?.map((item, idx) => ( {data?.length > 0 &&
<option value={item[0]} key={idx}>{item[1]}</option> data?.map((item, idx) => (
))} <option value={item[0]} key={idx}>
{item[1]}
</option>
))}
</select> </select>
</div> </div>
</div> </div>
) );
} };
@@ -0,0 +1,239 @@
import { useState, useEffect, useCallback } from "react";
import { useLocation, Link, useNavigate } from "react-router-dom";
import AuthLayout from "../AuthLayout";
import InputCom from "../../Helpers/Inputs/InputCom";
import usersService from "../../../services/UsersService";
import WrenchBoard from "../../../assets/images/wrenchboard.png";
import debounce from "../../../hooks/debounce";
export default function VerifyLink() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [msgError, setMsgError] = useState("");
const [linkLoader, setLinkLoader] = useState(false);
const [pageLoader, setPageLoader] = useState(true);
const [linkSuccess, setLinkSuccess] = useState(true);
const navigate = useNavigate();
const location = useLocation();
const queryParams = new URLSearchParams(location?.search);
const token = queryParams.get("vlnk");
const userApi = new usersService();
// email
const handleEmail = (e) => {
setEmail(e.target.value);
};
// password
const handlePassword = (e) => {
setPassword(e.target.value);
};
// if verification is okay. set a complete signup form
const completeSignup = async () => {
if (email === "" && password === "") {
setMsgError("Please fill in fields");
}
try {
if (email !== "" && password !== "") {
setLinkLoader(true);
var postData = {
username: email,
password: password,
login_mode: 100,
sessionid: "STARTER-NOTREAL",
verify_link: token,
action: 11012,
};
const res = await userApi.CompleteSignUp(postData);
if (res.status === 200) {
const { data } = res;
if (
data?.status > 0 &&
data?.internal_return == 100 &&
data?.session != ""
) {
localStorage.setItem("email", `${data?.email}`);
localStorage.setItem("member_id", `${data?.member_id}`);
localStorage.setItem("session_token", `${data?.session}`);
localStorage.setItem("session", `${data?.session}`);
navigate("/", { replace: true });
setLinkLoader(false);
} else {
setLinkLoader(false);
setMsgError("Invalid Link or Password Combination");
}
} else {
setLinkLoader(false);
setLinkSuccess(false)
setMsgError("An error occurred");
}
}
} catch (error) {
setLinkLoader(false);
setLinkSuccess(false)
throw new Error(error);
} finally {
setTimeout(() => {
setMsgError(null);
}, process.env.REACT_APP_SIGNUP_ERROR_TIMEOUT);
}
};
// for verifying the incoming verification link and render the correct component
const verifyEmail = useCallback(async (code) => {
try {
const verifyRes = await userApi.verifyEmail(code);
if (verifyRes.status === 200) {
let { data } = verifyRes;
if (
data &&
data.internal_return >= 0 &&
data.status_text === "Link Verfied"
) {
setPageLoader(false);
} else {
setPageLoader(false);
setLinkSuccess(false);
}
}
} catch (error) {
setPageLoader(false);
setLinkSuccess(false);
throw new Error(error);
}
}, []);
// delay verify requests by 10000ms
const debouncedEmail = debounce(verifyEmail, 1000);
useEffect(() => {
debouncedEmail(token);
}, []);
return (
<>
<AuthLayout slogan="Welcome to WrenchBoard">
{pageLoader ? (
<img src={WrenchBoard} alt="wrenchboard" className="h-10 mx-auto" />
) : (
<div className="w-full">
<div className="mb-12">
<Link to="#">
<img
src={WrenchBoard}
alt="wrenchboard"
className="h-10 mx-auto"
/>
</Link>
</div>
<div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center 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]">
{linkSuccess
? "Sign In to WrenchBoard"
: "Invalid verification link"}
</h1>
</div>
{/* If the verification was a success */}
{linkSuccess ? (
<SuccessfulComponent
email={email}
password={password}
handleEmail={handleEmail}
handlePassword={handlePassword}
onSubmit={completeSignup}
msgErr={msgError}
loader={linkLoader}
/>
) : (
<ErrorComponent onClick={() => navigate("/login")} />
)}
</div>
</div>
</div>
)}
</AuthLayout>
</>
);
}
const SuccessfulComponent = ({
onSubmit,
password,
handlePassword,
email,
handleEmail,
msgErr,
loader,
}) => (
<div className="input-area">
{/* INPUT */}
<div className="mb-5">
<InputCom
value={email}
inputHandler={handleEmail}
placeholder="support@mermsemr.com"
label="Email"
name="email"
type="email"
iconName="message"
/>
</div>
<div className="mb-5">
<InputCom
value={password}
inputHandler={handlePassword}
placeholder="● ● ● ● ● ●"
label="Password"
name="password"
type="password"
iconName="password"
/>
</div>
{msgErr && (
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">
{msgErr}
</div>
)}
<div className="signin-area mb-3.5">
<button
onClick={onSubmit}
type="button"
className={`btn-login rounded-[0.475rem] mb-6 text-xl text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center text-[15px]`}
>
{loader ? (
<div className="signup btn-loader"></div>
) : (
<span>Continue</span>
)}
</button>
</div>
</div>
);
const ErrorComponent = ({ onClick }) => (
<div className="input-area">
<div className="my-5">
<p className="text-[14px] leading-[19px] text-center text-[#181c32]">
This error occurs because you have already verified this link or the
link has expired. Try login or reset password. If none worked, try to
create the account from the start.
</p>
</div>
<div className="signin-area flex justify-center mb-3.5">
<button
onClick={onClick}
type="button"
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-[#009ef7] hover:text-white flex justify-center bg-[#f1faff] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
>
<span>Return Home</span>
</button>
</div>
</div>
);
+36 -29
View File
@@ -1,42 +1,49 @@
import React from "react"; import { useNavigate, Link } from "react-router-dom";
import titleShape from "../../../assets/images/shape/text-shape-three.svg";
import AuthLayout from "../AuthLayout"; import AuthLayout from "../AuthLayout";
import Otp from "./Otp"; import WrenchBoard from "../../../assets/images/wrenchboard.png"
export default function VerifyYou() { export default function VerifyYou() {
const navigate = useNavigate()
return ( return (
<> <>
<AuthLayout <AuthLayout
slogan="Welcome to WrenchBoard" slogan="Welcome to WrenchBoard"
> >
<div className="content-wrapper xl:bg-white dark:bg-dark-white w-full sm:w-auto px-5 xl:px-[70px] 2xl:px-[100px] h-[818px] rounded-xl flex flex-col justify-center"> <div className="w-full">
<div> <div className='mb-12'>
<div className="title-area flex flex-col justify-center items-center relative text-center mb-8"> <Link to='#'>
<h1 className="sm:text-5xl text-4xl font-bold leading-[74px] text-dark-gray dark:text-white"> <img src={WrenchBoard} alt="wrenchboard" className="h-10 mx-auto" />
Verification Code </Link>
</h1> </div>
<div className="shape sm:w-[377px] w-[270px] -mt-5 ml-5"> <div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5">
<img src={titleShape} alt="shape" /> <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]">
Let's verify your email now
</h1>
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">Check your email.</span>
</div> </div>
<div className="input-area">
<div className="mb-5">
<p className="text-[14px] leading-[19px] text-center text-[#181c32]">
<b>Verify Email.</b> Help us secure your WrenchBoard account by verifying your email registration address. Verification will let you access all of WrenchBoard's features.
</p>
</div>
<div className="mb-5">
<p className="text-[14px] leading-[19px] text-center text-[#181c32]">
If you do not receive the confirmation message within a few minutes of signing up, please check your Junk E-mail folder just in case the confirmation email got delivered there instead of your inbox. If so, select the confirmation message and click Not Junk, which will allow future messages to get through.
</p>
</div>
</div>
<div className="signin-area flex justify-center mb-3.5">
<button
onClick={() => navigate("/")}
type="button"
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-[#009ef7] hover:text-white flex justify-center bg-[#f1faff] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
>
<span>Return Home</span>
</button>
</div> </div>
<div className="input-area">
<Otp />
<div className="signin-area mb-3.5">
<a
href="/update-password"
className="w-full rounded-[50px] h-[58px] mb-6 text-xl text-white font-bold flex justify-center bg-purple items-center"
>
Continue
</a>
</div>
<div className="resend-code flex justify-center">
<p className="text-lg text-thin-light-gray font-normal">
Dontt have an aceount ?
<a href="#" className="ml-2 text-dark-gray dark:text-white font-bold">
Please resend
</a>
</p>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -0,0 +1,26 @@
import React from "react";
import { Link } from "react-router-dom";
import localImgLoad from "../../lib/localImgLoad";
export default function HomeBannerOffersCard(props) {
return (
<Link
to="/my-collection/collection-item"
className="item w-full block group banner-630-340"
>
<div className="flex flex-col justify-between h-full">
<div className="content flex justify-between items-center mb-5">
<div>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
<>Ab hshsh jsjsj hshdhhdjjd</>
</h1>
</div>
{/*<SelectBox datas={filterDatas} action={dataSetHandler} />*/}
</div>
<div className="h-[233px]">
BEST IMAGE IN THE WORLLD
</div>
</div>
</Link>
);
}
+2 -2
View File
@@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import Lottie from "react-lottie"; // import Lottie from "react-lottie";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import * as animationData from "../../assets/images/Lotties/77618-website-404-error-animation.json"; import * as animationData from "../../assets/images/Lotties/77618-website-404-error-animation.json";
@@ -16,7 +16,7 @@ export default function FourZeroFour() {
return ( return (
<div className="flex justify-center items-center w-full h-screen bg-[#232247]"> <div className="flex justify-center items-center w-full h-screen bg-[#232247]">
<div> <div>
<Lottie options={defaultOptions} width={600} height={600} /> {/* <Lottie options={defaultOptions} width={600} height={600} /> */}
<div className="flex justify-center"> <div className="flex justify-center">
<button <button
onClick={() => navigate(-1)} onClick={() => navigate(-1)}
@@ -1,4 +1,4 @@
import React from "react"; import React, { useRef } from "react";
import Icons from "../../Icons"; import Icons from "../../Icons";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
@@ -14,30 +14,80 @@ export default function InputCom({
forgotPassword, forgotPassword,
onClick, onClick,
disable, disable,
blurHandler, blurHandler
}) { }) {
const inputRef = useRef(null)
// Entry Validation
// for Min Length:
const minLengthValidation = () => {
if (inputRef && inputRef?.current && inputRef?.current?.name === 'email') {
return 7
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'first_name') {
return 3
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'last_name') {
return 3
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'address') {
return 5
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'password') {
return 8
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'state') {
return 3
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'province') {
return 3
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'city') {
return 3
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'amount') {
return 1
}
}
// for MaxLength
const maxLengthValidation = () => {
if (inputRef && inputRef?.current && inputRef?.current?.name === 'email') {
return 35
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'first_name') {
return 25
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'last_name') {
return 25
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'address') {
return 49
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'password') {
return 15
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'state') {
return 25
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'province') {
return 25
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'city') {
return 25
} else if (inputRef && inputRef?.current && inputRef?.current?.name === 'amount') {
return 9
}
}
return ( return (
<div className="input-com"> <div className="input-com">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
{label && ( {label && (
<label <label
className="input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5" className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block mb-2.5"
htmlFor={name} htmlFor={name}
> >
{label} {label}
</label> </label>
)} )}
{forgotPassword && <Link to="/forgot-password" className="text-base text-[#4687ba] hover:text-[#009ef7]">Forgot Password?</Link>} {forgotPassword && <Link to="/forgot-password" className="text-[13.975px] leading-[20.9625px] text-[#019ef7] hover:text-[#009ef7]">Forgot Password?</Link>}
</div> </div>
<div className="input-wrapper border border-[#f5f8fa]] dark:border-[#5e6278] w-full rounded-[0.475rem] h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base "> <div className="input-wrapper border border-[#f5f8fa]] dark:border-[#5e6278] w-full rounded-[0.475rem] h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base ">
<input <input
placeholder={placeholder} placeholder={placeholder}
value={value} value={value}
onChange={inputHandler} onChange={inputHandler}
className="input-field placeholder:text-base text-bese px-6 text-dark-gray dark:text-white w-full h-full bg-[#FAFAFA] dark:bg-[#11131F] focus:ring-0 focus:outline-none" className="input-field placeholder:text-base px-6 text-dark-gray dark:text-white w-full h-full bg-[#FAFAFA] dark:bg-[#11131F] focus:ring-0 focus:outline-none"
type={type} type={type}
id={name} id={name}
name={name} name={name}
minLength={minLengthValidation()}
maxLength={maxLengthValidation()}
ref={inputRef}
readOnly={disable} readOnly={disable}
onBlur={blurHandler} onBlur={blurHandler}
/> />
+14 -5
View File
@@ -9,6 +9,7 @@ import slider3 from "../../assets/images/slider-3.jpg";
import CountDown from "../Helpers/CountDown"; import CountDown from "../Helpers/CountDown";
import SliderCom from "../Helpers/SliderCom"; import SliderCom from "../Helpers/SliderCom";
import HomeSliders from "./HomeSliders"; import HomeSliders from "./HomeSliders";
import { useSelector } from "react-redux";
export default function Hero({ className }) { export default function Hero({ className }) {
const settings = { const settings = {
@@ -18,7 +19,10 @@ export default function Hero({ className }) {
infinite: true, infinite: true,
swipe: true, swipe: true,
}; };
const sildeData =null;
const [addFavorite, setValue] = useState(false); const [addFavorite, setValue] = useState(false);
const {userDetails} = useSelector((state) => state?.userDetails)
const favoriteHandler = () => { const favoriteHandler = () => {
if (!addFavorite) { if (!addFavorite) {
setValue(true); setValue(true);
@@ -28,6 +32,11 @@ export default function Hero({ className }) {
toast.warn("Remove to Favorite List"); toast.warn("Remove to Favorite List");
} }
}; };
let loginDate = userDetails?.last_login.split(' ')[0]
let {firstname, lastname, email, profile_pic} = userDetails
let userEmail = email.split('@')[0]
return ( return (
<div <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 lg:h-[444px] h-full lg:flex lg:p-8 p-4 justify-between items-center lg:space-x-28 rounded-2xl overflow-hidden ${
@@ -46,19 +55,19 @@ export default function Hero({ className }) {
Welcome Welcome
</h1> </h1>
<span className="text-[18px] font-thin tracking-wide text-white"> <span className="text-[18px] font-thin tracking-wide text-white">
Last Login : 10-10-2026 Last Login : {loginDate}
</span> </span>
</div> </div>
{/* user */} {/* user */}
<div className="flex items-center space-x-3"> <div className="flex items-center space-x-3">
<div className="w-14 h-14 flex justify-center items-center rounded-full overflow-hidden"> <div className="w-14 h-14 flex justify-center items-center rounded-full overflow-hidden">
<img src={heroUser} alt="" /> <img src={profile_pic != '' ? profile_pic : heroUser} alt="" />
</div> </div>
<div> <div>
<p className="text-xl tracking-wide font-bold antise text-white"> <p className="text-xl tracking-wide font-bold antise text-white">
Brokln Simons {`${firstname} ${lastname}`}
</p> </p>
<p className="text-sm tracking-wide text-white">@broklinslam_75</p> <p className="text-sm tracking-wide text-white">@{userEmail}</p>
</div> </div>
</div> </div>
{/* countdown */} {/* countdown */}
@@ -96,7 +105,7 @@ export default function Hero({ className }) {
</Link> </Link>
</div> </div>
</div> </div>
<HomeSliders settings={settings} /> <HomeSliders settings={settings} sideData={sildeData}/>
</div> </div>
); );
} }
+4
View File
@@ -2,6 +2,7 @@ import SliderCom from "../Helpers/SliderCom";
import slider1 from "../../assets/images/slider-1.jpg"; import slider1 from "../../assets/images/slider-1.jpg";
import slider2 from "../../assets/images/slider-2.jpg"; import slider2 from "../../assets/images/slider-2.jpg";
import slider3 from "../../assets/images/slider-3.jpg"; import slider3 from "../../assets/images/slider-3.jpg";
import HomeBannerOffersCard from "../Cards/HomeBannerOffersCard";
export default function HomeSliders(props) { export default function HomeSliders(props) {
@@ -20,6 +21,9 @@ export default function HomeSliders(props) {
<div className="item w-full h-full bg-white dark:bg-dark-white rounded-2xl overflow-hidden"> <div className="item w-full h-full bg-white dark:bg-dark-white rounded-2xl overflow-hidden">
<img src={slider3} alt="slider" className="w-full h-full" /> <img src={slider3} alt="slider" className="w-full h-full" />
</div> </div>
<div className="item w-full h-full bg-white dark:bg-dark-white rounded-2xl overflow-hidden">
<HomeBannerOffersCard />
</div>
</SliderCom> </SliderCom>
</div> </div>
</div> </div>
+5 -1
View File
@@ -10,6 +10,8 @@ import UpdateTable from "./UpdateTable";
import HomeTaskDisplay from "./HomeTaskDisplay"; import HomeTaskDisplay from "./HomeTaskDisplay";
import UsersService from "../../services/UsersService"; import UsersService from "../../services/UsersService";
import usersService from "../../services/UsersService"; import usersService from "../../services/UsersService";
import { useSelector } from "react-redux";
export default function Home() { export default function Home() {
const trending = datas.datas; const trending = datas.datas;
@@ -18,10 +20,12 @@ export default function Home() {
const userApi = new usersService(); const userApi = new usersService();
const homeData = userApi.getHomeDate(); const homeData = userApi.getHomeDate();
const {userDetails} = useSelector((state) => state?.userDetails)
return ( return (
<Layout> <Layout>
<div className="home-page-wrapper"> <div className="home-page-wrapper">
<Hero className="mb-10" /> <Hero className="mb-10" data={userDetails} />
{/* <CreateNft /> {/* <CreateNft />
<TrendingSection trending={trending} className="mb-10" />*/} <TrendingSection trending={trending} className="mb-10" />*/}
<HomeTaskDisplay <HomeTaskDisplay
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -4,11 +4,12 @@ import Layout from "../Partials/Layout";
import MyJobTable from "./MyJobTable"; import MyJobTable from "./MyJobTable";
import CommonHead from "../UserHeader/CommonHead"; import CommonHead from "../UserHeader/CommonHead";
export default function MyJobs() { export default function MyJobs(props) {
const [selectTab, setValue] = useState("today"); const [selectTab, setValue] = useState("today");
const filterHandler = (value) => { const filterHandler = (value) => {
setValue(value); setValue(value);
}; };
console.log("AMEYE LOC1", props.MyJobList);
return ( return (
<Layout> <Layout>
<CommonHead /> <CommonHead />
@@ -32,7 +33,7 @@ export default function MyJobs() {
</div> </div>
</div> </div>
</div> </div>
<MyJobTable /> <MyJobTable MyJobList={props.MyJobList} />
</div> </div>
</div> </div>
</Layout> </Layout>
+24 -8
View File
@@ -1,24 +1,39 @@
import React, {useState} from 'react' import React, {useState} from 'react'
import RecentActivityTable from './WalletComponent/RecentActivityTable' import RecentActivityTable from './WalletComponent/RecentActivityTable'
import LoadingSpinner from '../Spinners/LoadingSpinner' import LoadingSpinner from '../Spinners/LoadingSpinner'
import { useNavigate } from 'react-router-dom'
function AddFund({payment}) { function AddFund({payment}) {
//STATE FOR CONTROLLED INPUTS const navigate = useNavigate()
let [inputs, setInputs] = useState('0')
//STATE FOR CONTROLLED INPUT
let [input, setInput] = useState('0')
let [inputError, setInputError] = useState('')
// FUNCTION TO HANDLE INPUT CHANGE // FUNCTION TO HANDLE INPUT CHANGE
const handleChange = ({target:{name, value}}) => { const handleChange = ({target:{name, value}}) => {
setInputs(value) setInput(value)
} }
//FUNCTION TO HANDLE SUBMIT //FUNCTION TO HANDLE SUBMIT
const handleSubmit = (e) => { const handleSubmit = () => {
e.preventDefault(); setInputError('')
if(!input || input == '0'){
setInputError('Please Enter Amount')
return
}
//valid inputs before submitting. Just for texting remove later if(isNaN(input)){
setInputError('Amount must be a Number')
return
}
const stateData = {amount: Number(input)}
navigate('confirm-add-fund', {state: stateData})
setInputs('') setInput('')
} }
return ( return (
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin"> <div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
@@ -30,7 +45,7 @@ function AddFund({payment}) {
<div className='md:flex items-center'> <div className='md:flex items-center'>
<label className='w-full md:w-2/4 text-slate-600 text-lg'>Amount(Naira) <span className='text-red-500'>*</span></label> <label className='w-full md:w-2/4 text-slate-600 text-lg'>Amount(Naira) <span className='text-red-500'>*</span></label>
<input className='w-full md:w-2/4 p-3 text-lg text-right bg-slate-100 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg' <input className='w-full md:w-2/4 p-3 text-lg text-right bg-slate-100 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg'
value={inputs} value={input}
name='amount' name='amount'
type="text" type="text"
placeholder='Amount' placeholder='Amount'
@@ -38,6 +53,7 @@ function AddFund({payment}) {
onChange={handleChange} onChange={handleChange}
/> />
</div> </div>
{inputError && <p className='text-base text-red-500'>{inputError}</p>}
</form> </form>
<hr /> <hr />
<div className='md:p-8 p-4 add-fund-btn flex justify-end items-center py-4'> <div className='md:p-8 p-4 add-fund-btn flex justify-end items-center py-4'>
+339 -135
View File
@@ -1,161 +1,365 @@
import React, {useState} from 'react' import React, {useEffect, useState} from 'react'
import { Link } from 'react-router-dom' import { Link, useNavigate } from 'react-router-dom'
import Icons from '../Helpers/Icons' import Icons from '../Helpers/Icons'
import usersService from '../../services/UsersService'
import InputCom from '../Helpers/Inputs/InputCom'
import LoadingSpinner from '../Spinners/LoadingSpinner'
import {toast} from 'react-toastify'
import {Formik, Form} from 'formik'
import * as Yup from 'yup'
const validationSchema = Yup.object().shape({
firstname: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('Firstname is required'),
lastname: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('Lastname is required'),
country: Yup.string()
.min(1, 'Minimum 1 characters')
.max(25, 'Maximum 25 characters')
.required('Country is required'),
bank: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('Bank name is required'),
accountNumber: Yup.string()
.matches(/\d/, "must be a number")
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('Account Number is required'),
repeatAccountNumber: Yup.string()
.required('Repeat Account Number is required')
.oneOf([Yup.ref('accountNumber'), null], 'Must match Account Number'),
accountType: Yup.string()
.min(1, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('Account Type is required'),
city: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('City is required'),
state: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('State is required'),
})
const initialValues = {
firstname: '',
lastname: '',
country: '',
bank: '',
accountNumber: '',
repeatAccountNumber: '',
accountType: '',
state: '',
city: ''
}
function AddRecipient() { function AddRecipient() {
//STATE FOR CONTROLLED INPUTS const apiURL = new usersService()
let [inputs, setInputs] = useState({
firstname: '', const navigate = useNavigate()
lastname: '',
country: '', let [requestStatus, setRequestStatus] = useState({message: '', loading: false, status: false})
'bank-name': '',
'account-number': '', let [allCountries, setAllCountries] = useState({ // STATE TO HOLD LIST OF COUNTRIES
'repeat-account-number': '', loading: true,
'account-type': '', data: []
state: '',
city: ''
}) })
// FUNCTION TO HANDLE INPUT CHANGE let [bankName, setBankName] = useState({ // STATE TO HOLD LIST OF BANK NAME
const handleChange = ({target:{name, value}}) => { loading: true,
setInputs(prev => ({...prev, [name]:value})) data: []
})
let [accType, setAccType] = useState({ // STATE TO HOLD LIST ACCOUNT TYPE
loading: true,
data: []
})
//FUNCTION TO HANDLE ADD RECIPIENT SUBMIT
const handleSubmit = (values, helpers) => {
setRequestStatus({message: '', loading: true, status: false})
let reqData = { //REQUEST DATA FOR API CALL
firstname: values.firstname,
lastname: values.lastname,
bank_code: values.bank,
account_no: values.accountNumber,
account_type: values.accountType,
country: values.country,
state: values.state,
city: values.city
}
//CALL TO ADD RECIPIENT API
apiURL.addRecipient(reqData).then((res)=>{
if(res.data.internal_return < 0){
setRequestStatus({message: 'could not add recipient, try again!', loading: false, status: true})
return
}
// setRequestStatus({message: 'Recipient Added Successfully!', loading: false, status: true})
toast.success("Recipient Added Successfully!");
setTimeout(()=>{navigate('/my-wallet/transfer-fund',{replace:true})},1000)
}).catch((error)=>{
setRequestStatus({message: 'Opps! an error occured! Try again later', loading: false, status: false})
})
} }
//FUNCTION TO HANDLE SUBMIT
const handleSubmit = (e) => {
e.preventDefault();
//valid inputs before submitting. Just for texting remove later // FUNCTION TO GET COUNTRIES
const getCountry = ()=> {
// setInputs((prev)=>{ apiURL.getSignupCountryData().then((res)=>{
// for(let input in prev){ if(res.data.internal_return < 0){
// prev[input] = '' setAllCountries(prev => ({loading: false, data: []}))
// } return
// }) }
// RETURN INPUTS TO EMPTY STRING setAllCountries(prev => ({loading: false, data:res.data.signup_country}))
setInputs({ }).catch((error)=>{
firstname: '', setAllCountries(prev => ({loading: false, data: []}))
lastname: '',
country: '',
'bank-name': '',
'account-number': '',
'repeat-account-number': '',
'account-type': '',
state: '',
city: ''
}) })
} }
// END OF FUNCTION TO GET COUNTRIES
// FUNCTION TO GET COUNTRY BANK
const getCountryBank = ()=> {
apiURL.getCountryBank().then((res)=>{
if(res.data.internal_return < 0){
setBankName(prev => ({loading: false, data: []}))
return
}
setBankName(prev => ({loading: false, data:res.data.result_list}))
}).catch((error)=>{
setBankName(prev => ({loading: false, data: []}))
})
}
// END OF FUNCTION TO GET COUNTRY BANK
// FUNCTION TO GET ACCOUNT TYPES
const getAccountTypes = ()=> {
apiURL.getAccountTypes().then((res)=>{
if(res.data.internal_return < 0){
setAccType(prev => ({loading: false, data: []}))
return
}
setAccType(prev => ({loading: false, data:res.data.result_list}))
}).catch((error)=>{
setAccType(prev => ({loading: false, data: []}))
})
}
// END OF FUNCTION TO GET ACCOUNT TYPES
useEffect(()=>{
getCountry() // TO LOAD LIST COUNTRY
getCountryBank() // TO LOAD LIST COUNTRY BANK
getAccountTypes() // TO LOAD LIST ACCOUNT TYPES
},[])
return ( return (
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin"> <div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
<div className="w-full mb-10 lg:mb-0"> <div className="w-full mb-10 lg:mb-0">
<div className="w-full md:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl shadow"> <div className="w-full md:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl shadow">
<h2 className='my-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-semibold'>ADD BANK ACCOUNT</h2> <h2 className='my-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-semibold'>ADD BANK ACCOUNT</h2>
<form className='add-recipient-info px-1 md:px-[50px] lg:px-[100px]' onSubmit={handleSubmit}> <Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={handleSubmit}>
{(props)=>(
{/* inputs starts here */} <Form className='add-recipient-info px-1 md:px-[50px] lg:px-[100px]'>
<div className='add-recipient my-3 md:flex items-center justify-between'>
<label className='w-full md:w-1/4 text-slate-600 text-lg'>First Name <span className='text-red-500'>*</span></label> {/* inputs starts here */}
<input className='w-full md:w-3/4 p-3 text-lg bg-slate-100 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg' {/* firstname */}
value={inputs.firstname} <div className="xl:flex xl:space-x-7 mb-6">
name='firstname' <div className="field w-full mb-6 xl:mb-0">
type="text" <InputCom
placeholder='Account Firstname' label="Firstname"
required type="text"
onChange={handleChange} name="firstname"
/> placeholder="Account Firstname"
</div> value={props.values.firstname}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.firstname && props.touched.firstname) && <p className="text-sm text-red-500">{props.errors.firstname}</p>}
</div>
<div className='add-recipient my-3 md:flex items-center justify-between'> {/* lastname */}
<label className='w-full md:w-1/4 text-slate-600 text-lg'>Last Name <span className='text-red-500'>*</span></label> <div className="field w-full">
<input className='w-full md:w-3/4 p-3 text-lg bg-slate-100 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg' <InputCom
value={inputs.lastname} label="Lastname"
name='lastname' type="text"
type="text" name="lastname"
placeholder='Account Lastname' placeholder="Account Lastname"
required value={props.values.lastname}
onChange={handleChange} inputHandler={props.handleChange}
/> blurHandler={props.handleBlur}
</div> />
{(props.errors.lastname && props.touched.lastname) && <p className="text-sm text-red-500">{props.errors.lastname}</p>}
</div>
</div>
<div className='add-recipient my-3 md:flex items-center justify-between'>
<label className='w-full md:w-1/4 text-slate-600 text-lg'>Country <span className='text-red-500'>*</span></label> <div className="xl:flex xl:space-x-7 mb-6">
<select className='mt-2 w-full md:w-3/4 p-3 text-lg bg-white rounded-md border border-slate-300 outline-0' name='country' onChange={handleChange}> {/* country */}
<option className='text-slate-500 text-lg' value="">Select...</option> <div className='add-recipient w-full mb-6 xl:mb-0'>
</select> <label className='input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Country <span className='text-red-500'>*</span></label>
</div> <select className='w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0' name='country'
value={props.values.country}
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{allCountries.loading ?
<option className='text-slate-500 text-lg' value="">Loading...</option>
:
allCountries.data.length ?
<>
<option className='text-slate-500 text-lg' value="">Select...</option>
{allCountries.data.map((item, index)=>(
<option key={index} className='text-slate-500 text-lg' value={item[0]}>{item[1]}</option>
))}
</>
:
<option className='text-slate-500 text-lg' value="">No Options Found! Try Again</option>
}
</select>
{(props.errors.country && props.touched.country) && <p className="text-sm text-red-500">{props.errors.country}</p>}
</div>
{/* bank name */}
<div className='add-recipient w-full'>
<label className='input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Bank Name <span className='text-red-500'>*</span></label>
<select className='w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0' name='bank'
value={props.values.bank}
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{bankName.loading ?
<option className='text-slate-500 text-lg' value="">Loading...</option>
:
bankName.data.length ?
<>
<option className='text-slate-500 text-lg' value="">Select...</option>
{bankName.data.map((item, index)=>(
<option key={index} className='text-slate-500 text-lg' value={item.code}>{item.name}</option>
))}
</>
:
<option className='text-slate-500 text-lg' value="">No Options Found! Try Again</option>
}
</select>
{(props.errors.bank && props.touched.bank) && <p className="text-sm text-red-500">{props.errors.bank}</p>}
</div>
</div>
<div className='add-recipient my-3 md:flex items-center justify-between'> {/* ACCOUNT NUMBER */}
<label className='w-full md:w-1/4 text-slate-600 text-lg'>Bank Name <span className='text-red-500'>*</span></label> <div className="xl:flex xl:space-x-7 mb-6">
<select className='mt-2 w-full md:w-3/4 p-3 text-lg bg-white rounded-md border border-slate-300 outline-0' name='bank-name' onChange={handleChange}> <div className="field w-full mb-6 xl:mb-0">
<option className='text-slate-500 text-lg' value="">Select...</option> <InputCom
</select> label="Account Number"
</div> type="text"
name="accountNumber"
placeholder="Account No"
value={props.values.accountNumber}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.accountNumber && props.touched.accountNumber) && <p className="text-sm text-red-500">{props.errors.accountNumber}</p>}
</div>
<div className='add-recipient my-3 md:flex items-center justify-between'> {/* REPEAT ACCT. NUMBER */}
<label className='w-full md:w-1/4 text-slate-600 text-lg'>Account Number <span className='text-red-500'>*</span></label> <div className="field w-full">
<input className='w-full md:w-3/4 p-3 text-lg bg-slate-100 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg' <InputCom
value={inputs['account-number']} label="Repeat Account Number"
name='account-number' type="text"
type="text" name="repeatAccountNumber"
placeholder='Account No' placeholder="Repeat Account Number"
required value={props.values.repeatAccountNumber}
onChange={handleChange} inputHandler={props.handleChange}
/> blurHandler={props.handleBlur}
</div> />
{(props.errors.repeatAccountNumber && props.touched.repeatAccountNumber) && <p className="text-sm text-red-500">{props.errors.repeatAccountNumber}</p>}
</div>
</div>
<div className='add-recipient my-3 md:flex items-center justify-between'> <div className="xl:flex xl:space-x-7 mb-6">
<label className='w-full md:w-1/4 text-slate-600 text-lg'>Repeat Account Number <span className='text-red-500'>*</span></label> {/* Account Type */}
<input className='w-full md:w-3/4 p-3 text-lg bg-slate-100 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg' <div className='add-recipient w-full'>
value={inputs['repeat-account-number']} <label className='input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Account Type <span className='text-red-500'>*</span></label>
name='repeat-account-number' <select className='w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0' name='accountType'
type="text" value={props.values.accountType}
placeholder='Repeat Account No' onChange={props.handleChange}
required onBlur={props.handleBlur}
onChange={handleChange} >
/> {accType.loading ?
</div> <option className='text-slate-500 text-lg' value="">Loading...</option>
:
accType.data.length ?
<>
<option className='text-slate-500 text-lg' value="">Select...</option>
{accType.data.map((item, index)=>(
<option key={index} className='text-slate-500 text-lg' value={item.value}>{item.name}</option>
))}
</>
:
<option className='text-slate-500 text-lg' value="">No Options Found! Try Again</option>
}
</select>
{(props.errors.accountType && props.touched.accountType) && <p className="text-sm text-red-500">{props.errors.accountType}</p>}
</div>
</div>
<div className='add-recipient my-3 md:flex items-center justify-between'> {/* state */}
<label className='w-full md:w-1/4 text-slate-600 text-lg'>Account type <span className='text-red-500'>*</span></label> <div className="xl:flex xl:space-x-7 mb-6">
<select className='mt-2 w-full md:w-3/4 p-3 text-lg bg-white rounded-md border border-slate-300 outline-0' name='account-type' onChange={handleChange}> <div className="field w-full mb-6 xl:mb-0">
<option className='text-slate-500 text-lg' value="">Select...</option> <InputCom
</select> label="State"
</div> type="text"
name="state"
placeholder="State/Province"
value={props.values.state}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.state && props.touched.state) && <p className="text-sm text-red-500">{props.errors.state}</p>}
</div>
<div className='add-recipient my-3 md:flex items-center justify-between'> {/* city */}
<label className='w-full md:w-1/4 text-slate-600 text-lg'>State/Province <span className='text-red-500'>*</span></label> <div className="field w-full">
<input className='w-full md:w-3/4 p-3 text-lg bg-slate-100 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg' <InputCom
value={inputs.state} label="City"
name='state' type="text"
type="text" name="city"
placeholder='State' placeholder="City"
required value={props.values.city}
onChange={handleChange} inputHandler={props.handleChange}
/> blurHandler={props.handleBlur}
</div> />
{(props.errors.city && props.touched.city) && <p className="text-sm text-red-500">{props.errors.city}</p>}
</div>
</div>
{/* end of inputs starts here */}
<div className='add-recipient my-3 md:flex items-center justify-between'> {/* REQUEST ERROR DISPLAY */}
<label className='w-full md:w-1/4 text-slate-600 text-lg'>City <span className='text-red-500'>*</span></label> {requestStatus.message && <p className='text-sm text-red-500'>{requestStatus.message}</p>}
<input className='w-full md:w-3/4 p-3 text-lg bg-slate-100 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg'
value={inputs.city}
name='city'
type="text"
placeholder='City'
required
onChange={handleChange}
/>
</div>
{/* end of inputs starts here */} <div className='add-recipient-btn flex justify-end items-center py-4'>
{requestStatus.loading ?
<div className='add-recipient-btn flex justify-end items-center py-4'> <LoadingSpinner size={6} color='sky-blue' />
<button className='text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md flex items-center space-x-1'> :
<span className='pr-2'>ADD RECIPIENT</span> <button type='submit' className='text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md flex items-center space-x-1'>
<Icons name="arrows" /> <span className='pr-2'>ADD RECIPIENT</span>
</button> <Icons name="arrows" />
</div> </button>
</form> }
</div>
</Form>
)}
</Formik>
</div> </div>
</div> </div>
+2 -2
View File
@@ -31,11 +31,11 @@ function Balance({wallet, payment, coupon, purchase}) {
</div> </div>
<div className='balance-info'> <div className='balance-info'>
<p className='py-2'>balance</p> <p className='py-2'>balance</p>
<span className='text-sm py-1 px-2 bg-green-100 text-green-500 rounded-lg'>{item.symbol}{(item.amount*1).toFixed(2)}</span> <span className='text-sm py-1 px-2 bg-green-100 text-green-500 rounded-lg'>{item.symbol}{(item.amount*0.01).toFixed(2)}</span>
</div> </div>
<div className='balance-info'> <div className='balance-info'>
<p className='py-2'>Escrow</p> <p className='py-2'>Escrow</p>
<span className='text-sm py-1 px-2 bg-red-100 text-red-500 rounded-lg'>{item.symbol}{(item.escrow*1).toFixed(2)}</span> <span className='text-sm py-1 px-2 bg-red-100 text-red-500 rounded-lg'>{item.symbol}{(item.escrow*0.01).toFixed(2)}</span>
</div> </div>
</div> </div>
+132
View File
@@ -0,0 +1,132 @@
import React, {useState, useEffect} from 'react'
import RecentActivityTable from './WalletComponent/RecentActivityTable'
import LoadingSpinner from '../Spinners/LoadingSpinner'
import InputCom from '../Helpers/Inputs/InputCom'
import {toast} from 'react-toastify'
import { useLocation, useNavigate } from 'react-router-dom'
import { useSelector } from 'react-redux'
import usersService from '../../services/UsersService'
import { FlutterWaveButton, closePaymentModal } from 'flutterwave-react-v3'
function ConfirmAddFund({payment}) {
let {userDetails} = useSelector(state => state.userDetails) // TO GET LOGGEDIN USER DETAILS
let [pageLoading, setPageLoading] = useState(true)
let [requestStatus, setRequestStatus] = useState({message: '', loading: false, status: false}) // STATE FOR API REQUEST
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'}
apiURL.startTopUp(reqData).then((res)=>{
if(res.data.internal_return < 0){
setRequestStatus({message: 'Could not finish transaction', loading: false, status: false})
toast.success('Opps! something went wrong')
}
// do something
setRequestStatus({message: 'Topup successful', loading: false, status: true})
toast.success('Account Topup was sucessful')
setTimeout(()=>{
navigate('/my-wallet', {replace: true})
window.location.reload(true)
}, 1000)
}).catch(err => {
// do something
setRequestStatus({message: 'Opps! An Error Occured', loading: false, status: false})
toast.success('Opps! something went wrong')
})
}
const config = {
public_key: process.env.REACT_APP_FLUTTERWAVE_APIKEY,
tx_ref: Date.now(),
amount: state?.amount,
currency: 'NGN',
payment_options: 'card,mobilemoney,ussd',
customer: {
email: `${userDetails.email}`,
phone_number: userDetails.phone,
name: `${userDetails.lastname} ${userDetails.firstname}`
},
customizations: {
title: 'WrenchBoard',
description: 'Topup Payment',
logo: 'https://st2.depositphotos.com/4403291/7418/v/450/depositphotos_74189661-stock-illustration-online-shop-log.jpg',
},
};
const fwConfig = {
...config,
text: 'Proceed',
callback: (response) => {
onSuccessPayment()
closePaymentModal() // this will close the modal programmatically
},
onClose: () => {},
};
useEffect(()=>{
// what happens if not state redirect user
if(!state){
navigate('/my-wallet/add-fund',{replace: true})
}else{
setPageLoading(false)
}
},[])
return (
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
{pageLoading ?
<LoadingSpinner size='8' color='sky-blue' />
:
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl shadow">
<h2 className='md:p-8 p-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Confirm Add Fund To Account</h2>
<hr />
<div className='px-4 md:px-8 py-4 add-fund-info'>
<div className="field w-full mb-3">
<InputCom
label="Amount (Naira):"
type="text"
name="amount"
value={state.amount || ''}
disable={true}
/>
</div>
</div>
<hr />
<div className='md:p-8 p-4 add-fund-btn flex justify-end items-center py-4'>
<FlutterWaveButton {...fwConfig} className='text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md' />
</div>
</div>
</div>
}
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full max-h-[600px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className='text-gray-900 dark:text-white text-xl lg:text-2xl font-medium'>Recent Activity</h2>
<p className='text-base text-gray-600 dark:text-white'>Activity Report</p>
{payment.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
<RecentActivityTable payment={payment}/>
}
</div>
</div>
</div>
)
}
export default ConfirmAddFund
+168
View File
@@ -0,0 +1,168 @@
import React, {useState, useEffect} from 'react'
import {useLocation, useNavigate} from 'react-router-dom'
import RecentActivityTable from './WalletComponent/RecentActivityTable'
import LoadingSpinner from '../Spinners/LoadingSpinner'
import InputCom from '../Helpers/Inputs/InputCom'
import {toast} from 'react-toastify'
import usersService from '../../services/UsersService'
function ConfirmTransfer({payment, wallet}) {
const apiURL = new usersService()
const navigate = useNavigate()
let {state} = useLocation()
let [requestStatus, setRequestStatus] = useState({message: '', loading: false, status: false})
let [pageLoading, setPageLoading] = useState(true)
//FUNCTION TO HANDLE SUBMIT
const handleSubmit = () => {
setRequestStatus({message: '', loading: true, status: false})
let reqData = {
amount: Number(state.amount),
Fee: Number(state.fee),
recipientid: Number(state.recipientID)
}
apiURL.sendMoney(reqData).then((res)=>{
if(res.data.internal_return < 0){
setRequestStatus({message: 'Could not perform transaction', loading: false, status: false})
return
}
setRequestStatus({message: 'transfer successful', loading: false, status: true})
toast.success('Transfer sucessful')
setTimeout(()=>{
navigate('/my-wallet', {replace: true})
window.location.reload(true)
}, 1000)
}).catch(error=>{
setRequestStatus({message: 'Opps! something went wrong! Try Again', loading: false, status: false})
})
}
useEffect(()=>{
// what happens if not state redirect user
if(!state){
navigate('/my-wallet/transfer-fund',{replace: true})
}else{
setPageLoading(false)
}
},[])
return (
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
{pageLoading ?
<LoadingSpinner size='8' color='sky-blue' />
:
(
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl shadow">
<div className='px-4 md:px-8 py-4'>
{wallet.loading ?
<LoadingSpinner size='8' color='sky-blue' />
:
wallet.data.length ?
<h2 className='my-4 text-slate-500 dark:text-white text-sm xl:text-xl font-medium'>
{wallet.data.map(item => {
if(item.description == 'Naira'){
return `Withdraw from Naira Wallet : ${item.symbol}${(item.amount*0.01).toFixed(2)}`
}
})}
</h2>
:
wallet.error ?
<h2 className='my-4 text-slate-500 dark:text-white text-sm xl:text-xl font-medium'>Opps! An Error Occured</h2>
:
<h2 className='my-4 text-slate-500 dark:text-white text-sm xl:text-xl font-medium'>No Wallet Information Found!</h2>
}
</div>
<hr />
<div className='px-4 md:px-8 py-4 add-fund-info'>
<h2 className='my-2 text-slate-900 dark:text-white text-sm xl:text-xl font-medium'>Confirm Withdraw to Account</h2>
{/* AMOUNT */}
<div className="field w-full mb-3">
<InputCom
label="Amount:"
type="text"
name="amount"
value={state?.amount || ''}
disable={true}
/>
</div>
{/* RECIPIENT ACC: */}
<div className="field w-full mb-3">
<InputCom
label="Recipient Acc:"
type="text"
name="recipient"
value={state?.details.recipient || ''}
disable={true}
/>
</div>
{/* PROCESSING FEE: */}
<div className="field w-full mb-3">
<InputCom
label="Processing Fee:"
type="text"
name="processingFee"
value={state?.fee || ''}
disable={true}
/>
</div>
{/* TOTAL */}
<div className="field w-full mb-3">
<InputCom
label="Total"
type="text"
name="total"
value={state?.total || ''}
disable={true}
/>
</div>
{/* COMMENT/NOTE */}
<div className="field w-full mb-3">
<InputCom
label="Comment/Note:"
type="text"
name="comment"
value={state?.comment || ''}
disable={true}
/>
</div>
</div>
<hr />
{requestStatus.message && <p className={`text-base ${requestStatus.status? 'text-green-500' : 'text-red-500'} px-4 md:px-8 py-4`}>{requestStatus.message}</p>}
<div className='px-4 md:px-8 py-4 add-fund-btn flex justify-end items-center'>
{requestStatus.loading ?
<LoadingSpinner size='8' color='sky-blue' />
:
<button onClick={handleSubmit} className='text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md'>Transfer</button>
}
</div>
</div>
</div>
)
}
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full px-4 md:px-8 py-4 h-full max-h-[800px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className='text-gray-900 dark:text-white text-xl lg:text-2xl font-medium'>Recent Activity</h2>
<p className='text-base text-gray-600 dark:text-white'>Activity Report</p>
{payment.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
<RecentActivityTable payment={payment}/>
}
</div>
</div>
</div>
)
}
export default ConfirmTransfer
+170 -137
View File
@@ -1,29 +1,48 @@
import React, {useEffect, useState} from 'react' import React, {useEffect, useState} from 'react'
import { Link } from 'react-router-dom' import { Link, useNavigate } from 'react-router-dom'
import RecentActivityTable from './WalletComponent/RecentActivityTable' import RecentActivityTable from './WalletComponent/RecentActivityTable'
import LoadingSpinner from '../Spinners/LoadingSpinner' import LoadingSpinner from '../Spinners/LoadingSpinner'
import InputCom from '../Helpers/Inputs/InputCom'
import usersService from '../../services/UsersService' import usersService from '../../services/UsersService'
import {toast} from 'react-toastify'
import {Formik, Form} from 'formik'
import * as Yup from 'yup'
const validationSchema = Yup.object().shape({
amount: Yup.number()
.typeError("you must specify a number")
.min(1, 'Amount must be greater than 0')
.required('Amount is required'),
recipientID: Yup.string()
.min(1, 'Minimum 1 characters')
.max(50, 'Maximum 50 characters')
.required('Recipient is required'),
})
const initialValues = {
amount: '',
recipientID: '',
comment: '',
}
function TransferFund({payment, wallet}) { function TransferFund({payment, wallet}) {
const apiCall = new usersService() const apiCall = new usersService() // API CLASS CALL
let [newFee, setNewFee] = useState(false) const navigate = useNavigate()
let [recepients, setRecipients] = useState({ // FOR COUPON HISTORY let [requestStatus, setRequestStatus] = useState(false)
let [recipients, setRecipients] = useState({ // FOR COUPON HISTORY
loading: true, loading: true,
data: [], data: [],
error: false error: false
}) })
let [sendMoneyFee, setSendMoneyFee] = useState({fee: 0, total: 0}) // HOLD THE VALUE FOR SEND MONEY FEE let [sendMoneyFee, setSendMoneyFee] = useState({loading: false, fee: 0, total: 0}) // HOLD THE VALUE FOR SEND MONEY FEE
//STATE FOR CONTROLLED INPUTS
let [inputs, setInputs] = useState({
amount: '0',
recipient: '',
comment: ''
})
//FUNCTION TO GET RECIPIENT LIST //FUNCTION TO GET RECIPIENT LIST
const getRecipients = ()=>{ const getRecipients = ()=>{
@@ -39,158 +58,172 @@ function TransferFund({payment, wallet}) {
} }
//FUNCTION TO GET SEND MONEY FEE //FUNCTION TO GET SEND MONEY FEE
const getSendMoneyFee = ()=>{ const getSendMoneyFee = ({target:{value}})=>{
let {amount} = inputs setSendMoneyFee({loading: true, fee: 0, total: 0})
let amount = value
if(Number(amount) <= 0 || amount=='' || isNaN(amount)){ if(Number(amount) <= 0 || amount=='' || isNaN(amount)){
setSendMoneyFee({fee: 0, total: 0}) setSendMoneyFee({loading: false, fee: 0, total: 0})
return return
} }
apiCall.getSendMoneyFee(Number(amount)).then((res)=>{ apiCall.getSendMoneyFee(Number(amount)).then((res)=>{
setSendMoneyFee({fee: res.data.processing_fee, total: res.data.total_amount}) setSendMoneyFee({loading: false, fee: res.data.processing_fee, total: res.data.total_amount})
}).catch((error)=>{ }).catch((error)=>{
setSendMoneyFee({fee: 0, total: 0}) setSendMoneyFee({loading: false, fee: 0, total: 0})
}) })
} }
// FUNCTION TO HANDLE INPUT CHANGE
const handleChange = ({target:{name, value}}) => {
setInputs(prev => ({...prev, [name]:value}))
}
//FUNCTION TO HANDLE SUBMIT //FUNCTION TO HANDLE SUBMIT
const handleSubmit = (e) => { const handleSubmit = (values, helpers) => {
e.preventDefault(); setRequestStatus(true)
let recipientDetails = recipients.data?.filter(item => item.recipient_id == values.recipientID)
let stateData = {...values, ...sendMoneyFee, details:{...recipientDetails[0]}}
//valid inputs before submitting. Just for texting remove later. check amoutn to be number setTimeout(()=>{
setRequestStatus(false)
setInputs({ navigate('confirm-transfer', {state: stateData})
amount: '0', }, 1000)
recipient: '',
comment: ''
})
} }
useEffect(()=>{ useEffect(()=>{
getRecipients() getRecipients()
getSendMoneyFee() },[])
},[newFee])
return ( return (
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin"> <div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
<div className="lg:w-1/2 w-full mb-10 lg:mb-0"> <div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="add-fund w-full md:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl shadow"> <div className="add-fund w-full md:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl shadow">
<form className='transfer-fund-info' onSubmit={handleSubmit}> <Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={handleSubmit}>
{wallet.loading ? {(props)=>{
<LoadingSpinner size='8' color='sky-blue' /> return (
: <Form className='transfer-fund-info'>
wallet.data.length ? {wallet.loading ?
<h2 className='my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'> <LoadingSpinner size='8' color='sky-blue' />
{wallet.data.map(item => { :
if(item.description == 'Naira'){ wallet.data.length ?
return `Withdraw from Naira Wallet : ${item.symbol}${(item.amount*1).toFixed(2)}` <h2 className='my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>
} {wallet.data.map(item => {
})} if(item.description == 'Naira'){
</h2> return `Withdraw from Naira Wallet : ${item.symbol}${(item.amount*0.01).toFixed(2)}`
: }
wallet.error ? })}
<h2 className='my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Opps! An Error Occured</h2> </h2>
: :
<h2 className='my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>No Wallet Information Found!</h2> wallet.error ?
} <h2 className='my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Opps! An Error Occured</h2>
<div className='my-3 md:flex items-center justify-between space-x-2'> :
<div className='transfer-input w-full md:w-1/2'> <h2 className='my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>No Wallet Information Found!</h2>
<label className='w-full text-slate-600 text-lg'>Amount <span className='text-red-500'>*</span></label>
<input className='w-full p-3 text-lg text-right bg-slate-100 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg'
value={inputs.amount}
name='amount'
type="text"
placeholder='Amount'
required
onChange={handleChange}
onMouseEnter={()=>{setNewFee(false)}}
onMouseLeave={()=>{setNewFee(true)}}
/>
</div>
<div className='transfer-input w-full md:w-1/2'>
<label className='w-full text-slate-600 text-lg'>Fee <span className='text-red-500'>*</span></label>
<input className='w-full p-3 text-lg text-right bg-slate-100 opacity-50 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg'
value={sendMoneyFee.fee}
name='fee'
type="text"
placeholder='Fee'
required
disabled
/>
</div>
</div>
<div className='my-3 md:flex items-center justify-end space-x-2'>
<div className='transfer-input w-full md:w-1/2'>
<label className='w-full text-slate-600 text-lg'>Total <span className='text-red-500'>*</span></label>
<input className='w-full p-3 text-lg text-right bg-slate-100 opacity-50 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg'
value={sendMoneyFee.total}
name='total'
type="text"
placeholder='Total'
required
disabled
/>
</div>
</div>
<div className='relative my-3 md:flex items-center'>
<div className='transfer-input w-full'>
<div className='flex items-center justify-start'>
<label className='text-slate-600 text-lg'>Recipient
<span className='text-red-500 mx-2'>*</span>
<span title='Transfer Recipient' className={`text-white text-sm bg-slate-500 w-1 h-1 rounded-full px-3 py-1 cursor-pointer`}>!</span>
</label>
<Link to='add-recipient' className='mx-1 text-base text-white p-3 bg-[orange] rounded-md hover:opacity-80'>Add New</Link>
</div>
<select className='mt-2 w-full p-3 text-lg bg-white rounded-md border border-slate-300 outline-0' value={inputs.recipient} name='recipient' onChange={handleChange}>
{recepients.loading ?
<option className='text-slate-500 text-lg' value="">Loading...</option>
:
recepients.data.length ?
<>
<option className='text-slate-500 text-lg' value="">Select...</option>
{recepients.data.map((item, index)=>(
<option key={index} value={item.account_no} className='text-slate-500 text-lg'>{item.recipient}</option>
))}
</>
:
recepients.error ?
<option className='text-slate-500 text-lg' value="">Could'nt Load, try again!</option>
:
<option className='text-slate-500 text-lg' value="">No Recipient Found! Click Add to Add</option>
} }
</select> <div className="xl:flex xl:space-x-7 mb-6">
</div>
</div>
<div className='my-3 md:flex items-center'> <div className="field w-full mb-6 xl:mb-0">
<div className='transfer-input w-full'> <InputCom
<label className='w-full text-slate-600 text-lg'>Comment <span className='text-red-500'>*</span></label> label="Amount"
<input className='w-full p-3 text-lg bg-slate-100 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg' type="text"
value={inputs.comment} name="amount"
name='comment' placeholder='0'
type="text" value={props.values.amount}
placeholder='Comment' inputHandler={props.handleChange}
required blurHandler={(e)=>{
onChange={handleChange} getSendMoneyFee(e)
/> }}
</div> // props.handleBlur
</div> // onMouseLeave={(e)=>{getSendMoneyFee(e)}}
/>
{(props.errors.amount && props.touched.amount) && <p className="text-sm text-red-500">{props.errors.amount}</p>}
</div>
<div className="field w-full">
<InputCom
label="Fee"
type="text"
name="fee"
value={sendMoneyFee.loading ? 'loading' : sendMoneyFee.fee}
disable={true}
/>
</div>
</div>
<div className='transfer-fund-btn flex justify-end items-center py-4'> <div className='md:flex items-center justify-end'>
<button className='text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md'>Continue</button> <div className="field w-full lg:w-1/2 mb-6">
</div> <InputCom
</form> label="Total"
type="text"
name="total"
value={sendMoneyFee.loading ? 'loading' : sendMoneyFee.total}
disable={true}
/>
</div>
</div>
<div className='w-full'>
<div className='relative my-3 md:flex items-center'>
<div className='transfer-input w-full'>
<div className='flex items-center justify-start py-2'>
<label className='text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Recipient
<span className='text-red-500 mx-2'>*</span>
<span title='Transfer Recipient' className={`text-white text-sm bg-slate-500 w-1 h-1 rounded-full px-3 py-1 cursor-pointer`}>!</span>
</label>
<Link to='add-recipient' className='mx-1 text-base text-white p-2 bg-[orange] rounded-md hover:opacity-80'>Add New</Link>
</div>
<select className='w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0' value={props.values.recipientID} name='recipientID' onChange={props.handleChange} onBlur={props.handleBlur}>
{recipients.loading ?
<option className='text-slate-500 text-lg' value="">Loading...</option>
:
recipients.data.length ?
<>
<option className='text-slate-500 text-lg' value="">Select...</option>
{recipients.data.map((item, index)=>(
<option key={index} value={item.recipient_id} className='text-slate-500 text-lg'>{item.recipient}</option>
))}
</>
:
recipients.error ?
<option className='text-slate-500 text-lg' value="">Could'nt Load, try again!</option>
:
<option className='text-slate-500 text-lg' value="">No Recipient Found! Click Add to Add</option>
}
</select>
</div>
</div>
{(props.errors.recipientID && props.touched.recipientID) && <p className="text-sm text-red-500">{props.errors.recipientID}</p>}
</div>
<div className="field w-full mb-6">
{/* <InputCom
label="Comment"
type="text"
name="comment"
value={inputs.comment}
inputHandler={handleChange}
/> */}
<label className='text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Comment</label>
<textarea style={{resize: 'none'}}
className='text-base px-6 text-dark-gray dark:text-white w-full bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none'
name="comment"
value={props.values.comment}
onChange={props.handleChange}
onBlur={props.handleBlur}
cols="30"
rows="2"
/>
</div>
<div className='transfer-fund-btn flex justify-end items-center py-4'>
{requestStatus ?
<LoadingSpinner size='8' color='sky-blue' />
:
<button type='submit' className='text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md'>Continue</button>
}
</div>
</Form>
)
}}
</Formik>
</div> </div>
</div> </div>
<div className="lg:w-1/2 w-full mb-10 lg:mb-0"> <div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full max-h-[600px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow"> <div className="wallet w-full md:p-8 p-4 h-full max-h-[800px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Recent Activity</h2> <h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Recent Activity</h2>
<p className='text-base text-slate-500 dark:text-white'>Activity Report</p> <p className='text-base text-slate-500 dark:text-white'>Activity Report</p>
{payment.loading ? {payment.loading ?
+5 -1
View File
@@ -8,6 +8,8 @@ import Balance from './Balance'
import TransferFund from './TransferFund' import TransferFund from './TransferFund'
import AddFund from './AddFund' import AddFund from './AddFund'
import AddRecipient from './AddRecipient' import AddRecipient from './AddRecipient'
import ConfirmTransfer from './ConfirmTransfer'
import ConfirmAddFund from './ConfirmAddFund'
function Wallet() { function Wallet() {
return ( return (
@@ -111,10 +113,12 @@ const WalletRoutes = () => {
<Routes> <Routes>
<Route element={<Wallet />}> <Route element={<Wallet />}>
<Route path='add-fund' element={<AddFund payment={paymentHistory} />} /> <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 path='transfer-fund' element={<TransferFund payment={paymentHistory} wallet={walletList} />} />
<Route index element={<Balance payment={paymentHistory} purchase={purchaseHistory} coupon={couponHistory} wallet={walletList} />} /> <Route index element={<Balance payment={paymentHistory} purchase={purchaseHistory} coupon={couponHistory} wallet={walletList} />} />
<Route path='*' element={<Navigate to='/' />} />
<Route path='transfer-fund/add-recipient' element={<AddRecipient />} /> <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> </Route>
</Routes> </Routes>
) )
+1 -1
View File
@@ -58,7 +58,7 @@ export default function WalletHeader(props) {
</div> </div>
<div> <div>
<p className="eth text-xl font-bold text-purple"> <p className="eth text-xl font-bold text-purple">
{(value.amount*1).toFixed(2)} {value.code} {(value.amount*0.01).toFixed(2)} {value.code}
</p> </p>
<p className="usd text-base text-thin-light-gray text-right"> <p className="usd text-base text-thin-light-gray text-right">
{/*(773.69 USD)*/} {/*(773.69 USD)*/}
+11 -3
View File
@@ -15,6 +15,7 @@ import usersService from "../../services/UsersService";
import siteLogo from '../../assets/images/wrenchboard.png' import siteLogo from '../../assets/images/wrenchboard.png'
import Flag from '../../assets/images/united-states.svg' import Flag from '../../assets/images/united-states.svg'
import { useSelector } from "react-redux";
export default function Header({ logoutModalHandler, sidebarHandler }) { export default function Header({ logoutModalHandler, sidebarHandler }) {
@@ -24,6 +25,8 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
const [moneyPopup, setPopup] = useToggle(false); const [moneyPopup, setPopup] = useToggle(false);
const [toggleNotification, setToggleNotification] = useToggle(false) const [toggleNotification, setToggleNotification] = useToggle(false)
const darkMode = useContext(DarkModeContext); const darkMode = useContext(DarkModeContext);
const {userDetails} = useSelector((state) => state?.userDetails)
const [myWalletList, setMyWalletList] = useState([]); const [myWalletList, setMyWalletList] = useState([]);
const api = new usersService(); const api = new usersService();
@@ -87,6 +90,11 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
const setNotification = ()=> { const setNotification = ()=> {
setToggleNotification.toggle() setToggleNotification.toggle()
} }
// User Profile
let {firstname, lastname, email, profile_pic} = userDetails
let userEmail = email.split('@')[0]
return ( return (
<> <>
<div className="header-wrapper backdrop-blur-sm bg-[#efedfe5e]/60 dark:bg-transparent w-full h-full flex items-center xl:px-0 md:px-10 px-5"> <div className="header-wrapper backdrop-blur-sm bg-[#efedfe5e]/60 dark:bg-transparent w-full h-full flex items-center xl:px-0 md:px-10 px-5">
@@ -463,17 +471,17 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
{/* profile-image */} {/* profile-image */}
<div className="lg:w-[62px] lg:h-[62px] w-[50px] h-[50px] rounded-full overflow-hidden"> <div className="lg:w-[62px] lg:h-[62px] w-[50px] h-[50px] rounded-full overflow-hidden">
<img <img
src={profileImg} src={profile_pic != '' ? profile_pic : profileImg}
alt="profile" alt="profile"
className="w-full h-full" className="w-full h-full"
/> />
</div> </div>
<div className="lg:block hidden"> <div className="lg:block hidden">
<h1 className="text-xl font-bold text-dark-gray dark:text-white"> <h1 className="text-xl font-bold text-dark-gray dark:text-white">
Brokln Simons {`${firstname} ${lastname}`}
</h1> </h1>
<p className="text-sm text-thin-light-gray"> <p className="text-sm text-thin-light-gray">
@broklinslam_75 @{userEmail}
</p> </p>
</div> </div>
</div> </div>
+3 -3
View File
@@ -22,9 +22,9 @@ export default function Layout({ children }) {
const logOut = () => { const logOut = () => {
localStorage.removeItem("email"); localStorage.removeItem("email");
localStorage.clear(); localStorage.clear();
toast.success("Come Back Soon", { // toast.success("Come Back Soon", {
icon: `🙂`, // icon: `🙂`,
}); // });
navigate("/login", { replace: true }); navigate("/login", { replace: true });
}; };
+11 -3
View File
@@ -12,6 +12,7 @@ import EthIco from "../Helpers/Icons/EthIco";
import LtcIco from "../Helpers/Icons/LtcIco"; import LtcIco from "../Helpers/Icons/LtcIco";
import Usdt from "../Helpers/Icons/Usdt"; import Usdt from "../Helpers/Icons/Usdt";
import SelectBox from "../Helpers/SelectBox"; import SelectBox from "../Helpers/SelectBox";
import { NavLink } from "react-router-dom";
export default function RightSideBar() { export default function RightSideBar() {
const filterDatas = ["Last 15 days", "Last Month", "Last 6 month"]; const filterDatas = ["Last 15 days", "Last Month", "Last 6 month"];
@@ -108,7 +109,10 @@ export default function RightSideBar() {
{/* name */} {/* name */}
<div> <div>
<p className="text-thin-light-gray text-base font-medium"> <p className="text-thin-light-gray text-base font-medium">
Rarible <NavLink
to="/history">
History
</NavLink>
</p> </p>
</div> </div>
{/* action */} {/* action */}
@@ -152,7 +156,8 @@ export default function RightSideBar() {
{/* name */} {/* name */}
<div> <div>
<p className="text-thin-light-gray text-base font-medium"> <p className="text-thin-light-gray text-base font-medium">
Myth Market <NavLink
to="/referral">Refer a Friend</NavLink>
</p> </p>
</div> </div>
</div> </div>
@@ -186,7 +191,10 @@ export default function RightSideBar() {
{/* name */} {/* name */}
<div> <div>
<p className="text-thin-light-gray text-base font-medium"> <p className="text-thin-light-gray text-base font-medium">
KnownOrigin <NavLink
to="/resources">
Resources
</NavLink>
</p> </p>
</div> </div>
</div> </div>
+101 -101
View File
@@ -156,108 +156,108 @@ export default function Sidebar({ sidebar, action, logoutModalHandler }) {
</span> </span>
</NavLink> </NavLink>
</li> </li>
<li className="item group"> {/*<li className="item group">*/}
<NavLink {/* <NavLink*/}
to="/notification" {/* to="/notification"*/}
className={`nav-item flex items-center ${ {/* className={`nav-item flex items-center ${*/}
((navData) => (navData.isActive ? "active" : ""), {/* ((navData) => (navData.isActive ? "active" : ""),*/}
sidebar ? "justify-start space-x-3.5" : "justify-center") {/* sidebar ? "justify-start space-x-3.5" : "justify-center")*/}
}`} {/* }`}*/}
> {/* >*/}
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray"> {/* <span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">*/}
<Icons name="notification-setting" /> {/* <Icons name="notification-setting" />*/}
</span> {/* </span>*/}
<span {/* <span*/}
className={`item-content relative group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium ${ {/* className={`item-content relative group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium ${*/}
sidebar ? "active flex-1" : "w-0" {/* sidebar ? "active flex-1" : "w-0"*/}
}`} {/* }`}*/}
> {/* >*/}
Messages {/* Messages*/}
</span> {/* </span>*/}
</NavLink> {/* </NavLink>*/}
</li> {/*</li>*/}
<li className="item group"> {/*<li className="item group">*/}
<NavLink {/* <NavLink*/}
to="/my-wallet" {/* to="/my-wallet"*/}
className={`nav-item flex items-center ${ {/* className={`nav-item flex items-center ${*/}
((navData) => (navData.isActive ? "active" : ""), {/* ((navData) => (navData.isActive ? "active" : ""),*/}
sidebar ? "justify-start space-x-3.5" : "justify-center") {/* sidebar ? "justify-start space-x-3.5" : "justify-center")*/}
}`} {/* }`}*/}
> {/* >*/}
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray"> {/* <span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">*/}
<Icons name="wallet-two" /> {/* <Icons name="wallet-two" />*/}
</span> {/* </span>*/}
<span {/* <span*/}
className={`item-content relative group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium ${ {/* className={`item-content relative group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium ${*/}
sidebar ? "active flex-1" : "w-0" {/* sidebar ? "active flex-1" : "w-0"*/}
}`} {/* }`}*/}
> {/* >*/}
My Wallet {/* My Wallet*/}
</span> {/* </span>*/}
</NavLink> {/* </NavLink>*/}
</li> {/*</li>*/}
<li className="item group"> {/*<li className="item group">*/}
<NavLink {/* <NavLink*/}
to="/resources" {/* to="/resources"*/}
className={`nav-item flex items-center ${ {/* className={`nav-item flex items-center ${*/}
((navData) => (navData.isActive ? "active" : ""), {/* ((navData) => (navData.isActive ? "active" : ""),*/}
sidebar ? "justify-start space-x-3.5" : "justify-center") {/* sidebar ? "justify-start space-x-3.5" : "justify-center")*/}
}`} {/* }`}*/}
> {/* >*/}
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray"> {/* <span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">*/}
<Icons name="star" /> {/* <Icons name="star" />*/}
</span> {/* </span>*/}
<span {/* <span*/}
className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${ {/* className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${*/}
sidebar ? "active flex-1" : "w-0" {/* sidebar ? "active flex-1" : "w-0"*/}
}`} {/* }`}*/}
> {/* >*/}
Resources {/* Resources*/}
</span> {/* </span>*/}
</NavLink> {/* </NavLink>*/}
</li> {/*</li>*/}
<li className="item group"> {/*<li className="item group">*/}
<NavLink {/* <NavLink*/}
to="/history" {/* to="/history"*/}
className={`nav-item flex items-center ${ {/* className={`nav-item flex items-center ${*/}
((navData) => (navData.isActive ? "active" : ""), {/* ((navData) => (navData.isActive ? "active" : ""),*/}
sidebar ? "justify-start space-x-3.5" : "justify-center") {/* sidebar ? "justify-start space-x-3.5" : "justify-center")*/}
}`} {/* }`}*/}
> {/* >*/}
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray"> {/* <span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">*/}
<Icons name="history" /> {/* <Icons name="history" />*/}
</span> {/* </span>*/}
<span {/* <span*/}
className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${ {/* className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${*/}
sidebar ? "active flex-1" : "w-0" {/* sidebar ? "active flex-1" : "w-0"*/}
}`} {/* }`}*/}
> {/* >*/}
History {/* History*/}
</span> {/* </span>*/}
</NavLink> {/* </NavLink>*/}
</li> {/*</li>*/}
<li className="item group"> {/*<li className="item group">*/}
<NavLink {/* <NavLink*/}
to="/referral" {/* to="/referral"*/}
className={`nav-item flex items-center ${ {/* className={`nav-item flex items-center ${*/}
((navData) => (navData.isActive ? "active" : ""), {/* ((navData) => (navData.isActive ? "active" : ""),*/}
sidebar ? "justify-start space-x-3.5" : "justify-center") {/* sidebar ? "justify-start space-x-3.5" : "justify-center")*/}
}`} {/* }`}*/}
> {/* >*/}
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray"> {/* <span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">*/}
<Icons name="history" /> {/* <Icons name="history" />*/}
</span> {/* </span>*/}
<span {/* <span*/}
className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${ {/* className={`item-content group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray relative font-medium ${*/}
sidebar ? "active flex-1" : "w-0" {/* sidebar ? "active flex-1" : "w-0"*/}
}`} {/* }`}*/}
> {/* >*/}
Refer a Friend {/* Refer a Friend*/}
</span> {/* </span>*/}
</NavLink> {/* </NavLink>*/}
</li> {/*</li>*/}
</ul> </ul>
</div> </div>
</div> </div>
@@ -290,7 +290,7 @@ export default function Sidebar({ sidebar, action, logoutModalHandler }) {
</li> </li>
<li className="item group"> <li className="item group">
<NavLink <NavLink
to="/market" to="/my-active-jobs"
className={`nav-item flex items-center ${ className={`nav-item flex items-center ${
((navData) => (navData.isActive ? "active" : ""), ((navData) => (navData.isActive ? "active" : ""),
sidebar ? "justify-start space-x-3.5" : "justify-center") sidebar ? "justify-start space-x-3.5" : "justify-center")
+89 -84
View File
@@ -2,6 +2,33 @@ import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import usersService from '../../services/UsersService'; import usersService from '../../services/UsersService';
import InputCom from '../Helpers/Inputs/InputCom';
import LoadingSpinner from '../Spinners/LoadingSpinner';
import {Formik, Form} from 'formik'
import * as Yup from 'yup'
const validationSchema = Yup.object().shape({
email: Yup.string()
.email('Wrong email format')
.min(3, 'Minimum 3 characters')
.max(50, 'Maximum 50 characters')
.required('Email is required'),
firstname: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('Firstname is required'),
lastname: Yup.string()
.min(3, 'Minimum 3 characters')
.max(25, 'Maximum 25 characters')
.required('Lastname is required'),
})
const initialValues = {
firstname: '',
lastname: '',
email: ''
}
function ReferralDisplay() { function ReferralDisplay() {
const apiCall = new usersService() // GET API CALL const apiCall = new usersService() // GET API CALL
@@ -16,7 +43,7 @@ function ReferralDisplay() {
data: [] data: []
}) })
let [error, setError] = useState({message: '', loading: false}) // for displaying error message on the page let [error, setError] = useState({message: '', loading: false, status: false}) // for displaying error message on the page
//function to call referral history API //function to call referral history API
const allReferrals = () => { const allReferrals = () => {
@@ -38,49 +65,28 @@ function ReferralDisplay() {
const sendReferralMsg = (postData) => { const sendReferralMsg = (postData) => {
apiCall.sendReferralMsg(postData).then((res)=>{ apiCall.sendReferralMsg(postData).then((res)=>{
if(res.data.internal_return < 0){ if(res.data.internal_return < 0){
setError({message:'Email already referred', loading: false}) setError({message:'Email already referred', loading: false, status: false})
return return
}else{ }else{
setInputs({ firstname: '', lastname: '', email: '',})
toast.success("Message Sent"); toast.success("Message Sent");
setError({message:'', loading: false}) setError({message:'', loading: false, status: true})
setRefHistoryReload(prev => !prev) setRefHistoryReload(prev => !prev)
} }
}).catch((error)=>{ }).catch((error)=>{
setError({message:'Opps! an error occured, try again later', loading: false}) setError({message:'Opps! an error occured, try again later', loading: false, status: false})
}) })
} }
//STATE FOR CONTROLLED INPUTS
let [inputs, setInputs] = useState({
firstname: '',
lastname: '',
email: ''
})
// FUNCTION TO HANDLE INPUT CHANGE
const handleChange = ({target:{name, value}}) => {
setInputs(prev => ({...prev, [name]:value}))
}
//FUNCTION TO HANDLE SUBMIT //FUNCTION TO HANDLE SUBMIT
const handleSubmit = (e) => { const handleSubmit = (values, helpers) => {
e.preventDefault(); setError({message: '', loading: true, status: false})
setError({message: '', loading: true})
let {firstname, lastname, email} = inputs
if(!firstname || !lastname || !email){
setError({message: 'Please fill all fields', loading: false})
return
}
var postData = { var postData = {
uid: localStorage.getItem("uid"), uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"), member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"), sessionid: localStorage.getItem("session_token"),
action: 11032, action: 11032,
ref_firstname: firstname, ...values
ref_lastname: lastname,
ref_email: email
}; };
sendReferralMsg(postData) // FUNCTION TO SEND REFERRAL MESSAGE sendReferralMsg(postData) // FUNCTION TO SEND REFERRAL MESSAGE
@@ -95,56 +101,62 @@ function ReferralDisplay() {
<div className="lg:w-1/2 w-full mb-10 lg:mb-0"> <div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="referral w-full md:p-8 p-4 h-full bg-white dark:bg-dark-white rounded-2xl shadow"> <div className="referral w-full md:p-8 p-4 h-full bg-white dark:bg-dark-white rounded-2xl shadow">
<h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Send Referral</h2> <h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Send Referral</h2>
<form className='referral-info' onSubmit={handleSubmit}> <Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={handleSubmit}>
<div className='md:flex items-center my-4'> {(props)=>(
<label className='w-full md:w-1/4 text-slate-900 text-lg'>Firstname <span className='text-red-500'>*</span></label> <Form className='referral-info'>
<input className='w-full md:w-3/4 p-3 text-lg bg-slate-100 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg' {/* Firstname */}
value={inputs.firstname} <div className="field w-full mb-6">
name='firstname' <InputCom
type="text" label="Firstname"
placeholder='Firstname' type="text"
onChange={handleChange} name="firstname"
placeholder="Firstname"
value={props.values.firstname}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/> />
</div> {(props.errors.firstname && props.touched.firstname) && <p className="text-sm text-red-500">{props.errors.firstname}</p>}
<div className='md:flex items-center my-4'>
<label className='w-full md:w-1/4 text-slate-900 text-lg'>Lastname <span className='text-red-500'>*</span></label>
<input className='w-full md:w-3/4 p-3 text-lg bg-slate-100 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg'
value={inputs.lastname}
name='lastname'
type="text"
placeholder='Lastname'
onChange={handleChange}
/>
</div>
<div className='md:flex items-center my-4'>
<label className='w-full md:w-1/4 text-slate-900 text-lg'>Email <span className='text-red-500'>*</span></label>
<input className='w-full md:w-3/4 p-3 text-lg bg-slate-100 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg'
value={inputs.email}
name='email'
type="email"
placeholder='Email'
onChange={handleChange}
/>
</div>
<hr />
{error.message != '' && <p className='text-base text-red-500 py-2'>{error.message}</p>}
<div className='referral-btn flex justify-end items-center py-4 border-b-4'>
{error.loading ?
<div className='flex items-center justify-center'>
<div role="status">
<svg aria-hidden="true" class="w-8 h-8 text-gray-200 animate-spin dark:text-gray-600 fill-sky-blue" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
<path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/>
</svg>
</div> </div>
</div>
: {/* Lastname */}
<button type='submit' className='text-lg text-white bg-sky-blue p-2 hover:opacity-90 rounded-md'>Send Message</button> <div className="field w-full mb-6">
} <InputCom
</div> label="Lastname"
</form> type="text"
name="lastname"
placeholder="Lastname"
value={props.values.lastname}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.lastname && props.touched.lastname) && <p className="text-sm text-red-500">{props.errors.lastname}</p>}
</div>
<div className="field w-full mb-6">
<InputCom
label="Email"
type="text"
name="email"
placeholder="Email"
value={props.values.email}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{(props.errors.email && props.touched.email) && <p className="text-sm text-red-500">{props.errors.email}</p>}
</div>
<hr />
{error.message != '' && <p className='text-base text-red-500 py-2'>{error.message}</p>}
<div className='referral-btn flex justify-end items-center py-4 border-b-4'>
{error.loading ?
<LoadingSpinner size='6' color='sky-blue' />
:
<button type='submit' className='text-lg text-white bg-sky-blue p-2 hover:opacity-90 rounded-md'>Send Message</button>
}
</div>
</Form>
)}
</Formik>
</div> </div>
</div> </div>
@@ -153,14 +165,7 @@ function ReferralDisplay() {
<h2 className='mb-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Referral List</h2> <h2 className='mb-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Referral List</h2>
{referralList.loading ? {referralList.loading ?
( (
<div className='flex items-center justify-center'> <LoadingSpinner size='32' color='sky-blue' />
<div role="status">
<svg aria-hidden="true" class="w-32 h-32 text-gray-200 animate-spin dark:text-gray-600 fill-sky-blue" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
<path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/>
</svg>
</div>
</div>
) )
: :
( (
@@ -4,6 +4,7 @@ import InputCom from "../../Helpers/Inputs/InputCom";
import {Link, useNavigate} from 'react-router-dom' import {Link, useNavigate} from 'react-router-dom'
import usersService from "../../../services/UsersService"; import usersService from "../../../services/UsersService";
import LoadingSpinner from "../../Spinners/LoadingSpinner"; import LoadingSpinner from "../../Spinners/LoadingSpinner";
import { useSelector } from "react-redux";
import {toast} from 'react-toastify' import {toast} from 'react-toastify'
@@ -34,14 +35,6 @@ const validationSchema = Yup.object().shape({
.required('State is required'), .required('State is required'),
}) })
const initialValues = {
firstname: '',
lastname: '',
state: '',
city: '',
email: ''
}
export default function PersonalInfoTab({ export default function PersonalInfoTab({
datas, datas,
frstNmeHndlr, frstNmeHndlr,
@@ -57,13 +50,23 @@ export default function PersonalInfoTab({
coverImgChangHandler, coverImgChangHandler,
}) { }) {
let {userDetails} = useSelector((state) => state.userDetails)
const apiCall = new usersService() const apiCall = new usersService()
let navigate = useNavigate() let navigate = useNavigate()
let [togglePromotion, setTogglePromotion] = useState(false) let [togglePromotion, setTogglePromotion] = useState(false)
const initialValues = {
firstname: userDetails?.firstname,
lastname: userDetails?.lastname,
state: userDetails?.state,
city: userDetails?.city,
email: userDetails?.email
}
let [profile, setProfile] = useState({ // state for requesting from load profile API let [profile, setProfile] = useState({ // state for requesting from load profile API
data: [],
loading: true, loading: true,
status: false status: false
}) })
@@ -74,55 +77,27 @@ export default function PersonalInfoTab({
status: false status: false
}) })
let [inputs, setInputs] = useState({ // State for input fields
firstname: '',
lastname: '',
state: '',
city: '',
email: ''
})
// const handleChange = ({target:{name, value}}) => {
// setInputs(prev => ({...prev, [name]:value}))
// }
const handleUpdateUser = (values, helpers)=> { const handleUpdateUser = (values, helpers)=> {
setRequestState({message: '', loading: true, status: false}) setRequestState({message: '', loading: true, status: false})
apiCall.updateProfile(values).then((res)=>{ apiCall.updateProfile(values).then((res)=>{ // API CALL TO UPDATE USER DETAILS
if(res.data.internal_return < 0){ if(res.data.internal_return < 0){
setRequestState({message: 'Profile Was unable to update', loading: false, status: false}) setRequestState({message: 'Profile Was unable to update', loading: false, status: false})
return return
} }
// setRequestState({message: 'Profile update successfully', loading: false, status: true}) // setRequestState({message: 'Profile update successfully', loading: false, status: true})
toast.success("Update Successful"); toast.success("Update Successful");
setTimeout(()=>{navigate('/',{replace:true})},1000) setTimeout(()=>{
navigate('/',{replace:true})
window.location.reload(true)
},1000)
}).catch(error => { }).catch(error => {
setRequestState({message: 'Opps! an error occurred. Try Agian', loading: false, status: false}) setRequestState({message: 'Opps! an error occurred. Try Agian', loading: false, status: false})
}) })
} }
const loadProfile = ()=>{ // function to load user profile
apiCall.loadProfile().then((res)=>{
if(res.data.internal_return < 0){
setProfile(prev => ({...prev, loading: false, status: true}))
return
}
setProfile(prev => ({...prev, data: [res.data], loading: false, status: true}))
setInputs({
firstname: res.data.firstname,
lastname: res.data.lastname,
state: res.data.state,
city: res.data.city,
email: res.data.email
})
}).catch(error =>{
setProfile(prev => ({...prev, loading: false, status: false}))
})
}
useEffect(()=>{ useEffect(()=>{
loadProfile() // loads user profile unto the page setProfile({loading: false, status: true})
},[]) },[])
return ( return (
@@ -135,14 +110,12 @@ export default function PersonalInfoTab({
</div> </div>
: :
<div className="personal-info-tab w-full flex flex-col justify-between"> <div className="personal-info-tab w-full flex flex-col justify-between">
<Formik initialValues={inputs} validationSchema={validationSchema} onSubmit={handleUpdateUser}> <Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={handleUpdateUser}>
{(props => { {(props => {
return ( return (
<Form> <Form>
{
profile.data.length ? <div className="flex flex-col-reverse sm:flex-row">
profile.data.map((item, index) => (
<div key={index} className="flex flex-col-reverse sm:flex-row">
<div className="flex-1 sm:mr-10"> <div className="flex-1 sm:mr-10">
<div className="fields w-full"> <div className="fields w-full">
{/* inputs starts here */} {/* inputs starts here */}
@@ -153,7 +126,7 @@ export default function PersonalInfoTab({
type="text" type="text"
name="username" name="username"
placeholder="" placeholder=""
value={item.username} value={userDetails.username}
disable={true} disable={true}
/> />
</div> </div>
@@ -205,7 +178,7 @@ export default function PersonalInfoTab({
label="Country" label="Country"
type="text" type="text"
name="country" name="country"
value={item.country} value={userDetails.country}
disable={true} disable={true}
/> />
</div> </div>
@@ -324,41 +297,35 @@ export default function PersonalInfoTab({
</div> </div>
</div> </div>
</div> </div>
</div> </div>
))
:
profile.status ?
<div className="py-3 text-slate-500">No User Information Found!</div>
:
<div className="py-3 text-slate-500">Opps! something went wrong. Try Again Later!</div>
}
<div className="content-footer w-full">
{requestStatus.message != '' && <p className={`text-center text-base ${requestStatus.status ? 'text-green-800' : 'text-red-600'}`}>{requestStatus.message}</p>}
<div className="w-full h-[120px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
<div className="flex items-center space-x-4 mr-9">
<Link
to='/'
className="text-18 text-light-red tracking-wide "
>
<span className="border-b dark:border-[#5356fb29] border-light-red">
{" "}
Cancel
</span>
</Link>
{requestStatus.loading ? <div className="content-footer w-full">
<LoadingSpinner size='8' color='sky-blue' /> {requestStatus.message != '' && <p className={`text-center text-base ${requestStatus.status ? 'text-green-800' : 'text-red-600'}`}>{requestStatus.message}</p>}
: <div className="w-full h-[120px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
<button <div className="flex items-center space-x-4 mr-9">
type="submit" <Link
className="w-[152px] h-[46px] flex justify-center items-center btn-gradient text-base rounded-full text-white" to='/'
> className="text-18 text-light-red tracking-wide "
Update Profile >
</button> <span className="border-b dark:border-[#5356fb29] border-light-red">
} {" "}
Cancel
</span>
</Link>
{requestStatus.loading ?
<LoadingSpinner size='8' color='sky-blue' />
:
<button
type="submit"
className="w-[152px] h-[46px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Update Profile
</button>
}
</div>
</div> </div>
</div> </div>
</div>
</Form> </Form>
) )
})} })}
+21
View File
@@ -40,6 +40,10 @@ export default function Settings() {
}, },
{ {
id: 7, id: 7,
name: "privacy",
},
{
id: 8,
name: "terms", name: "terms",
}, },
]; ];
@@ -191,6 +195,23 @@ export default function Settings() {
<p className="text-18 tracking-wide">FAQ</p> <p className="text-18 tracking-wide">FAQ</p>
</div> </div>
</li> </li>
<li
onClick={() => tabHandler("terms")}
className={`flex lg:space-x-4 space-x-2 hover:text-purple transition-all duration-300 ease-in-out items-center cursor-pointer lg:mb-11 mb-2 mr-6 lg:mr-0 float-left lg:float-none overflow-hidden ${
tab === "privacy"
? "text-purple"
: " text-thin-light-gray"
}`}
>
<div>
<Icons name="page-right" />
</div>
<div>
<p className="text-18 tracking-wide">
Privacy Policy
</p>
</div>
</li>
<li <li
onClick={() => tabHandler("terms")} onClick={() => tabHandler("terms")}
className={`flex lg:space-x-4 space-x-2 hover:text-purple transition-all duration-300 ease-in-out items-center cursor-pointer lg:mb-11 mb-2 mr-6 lg:mr-0 float-left lg:float-none overflow-hidden ${ className={`flex lg:space-x-4 space-x-2 hover:text-purple transition-all duration-300 ease-in-out items-center cursor-pointer lg:mb-11 mb-2 mr-6 lg:mr-0 float-left lg:float-none overflow-hidden ${
+2 -2
View File
@@ -1,8 +1,8 @@
import React from 'react' import React from 'react'
function LoadingSpinner({size, color}) { function LoadingSpinner({size, color, height}) {
return ( return (
<div className='flex items-center justify-center'> <div className={`flex items-center justify-center ${height ? height : ''}`}>
<div role="status"> <div role="status">
<svg aria-hidden="true" className={`w-${size} h-${size} text-gray-200 animate-spin dark:text-gray-600 fill-${color}`} viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg aria-hidden="true" className={`w-${size} h-${size} text-gray-200 animate-spin dark:text-gray-600 fill-${color}`} viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/> <path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
+21
View File
@@ -0,0 +1,21 @@
/**
Returns a debounced version of a given function, which means that it delays the execution of the function until a certain amount of time has passed without the function being called again. This can be useful for performance optimization, especially when dealing with expensive or resource-intensive functions that are called frequently.
@param {Function} func - The function to debounce.
@param {number} delay - The number of milliseconds to wait before executing the debounced function.
@returns {Function} - The debounced version of the original function.
*/
export default function debounce(func, delay) {
let timeoutId;
return function (...args) {
const context = this;
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func.apply(context, args);
}, delay);
};
}
+6
View File
@@ -10,6 +10,12 @@
src: url("./assets/fonts/Product Sans Bold.ttf"); src: url("./assets/fonts/Product Sans Bold.ttf");
} }
.banner-630-340{
width: 630px;
height: 340px;
background-color: aliceblue;
}
/* Bold italic Weight */ /* Bold italic Weight */
@font-face { @font-face {
font-family: "Product Sans"; font-family: "Product Sans";
+51 -25
View File
@@ -1,38 +1,31 @@
import { useEffect, useState } from "react"; import { useEffect, useState, useCallback } from "react";
import { Navigate, Outlet, useLocation, useNavigate } from "react-router-dom"; import { Navigate, Outlet, useLocation, useNavigate } from "react-router-dom";
import usersService from '../services/UsersService'
import LoadingSpinner from '../components/Spinners/LoadingSpinner'
import WrenchBoard from "../assets/images/wrenchboard.png"
import { useDispatch, useSelector } from "react-redux";
import {updateUserDetails} from '../store/UserDetails'
const AuthRoute = ({ redirectPath = "/login", children }) => { const AuthRoute = ({ redirectPath = "/login", children }) => {
const apiCall = new usersService()
const dispatch = useDispatch()
const [lastActivityTime, setLastActivityTime] = useState(Date.now()); const [lastActivityTime, setLastActivityTime] = useState(Date.now());
const isLogin = localStorage.getItem("email"); let [isLogin, setIsLogin] = useState({loading: true, status: false})
const navigate = useNavigate(); const navigate = useNavigate();
const { pathname } = useLocation();
//Removing Data stored at localStorage after session expires //Removing Data stored at localStorage after session expires
const expireSession = () => { const expireSession = () => {
localStorage.removeItem("email");
localStorage.removeItem('session_token'); localStorage.removeItem('session_token');
localStorage.removeItem('firstname');
localStorage.removeItem('member_id'); localStorage.removeItem('member_id');
localStorage.removeItem('lastname');
localStorage.removeItem('state');
localStorage.removeItem('last_login');
localStorage.removeItem('uid'); localStorage.removeItem('uid');
localStorage.removeItem('session'); localStorage.removeItem('session');
localStorage.removeItem('city');
localStorage.removeItem('country');
localStorage.removeItem('loglevel');
localStorage.removeItem('zip_code');
localStorage.removeItem('added');
navigate("/login", { replace: true }); // redirects user to login page after session expires navigate("/login", { replace: true }); // redirects user to login page after session expires
}; };
const checkInactivity = setInterval(() => {
if (Date.now() - lastActivityTime > process.env.REACT_APP_SESSION_EXPIRE_MINUTES) {
expireSession()
}
}, process.env.REACT_APP_SESSION_EXPIRE_CHECKER) // Checks for inactivity every minute
// Reset last activity time on user input // Reset last activity time on user input
const resetTime = () => { const resetTime = () => {
setLastActivityTime(Date.now()); setLastActivityTime(Date.now());
@@ -40,19 +33,52 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
window.addEventListener('mousemove', resetTime) window.addEventListener('mousemove', resetTime)
window.addEventListener('keydown', resetTime) window.addEventListener('keydown', resetTime)
const loadProfile = ()=>{ // function to load user profile
setIsLogin({loading: true, status: false})
apiCall.loadProfile().then((res)=>{
if(res.data.internal_return < 0){
setIsLogin({loading: false, status: false})
return
}
dispatch(updateUserDetails(res.data))
setIsLogin({loading: false, status: true})
}).catch(error =>{
setIsLogin({loading: false, status: false})
})
}
useEffect(() => { useEffect(() => {
if(!isLogin.status){
loadProfile() // LOADS USER PROFILE DETAILS AND CALLS DISPATCH UPDATEUSERDETAILS TO UPDATE USERDETAILS SLICE IN STORE
}
const checkInactivity = setInterval(() => {
if (Date.now() - lastActivityTime > process.env.REACT_APP_SESSION_EXPIRE_MINUTES) {
expireSession()
}
}, process.env.REACT_APP_SESSION_EXPIRE_CHECKER) // Checks for inactivity every minute
// cleaning up listeners // cleaning up listeners
return () => { return () => {
clearInterval(checkInactivity) clearInterval(checkInactivity)
window.removeEventListener('mousemove', resetTime) window.removeEventListener('mousemove', resetTime)
window.removeEventListener('keydown', resetTime) window.removeEventListener('keydown', resetTime)
} }
}, [pathname, lastActivityTime]) }, [lastActivityTime])
if (!isLogin) { return (
return <Navigate to={redirectPath} replace />; isLogin.loading ?
} <LoadingSpinner size='32' color='sky-blue' height='h-screen' />
return children || <Outlet />; // Stills needs fixing
// <div className="h-screen m-auto">
// <img src={WrenchBoard} alt="wrenchboard" className="h-10" />
// </div>
:
!isLogin.status ?
<Navigate to={redirectPath} replace />
:
(children || <Outlet />)
)
}; };
export default AuthRoute; export default AuthRoute;
+86 -2
View File
@@ -11,6 +11,11 @@ class usersService {
return this.postAuxEnd("/createuser", reqData); return this.postAuxEnd("/createuser", reqData);
} }
CompleteSignUp(reqData){
localStorage.setItem("session_token", ``);
return this.postAuxEnd("/completesignuplink", reqData);
}
getHomeDate(){ getHomeDate(){
var postData = { var postData = {
uuid: localStorage.getItem("uuid"), uuid: localStorage.getItem("uuid"),
@@ -96,7 +101,7 @@ class usersService {
return this.postAuxEnd("/getjobsdata", postData); return this.postAuxEnd("/getjobsdata", postData);
} }
getMyJobList(){ getHeroJBanners(){
var postData = { var postData = {
uuid: localStorage.getItem("uid"), uuid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"), member_id: localStorage.getItem("member_id"),
@@ -104,7 +109,19 @@ class usersService {
page:0, page:0,
limit :100 limit :100
}; };
return this.postAuxEnd("/myjobs", postData); return this.postAuxEnd("/homebanners", postData);
}
getMyJobList(){
var postData = {
uuid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
page:0,
offset:0,
limit :100
};
return this.postAuxEnd("/jobmanagerlist", postData);
} }
getGetPendingJobs(){ getGetPendingJobs(){
@@ -153,6 +170,17 @@ class usersService {
return this.postAuxEnd("/recipients", postData); return this.postAuxEnd("/recipients", postData);
} }
//END POINT CALL FOR UPDATE PROFILE
addRecipient(data){
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
...data
};
return this.postAuxEnd("/addrecipient", postData);
}
// API FUNCTION TO GET SEND MONEY FEE // API FUNCTION TO GET SEND MONEY FEE
getSendMoneyFee(amount){ getSendMoneyFee(amount){
var postData = { var postData = {
@@ -202,6 +230,19 @@ class usersService {
}; };
return this.postAuxEnd("/paymenthx", postData); return this.postAuxEnd("/paymenthx", postData);
} }
// API FUNCTION TO GET PAYMENT HISTORY
sendMoney(reqData){
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
senderid: localStorage.getItem("member_id"),
action: 33020,
...reqData
};
return this.postAuxEnd("/sendmoney", postData);
}
//END POINT CALL FOR REFERRAL HISTORY //END POINT CALL FOR REFERRAL HISTORY
getReferralHx(){ getReferralHx(){
@@ -238,6 +279,18 @@ class usersService {
return this.postAuxEnd("/loadprofile", postData); return this.postAuxEnd("/loadprofile", postData);
} }
//END POINT CALL FOR ACCOUNT TOP
startTopUp(post){
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 11062,
...post
};
return this.postAuxEnd("/starttopup", postData);
}
//END POINT CALL FOR SENDING REFERRAL MESSAGE //END POINT CALL FOR SENDING REFERRAL MESSAGE
sendReferralMsg(postData){ sendReferralMsg(postData){
return this.postAuxEnd("/sendreferral", postData); return this.postAuxEnd("/sendreferral", postData);
@@ -263,6 +316,37 @@ class usersService {
return this.postAuxEnd("/signupcountry", null); return this.postAuxEnd("/signupcountry", null);
} }
// END POINT TO GET BANK NAME
getCountryBank() {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 11183,
country: 'NG'
};
return this.postAuxEnd("/countrybanks", postData);
}
// END POINT TO GET ACCOUNT TYPE
getAccountTypes() {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 11177
};
return this.postAuxEnd("/accounttypes", postData);
}
verifyEmail(code) {
const reqData = {
verify_link: code,
action: 11015
}
return this.postAuxEnd("/verifysignuplink", reqData);
}
/* /*
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(username) - 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(username)
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(password) - 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(password)
+20
View File
@@ -0,0 +1,20 @@
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
userDetails: {}
};
export const userSlice = createSlice({
name: "userDetails",
initialState,
reducers: {
updateUserDetails: (state,payload) => {
state.userDetails = {...payload.payload}
},
},
});
// Action creators are generated for each case reducer function
export const { updateUserDetails } = userSlice.actions;
export default userSlice.reducer;
+4 -1
View File
@@ -1,8 +1,11 @@
import { configureStore } from "@reduxjs/toolkit"; import { configureStore } from "@reduxjs/toolkit";
import drawerReducer from "./drawer"; import drawerReducer from "./drawer";
import userDetailReducer from "./UserDetails";
export default configureStore({ export default configureStore({
reducer: { reducer: {
drawer: drawerReducer, drawer: drawerReducer,
userDetails: userDetailReducer,
}, },
}); });
+18 -2
View File
@@ -1,7 +1,23 @@
import React from "react"; import React, {useState, useEffect} from 'react'
import Home from "../components/Home"; import Home from "../components/Home";
import usersService from "../services/UsersService";
export default function HomePages() { export default function HomePages() {
const [marketActiveJobList, setMarketActiveJobList] = useState([]);
const api = new usersService();
const getMarketActiveJobList = async () => {
try {
const res = await api.getHeroJBanners();
setMarketActiveJobList(res.data);
} catch (error) {
console.log("Error getting mode");
}
};
useEffect(() => {
getMarketActiveJobList();
}, []);
return ( return (
<> <>
<Home /> <Home />
+2 -2
View File
@@ -24,10 +24,10 @@ export default function MyJobsPage() {
getMyJobList(); getMyJobList();
}, []); }, []);
debugger; // debugger;
return ( return (
<> <>
<MyJobs /> <MyJobs MyJobList={MyJobList} />
</> </>
); );
} }
+5
View File
@@ -0,0 +1,5 @@
import VerifyLink from "../components/AuthPages/VerifyLink";
export default function VerifyLinkPages() {
return <VerifyLink />;
}
+4042 -4758
View File
File diff suppressed because it is too large Load Diff