Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 39b3218545 | |||
| e26330af9a | |||
| ccc43bb55d | |||
| 2b0d344dfa | |||
| 53b9db85a5 | |||
| ecdd8f9180 | |||
| 25dcfecfaf | |||
| ed638f5c0f | |||
| 033d87fdf6 | |||
| babed484b2 | |||
| e2b4aaa105 | |||
| ce01b2637b | |||
| d91241dad9 | |||
| 1ad3b74610 | |||
| d94ff616a9 | |||
| f87dbcbe5e | |||
| 4df1589222 | |||
| 886b73ffa3 | |||
| 6cb0871d34 | |||
| 3ed764e8f4 | |||
| c87fc4f32d | |||
| 75015e84d2 | |||
| 24a5b8e785 | |||
| 03ca576e16 | |||
| 8886544024 | |||
| cadd2aa4c4 | |||
| 104cd15f64 | |||
| 3acdbfb6e0 | |||
| f30600816b | |||
| 627774c910 | |||
| ee59990d85 | |||
| 7f4d8f3ff0 | |||
| b888e9f5df | |||
| e6153e0b3d | |||
| 02fe8cb399 | |||
| 0819105fcb | |||
| 9070d99b1d | |||
| 2da53ecc2e | |||
| 3c4ebc402e | |||
| a18e87e0d6 | |||
| 7762c394a4 | |||
| c45815d437 | |||
| f86ac54e5c | |||
| 636651aa38 | |||
| 32cfed3394 | |||
| 425df92dba |
@@ -21,6 +21,10 @@ REACT_APP_SESSION_EXPIRE_MINUTES=300000
|
||||
REACT_APP_SESSION_EXPIRE_CHECKER=60000
|
||||
|
||||
REACT_APP_LOGIN_ERROR_TIMEOUT=7000
|
||||
REACT_APP_SIGNUP_ERROR_TIMEOUT=7000
|
||||
|
||||
# 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
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
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
|
||||
|
||||
# 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
|
||||
@@ -0,0 +1,30 @@
|
||||
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
|
||||
|
||||
# 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
|
||||
@@ -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"]
|
||||
}
|
||||
+36
@@ -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
@@ -4,7 +4,9 @@ services:
|
||||
image: registry.chiefsoft.net/wrenchboard-users-wrench:latest
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/Dockerfile
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- NODE_ENV=production
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 9082:3000
|
||||
@@ -13,19 +15,20 @@ services:
|
||||
working_dir: /usr/src/app
|
||||
volumes:
|
||||
- ./:/usr/src/app
|
||||
- /usr/src/app/node_modules
|
||||
- ./src/:/usr/src/app/src
|
||||
- ./vendors/:/usr/src/app/vendors
|
||||
- ./run.sh:/usr/src/app/run.sh
|
||||
extra_hosts:
|
||||
- backend.wrenchboard.api.live:10.10.33.15
|
||||
- backend.wrenchboard.api.test: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.test:10.20.30.27
|
||||
- apigateway.wrenchboard.app.dev.fluxtra.net:10.20.30.19
|
||||
- apigateway.wrenchboard.app.lotus.fluxtra.net:172.31.4.19
|
||||
environment:
|
||||
- CHOKIDAR_USEPOLLING=true
|
||||
- NODE_ENV=${NODE_ENV:-production}
|
||||
# volumes:
|
||||
# - ./:/app
|
||||
# - /app/node_modules
|
||||
|
||||
+15
-1
@@ -3,7 +3,15 @@
|
||||
|
||||
FROM alpine:3.15
|
||||
|
||||
# Build args
|
||||
ARG NODE_ENV
|
||||
|
||||
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 \
|
||||
&& 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 /usr/src/app/node_modules/.bin:$PATH
|
||||
|
||||
COPY nginx.conf ./
|
||||
|
||||
COPY run.sh ./
|
||||
|
||||
# install app dependencies
|
||||
COPY package.json ./
|
||||
RUN npm install
|
||||
@@ -114,7 +126,9 @@ RUN npm install
|
||||
COPY . ./
|
||||
|
||||
# start app
|
||||
CMD ["npm","run", "start"]
|
||||
# CMD ["npm","run", "start"]
|
||||
|
||||
# CMD ["yarn", "start"]
|
||||
|
||||
# start app
|
||||
CMD /bin/sh ./run.sh
|
||||
|
||||
+29
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+10992
-6604
File diff suppressed because it is too large
Load Diff
+6
-20
@@ -13,6 +13,7 @@
|
||||
"chartjs": "^0.3.24",
|
||||
"cors": "^2.8.5",
|
||||
"faker": "^6.6.6",
|
||||
"formik": "^2.2.9",
|
||||
"react": "^18.0.0",
|
||||
"react-chartjs-2": "^4.1.0",
|
||||
"react-countup": "^6.2.0",
|
||||
@@ -25,14 +26,14 @@
|
||||
"react-toastify": "^9.0.1",
|
||||
"redux": "^4.2.0",
|
||||
"slick-carousel": "^1.8.1",
|
||||
"web-vitals": "^1.0.1"
|
||||
"web-vitals": "^1.0.1",
|
||||
"yup": "^1.1.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"start": "react-scripts start -e .env.development",
|
||||
"build": "react-scripts build -e .env.production",
|
||||
"test": "react-scripts test",
|
||||
"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"
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
@@ -51,20 +52,5 @@
|
||||
"last 1 firefox 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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/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
|
||||
npm install --legacy-peer-deps
|
||||
npm start
|
||||
else
|
||||
# build the app and serve it via nginx
|
||||
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
|
||||
@@ -30,6 +30,7 @@ import ResourcePage from "./views/ResourcePage";
|
||||
import MyTaskPage from "./views/MyTaskPage";
|
||||
import MyJobsPage from "./views/MyJobsPage";
|
||||
import ReferralPage from "./views/ReferralPage";
|
||||
import VerifyLinkPages from "./views/VerifyLinkPages";
|
||||
|
||||
export default function Routers() {
|
||||
return (
|
||||
@@ -48,6 +49,7 @@ export default function Routers() {
|
||||
path="/update-password"
|
||||
element={<UpdatePasswordPages />}
|
||||
/>
|
||||
<Route path="/vemail" element={<VerifyLinkPages />} />
|
||||
<Route exact path="/verify-you" element={<VerifyYouPages />} />
|
||||
|
||||
{/* private route */}
|
||||
|
||||
@@ -1,49 +1,153 @@
|
||||
import React from "react";
|
||||
import { Link } from 'react-router-dom';
|
||||
import titleShape from "../../../assets/images/shape/title-shape-two.svg";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import WrenchBoard from "../../../assets/images/wrenchboard.png"
|
||||
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||
import AuthLayout from "../AuthLayout";
|
||||
import usersService from "../../../services/UsersService";
|
||||
|
||||
export default function ForgotPassword() {
|
||||
const [checked, setValue] = useState(false);
|
||||
const [resetLoading, setResetLoading] = useState(false)
|
||||
// email
|
||||
const [email, setMail] = useState("");
|
||||
const [msgError, setMsgError] = useState('');
|
||||
|
||||
const navigate = useNavigate();
|
||||
const userApi = new usersService();
|
||||
|
||||
const handleEmail = (e) => {
|
||||
setMail(e?.target.value);
|
||||
};
|
||||
|
||||
const humanChecker = () => {
|
||||
setValue(!checked);
|
||||
};
|
||||
|
||||
const resetHandler = async () => {
|
||||
if (email == '') {
|
||||
setMsgError('An email is required')
|
||||
} else if (!checked) {
|
||||
setMsgError('Check if you are human')
|
||||
}
|
||||
|
||||
if (email != '' && checked) {
|
||||
const reqData = { email }
|
||||
setResetLoading(true)
|
||||
try {
|
||||
const res = await userApi.StartResetPassword(reqData)
|
||||
if (res.status === 200) {
|
||||
const { data } = res
|
||||
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("")
|
||||
}
|
||||
} catch (error) {
|
||||
setResetLoading(false)
|
||||
setMail("")
|
||||
setMsgError('An error occurred')
|
||||
throw new Error(error)
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
setMsgError(null)
|
||||
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT)
|
||||
}
|
||||
}
|
||||
setTimeout(() => {
|
||||
setMsgError(null)
|
||||
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<AuthLayout
|
||||
slogan="Welcome to WrenchBoard"
|
||||
>
|
||||
<div className="content-wrapper xl:bg-white dark:bg-dark-white xl:px-[70px] w-full sm:w-auto 2xl:px-[100px] h-[818px] rounded-xl ">
|
||||
<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">
|
||||
<h1 className="sm:text-5xl text-4xl font-bold sm:leading-[74px] text-dark-gray dark:text-white">
|
||||
Forget Password
|
||||
</h1>
|
||||
<div className="shape sm:w-[377px] w-[270px] -mt-1 ml-0">
|
||||
<img src={titleShape} alt="shape" />
|
||||
<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 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="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={{
|
||||
fontSize: 'calc(1rem + .6vw)'
|
||||
}}>
|
||||
Forget Password
|
||||
</h1>
|
||||
<span className="text-gray-400 font-medium text-xl">Enter your email to reset your password.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="input-area">
|
||||
<div className="input-item mb-5">
|
||||
<InputCom
|
||||
placeholder="example@quomodosoft.com"
|
||||
label="Email Address"
|
||||
name="email"
|
||||
type="email"
|
||||
iconName="message"
|
||||
/>
|
||||
</div>
|
||||
<div className="signin-area mb-3.5">
|
||||
<a
|
||||
href="/verify-you"
|
||||
className="w-full rounded-[50px] mb-5 h-[58px] text-xl text-white font-bold flex justify-center bg-purple items-center"
|
||||
>
|
||||
Send Code
|
||||
</a>
|
||||
|
||||
|
||||
<Link to="/"
|
||||
className=" my-40 font-bold flex justify-center text-red-500 items-center"
|
||||
>
|
||||
Back to Home
|
||||
</Link>
|
||||
<div className="input-area">
|
||||
<div className="input-item mb-10">
|
||||
<InputCom
|
||||
placeholder="Your Username/Email"
|
||||
label="Email"
|
||||
name="email"
|
||||
type="email"
|
||||
value={email}
|
||||
inputHandler={handleEmail}
|
||||
iconName="message"
|
||||
/>
|
||||
</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 */}
|
||||
<div className="mb-10">
|
||||
<div className="w-[303px] h-[78px] mx-auto overflow-hidden">
|
||||
<div className="w-[300px] h-[74px] bg-white bottom-[1px] rounded border-gray-100 overflow-hidden cursor-pointer">
|
||||
{/* Checkbox */}
|
||||
<div className="h-full relative inline-block">
|
||||
<div className="relative table top-0 h-full">
|
||||
<div className="table-cell align-middle">
|
||||
<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} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="h-full relative inline-block w-[170px]">
|
||||
<label className="relative table top-0 h-full">
|
||||
<label className="table-cell align-middle">
|
||||
<label className="text-800 text-sm" htmlFor="human-checkbox">
|
||||
I am human
|
||||
</label>
|
||||
</label>
|
||||
</label>
|
||||
</div>
|
||||
<div className="h-full relative inline-block w-16"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="signin-area mb-3.5">
|
||||
<div className="flex justify-center items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
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]`}
|
||||
>
|
||||
{resetLoading ? (
|
||||
<div className="signup btn-loader"></div>
|
||||
) : (
|
||||
<span>Send Code</span>
|
||||
)}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
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] `}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,8 +4,6 @@ import { toast } from "react-toastify";
|
||||
import googleLogo from "../../../assets/images/google-logo.svg";
|
||||
import appleLogo from "../../../assets/images/apple-black.svg";
|
||||
import facebookLogo from "../../../assets/images/facebook-4.svg";
|
||||
// import titleShape from "../../../assets/images/shape/title-shape.svg";
|
||||
import titleShape from "../../../assets/images/shape/login_straight_underline.svg";
|
||||
import WrenchBoard from "../../../assets/images/wrenchboard.png"
|
||||
import usersService from "../../../services/UsersService";
|
||||
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||
@@ -24,8 +22,6 @@ export default function Login() {
|
||||
setValue(!checked);
|
||||
};
|
||||
|
||||
console.log(process.env.REACT_APP_LOGIN_ERROR_TIMEOUT)
|
||||
|
||||
// email
|
||||
const [email, setMail] = useState("");
|
||||
const handleEmail = (e) => {
|
||||
@@ -71,7 +67,6 @@ export default function Login() {
|
||||
setLoginLoading(true);
|
||||
// userApi.getUserReminders(); //testing
|
||||
setTimeout(() => {
|
||||
toast.success("Login Successfully");
|
||||
navigate("/", { replace: true });
|
||||
setLoginLoading(false);
|
||||
}, 2000);
|
||||
@@ -123,6 +118,8 @@ export default function Login() {
|
||||
iconName="message"
|
||||
/>
|
||||
</div>
|
||||
<input type="text" placeholder="boyce" />
|
||||
|
||||
<div className="input-item mb-5">
|
||||
<InputCom
|
||||
value={password}
|
||||
@@ -168,7 +165,7 @@ export default function Login() {
|
||||
Forgot Password
|
||||
</a>
|
||||
</div> */}
|
||||
{loginError && <div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light 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]">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>}
|
||||
<div className="signin-area mb-3.5">
|
||||
<div className="flex justify-center">
|
||||
|
||||
@@ -29,14 +29,15 @@ export default function SignUp() {
|
||||
// To Show and Hide Password
|
||||
const togglePasswordVisibility = () => {
|
||||
setShowPassword(!showPassword);
|
||||
// return console.log('showPassword')
|
||||
};
|
||||
|
||||
const rememberMe = () => {
|
||||
setValue(!checked);
|
||||
};
|
||||
|
||||
const navigate = useNavigate();
|
||||
const userApi = new usersService();
|
||||
|
||||
// Get Country Api
|
||||
const getCountryList = async () => {
|
||||
const res = await userApi.getSignupCountryData()
|
||||
@@ -45,7 +46,7 @@ export default function SignUp() {
|
||||
if (res.status === 200) {
|
||||
const { signup_country } = await res.data
|
||||
setCountries(signup_country)
|
||||
} else if (res.data.result != 100) {
|
||||
} else if (res.data.result !== 100) {
|
||||
setCountries('Nothing see here!')
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -56,12 +57,13 @@ export default function SignUp() {
|
||||
const handleSignUp = async () => {
|
||||
let { country, first_name, last_name, email, password } = formData
|
||||
|
||||
if (email == '' && password == '' && first_name == '') {
|
||||
if (email === '' && password === '' && first_name === '') {
|
||||
setMsgError('Please fill in fields')
|
||||
}
|
||||
|
||||
try {
|
||||
if (email !== '' && password !== '' && first_name !== '' && last_name !== '') {
|
||||
setSignUpLoading(true)
|
||||
const reqData = {
|
||||
country: country,
|
||||
firstname: first_name,
|
||||
@@ -74,41 +76,46 @@ export default function SignUp() {
|
||||
}
|
||||
|
||||
const res = await userApi.CreateUser(reqData)
|
||||
|
||||
if (res.status === 200) {
|
||||
const { data } = res
|
||||
if (data.status == -1 && data.acc == 'DULPICATE') {
|
||||
if (data.status === -1 && data.acc === 'DULPICATE') {
|
||||
setMsgError('This account has been already created')
|
||||
setSignUpLoading(false)
|
||||
}
|
||||
if (data.status > 0 && data.internal_return == 100 && data.session != '') {
|
||||
localStorage.setItem("email", `${data.email}`);
|
||||
localStorage.setItem("country", `${data.country}`);
|
||||
localStorage.setItem("firstname", `${data.firstname}`);
|
||||
localStorage.setItem("lastname", `${data.lastname}`);
|
||||
setSignUpLoading(true)
|
||||
|
||||
if (data && data.status === '1') {
|
||||
setTimeout(() => {
|
||||
navigate("/", { replace: true });
|
||||
navigate("/verify-you", { replace: true });
|
||||
setSignUpLoading(false)
|
||||
}, 2000)
|
||||
console.log('Success')
|
||||
} else {
|
||||
setMsgError(data.status)
|
||||
setSignUpLoading(false)
|
||||
setMsgError('This account does not exist')
|
||||
}
|
||||
} else {
|
||||
setSignUpLoading(false)
|
||||
setMsgError('An error occurred')
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(error)
|
||||
setMsgError('An error occurred')
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
setMsgError(null)
|
||||
}, 7000)
|
||||
}, process.env.REACT_APP_SIGNUP_ERROR_TIMEOUT)
|
||||
setFormData({
|
||||
first_name: '',
|
||||
last_name: '',
|
||||
email: '',
|
||||
country: '',
|
||||
password: ''
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getCountryList()
|
||||
}, [])
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
import { useState, useLayoutEffect, 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"
|
||||
|
||||
export default function VerifyLink() {
|
||||
const [pageLoader, setPageLoader] = useState(true)
|
||||
const [linkSuccess, setLinkSuccess] = useState(false)
|
||||
const [linkError, setLinkError] = useState(false)
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation();
|
||||
const queryParams = new URLSearchParams(location?.search)
|
||||
const token = queryParams.get('vlink')
|
||||
|
||||
const verifyEmail = useCallback(
|
||||
async (code) => {
|
||||
const userApi = new usersService()
|
||||
|
||||
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)
|
||||
setLinkSuccess(true)
|
||||
} else {
|
||||
setPageLoader(false)
|
||||
setLinkError(true)
|
||||
}
|
||||
console.log(data)
|
||||
}
|
||||
} catch (error) {
|
||||
setPageLoader(false)
|
||||
setLinkError(true)
|
||||
throw new Error(error)
|
||||
}
|
||||
}, []
|
||||
)
|
||||
|
||||
useLayoutEffect(() => {
|
||||
verifyEmail(token)
|
||||
})
|
||||
|
||||
console.log(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" style={{
|
||||
fontSize: 'calc(1rem + .6vw)'
|
||||
}}>
|
||||
{linkError && 'Invalid verification link'}
|
||||
{linkSuccess && 'Sign In to WrenchBoard'}
|
||||
</h1>
|
||||
</div>
|
||||
{/* If the verification was a success */}
|
||||
{linkSuccess && <SuccessfulComponent />}
|
||||
|
||||
{/* If the verification was unsuccessful */}
|
||||
{linkError && <ErrorComponent onClick={() => navigate('/login')} />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</AuthLayout>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const SuccessfulComponent = ({ onClick }) => (
|
||||
<div className="input-area">
|
||||
{/* INPUT */}
|
||||
<div className="mb-5">
|
||||
<InputCom
|
||||
// value={password}
|
||||
// inputHandler={handlePassword}
|
||||
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>
|
||||
<div className="signin-area mb-3.5">
|
||||
<button
|
||||
onClick={onClick}
|
||||
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 $`}
|
||||
>
|
||||
<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-[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.81rem]`}
|
||||
>
|
||||
<span>Return Home</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -1,7 +1,4 @@
|
||||
import React from "react";
|
||||
import titleShape from "../../../assets/images/shape/text-shape-three.svg";
|
||||
import AuthLayout from "../AuthLayout";
|
||||
import Otp from "./Otp";
|
||||
|
||||
export default function VerifyYou() {
|
||||
return (
|
||||
@@ -9,32 +6,24 @@ export default function VerifyYou() {
|
||||
<AuthLayout
|
||||
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>
|
||||
<div className="title-area flex flex-col justify-center items-center relative text-center mb-8">
|
||||
<h1 className="sm:text-5xl text-4xl font-bold leading-[74px] text-dark-gray dark:text-white">
|
||||
Verification Code
|
||||
<div className="content-wrapper login dark:bg-dark-white w-full lg:max-w-[500px] 2xl:w-[828px] rounded-xl flex flex-col justify-center 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" style={{
|
||||
fontSize: 'calc(1rem + .6vw)'
|
||||
}}>
|
||||
Verification Sent
|
||||
</h1>
|
||||
<div className="shape sm:w-[377px] w-[270px] -mt-5 ml-5">
|
||||
<img src={titleShape} alt="shape" />
|
||||
</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 className="mb-5">
|
||||
<p className="text-[14px] leading-[19px] text-center text-[#181c32]">
|
||||
To complete the verification process, you should check your email inbox and look for the verification email. It may take a few minutes for the email to arrive, so be patient. Once you receive the email, open it and click on the verification link provided.
|
||||
</p>
|
||||
</div>
|
||||
<div className="resend-code flex justify-center">
|
||||
<p className="text-lg text-thin-light-gray font-normal">
|
||||
Dont’t have an aceount ?
|
||||
<a href="#" className="ml-2 text-dark-gray dark:text-white font-bold">
|
||||
Please resend
|
||||
</a>
|
||||
<div className="mb-5">
|
||||
<p className="text-[14px] leading-[19px] text-center text-[#181c32]">
|
||||
If you haven't received the verification email after a reasonable amount of time, make sure to check your spam or junk mail folder. It's also possible that the email was sent to the wrong email address, so double-check that you entered your email address correctly.
|
||||
</p>
|
||||
</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>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import React, { useRef } from "react";
|
||||
import Icons from "../../Icons";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
@@ -12,8 +12,59 @@ export default function InputCom({
|
||||
inputHandler,
|
||||
value,
|
||||
forgotPassword,
|
||||
onClick
|
||||
onClick,
|
||||
disable,
|
||||
blurHandler,
|
||||
onMouseEnter,
|
||||
onMouseLeave
|
||||
}) {
|
||||
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 (
|
||||
<div className="input-com">
|
||||
<div className="flex items-center justify-between">
|
||||
@@ -25,7 +76,7 @@ export default function InputCom({
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
{forgotPassword && <Link href="/forgot-password" className="text-base text-[#4687ba] hover:text-[#009ef7]">Forgot Password?</Link>}
|
||||
{forgotPassword && <Link to="/forgot-password" className="text-base text-[#4687ba] hover:text-[#009ef7]">Forgot Password?</Link>}
|
||||
</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 ">
|
||||
<input
|
||||
@@ -36,7 +87,13 @@ export default function InputCom({
|
||||
type={type}
|
||||
id={name}
|
||||
name={name}
|
||||
required
|
||||
minLength={minLengthValidation()}
|
||||
maxLength={maxLengthValidation()}
|
||||
ref={inputRef}
|
||||
readOnly={disable}
|
||||
onBlur={blurHandler}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
/>
|
||||
{iconName && (
|
||||
<div className="absolute right-6 bottom-[10px] z-10">
|
||||
|
||||
@@ -18,6 +18,7 @@ export default function Hero({ className }) {
|
||||
infinite: true,
|
||||
swipe: true,
|
||||
};
|
||||
const sildeData =null;
|
||||
const [addFavorite, setValue] = useState(false);
|
||||
const favoriteHandler = () => {
|
||||
if (!addFavorite) {
|
||||
@@ -96,7 +97,7 @@ export default function Hero({ className }) {
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<HomeSliders settings={settings} />
|
||||
<HomeSliders settings={settings} sideData={sildeData}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import SliderCom from "../Helpers/SliderCom";
|
||||
import slider1 from "../../assets/images/slider-1.jpg";
|
||||
import slider2 from "../../assets/images/slider-2.jpg";
|
||||
import slider3 from "../../assets/images/slider-3.jpg";
|
||||
import HomeBannerOffersCard from "../Cards/HomeBannerOffersCard";
|
||||
|
||||
|
||||
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">
|
||||
<img src={slider3} alt="slider" className="w-full h-full" />
|
||||
</div>
|
||||
<div className="item w-full h-full bg-white dark:bg-dark-white rounded-2xl overflow-hidden">
|
||||
<HomeBannerOffersCard />
|
||||
</div>
|
||||
</SliderCom>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,11 +4,12 @@ import Layout from "../Partials/Layout";
|
||||
import MyJobTable from "./MyJobTable";
|
||||
import CommonHead from "../UserHeader/CommonHead";
|
||||
|
||||
export default function MyJobs() {
|
||||
export default function MyJobs(props) {
|
||||
const [selectTab, setValue] = useState("today");
|
||||
const filterHandler = (value) => {
|
||||
setValue(value);
|
||||
};
|
||||
console.log("AMEYE LOC1", props.MyJobList);
|
||||
return (
|
||||
<Layout>
|
||||
<CommonHead />
|
||||
@@ -32,7 +33,7 @@ export default function MyJobs() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<MyJobTable />
|
||||
<MyJobTable MyJobList={props.MyJobList} />
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
@@ -1,161 +1,365 @@
|
||||
import React, {useState} from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import React, {useEffect, useState} from 'react'
|
||||
import { Link, useNavigate } from 'react-router-dom'
|
||||
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 3 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() {
|
||||
|
||||
//STATE FOR CONTROLLED INPUTS
|
||||
let [inputs, setInputs] = useState({
|
||||
firstname: '',
|
||||
lastname: '',
|
||||
country: '',
|
||||
'bank-name': '',
|
||||
'account-number': '',
|
||||
'repeat-account-number': '',
|
||||
'account-type': '',
|
||||
state: '',
|
||||
city: ''
|
||||
|
||||
const apiURL = new usersService()
|
||||
|
||||
const navigate = useNavigate()
|
||||
|
||||
let [requestStatus, setRequestStatus] = useState({message: '', loading: false, status: false})
|
||||
|
||||
let [allCountries, setAllCountries] = useState({ // STATE TO HOLD LIST OF COUNTRIES
|
||||
loading: true,
|
||||
data: []
|
||||
})
|
||||
|
||||
// FUNCTION TO HANDLE INPUT CHANGE
|
||||
const handleChange = ({target:{name, value}}) => {
|
||||
setInputs(prev => ({...prev, [name]:value}))
|
||||
let [bankName, setBankName] = useState({ // STATE TO HOLD LIST OF BANK NAME
|
||||
loading: true,
|
||||
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('../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
|
||||
|
||||
// setInputs((prev)=>{
|
||||
// for(let input in prev){
|
||||
// prev[input] = ''
|
||||
// }
|
||||
// })
|
||||
// RETURN INPUTS TO EMPTY STRING
|
||||
setInputs({
|
||||
firstname: '',
|
||||
lastname: '',
|
||||
country: '',
|
||||
'bank-name': '',
|
||||
'account-number': '',
|
||||
'repeat-account-number': '',
|
||||
'account-type': '',
|
||||
state: '',
|
||||
city: ''
|
||||
// FUNCTION TO GET COUNTRIES
|
||||
const getCountry = ()=> {
|
||||
apiURL.getSignupCountryData().then((res)=>{
|
||||
if(res.data.internal_return < 0){
|
||||
setAllCountries(prev => ({loading: false, data: []}))
|
||||
return
|
||||
}
|
||||
setAllCountries(prev => ({loading: false, data:res.data.signup_country}))
|
||||
}).catch((error)=>{
|
||||
setAllCountries(prev => ({loading: false, data: []}))
|
||||
})
|
||||
}
|
||||
// END OF FUNCTION TO GET COUNTRIES
|
||||
|
||||
// FUNCTION TO GET COUNTRY BANK
|
||||
const getCountryBank = ()=> {
|
||||
apiURL.getCountryBank().then((res)=>{
|
||||
if(res.data.internal_return < 0){
|
||||
setBankName(prev => ({loading: false, data: []}))
|
||||
return
|
||||
}
|
||||
setBankName(prev => ({loading: false, data:res.data.result_list}))
|
||||
}).catch((error)=>{
|
||||
setBankName(prev => ({loading: false, data: []}))
|
||||
})
|
||||
}
|
||||
// END OF FUNCTION TO GET COUNTRY BANK
|
||||
|
||||
// FUNCTION TO GET 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 (
|
||||
<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 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>
|
||||
<form className='add-recipient-info px-1 md:px-[50px] lg:px-[100px]' onSubmit={handleSubmit}>
|
||||
|
||||
{/* inputs starts here */}
|
||||
<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>
|
||||
<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.firstname}
|
||||
name='firstname'
|
||||
type="text"
|
||||
placeholder='Account Firstname'
|
||||
required
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
<h2 className='my-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-semibold'>ADD BANK ACCOUNT</h2>
|
||||
<Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={handleSubmit}>
|
||||
{(props)=>(
|
||||
<Form className='add-recipient-info px-1 md:px-[50px] lg:px-[100px]'>
|
||||
|
||||
{/* inputs starts here */}
|
||||
{/* firstname */}
|
||||
<div className="xl:flex xl:space-x-7 mb-6">
|
||||
<div className="field w-full mb-6 xl:mb-0">
|
||||
<InputCom
|
||||
label="Firstname"
|
||||
type="text"
|
||||
name="firstname"
|
||||
placeholder="Account Firstname"
|
||||
value={props.values.firstname}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{(props.errors.firstname && props.touched.firstname) && <p className="text-sm text-red-500">{props.errors.firstname}</p>}
|
||||
</div>
|
||||
|
||||
<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'>Last Name <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='Account Lastname'
|
||||
required
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
{/* lastname */}
|
||||
<div className="field w-full">
|
||||
<InputCom
|
||||
label="Lastname"
|
||||
type="text"
|
||||
name="lastname"
|
||||
placeholder="Account Lastname"
|
||||
value={props.values.lastname}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{(props.errors.lastname && props.touched.lastname) && <p className="text-sm text-red-500">{props.errors.lastname}</p>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='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>
|
||||
<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}>
|
||||
<option className='text-slate-500 text-lg' value="">Select...</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="xl:flex xl:space-x-7 mb-6">
|
||||
{/* country */}
|
||||
<div className='add-recipient w-full mb-6 xl:mb-0'>
|
||||
<label className='input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Country <span className='text-red-500'>*</span></label>
|
||||
<select className='w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0' name='country'
|
||||
value={props.values.country}
|
||||
onChange={props.handleChange}
|
||||
onBlur={props.handleBlur}
|
||||
>
|
||||
{allCountries.loading ?
|
||||
<option className='text-slate-500 text-lg' value="">Loading...</option>
|
||||
:
|
||||
allCountries.data.length ?
|
||||
<>
|
||||
<option className='text-slate-500 text-lg' value="">Select...</option>
|
||||
{allCountries.data.map((item, index)=>(
|
||||
<option key={index} className='text-slate-500 text-lg' value={item[0]}>{item[1]}</option>
|
||||
))}
|
||||
</>
|
||||
:
|
||||
<option className='text-slate-500 text-lg' value="">No Options Found! Try Again</option>
|
||||
}
|
||||
</select>
|
||||
{(props.errors.country && props.touched.country) && <p className="text-sm text-red-500">{props.errors.country}</p>}
|
||||
</div>
|
||||
|
||||
{/* bank name */}
|
||||
<div className='add-recipient w-full'>
|
||||
<label className='input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Bank Name <span className='text-red-500'>*</span></label>
|
||||
<select className='w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0' name='bank'
|
||||
value={props.values.bank}
|
||||
onChange={props.handleChange}
|
||||
onBlur={props.handleBlur}
|
||||
>
|
||||
{bankName.loading ?
|
||||
<option className='text-slate-500 text-lg' value="">Loading...</option>
|
||||
:
|
||||
bankName.data.length ?
|
||||
<>
|
||||
<option className='text-slate-500 text-lg' value="">Select...</option>
|
||||
{bankName.data.map((item, index)=>(
|
||||
<option key={index} className='text-slate-500 text-lg' value={item.code}>{item.name}</option>
|
||||
))}
|
||||
</>
|
||||
:
|
||||
<option className='text-slate-500 text-lg' value="">No Options Found! Try Again</option>
|
||||
}
|
||||
</select>
|
||||
{(props.errors.bank && props.touched.bank) && <p className="text-sm text-red-500">{props.errors.bank}</p>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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'>Bank Name <span className='text-red-500'>*</span></label>
|
||||
<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}>
|
||||
<option className='text-slate-500 text-lg' value="">Select...</option>
|
||||
</select>
|
||||
</div>
|
||||
{/* ACCOUNT NUMBER */}
|
||||
<div className="xl:flex xl:space-x-7 mb-6">
|
||||
<div className="field w-full mb-6 xl:mb-0">
|
||||
<InputCom
|
||||
label="Account Number"
|
||||
type="text"
|
||||
name="accountNumber"
|
||||
placeholder="Account No"
|
||||
value={props.values.accountNumber}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{(props.errors.accountNumber && props.touched.accountNumber) && <p className="text-sm text-red-500">{props.errors.accountNumber}</p>}
|
||||
</div>
|
||||
|
||||
<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'>Account Number <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['account-number']}
|
||||
name='account-number'
|
||||
type="text"
|
||||
placeholder='Account No'
|
||||
required
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
{/* REPEAT ACCT. NUMBER */}
|
||||
<div className="field w-full">
|
||||
<InputCom
|
||||
label="Repeat Account Number"
|
||||
type="text"
|
||||
name="repeatAccountNumber"
|
||||
placeholder="Repeat Account Number"
|
||||
value={props.values.repeatAccountNumber}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{(props.errors.repeatAccountNumber && props.touched.repeatAccountNumber) && <p className="text-sm text-red-500">{props.errors.repeatAccountNumber}</p>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='add-recipient my-3 md:flex items-center justify-between'>
|
||||
<label className='w-full md:w-1/4 text-slate-600 text-lg'>Repeat Account Number <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['repeat-account-number']}
|
||||
name='repeat-account-number'
|
||||
type="text"
|
||||
placeholder='Repeat Account No'
|
||||
required
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="xl:flex xl:space-x-7 mb-6">
|
||||
{/* Account Type */}
|
||||
<div className='add-recipient w-full'>
|
||||
<label className='input-label text-[#181c32] dark:text-white text-base font-semibold block mb-2.5'>Account Type <span className='text-red-500'>*</span></label>
|
||||
<select className='w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0' name='accountType'
|
||||
value={props.values.accountType}
|
||||
onChange={props.handleChange}
|
||||
onBlur={props.handleBlur}
|
||||
>
|
||||
{accType.loading ?
|
||||
<option className='text-slate-500 text-lg' value="">Loading...</option>
|
||||
:
|
||||
accType.data.length ?
|
||||
<>
|
||||
<option className='text-slate-500 text-lg' value="">Select...</option>
|
||||
{accType.data.map((item, index)=>(
|
||||
<option key={index} className='text-slate-500 text-lg' value={item.value}>{item.name}</option>
|
||||
))}
|
||||
</>
|
||||
:
|
||||
<option className='text-slate-500 text-lg' value="">No Options Found! Try Again</option>
|
||||
}
|
||||
</select>
|
||||
{(props.errors.accountType && props.touched.accountType) && <p className="text-sm text-red-500">{props.errors.accountType}</p>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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'>Account type <span className='text-red-500'>*</span></label>
|
||||
<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}>
|
||||
<option className='text-slate-500 text-lg' value="">Select...</option>
|
||||
</select>
|
||||
</div>
|
||||
{/* state */}
|
||||
<div className="xl:flex xl:space-x-7 mb-6">
|
||||
<div className="field w-full mb-6 xl:mb-0">
|
||||
<InputCom
|
||||
label="State"
|
||||
type="text"
|
||||
name="state"
|
||||
placeholder="State/Province"
|
||||
value={props.values.state}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{(props.errors.state && props.touched.state) && <p className="text-sm text-red-500">{props.errors.state}</p>}
|
||||
</div>
|
||||
|
||||
<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'>State/Province <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.state}
|
||||
name='state'
|
||||
type="text"
|
||||
placeholder='State'
|
||||
required
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
{/* city */}
|
||||
<div className="field w-full">
|
||||
<InputCom
|
||||
label="City"
|
||||
type="text"
|
||||
name="city"
|
||||
placeholder="City"
|
||||
value={props.values.city}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{(props.errors.city && props.touched.city) && <p className="text-sm text-red-500">{props.errors.city}</p>}
|
||||
</div>
|
||||
</div>
|
||||
{/* end of inputs starts here */}
|
||||
|
||||
<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'>City <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.city}
|
||||
name='city'
|
||||
type="text"
|
||||
placeholder='City'
|
||||
required
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
{/* REQUEST ERROR DISPLAY */}
|
||||
{requestStatus.message && <p className='text-sm text-red-500'>{requestStatus.message}</p>}
|
||||
|
||||
{/* end of inputs starts here */}
|
||||
|
||||
<div className='add-recipient-btn flex justify-end items-center py-4'>
|
||||
<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>
|
||||
<Icons name="arrows" />
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<div className='add-recipient-btn flex justify-end items-center py-4'>
|
||||
{requestStatus.loading ?
|
||||
<LoadingSpinner size={6} color='sky-blue' />
|
||||
:
|
||||
<button type='submit' className='text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-md flex items-center space-x-1'>
|
||||
<span className='pr-2'>ADD RECIPIENT</span>
|
||||
<Icons name="arrows" />
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, {useEffect, useState} from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import RecentActivityTable from './WalletComponent/RecentActivityTable'
|
||||
import LoadingSpinner from '../Spinners/LoadingSpinner'
|
||||
import InputCom from '../Helpers/Inputs/InputCom'
|
||||
|
||||
import usersService from '../../services/UsersService'
|
||||
|
||||
@@ -97,57 +98,53 @@ function TransferFund({payment, wallet}) {
|
||||
:
|
||||
<h2 className='my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>No Wallet Information Found!</h2>
|
||||
}
|
||||
<div className='my-3 md:flex items-center justify-between space-x-2'>
|
||||
<div className='transfer-input w-full md:w-1/2'>
|
||||
<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}
|
||||
<div className="xl:flex xl:space-x-7 mb-6">
|
||||
|
||||
<div className="field w-full mb-6 xl:mb-0">
|
||||
<InputCom
|
||||
label="Amount"
|
||||
type="text"
|
||||
name="amount"
|
||||
value={inputs.amount}
|
||||
inputHandler={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 className="field w-full">
|
||||
<InputCom
|
||||
label="Fee"
|
||||
type="text"
|
||||
name="fee"
|
||||
value={sendMoneyFee.fee}
|
||||
disable={true}
|
||||
/>
|
||||
</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 className='md:flex items-center justify-end'>
|
||||
<div className="field w-full lg:w-1/2 mb-6">
|
||||
<InputCom
|
||||
label="Total"
|
||||
type="text"
|
||||
name="total"
|
||||
value={sendMoneyFee.total}
|
||||
disable={true}
|
||||
/>
|
||||
</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
|
||||
<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-3 bg-[orange] rounded-md hover:opacity-80'>Add New</Link>
|
||||
<Link to='add-recipient' className='mx-1 text-base text-white p-2 bg-[orange] rounded-md hover:opacity-80'>Add New</Link>
|
||||
</div>
|
||||
<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}>
|
||||
<select className='w-full text-base p-2 text-dark-gray dark:text-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>
|
||||
:
|
||||
@@ -168,18 +165,23 @@ function TransferFund({payment, wallet}) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='my-3 md:flex items-center'>
|
||||
<div className='transfer-input w-full'>
|
||||
<label className='w-full text-slate-600 text-lg'>Comment <span className='text-red-500'>*</span></label>
|
||||
<input className='w-full p-3 text-lg bg-slate-100 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg'
|
||||
value={inputs.comment}
|
||||
name='comment'
|
||||
type="text"
|
||||
placeholder='Comment'
|
||||
required
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</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={inputs.comment}
|
||||
onChange={handleChange}
|
||||
cols="30"
|
||||
rows="2"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='transfer-fund-btn flex justify-end items-center py-4'>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import Icons from "../../Helpers/Icons";
|
||||
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||
import {Link, useNavigate} from 'react-router-dom'
|
||||
@@ -7,6 +7,41 @@ 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({
|
||||
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'),
|
||||
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: '',
|
||||
state: '',
|
||||
city: '',
|
||||
email: ''
|
||||
}
|
||||
|
||||
export default function PersonalInfoTab({
|
||||
datas,
|
||||
frstNmeHndlr,
|
||||
@@ -27,7 +62,13 @@ export default function PersonalInfoTab({
|
||||
|
||||
let [togglePromotion, setTogglePromotion] = useState(false)
|
||||
|
||||
let [requestStatus, setRequestState] = useState({
|
||||
let [profile, setProfile] = useState({ // state for requesting from load profile API
|
||||
data: [],
|
||||
loading: true,
|
||||
status: false
|
||||
})
|
||||
|
||||
let [requestStatus, setRequestState] = useState({ // state for requesting from update api
|
||||
message: '',
|
||||
loading: false,
|
||||
status: false
|
||||
@@ -41,40 +82,18 @@ export default function PersonalInfoTab({
|
||||
email: ''
|
||||
})
|
||||
|
||||
const handleChange = ({target:{name, value}}) => {
|
||||
setInputs(prev => ({...prev, [name]:value}))
|
||||
}
|
||||
// const handleChange = ({target:{name, value}}) => {
|
||||
// setInputs(prev => ({...prev, [name]:value}))
|
||||
// }
|
||||
|
||||
const handleUpdateUser = ()=> {
|
||||
const handleUpdateUser = (values, helpers)=> {
|
||||
setRequestState({message: '', loading: true, status: false})
|
||||
|
||||
let {firstname, lastname, state, city, email} = inputs
|
||||
|
||||
if(!firstname || !lastname || !state || !city || !email){
|
||||
setRequestState({message: 'Please Fill all fields', loading: false, status: false})
|
||||
return
|
||||
}
|
||||
|
||||
//checks if email is a valid email address
|
||||
let regEx = /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/;
|
||||
if (regEx.test(email) == false) {
|
||||
setRequestState({message: 'Your Email is Invalid', loading: false, status: false})
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
apiCall.updateProfile(inputs).then((res)=>{
|
||||
apiCall.updateProfile(values).then((res)=>{
|
||||
if(res.data.internal_return < 0){
|
||||
setRequestState({message: 'Profile Was unable to update', loading: false, status: false})
|
||||
return
|
||||
}
|
||||
setInputs({
|
||||
firstname: '',
|
||||
lastname: '',
|
||||
state: '',
|
||||
city: '',
|
||||
email: ''
|
||||
})
|
||||
// setRequestState({message: 'Profile update successfully', loading: false, status: true})
|
||||
toast.success("Update Successful");
|
||||
setTimeout(()=>{navigate('/',{replace:true})},1000)
|
||||
@@ -83,258 +102,267 @@ export default function PersonalInfoTab({
|
||||
})
|
||||
}
|
||||
|
||||
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(()=>{
|
||||
loadProfile() // loads user profile unto the page
|
||||
},[])
|
||||
|
||||
return (
|
||||
<div className="personal-info-tab w-full flex flex-col justify-between">
|
||||
<div className="flex flex-col-reverse sm:flex-row">
|
||||
<div className="flex-1 sm:mr-10">
|
||||
<div className="fields w-full">
|
||||
{/* inputs starts here */}
|
||||
{/* username */}
|
||||
<div className='profile-input my-3'>
|
||||
<label className='w-full text-slate-600 text-lg'>Username <span className='text-red-500'>*</span></label>
|
||||
<input className='w-full p-3 text-lg text-slate-500 bg-slate-200 opacity-90 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg'
|
||||
value={'username@gamil.com'}
|
||||
name='username'
|
||||
type="text"
|
||||
placeholder='username@gamil.com'
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Email */}
|
||||
<div className='profile-input my-3'>
|
||||
<label className='w-full text-slate-600 text-lg'>Email <span className='text-red-500'>*</span></label>
|
||||
<input className='w-full p-3 text-lg text-slate-500 bg-slate-200 opacity-90 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg'
|
||||
value={inputs.email}
|
||||
name='email'
|
||||
type="text"
|
||||
placeholder='Firstname'
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Fullname */}
|
||||
<div className='profile-input my-3'>
|
||||
<label className='w-full text-slate-600 text-lg'>Fullname <span className='text-red-500'>*</span></label>
|
||||
<div className="w-full flex items-center justify-center space-x-1 space-y-1">
|
||||
<input className='p-3 text-lg text-slate-500 bg-slate-100 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg'
|
||||
value={inputs.firstname}
|
||||
name='firstname'
|
||||
type="text"
|
||||
placeholder='Firstname'
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<input className='p-3 text-lg text-slate-500 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>
|
||||
|
||||
{/* Country */}
|
||||
<div className='profile-input my-3'>
|
||||
<label className='w-full text-slate-600 text-lg'>Country <span className='text-red-500'>*</span></label>
|
||||
<input className='w-full p-3 text-lg text-slate-500 bg-slate-200 opacity-90 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg'
|
||||
value='Nigeria'
|
||||
name='country'
|
||||
type="text"
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* State/Province */}
|
||||
<div className='profile-input my-3'>
|
||||
<label className='w-full text-slate-600 text-lg'>State/Province <span className='text-red-500'>*</span></label>
|
||||
<input className='w-full p-3 text-lg text-slate-500 bg-slate-100 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg'
|
||||
value={inputs.state}
|
||||
name='state'
|
||||
type="text"
|
||||
placeholder='State'
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* City */}
|
||||
<div className='profile-input my-3'>
|
||||
<label className='w-full text-slate-600 text-lg'>City <span className='text-red-500'>*</span></label>
|
||||
<input className='w-full p-3 text-lg text-slate-500 bg-slate-100 rounded-md outline-0 placeholder:text-slate-500 placeholder:text-lg'
|
||||
value={inputs.city}
|
||||
name='city'
|
||||
type="text"
|
||||
placeholder='City'
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Preferred Communication*/}
|
||||
<div className='profile-input my-3'>
|
||||
<label className='text-slate-600 text-lg'>Pref. Communication <span className='text-red-500'>*</span></label>
|
||||
<div className="check-box">
|
||||
<div className="flex items-center justify-start">
|
||||
<div className="check-input flex items-center">
|
||||
<input className="mx-2 w-4 h-4 cursor-pointer" type="checkbox" name="prefcomm1" id="" />
|
||||
<span className="text-slate-600 text-lg">Email</span>
|
||||
</div>
|
||||
<div className="check-input flex items-center">
|
||||
<input className="mx-2 w-4 h-4 cursor-pointer" type="checkbox" name="prefcomm2" id="" />
|
||||
<span className="text-slate-600 text-lg">Phone</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Allow Promotions */}
|
||||
<div className='profile-input my-3 flex items-center space-x-4'>
|
||||
<label className='text-slate-600 text-lg'>Allow Promotions</label>
|
||||
<div className="cursor-pointer flex items-center" onClick={()=>setTogglePromotion(prev => !prev)}>
|
||||
<div className={`h-6 w-8 mr-1 p-1 ${togglePromotion ? 'bg-sky-blue flex justify-end items-center': 'bg-slate-200'} rounded-full transition`}>
|
||||
<div className="w-4 h-full bg-white rounded-full"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* inputs ends here */}
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-[232px] mb-10">
|
||||
<div className="update-profile w-full mb-9">
|
||||
<h1 className="text-xl tracking-wide font-bold text-dark-gray dark:text-white flex items-center mb-2">
|
||||
Update Profile
|
||||
<span className="ml-1">
|
||||
<Icons name="block-question" />
|
||||
</span>
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray mb-5">
|
||||
Profile of at least Size
|
||||
<span className="ml-1 text-dark-gray dark:text-white">
|
||||
300x300
|
||||
</span>
|
||||
. Gifs work too.
|
||||
<span className="ml-1 text-dark-gray dark:text-white">
|
||||
Max 5mb
|
||||
</span>
|
||||
.
|
||||
</p>
|
||||
<div className="flex justify-center">
|
||||
<div className="w-full relative">
|
||||
<img
|
||||
src={profileImg}
|
||||
alt=""
|
||||
className="sm:w-[198px] sm:h-[198px] w-[120px] h-[120px] rounded-full overflow-hidden object-cover"
|
||||
/>
|
||||
<input
|
||||
ref={profileImgInput}
|
||||
onChange={(e) => profileImgChangHandler(e)}
|
||||
type="file"
|
||||
className="hidden"
|
||||
/>
|
||||
<div
|
||||
onClick={browseProfileImg}
|
||||
className="w-[32px] h-[32px] absolute bottom-7 sm:right-10 right-[105px] hover:bg-pink bg-dark-gray rounded-full cursor-pointer"
|
||||
>
|
||||
<svg
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 32 32"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16.5147 11.5C17.7284 12.7137 18.9234 13.9087 20.1296 15.115C19.9798 15.2611 19.8187 15.4109 19.6651 15.5683C17.4699 17.7635 15.271 19.9587 13.0758 22.1539C12.9334 22.2962 12.7948 22.4386 12.6524 22.5735C12.6187 22.6034 12.5663 22.6296 12.5213 22.6296C11.3788 22.6334 10.2362 22.6297 9.09365 22.6334C9.01498 22.6334 9 22.6034 9 22.536C9 21.4009 9 20.2621 9.00375 19.1271C9.00375 19.0746 9.02997 19.0109 9.06368 18.9772C10.4123 17.6249 11.7609 16.2763 13.1095 14.9277C14.2295 13.8076 15.3459 12.6913 16.466 11.5712C16.4884 11.5487 16.4997 11.5187 16.5147 11.5Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M20.9499 14.2904C19.7436 13.0842 18.5449 11.8854 17.3499 10.6904C17.5634 10.4694 17.7844 10.2446 18.0054 10.0199C18.2639 9.76139 18.5261 9.50291 18.7884 9.24443C19.118 8.91852 19.5713 8.91852 19.8972 9.24443C20.7251 10.0611 21.5492 10.8815 22.3771 11.6981C22.6993 12.0165 22.7105 12.4698 22.3996 12.792C21.9238 13.2865 21.4443 13.7772 20.9686 14.2717C20.9648 14.2792 20.9536 14.2867 20.9499 14.2904Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="update-profile w-full">
|
||||
<h1 className="text-xl tracking-wide font-bold text-dark-gray dark:text-white flex items-center mb-2">
|
||||
Update Cover
|
||||
<span className="ml-1">
|
||||
<Icons name="block-question" />
|
||||
</span>
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray mb-5">
|
||||
Cover of at least Size
|
||||
<span className="ml-1 text-dark-gray dark:text-white">
|
||||
1170x920
|
||||
</span>
|
||||
.
|
||||
</p>
|
||||
<div className="flex justify-center">
|
||||
<div className="w-full relative">
|
||||
<img
|
||||
src={coverImg}
|
||||
alt=""
|
||||
className="w-full h-[120px] rounded-lg overflow-hidden object-cover"
|
||||
/>
|
||||
<input
|
||||
ref={coverImgInput}
|
||||
onChange={(e) => coverImgChangHandler(e)}
|
||||
type="file"
|
||||
className="hidden"
|
||||
/>
|
||||
<div
|
||||
onClick={browseCoverImg}
|
||||
className="w-[32px] h-[32px] absolute -bottom-4 right-4 bg-dark-gray hover:bg-pink rounded-full cursor-pointer"
|
||||
>
|
||||
<svg
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 32 32"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16.5147 11.5C17.7284 12.7137 18.9234 13.9087 20.1296 15.115C19.9798 15.2611 19.8187 15.4109 19.6651 15.5683C17.4699 17.7635 15.271 19.9587 13.0758 22.1539C12.9334 22.2962 12.7948 22.4386 12.6524 22.5735C12.6187 22.6034 12.5663 22.6296 12.5213 22.6296C11.3788 22.6334 10.2362 22.6297 9.09365 22.6334C9.01498 22.6334 9 22.6034 9 22.536C9 21.4009 9 20.2621 9.00375 19.1271C9.00375 19.0746 9.02997 19.0109 9.06368 18.9772C10.4123 17.6249 11.7609 16.2763 13.1095 14.9277C14.2295 13.8076 15.3459 12.6913 16.466 11.5712C16.4884 11.5487 16.4997 11.5187 16.5147 11.5Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M20.9499 14.2904C19.7436 13.0842 18.5449 11.8854 17.3499 10.6904C17.5634 10.4694 17.7844 10.2446 18.0054 10.0199C18.2639 9.76139 18.5261 9.50291 18.7884 9.24443C19.118 8.91852 19.5713 8.91852 19.8972 9.24443C20.7251 10.0611 21.5492 10.8815 22.3771 11.6981C22.6993 12.0165 22.7105 12.4698 22.3996 12.792C21.9238 13.2865 21.4443 13.7772 20.9686 14.2717C20.9648 14.2792 20.9536 14.2867 20.9499 14.2904Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
profile.loading ?
|
||||
<div className="personal-info-tab w-full flex flex-col justify-between">
|
||||
<div className="p-3">
|
||||
<LoadingSpinner size='32' color='sky-blue' />
|
||||
</div>
|
||||
</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>
|
||||
:
|
||||
<div className="personal-info-tab w-full flex flex-col justify-between">
|
||||
<Formik initialValues={inputs} validationSchema={validationSchema} onSubmit={handleUpdateUser}>
|
||||
{(props => {
|
||||
return (
|
||||
<Form>
|
||||
{
|
||||
profile.data.length ?
|
||||
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="fields w-full">
|
||||
{/* inputs starts here */}
|
||||
{/* username */}
|
||||
<div className="field w-full mb-6">
|
||||
<InputCom
|
||||
label="User Name"
|
||||
type="text"
|
||||
name="username"
|
||||
placeholder=""
|
||||
value={item.username}
|
||||
disable={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{requestStatus.loading ?
|
||||
<LoadingSpinner size='8' color='sky-blue' />
|
||||
{/* Email */}
|
||||
<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>
|
||||
{/* first name and last name */}
|
||||
<div className="xl:flex xl:space-x-7 mb-6">
|
||||
<div className="field w-full mb-6 xl:mb-0">
|
||||
<InputCom
|
||||
label="First Name"
|
||||
type="text"
|
||||
name="firstname"
|
||||
placeholder="First Name"
|
||||
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="field w-full">
|
||||
<InputCom
|
||||
label="Last Name"
|
||||
type="text"
|
||||
name="lastname"
|
||||
placeholder="Last Name"
|
||||
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>
|
||||
|
||||
{/* Country */}
|
||||
<div className="field w-full mb-6">
|
||||
<InputCom
|
||||
label="Country"
|
||||
type="text"
|
||||
name="country"
|
||||
value={item.country}
|
||||
disable={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* State/Province */}
|
||||
<div className="field w-full mb-6">
|
||||
<InputCom
|
||||
label="State/Province"
|
||||
type="text"
|
||||
name="state"
|
||||
placeholder="State"
|
||||
value={props.values.state}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{(props.errors.state && props.touched.state) && <p className="text-sm text-red-500">{props.errors.state}</p>}
|
||||
</div>
|
||||
|
||||
{/* City */}
|
||||
<div className="field w-full mb-6">
|
||||
<InputCom
|
||||
label="City"
|
||||
type="text"
|
||||
name="city"
|
||||
placeholder="City"
|
||||
value={props.values.city}
|
||||
inputHandler={props.handleChange}
|
||||
blurHandler={props.handleBlur}
|
||||
/>
|
||||
{(props.errors.city && props.touched.city) && <p className="text-sm text-red-500">{props.errors.city}</p>}
|
||||
</div>
|
||||
|
||||
{/* Preferred Communication*/}
|
||||
<div className='field w-full mb-6 md:flex items-center space-x-4'>
|
||||
<label className='input-label text-[#181c32] dark:text-white text-base font-semibold'>Pref. Communication</label>
|
||||
<div className="check-box">
|
||||
<div className="flex items-center justify-start">
|
||||
<div className="check-input flex items-center mr-1">
|
||||
<input className="w-4 h-4 cursor-pointer" type="checkbox" name="prefcomm1" id="" />
|
||||
<span className="mx-2 text-base text-dark-gray dark:text-white">Email</span>
|
||||
</div>
|
||||
<div className="check-input flex items-center">
|
||||
<input className="w-4 h-4 cursor-pointer" type="checkbox" name="prefcomm2" id="" />
|
||||
<span className="mx-2 text-base text-dark-gray dark:text-white">Phone</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Allow Promotions */}
|
||||
<div className='field w-full mb-6 flex items-center space-x-4'>
|
||||
<label className='input-label text-[#181c32] dark:text-white text-base font-semibold'>Allow Promotions</label>
|
||||
<div className="cursor-pointer flex items-center" onClick={()=>setTogglePromotion(prev => !prev)}>
|
||||
<div className={`h-6 w-8 mr-1 p-1 ${togglePromotion ? 'bg-sky-blue flex justify-end items-center': 'bg-slate-200'} rounded-full transition`}>
|
||||
<div className="w-4 h-full bg-white rounded-full"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* inputs ends here */}
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-[232px] mb-10">
|
||||
<div className="update-profile w-full mb-9">
|
||||
<h1 className="text-xl tracking-wide font-bold text-dark-gray dark:text-white flex items-center mb-2">
|
||||
Update Profile
|
||||
<span className="ml-1">
|
||||
<Icons name="block-question" />
|
||||
</span>
|
||||
</h1>
|
||||
<p className="text-base text-thin-light-gray mb-5">
|
||||
Profile of at least Size
|
||||
<span className="ml-1 text-dark-gray dark:text-white">
|
||||
300x300
|
||||
</span>
|
||||
. Gifs work too.
|
||||
<span className="ml-1 text-dark-gray dark:text-white">
|
||||
Max 5mb
|
||||
</span>
|
||||
.
|
||||
</p>
|
||||
<div className="flex justify-center">
|
||||
<div className="w-full relative">
|
||||
<img
|
||||
src={profileImg}
|
||||
alt=""
|
||||
className="sm:w-[198px] sm:h-[198px] w-[120px] h-[120px] rounded-full overflow-hidden object-cover"
|
||||
/>
|
||||
<input
|
||||
ref={profileImgInput}
|
||||
onChange={(e) => profileImgChangHandler(e)}
|
||||
type="file"
|
||||
className="hidden"
|
||||
/>
|
||||
<div
|
||||
onClick={browseProfileImg}
|
||||
className="w-[32px] h-[32px] absolute bottom-7 sm:right-10 right-[105px] hover:bg-pink bg-dark-gray rounded-full cursor-pointer"
|
||||
>
|
||||
<svg
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 32 32"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16.5147 11.5C17.7284 12.7137 18.9234 13.9087 20.1296 15.115C19.9798 15.2611 19.8187 15.4109 19.6651 15.5683C17.4699 17.7635 15.271 19.9587 13.0758 22.1539C12.9334 22.2962 12.7948 22.4386 12.6524 22.5735C12.6187 22.6034 12.5663 22.6296 12.5213 22.6296C11.3788 22.6334 10.2362 22.6297 9.09365 22.6334C9.01498 22.6334 9 22.6034 9 22.536C9 21.4009 9 20.2621 9.00375 19.1271C9.00375 19.0746 9.02997 19.0109 9.06368 18.9772C10.4123 17.6249 11.7609 16.2763 13.1095 14.9277C14.2295 13.8076 15.3459 12.6913 16.466 11.5712C16.4884 11.5487 16.4997 11.5187 16.5147 11.5Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M20.9499 14.2904C19.7436 13.0842 18.5449 11.8854 17.3499 10.6904C17.5634 10.4694 17.7844 10.2446 18.0054 10.0199C18.2639 9.76139 18.5261 9.50291 18.7884 9.24443C19.118 8.91852 19.5713 8.91852 19.8972 9.24443C20.7251 10.0611 21.5492 10.8815 22.3771 11.6981C22.6993 12.0165 22.7105 12.4698 22.3996 12.792C21.9238 13.2865 21.4443 13.7772 20.9686 14.2717C20.9648 14.2792 20.9536 14.2867 20.9499 14.2904Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
:
|
||||
<button
|
||||
type="button"
|
||||
className="w-[152px] h-[46px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
onClick={handleUpdateUser}
|
||||
>
|
||||
Upadate Profile
|
||||
</button>
|
||||
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>
|
||||
</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 ?
|
||||
<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>
|
||||
</Form>
|
||||
)
|
||||
})}
|
||||
</Formik>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
src: url("./assets/fonts/Product Sans Bold.ttf");
|
||||
}
|
||||
|
||||
.banner-630-340{
|
||||
width: 630px;
|
||||
height: 340px;
|
||||
background-color: aliceblue;
|
||||
}
|
||||
|
||||
/* Bold italic Weight */
|
||||
@font-face {
|
||||
font-family: "Product Sans";
|
||||
|
||||
@@ -8,7 +8,6 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||
const navigate = useNavigate();
|
||||
const { pathname } = useLocation();
|
||||
|
||||
|
||||
//Removing Data stored at localStorage after session expires
|
||||
const expireSession = () => {
|
||||
localStorage.removeItem("email");
|
||||
|
||||
@@ -6,6 +6,11 @@ class usersService {
|
||||
console.log("WRB Service Entry");
|
||||
}
|
||||
|
||||
CreateUser(reqData){
|
||||
localStorage.setItem("session_token", ``);
|
||||
return this.postAuxEnd("/createuser", reqData);
|
||||
}
|
||||
|
||||
getHomeDate(){
|
||||
var postData = {
|
||||
uuid: localStorage.getItem("uuid"),
|
||||
@@ -48,11 +53,6 @@ class usersService {
|
||||
return this.postAuxEnd("/apigate", null);
|
||||
}
|
||||
|
||||
CreateUser(reqData){
|
||||
localStorage.setItem("session_token", ``);
|
||||
return this.postAuxEnd("/createuser", reqData);
|
||||
}
|
||||
|
||||
getLoadProfile(){
|
||||
var postData = {
|
||||
uuid: localStorage.getItem("uid"),
|
||||
@@ -96,7 +96,7 @@ class usersService {
|
||||
return this.postAuxEnd("/getjobsdata", postData);
|
||||
}
|
||||
|
||||
getMyJobList(){
|
||||
getHeroJBanners(){
|
||||
var postData = {
|
||||
uuid: localStorage.getItem("uid"),
|
||||
member_id: localStorage.getItem("member_id"),
|
||||
@@ -104,7 +104,19 @@ class usersService {
|
||||
page:0,
|
||||
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(){
|
||||
@@ -153,6 +165,17 @@ class usersService {
|
||||
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
|
||||
getSendMoneyFee(amount){
|
||||
var postData = {
|
||||
@@ -228,11 +251,25 @@ class usersService {
|
||||
return this.postAuxEnd("/updateprofile", postData);
|
||||
}
|
||||
|
||||
//END POINT CALL FOR GETTING USER PROFILE
|
||||
loadProfile(post){
|
||||
var postData = {
|
||||
uid: localStorage.getItem("uid"),
|
||||
member_id: localStorage.getItem("member_id"),
|
||||
sessionid: localStorage.getItem("session_token"),
|
||||
};
|
||||
return this.postAuxEnd("/loadprofile", postData);
|
||||
}
|
||||
|
||||
//END POINT CALL FOR SENDING REFERRAL MESSAGE
|
||||
sendReferralMsg(postData){
|
||||
return this.postAuxEnd("/sendreferral", postData);
|
||||
}
|
||||
|
||||
StartResetPassword(reqData){
|
||||
return this.postAuxEnd("/startresetpasword", reqData)
|
||||
}
|
||||
|
||||
getCouponRedeem(){
|
||||
var postData = {
|
||||
uuid: localStorage.getItem("uid"),
|
||||
@@ -249,6 +286,37 @@ class usersService {
|
||||
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(password)
|
||||
|
||||
+18
-2
@@ -1,7 +1,23 @@
|
||||
import React from "react";
|
||||
import React, {useState, useEffect} from 'react'
|
||||
import Home from "../components/Home";
|
||||
|
||||
import usersService from "../services/UsersService";
|
||||
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 (
|
||||
<>
|
||||
<Home />
|
||||
|
||||
@@ -24,10 +24,10 @@ export default function MyJobsPage() {
|
||||
getMyJobList();
|
||||
}, []);
|
||||
|
||||
debugger;
|
||||
// debugger;
|
||||
return (
|
||||
<>
|
||||
<MyJobs />
|
||||
<MyJobs MyJobList={MyJobList} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import VerifyLink from "../components/AuthPages/VerifyLink";
|
||||
|
||||
export default function VerifyLinkPages() {
|
||||
return <VerifyLink />;
|
||||
}
|
||||
Reference in New Issue
Block a user