Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f70659901c | |||
| 451e4624b1 | |||
| 1557ba1040 | |||
| 7133ad8de3 | |||
| 9fd8944987 | |||
| 874276dcba | |||
| be1454f1b8 | |||
| 6a34ca6c18 | |||
| fc09771b8d | |||
| cab5ed0ece | |||
| 8d3dca96b4 | |||
| e71a25630d | |||
| cf79a15837 | |||
| 042e8c2c17 | |||
| 46d286e8f3 | |||
| c2bfcc81ea | |||
| 654ed3741c | |||
| 6cccd1c372 | |||
| 1e6be76449 | |||
| 476ca04f5f | |||
| ce41db474d | |||
| 7ace7e5b5d | |||
| 51e829f7b4 | |||
| 173b2adc66 | |||
| 31cb7a521d | |||
| ad4f68b252 | |||
| 10abf35d4f | |||
| ce767086fd | |||
| 0f44616767 |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" id="error"><path fill="#ff1d25" d="M29.75,25.73,18.68,3.59a3,3,0,0,0-4-1.33,3.05,3.05,0,0,0-1.33,1.33L2.25,25.73a3,3,0,0,0,2.68,4.34H27.07a3,3,0,0,0,3-3A2.88,2.88,0,0,0,29.75,25.73ZM16,25.38a.94.94,0,1,1,.94-.94A.94.94,0,0,1,16,25.38Zm.94-4.69a.94.94,0,1,1-1.88,0V11.31a.94.94,0,1,1,1.88,0Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 365 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" id="success"><path fill="#80af52" d="M256 26c127.03 0 230 102.97 230 230S383.03 486 256 486 26 383.03 26 256 128.97 26 256 26z"></path><path fill="#fff" d="M215.999 386a9.998 9.998 0 0 1-7.525-3.415l-70-80c-3.637-4.156-3.215-10.474.941-14.11s10.475-3.217 14.111.94l60.961 69.67 142.938-238.23c2.842-4.736 8.983-6.273 13.72-3.43 4.736 2.841 6.271 8.984 3.431 13.72l-150 250a9.998 9.998 0 0 1-8.577 4.855z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 483 B |
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
@@ -0,0 +1,37 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
import localImgLoad from '../../lib/localImgLoad'
|
||||||
|
|
||||||
|
const ForgetPwdResponse = ({title, message, type}) => {
|
||||||
|
const navigate = useNavigate()
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
||||||
|
<h1 className={`${type ? 'text-black' : 'text-red-500'}text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]`}>
|
||||||
|
{title}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<div className="title-area w-[100px] h-[100px] mx-auto flex flex-col justify-center items-center relative text-center mb-7">
|
||||||
|
<img className='w-full h-full' src={`${type ? localImgLoad('images/icons/success.svg') : localImgLoad('images/icons/error.svg')}`} alt='alert-banner' />
|
||||||
|
</div>
|
||||||
|
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
||||||
|
<p className={`${type ? 'text-sky-blue' : 'text-red-500'} font-semibold dark:text-white mb-3 leading-[27.3px] text-[18px]`}>
|
||||||
|
{message}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="signin-area mb-3.5">
|
||||||
|
<div className="flex justify-center items-center gap-2">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => navigate("/login")}
|
||||||
|
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
|
||||||
|
>
|
||||||
|
<span>Home</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ForgetPwdResponse
|
||||||
@@ -4,6 +4,8 @@ import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
|
|||||||
import usersService from "../../../services/UsersService";
|
import usersService from "../../../services/UsersService";
|
||||||
import InputCom from "../../Helpers/Inputs/InputCom";
|
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||||
import AuthLayout from "../AuthLayout";
|
import AuthLayout from "../AuthLayout";
|
||||||
|
import EmailValidator from "../../../lib/EmailValidator";
|
||||||
|
import ForgetPwdResponse from "../ForgetPwdResponse";
|
||||||
|
|
||||||
export default function ForgotPassword() {
|
export default function ForgotPassword() {
|
||||||
const [checked, setValue] = useState(false);
|
const [checked, setValue] = useState(false);
|
||||||
@@ -11,7 +13,7 @@ export default function ForgotPassword() {
|
|||||||
// email
|
// email
|
||||||
const [email, setMail] = useState("");
|
const [email, setMail] = useState("");
|
||||||
const [msgError, setMsgError] = useState("");
|
const [msgError, setMsgError] = useState("");
|
||||||
const [msgSuccess, setMsgSuccess] = useState(false);
|
const [msgSuccess, setMsgSuccess] = useState(null);
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const userApi = new usersService();
|
const userApi = new usersService();
|
||||||
@@ -27,12 +29,26 @@ export default function ForgotPassword() {
|
|||||||
const resetHandler = async () => {
|
const resetHandler = async () => {
|
||||||
if (email == "") {
|
if (email == "") {
|
||||||
setMsgError("An email is required");
|
setMsgError("An email is required");
|
||||||
} else if (!checked) {
|
return setTimeout(() => {
|
||||||
|
setMsgError(null);
|
||||||
|
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
|
||||||
|
}
|
||||||
|
if (!checked) {
|
||||||
setMsgError("Check if you are human");
|
setMsgError("Check if you are human");
|
||||||
|
return setTimeout(() => {
|
||||||
|
setMsgError(null);
|
||||||
|
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!EmailValidator(email)){ // CHECKS IF EMAIL IS VALID
|
||||||
|
setMsgError("Invalid Email");
|
||||||
|
return setTimeout(() => {
|
||||||
|
setMsgError(null);
|
||||||
|
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (email !== "" && checked) {
|
if (email !== "" && checked) {
|
||||||
const reqData = { email };
|
const reqData = { email, action:11013 };
|
||||||
setResetLoading(true);
|
setResetLoading(true);
|
||||||
try {
|
try {
|
||||||
const res = await userApi.StartResetPassword(reqData);
|
const res = await userApi.StartResetPassword(reqData);
|
||||||
@@ -41,8 +57,11 @@ export default function ForgotPassword() {
|
|||||||
setMail("");
|
setMail("");
|
||||||
setValue(false);
|
setValue(false);
|
||||||
setResetLoading(false);
|
setResetLoading(false);
|
||||||
|
}else{
|
||||||
|
setMsgSuccess(false);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
setMsgSuccess(false);
|
||||||
setResetLoading(false);
|
setResetLoading(false);
|
||||||
setMail("");
|
setMail("");
|
||||||
setMsgError("An error occurred");
|
setMsgError("An error occurred");
|
||||||
@@ -53,9 +72,6 @@ export default function ForgotPassword() {
|
|||||||
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
|
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
|
||||||
setMsgError(null);
|
|
||||||
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -73,106 +89,102 @@ export default function ForgotPassword() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5">
|
<div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5">
|
||||||
<div className="flex flex-col justify-center w-full h-full px-5">
|
<div className="flex flex-col justify-center w-full h-full px-5">
|
||||||
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
{msgSuccess == null ?
|
||||||
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
|
<>
|
||||||
Forget Password
|
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
||||||
</h1>
|
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
|
||||||
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
|
Forget Password
|
||||||
Enter your email to reset your password.
|
</h1>
|
||||||
</span>
|
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
|
||||||
</div>
|
Enter your email to reset your password.
|
||||||
<div className="input-area">
|
</span>
|
||||||
<div className="input-item mb-10">
|
|
||||||
<InputCom
|
|
||||||
fieldClass="px-6"
|
|
||||||
placeholder="Your Username/Email"
|
|
||||||
label="Email"
|
|
||||||
name="email"
|
|
||||||
type="email"
|
|
||||||
value={email}
|
|
||||||
inputHandler={handleEmail}
|
|
||||||
iconName="message"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
{/* hCaptha clone for the time being */}
|
<div className="input-area">
|
||||||
<div className="mb-10">
|
<div className="input-item mb-10">
|
||||||
<div className="w-[303px] h-[78px] mx-auto overflow-hidden">
|
<InputCom
|
||||||
<div className="w-[300px] h-[74px] bg-white bottom-[1px] rounded border-gray-100 overflow-hidden cursor-pointer">
|
fieldClass="px-6"
|
||||||
{/* Checkbox */}
|
placeholder="Your Username/Email"
|
||||||
<div className="h-full relative inline-block">
|
label="Email"
|
||||||
<div className="relative table top-0 h-full">
|
name="email"
|
||||||
<div className="table-cell align-middle">
|
type="email"
|
||||||
<div className="relative w-[30px] h-[30px] mx-[15px]">
|
value={email}
|
||||||
<input
|
inputHandler={handleEmail}
|
||||||
type="checkbox"
|
iconName="message"
|
||||||
name="human-checkbox"
|
/>
|
||||||
id="human-checkbox"
|
</div>
|
||||||
className="w-[28px] h-[28px] border-[1px] rounded border-gray-400 checked:bg-white"
|
{/* hCaptha clone for the time being */}
|
||||||
checked={checked}
|
<div className="mb-10">
|
||||||
onChange={humanChecker}
|
<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"
|
||||||
|
checked={checked}
|
||||||
|
onChange={humanChecker}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="h-full relative inline-block w-[170px]">
|
||||||
<div className="h-full relative inline-block w-[170px]">
|
<label className="relative table top-0 h-full">
|
||||||
<label className="relative table top-0 h-full">
|
<label className="table-cell align-middle">
|
||||||
<label className="table-cell align-middle">
|
<label
|
||||||
<label
|
className="text-800 text-sm"
|
||||||
className="text-800 text-sm"
|
htmlFor="human-checkbox"
|
||||||
htmlFor="human-checkbox"
|
>
|
||||||
>
|
I am human
|
||||||
I am human
|
</label>
|
||||||
</label>
|
</label>
|
||||||
</label>
|
</label>
|
||||||
</label>
|
</div>
|
||||||
|
<div className="h-full relative inline-block w-16"></div>
|
||||||
</div>
|
</div>
|
||||||
<div className="h-full relative inline-block w-16"></div>
|
</div>
|
||||||
|
</div>
|
||||||
|
{msgError && (
|
||||||
|
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">
|
||||||
|
{msgError}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<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-[15px] font-semibold text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
|
||||||
|
>
|
||||||
|
{resetLoading ? (
|
||||||
|
<div className="signup btn-loader"></div>
|
||||||
|
) : (
|
||||||
|
<span>Send Code</span>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => navigate("/login")}
|
||||||
|
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-[#009ef7] hover:text-white flex justify-center bg-[#f1faff] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.8125rem] `}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{msgError && (
|
</>
|
||||||
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">
|
:
|
||||||
{msgError}
|
<ForgetPwdResponse
|
||||||
</div>
|
title={'Forget Password'}
|
||||||
)}
|
message={msgSuccess? `Check your email for the link to continue password reset. Note the reset link will expire short time` : 'We are unable to continue with your request. Please try another username or contact us for help'}
|
||||||
{msgSuccess && (
|
type={msgSuccess}
|
||||||
<div className="relative p-4 text-[#44228c] bg-[#e3d7fb] border-[#d5c4f9] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">
|
/>
|
||||||
If we find your email, you will receive a link to reset your
|
}
|
||||||
password. Please use or{" "}
|
|
||||||
<Link
|
|
||||||
to="/contact"
|
|
||||||
className="text-[#4687ba] hover:text-[#009ef7]"
|
|
||||||
>
|
|
||||||
contact form
|
|
||||||
</Link>{" "}
|
|
||||||
if you did not get our message after few minutes.
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="signin-area mb-3.5">
|
|
||||||
<div className="flex justify-center items-center gap-2">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={resetHandler}
|
|
||||||
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
|
|
||||||
>
|
|
||||||
{resetLoading ? (
|
|
||||||
<div className="signup btn-loader"></div>
|
|
||||||
) : (
|
|
||||||
<span>Send Code</span>
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => navigate("/login")}
|
|
||||||
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-[#009ef7] hover:text-white flex justify-center bg-[#f1faff] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.8125rem] `}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Link, useLocation, useNavigate } from "react-router-dom";
|
import { Link, useLocation, useNavigate } from "react-router-dom";
|
||||||
import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
|
import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
|
||||||
import usersService from "../../../services/UsersService";
|
import usersService from "../../../services/UsersService";
|
||||||
import InputCom from "../../Helpers/Inputs/InputCom";
|
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||||
import AuthLayout from "../AuthLayout";
|
import AuthLayout from "../AuthLayout";
|
||||||
|
import ForgetPwdResponse from "../ForgetPwdResponse";
|
||||||
|
import PasswordValidator from "../../../lib/PasswordValidator";
|
||||||
|
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||||
|
|
||||||
const VerifyPassword = () => {
|
const VerifyPassword = () => {
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
const [confirmPassword, setConfirmPassword] = useState("");
|
const [confirmPassword, setConfirmPassword] = useState("");
|
||||||
|
const [requestStatus, setRequestStatus] = useState({loading: true, status:false, data: []})
|
||||||
const [msgError, setMsgError] = useState("");
|
const [msgError, setMsgError] = useState("");
|
||||||
const [linkLoader, setLinkLoader] = useState(false);
|
const [linkLoader, setLinkLoader] = useState(false);
|
||||||
const [linkSuccess, setLinkSuccess] = useState(true);
|
const [linkSuccess, setLinkSuccess] = useState(null);
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
@@ -23,11 +27,6 @@ const VerifyPassword = () => {
|
|||||||
setShowPassword(!showPassword);
|
setShowPassword(!showPassword);
|
||||||
};
|
};
|
||||||
|
|
||||||
// little checker for the validity of the token
|
|
||||||
if (token?.length != 64) {
|
|
||||||
setLinkSuccess(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Password
|
// Password
|
||||||
const handlePassword = (e) => {
|
const handlePassword = (e) => {
|
||||||
let { name, value } = e?.target;
|
let { name, value } = e?.target;
|
||||||
@@ -36,46 +35,60 @@ const VerifyPassword = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const completeReset = async () => {
|
const completeReset = async () => {
|
||||||
|
if(!password || !confirmPassword){ // CHECKS IF PASSWORD IS EMPTY
|
||||||
|
setMsgError("Please fill in fields");
|
||||||
|
return setTimeout(() => {
|
||||||
|
setMsgError(null);
|
||||||
|
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
|
||||||
|
}
|
||||||
|
if(password != confirmPassword){ // CHECKS IF PASSWORD EQUALS CONFIRM PASSWORD
|
||||||
|
setMsgError("Passwords does not match");
|
||||||
|
return setTimeout(() => {
|
||||||
|
setMsgError(null);
|
||||||
|
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
|
||||||
|
}
|
||||||
|
if(password.length < 6){ // CHECKS IF PASSWORD LENGTH IS UPTO 6 CHARACTERS
|
||||||
|
setMsgError("Password must be upto six characters");
|
||||||
|
return setTimeout(() => {
|
||||||
|
setMsgError(null);
|
||||||
|
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
|
||||||
|
}
|
||||||
|
if(!PasswordValidator(password)){ // CHECKS IF PASSWORD IS VALID
|
||||||
|
setMsgError("Password must contain alphanumeric, uppercase and special character: eg: Password1@");
|
||||||
|
return setTimeout(() => {
|
||||||
|
setMsgError(null);
|
||||||
|
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
if (password !== "" && confirmPassword !== "") {
|
|
||||||
if (password === confirmPassword) {
|
|
||||||
setLinkLoader(true);
|
setLinkLoader(true);
|
||||||
var reqData = {
|
var reqData = {
|
||||||
sessionid: "DUMMY-CANNOT_BE_EMPTY",
|
sessionid: "DUMMY-CANNOT_BE_EMPTY",
|
||||||
reset_link: token,
|
reset_link: token,
|
||||||
newpass: password,
|
newpass: password,
|
||||||
|
m_uid: requestStatus.data?.m_uid || '',
|
||||||
|
reset_uid: requestStatus.data?.reset_uid || '',
|
||||||
step: 300,
|
step: 300,
|
||||||
action: 730,
|
action: 730,
|
||||||
};
|
};
|
||||||
|
|
||||||
const res = await userApi?.CompleteResetPassword(reqData);
|
const res = await userApi?.CompleteResetPassword(reqData);
|
||||||
|
|
||||||
if (res.status === 200) {
|
if (res.status == 200) {
|
||||||
const { data } = res;
|
const { data } = res;
|
||||||
|
if (data?.internal_return >= 0) {
|
||||||
if (data?.status > 0 && data?.email) {
|
// setTimeout(() => {
|
||||||
setTimeout(() => {
|
// navigate("/login", { replace: true });
|
||||||
navigate("/login", { replace: true });
|
// setLinkLoader(false);
|
||||||
setLinkLoader(false);
|
// }, 2000);
|
||||||
}, 2000);
|
setLinkSuccess(true);
|
||||||
} else if (data && data?.status == "Invalid Request") {
|
|
||||||
setLinkLoader(false);
|
|
||||||
setLinkSuccess(false);
|
|
||||||
} else {
|
} else {
|
||||||
setLinkLoader(false);
|
setLinkLoader(false);
|
||||||
setMsgError("An error occurred");
|
setMsgError("An error occurred");
|
||||||
|
setLinkSuccess(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setLinkLoader(false);
|
setLinkLoader(false);
|
||||||
setLinkSuccess(false);
|
setLinkSuccess(false);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
setLinkLoader(false);
|
|
||||||
setMsgError("Passwords does not match");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setMsgError("Please fill in fields");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setLinkLoader(false);
|
setLinkLoader(false);
|
||||||
setLinkSuccess(false);
|
setLinkSuccess(false);
|
||||||
@@ -87,6 +100,31 @@ const VerifyPassword = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const verifyResetPwd = () => { // FUNCTION TO VERIFY RESET PASSWORD LINK
|
||||||
|
setRequestStatus({loading: true, status:false, data: []})
|
||||||
|
var reqData = {
|
||||||
|
sessionid: "DUMMY-CANNOT_BE_EMPTY",
|
||||||
|
reset_link: token,
|
||||||
|
step: 200,
|
||||||
|
action: 730,
|
||||||
|
};
|
||||||
|
userApi.CompleteResetPassword(reqData).then(res => {
|
||||||
|
if(res.status != 200 || res.data.internal_return < 0){
|
||||||
|
return setRequestStatus({loading: false, status:false, data: []})
|
||||||
|
}
|
||||||
|
setRequestStatus({loading: false, status:true, data: res.data})
|
||||||
|
}).catch(error => {
|
||||||
|
setRequestStatus({loading: false, status:false, data: []})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
// little checker for the validity of the token
|
||||||
|
if (token==null || token?.length != 64) {
|
||||||
|
return setRequestStatus({loading: false, status:false, data: []});
|
||||||
|
}
|
||||||
|
verifyResetPwd()
|
||||||
|
},[])
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AuthLayout slogan="Welcome to WrenchBoard">
|
<AuthLayout slogan="Welcome to WrenchBoard">
|
||||||
@@ -101,39 +139,59 @@ const VerifyPassword = () => {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</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="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">
|
||||||
|
{requestStatus.loading ?
|
||||||
|
<LoadingSpinner color='sky-blue' size='16' height='h-300px' />
|
||||||
|
:
|
||||||
|
!requestStatus.loading && requestStatus.status ?
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
{linkSuccess == null ?
|
||||||
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
|
<>
|
||||||
{linkSuccess ? "Password Reset" : "Invalid verification link"}
|
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
||||||
</h1>
|
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
|
||||||
{linkSuccess && (
|
Password Reset
|
||||||
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
|
</h1>
|
||||||
Enter a new password to reset
|
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
|
||||||
</span>
|
Enter a new password to reset
|
||||||
)}
|
</span>
|
||||||
{linkSuccess && (
|
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
|
||||||
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
|
We'll send an email to confirm reset
|
||||||
We'll send an email to confirm reset
|
</span>
|
||||||
</span>
|
</div>
|
||||||
)}
|
<div>
|
||||||
</div>
|
<p className="text-red-500 font-semibold mb-3 leading-[27.3px] text-[13px]">
|
||||||
{/* If the verification was a success */}
|
Must include a special, numeric, uppercase and lowercase character
|
||||||
{linkSuccess ? (
|
</p>
|
||||||
<SuccessfulComponent
|
</div>
|
||||||
password={password}
|
<SuccessfulComponent
|
||||||
confirmPassword={confirmPassword}
|
password={password}
|
||||||
handlePassword={handlePassword}
|
confirmPassword={confirmPassword}
|
||||||
onSubmit={completeReset}
|
handlePassword={handlePassword}
|
||||||
msgErr={msgError}
|
onSubmit={completeReset}
|
||||||
loader={linkLoader}
|
msgErr={msgError}
|
||||||
showPassword={showPassword}
|
loader={linkLoader}
|
||||||
onClick={togglePasswordVisibility}
|
showPassword={showPassword}
|
||||||
navigateHandler={() => navigate("/login")}
|
onClick={togglePasswordVisibility}
|
||||||
/>
|
navigateHandler={() => navigate("/login")}
|
||||||
) : (
|
/>
|
||||||
<ErrorComponent onClick={() => navigate("/login")} />
|
</>
|
||||||
)}
|
:
|
||||||
|
<ForgetPwdResponse
|
||||||
|
title={linkSuccess? 'Password Reset Complete' : 'Password Reset Error'}
|
||||||
|
message={linkSuccess? 'Password Reset Complete. You can login now with your new credentials' : 'Password Reset Error. Please get in touch with support for further support'
|
||||||
|
}
|
||||||
|
type={linkSuccess}
|
||||||
|
/>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
:
|
||||||
|
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
||||||
|
<ForgetPwdResponse
|
||||||
|
title={'Forget Password'}
|
||||||
|
message={'We are unable to continue to reset process. This error is usually due to expired links. Please start all over or contact us'}
|
||||||
|
type={requestStatus.status}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</AuthLayout>
|
</AuthLayout>
|
||||||
@@ -159,7 +217,7 @@ const SuccessfulComponent = ({
|
|||||||
<div className="mb-5">
|
<div className="mb-5">
|
||||||
<InputCom
|
<InputCom
|
||||||
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
|
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
|
||||||
value={password?.replace(/./g, "●")}
|
value={password}
|
||||||
inputHandler={handlePassword}
|
inputHandler={handlePassword}
|
||||||
placeholder="● ● ● ● ● ●"
|
placeholder="● ● ● ● ● ●"
|
||||||
label="Password"
|
label="Password"
|
||||||
@@ -172,7 +230,7 @@ const SuccessfulComponent = ({
|
|||||||
<div className="mb-5">
|
<div className="mb-5">
|
||||||
<InputCom
|
<InputCom
|
||||||
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
|
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
|
||||||
value={confirmPassword?.replace(/./g, "●")}
|
value={confirmPassword}
|
||||||
inputHandler={handlePassword}
|
inputHandler={handlePassword}
|
||||||
placeholder="● ● ● ● ● ●"
|
placeholder="● ● ● ● ● ●"
|
||||||
label="Confirm Password"
|
label="Confirm Password"
|
||||||
@@ -209,25 +267,3 @@ const SuccessfulComponent = ({
|
|||||||
</div>
|
</div>
|
||||||
</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 used this link or the link
|
|
||||||
has broken/expired. Start with the reset process again. If it doesn't
|
|
||||||
work, try to create the account from the start.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="signin-area flex justify-center mb-3.5">
|
|
||||||
<button
|
|
||||||
onClick={onClick}
|
|
||||||
type="button"
|
|
||||||
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-[#009ef7] hover:text-white flex justify-center bg-[#f1faff] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
|
|
||||||
>
|
|
||||||
<span>Return Home</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import Layout from "../Partials/Layout";
|
|
||||||
import CommonHead from "../UserHeader/CommonHead";
|
|
||||||
import usersService from "../../services/UsersService";
|
import usersService from "../../services/UsersService";
|
||||||
|
import Layout from "../Partials/Layout";
|
||||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
|
import CommonHead from "../UserHeader/CommonHead";
|
||||||
|
|
||||||
export default function BlogItem(props) {
|
export default function BlogItem(props) {
|
||||||
|
|
||||||
@@ -16,6 +16,7 @@ export default function BlogItem(props) {
|
|||||||
const filterHandler = (value) => {
|
const filterHandler = (value) => {
|
||||||
setValue(value);
|
setValue(value);
|
||||||
};
|
};
|
||||||
|
// eslint-disable-next-line no-restricted-globals
|
||||||
const queryParams = new URLSearchParams(location?.search);
|
const queryParams = new URLSearchParams(location?.search);
|
||||||
const blog_id = queryParams.get("blog_id");
|
const blog_id = queryParams.get("blog_id");
|
||||||
|
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ function AddFundDollars(props) {
|
|||||||
|
|
||||||
{/* previous tab */}
|
{/* previous tab */}
|
||||||
{tab === "previous" && (
|
{tab === "previous" && (
|
||||||
<div className="p-4 previous-details w-full min-h-[16rem] flex flex-col">
|
<div className="p-4 previous-details w-full min-h-[16.5rem] flex flex-col">
|
||||||
{payListCards.loading ? (
|
{payListCards.loading ? (
|
||||||
<LoadingSpinner size="10" color="sky-blue" />
|
<LoadingSpinner size="10" color="sky-blue" />
|
||||||
) : payListCards?.data?.length ? (
|
) : payListCards?.data?.length ? (
|
||||||
@@ -313,7 +313,7 @@ function AddFundDollars(props) {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{tab === "new" && (
|
{tab === "new" && (
|
||||||
<div className="new-details w-full max-h-[23rem]">
|
<div className="new-details w-full max-h-[22rem]">
|
||||||
<div className="w-full flex flex-col justify-between">
|
<div className="w-full flex flex-col justify-between">
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
@@ -527,9 +527,9 @@ function AddFundDollars(props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="md:px-8 add-fund-btn flex justify-end items-center gap-3">
|
<div className="add-fund-btn flex justify-end items-center gap-2 mt-4">
|
||||||
<button
|
<button
|
||||||
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center border-gradient text-base rounded-full"
|
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center bg-[#f5a430] text-black items-center text-base rounded-full"
|
||||||
onClick={handleClose}
|
onClick={handleClose}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
@@ -558,9 +558,9 @@ function AddFundDollars(props) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{tab == "previous" && (
|
{tab == "previous" && (
|
||||||
<div className="md:py-8 px-[38px] add-fund-btn flex justify-end items-center gap-4 py-4">
|
<div className="md:py-8 add-fund-btn flex justify-end items-center gap-2 py-4">
|
||||||
<button
|
<button
|
||||||
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center border-gradient text-base rounded-full"
|
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center bg-[#f5a430] text-black items-center text-base rounded-full"
|
||||||
onClick={props.onClose}
|
onClick={props.onClose}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
|
|||||||
@@ -138,12 +138,12 @@ function AddFundPop({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{countryWallet == "NG" && <div className="h-[18rem]"></div>}
|
{countryWallet == "NG" && <div className="h-[19rem]"></div>}
|
||||||
|
|
||||||
{countryWallet == "NG" && (
|
{countryWallet == "NG" && (
|
||||||
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4 gap-4">
|
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4 gap-4">
|
||||||
<button
|
<button
|
||||||
className="px-4 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center bg-[#f5a430] text-black text-base rounded-full"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
|
|||||||
@@ -63,7 +63,8 @@ function CompleteConfirmCredit({ onClose, confirmCredit }) {
|
|||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{data?.internal_return >= 0 ? (
|
{data?.internal_return >= 0 &&
|
||||||
|
data?.result !== "Charge failed" ? (
|
||||||
<>
|
<>
|
||||||
<div className="flex items-center gap-8">
|
<div className="flex items-center gap-8">
|
||||||
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ function ConfirmAddFund({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
public_key: process.env.REACT_APP_FLUTTERWAVE_APIKEY,
|
public_key: __confirmData?.flutterwave_key,
|
||||||
tx_ref: __confirmData?.credit_reference,
|
tx_ref: __confirmData?.credit_reference,
|
||||||
currency: "NGN",
|
currency: "NGN",
|
||||||
amount: Number(__confirmData.amount),
|
amount: Number(__confirmData.amount),
|
||||||
@@ -379,7 +379,7 @@ function ConfirmAddFund({
|
|||||||
<hr />
|
<hr />
|
||||||
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4 gap-4">
|
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4 gap-4">
|
||||||
<button
|
<button
|
||||||
className="px-4 h-11 flex justify-center items-center border-gradient text-base rounded-full"
|
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center bg-[#f5a430] text-black items-center text-base rounded-full"
|
||||||
onClick={getBack}
|
onClick={getBack}
|
||||||
>
|
>
|
||||||
Back
|
Back
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { useDispatch } from "react-redux";
|
||||||
import usersService from "../../../services/UsersService";
|
import usersService from "../../../services/UsersService";
|
||||||
|
import { tableReload } from "../../../store/TableReloads";
|
||||||
import InputCom from "../../Helpers/Inputs/InputCom";
|
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||||
import ModalCom from "../../Helpers/ModalCom";
|
import ModalCom from "../../Helpers/ModalCom";
|
||||||
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||||
import { useDispatch } from "react-redux";
|
|
||||||
import { tableReload } from "../../../store/TableReloads";
|
|
||||||
|
|
||||||
function ConfirmNairaWithdraw({
|
function ConfirmNairaWithdraw({
|
||||||
payment,
|
payment,
|
||||||
@@ -393,9 +393,9 @@ function ConfirmNairaWithdraw({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={action}
|
onClick={action}
|
||||||
className="border-gradient text-base tracking-wide px-4 py-2 rounded-full"
|
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center bg-[#f5a430] text-black text-base rounded-full"
|
||||||
>
|
>
|
||||||
<span className="text-gradient">Cancel</span>
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -25,8 +25,10 @@ const CreditPopup = ({ details, onClose, situation, walletItem }) => {
|
|||||||
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
|
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
|
||||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
||||||
{confirmCredit?.show?.acceptConfirm?.state &&
|
{confirmCredit?.show?.acceptConfirm?.state &&
|
||||||
(confirmCredit?.data?.internal_return < 0 ||
|
(confirmCredit?.data?.internal_return < 0
|
||||||
confirmCredit?.data?.status !== "successful") ? (
|
// ||
|
||||||
|
// confirmCredit?.data?.status !== "successful"
|
||||||
|
) ? (
|
||||||
"Credit Unsuccessful"
|
"Credit Unsuccessful"
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ function NairaWithdraw({
|
|||||||
setErrorMsgs({ amount: "amount required" });
|
setErrorMsgs({ amount: "amount required" });
|
||||||
setTimeout(() => setErrorMsgs({ amount: "" }), 3000);
|
setTimeout(() => setErrorMsgs({ amount: "" }), 3000);
|
||||||
return;
|
return;
|
||||||
}else if (Number(values.amount * 100) > Number(wallet?.transfer_limit)) {
|
} else if (Number(values.amount * 100) > Number(wallet?.transfer_limit)) {
|
||||||
setErrorMsgs({ amount: "Withdraw limit has been exceeded" });
|
setErrorMsgs({ amount: "Withdraw limit has been exceeded" });
|
||||||
setTimeout(() => setErrorMsgs({ amount: "" }), 3000);
|
setTimeout(() => setErrorMsgs({ amount: "" }), 3000);
|
||||||
return;
|
return;
|
||||||
@@ -517,7 +517,7 @@ function NairaWithdraw({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="h-[7.8rem]"></div>
|
<div className="h-[6.1rem]"></div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -796,9 +796,9 @@ function NairaWithdraw({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={action}
|
onClick={action}
|
||||||
className="border-gradient text-base tracking-wide px-4 py-2 rounded-full"
|
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center bg-[#f5a430] text-black items-center text-base rounded-full"
|
||||||
>
|
>
|
||||||
<span className="text-gradient">Cancel</span>
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import bank1 from "../../assets/images/bank-1.png";
|
|||||||
import bank2 from "../../assets/images/bank-2.png";
|
import bank2 from "../../assets/images/bank-2.png";
|
||||||
import bank3 from "../../assets/images/bank-3.png";
|
import bank3 from "../../assets/images/bank-3.png";
|
||||||
import bank4 from "../../assets/images/bank-4.png";
|
import bank4 from "../../assets/images/bank-4.png";
|
||||||
import profileImg from "../../assets/images/profile-pic.jpg";
|
import profileImg from "../../assets/images/profile.jpg";
|
||||||
import useToggle from "../../hooks/useToggle";
|
import useToggle from "../../hooks/useToggle";
|
||||||
import usersService from "../../services/UsersService";
|
import usersService from "../../services/UsersService";
|
||||||
import DarkModeContext from "../Contexts/DarkModeContext";
|
import DarkModeContext from "../Contexts/DarkModeContext";
|
||||||
@@ -15,10 +15,10 @@ import WalletHeader from "../MyWallet/WalletHeader";
|
|||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import Flag from "../../assets/images/united-states.svg";
|
import Flag from "../../assets/images/united-states.svg";
|
||||||
import siteLogo from "../../assets/images/wrenchboard-logo-text.png";
|
import siteLogo from "../../assets/images/wrenchboard-logo-text.png";
|
||||||
import formattedDate from "../../lib/fomattedDate";
|
|
||||||
import { updateNotifications } from "../../store/notifications";
|
|
||||||
import TimeDifference from "../Helpers/TimeDifference";
|
import TimeDifference from "../Helpers/TimeDifference";
|
||||||
|
|
||||||
|
const DEFAULT_PROFILE_IMAGE = require("../../assets/images/profile.jpg");
|
||||||
|
|
||||||
export default function Header({ logoutModalHandler, sidebarHandler }) {
|
export default function Header({ logoutModalHandler, sidebarHandler }) {
|
||||||
const [balanceDropdown, setbalanceValue] = useToggle(false);
|
const [balanceDropdown, setbalanceValue] = useToggle(false);
|
||||||
const [notificationDropdown, setNotificationValue] = useToggle(false);
|
const [notificationDropdown, setNotificationValue] = useToggle(false);
|
||||||
@@ -30,7 +30,7 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
|||||||
const [myWalletList, setMyWalletList] = useState([]);
|
const [myWalletList, setMyWalletList] = useState([]);
|
||||||
const api = useMemo(() => new usersService(), []);
|
const api = useMemo(() => new usersService(), []);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const { notifications } = useSelector((state) => state?.notifications); // NOTIFICATION STORE
|
const { notifications } = useSelector((state) => state?.notifications); // NOTIFICATION STORE
|
||||||
|
|
||||||
@@ -100,10 +100,10 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// User Profile
|
// User Profile
|
||||||
let { firstname, lastname, email, profile_pic } = userDetails;
|
let { firstname, lastname, email, profile_pic_url } = userDetails;
|
||||||
let userEmail = email?.split("@")[0];
|
let userEmail = email?.split("@")[0];
|
||||||
|
const userProfileImage = profile_pic_url || DEFAULT_PROFILE_IMAGE;
|
||||||
|
|
||||||
// console.log("Notify: ", notifications?.data?.raw);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -255,9 +255,7 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
|||||||
>
|
>
|
||||||
<Icons name="notification" />
|
<Icons name="notification" />
|
||||||
<span className="absolute right-2 top-2 z-10 text-xs lg:w-5 lg:h-5 w-4 h-4 flex justify-center items-center rounded-full primary-gradient text-white cursor-default">
|
<span className="absolute right-2 top-2 z-10 text-xs lg:w-5 lg:h-5 w-4 h-4 flex justify-center items-center rounded-full primary-gradient text-white cursor-default">
|
||||||
{notifications?.loading
|
{notifications?.loading ? "●" : notifications?.data?.length}
|
||||||
? "●"
|
|
||||||
: notifications?.data?.length}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -273,46 +271,45 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
|||||||
|
|
||||||
<div className="content px-7 pb-7">
|
<div className="content px-7 pb-7">
|
||||||
<ul>
|
<ul>
|
||||||
{notifications?.data?.length && notifications?.data?.map((item, idx) =>
|
{notifications?.data?.length &&
|
||||||
{
|
notifications?.data?.map((item, idx) => {
|
||||||
if(idx < 5){
|
if (idx < 5) {
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
className={`content-item ${
|
className={`content-item ${
|
||||||
idx == 4
|
idx == 4
|
||||||
? "py-5 "
|
? "py-5 "
|
||||||
: "py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple"
|
: "py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple"
|
||||||
}`}
|
}`}
|
||||||
key={idx}
|
key={idx}
|
||||||
>
|
>
|
||||||
<div className="notifications flex space-x-4 items-center">
|
<div className="notifications flex space-x-4 items-center">
|
||||||
<div className="icon max-w-[52px] max-h-[52px] w-full h-full rounded-full object-cover">
|
<div className="icon max-w-[52px] max-h-[52px] w-full h-full rounded-full object-cover">
|
||||||
<img
|
<img
|
||||||
src={require(`../../assets/images/notifications/${item?.icon}`)}
|
src={require(`../../assets/images/notifications/${item?.icon}`)}
|
||||||
alt="icon"
|
alt="icon"
|
||||||
className="w-full h-full"
|
className="w-full h-full"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="name">
|
<div className="name">
|
||||||
<p className="text-base text-dark-gray dark:text-white font-medium mb-2">
|
<p className="text-base text-dark-gray dark:text-white font-medium mb-2">
|
||||||
{item?.title}
|
{item?.title}
|
||||||
{/* <span className="ml-1 font-bold">
|
{/* <span className="ml-1 font-bold">
|
||||||
successfully done
|
successfully done
|
||||||
</span> */}
|
</span> */}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm text-thin-light-gray font-medium">
|
<p className="text-sm text-thin-light-gray font-medium">
|
||||||
<TimeDifference
|
<TimeDifference
|
||||||
time={item?.date}
|
time={item?.date}
|
||||||
key={item?.uid}
|
key={item?.uid}
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
})
|
})}
|
||||||
}
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div className="add-money-btn flex justify-center items-center">
|
<div className="add-money-btn flex justify-center items-center">
|
||||||
@@ -351,9 +348,9 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
|||||||
{/* profile-image */}
|
{/* profile-image */}
|
||||||
<div className="lg:w-[62px] lg:h-[62px] w-[50px] h-[50px] rounded-full overflow-hidden">
|
<div className="lg:w-[62px] lg:h-[62px] w-[50px] h-[50px] rounded-full overflow-hidden">
|
||||||
<img
|
<img
|
||||||
src={profile_pic != "" ? profile_pic : profileImg}
|
src={userProfileImage}
|
||||||
alt="profile"
|
alt="profile"
|
||||||
className="w-full h-full"
|
className="w-full h-full object-cover"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="lg:block hidden">
|
<div className="lg:block hidden">
|
||||||
@@ -375,7 +372,7 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
|||||||
<img
|
<img
|
||||||
src={profileImg}
|
src={profileImg}
|
||||||
alt="profile"
|
alt="profile"
|
||||||
className="w-full h-full"
|
className="w-full h-full object-cover object-center"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export default function Layout({ children }) {
|
|||||||
drawer
|
drawer
|
||||||
? "2xl:w-[335px] w-[280px] 2xl:pl-20 pl-10 pr-6 "
|
? "2xl:w-[335px] w-[280px] 2xl:pl-20 pl-10 pr-6 "
|
||||||
: "w-[70px]"
|
: "w-[70px]"
|
||||||
} bg-white dark:bg-dark-white h-full overflow-y-scroll overflow-style-none fixed left-0 top-0 pt-8`}
|
} bg-white dark:bg-dark-white h-full overflow-y-scroll overflow-style-none fixed left-0 top-0 pt-[30px]`}
|
||||||
>
|
>
|
||||||
<Sidebar
|
<Sidebar
|
||||||
logoutModalHandler={logoutModalHandler}
|
logoutModalHandler={logoutModalHandler}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export default function Sidebar({
|
|||||||
{/* logo-area */}
|
{/* logo-area */}
|
||||||
<div
|
<div
|
||||||
className={`w-full flex items-center transition-all duration-300 ease-in-out ${
|
className={`w-full flex items-center transition-all duration-300 ease-in-out ${
|
||||||
sidebar ? "justify-between mb-14" : "justify-center"
|
sidebar ? "justify-start gap-3 mb-14" : "justify-center"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className={`sidebar-logo ${sidebar ? "enter" : ""}`}>
|
<div className={`sidebar-logo ${sidebar ? "enter" : ""}`}>
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ export default function PersonalInfoTab({
|
|||||||
state: userDetails?.state,
|
state: userDetails?.state,
|
||||||
city: userDetails?.city,
|
city: userDetails?.city,
|
||||||
email: userDetails?.email,
|
email: userDetails?.email,
|
||||||
|
profile: userDetails?.profile_pic,
|
||||||
};
|
};
|
||||||
|
|
||||||
let [profile, setProfile] = useState({
|
let [profile, setProfile] = useState({
|
||||||
@@ -86,6 +87,9 @@ export default function PersonalInfoTab({
|
|||||||
const handleUpdateUser = (values, helpers) => {
|
const handleUpdateUser = (values, helpers) => {
|
||||||
setRequestState({ message: "", loading: true, status: false });
|
setRequestState({ message: "", loading: true, status: false });
|
||||||
|
|
||||||
|
// there is no profile accommodation on the payload
|
||||||
|
delete values?.profile;
|
||||||
|
|
||||||
apiCall
|
apiCall
|
||||||
.updateProfile(values)
|
.updateProfile(values)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
@@ -336,8 +340,8 @@ export default function PersonalInfoTab({
|
|||||||
<div className="w-full relative">
|
<div className="w-full relative">
|
||||||
<img
|
<img
|
||||||
src={profileImg}
|
src={profileImg}
|
||||||
alt=""
|
alt="profile"
|
||||||
className="sm:w-[198px] sm:h-[198px] w-[120px] h-[120px] rounded-full overflow-hidden object-cover"
|
className="sm:w-[198px] sm:h-[198px] w-[120px] h-[120px] rounded-full overflow-hidden object-contain object-center"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
ref={profileImgInput}
|
ref={profileImgInput}
|
||||||
@@ -384,7 +388,8 @@ export default function PersonalInfoTab({
|
|||||||
)}
|
)}
|
||||||
<div className="w-full h-[120px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
|
<div className="w-full h-[120px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
|
||||||
<div className="flex items-center space-x-4 mr-9">
|
<div className="flex items-center space-x-4 mr-9">
|
||||||
<Link
|
|
||||||
|
{/* <Link
|
||||||
to="/"
|
to="/"
|
||||||
className="text-18 text-light-red tracking-wide "
|
className="text-18 text-light-red tracking-wide "
|
||||||
>
|
>
|
||||||
@@ -392,7 +397,7 @@ export default function PersonalInfoTab({
|
|||||||
{" "}
|
{" "}
|
||||||
Cancel
|
Cancel
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link> */}
|
||||||
|
|
||||||
{requestStatus.loading ? (
|
{requestStatus.loading ? (
|
||||||
<LoadingSpinner size="8" color="sky-blue" />
|
<LoadingSpinner size="8" color="sky-blue" />
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ import React, {
|
|||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
import cover from "../../assets/images/profile-info-cover.png";
|
import cover from "../../assets/images/profile-info-cover.png";
|
||||||
import profile from "../../assets/images/profile-info-profile.png";
|
import profile from "../../assets/images/profile.jpg";
|
||||||
import usersService from "../../services/UsersService";
|
import usersService from "../../services/UsersService";
|
||||||
import Icons from "../Helpers/Icons";
|
import Icons from "../Helpers/Icons";
|
||||||
import Layout from "../Partials/Layout";
|
import Layout from "../Partials/Layout";
|
||||||
@@ -23,15 +24,19 @@ import {
|
|||||||
import RecipientAccountTab from "./Tabs/RecipientAccountTab";
|
import RecipientAccountTab from "./Tabs/RecipientAccountTab";
|
||||||
|
|
||||||
export default function Settings({ faq }) {
|
export default function Settings({ faq }) {
|
||||||
const [profileImg, setProfileImg] = useState(profile);
|
const { userDetails } = useSelector((state) => state?.userDetails);
|
||||||
|
const [profileImg, setProfileImg] = useState(
|
||||||
|
userDetails?.profile_pic_url ? userDetails.profile_pic_url : profile
|
||||||
|
);
|
||||||
const [coverImg, setCoverImg] = useState(cover);
|
const [coverImg, setCoverImg] = useState(cover);
|
||||||
const [reloadCardList, setReloadCardList] = useState(false) // STATE TO DETERMINE WHEN CARD LIST RELOADS. EG: WHEN USER DELETES A CARD
|
const [reloadCardList, setReloadCardList] = useState(false); // STATE TO DETERMINE WHEN CARD LIST RELOADS. EG: WHEN USER DELETES A CARD
|
||||||
|
|
||||||
// profile img
|
// profile img
|
||||||
const profileImgInput = useRef(null);
|
const profileImgInput = useRef(null);
|
||||||
const browseProfileImg = () => {
|
const browseProfileImg = () => {
|
||||||
profileImgInput.current.click();
|
profileImgInput.current.click();
|
||||||
};
|
};
|
||||||
|
|
||||||
const profileImgChangHandler = (e) => {
|
const profileImgChangHandler = (e) => {
|
||||||
if (e.target.value !== "") {
|
if (e.target.value !== "") {
|
||||||
const imgReader = new FileReader();
|
const imgReader = new FileReader();
|
||||||
|
|||||||
@@ -42,18 +42,18 @@ function PendingJobsPopout({ details, onClose, situation }) {
|
|||||||
setPendingJobLoader({ extend: true });
|
setPendingJobLoader({ extend: true });
|
||||||
apiCall.pendingJobExtend(reqData).then(res => {
|
apiCall.pendingJobExtend(reqData).then(res => {
|
||||||
setRequestMessage({status: true, message: res.data.status})
|
setRequestMessage({status: true, message: res.data.status})
|
||||||
dispatch(tableReload({ type: "PENDINGTABLE" }));
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setPendingJobLoader({ extend: false, offer: false });
|
setPendingJobLoader({ extend: false, offer: false });
|
||||||
setRequestMessage({status: false, message: ''})
|
setRequestMessage({status: false, message: ''})
|
||||||
onClose();
|
onClose();
|
||||||
}, 2700);
|
dispatch(tableReload({ type: "PENDINGTABLE" }));
|
||||||
|
}, 4000);
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
setRequestMessage({status: false, message:'Try Again'})
|
setRequestMessage({status: false, message:'Try Again'})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setPendingJobLoader({ extend: false, offer: false });
|
setPendingJobLoader({ extend: false, offer: false });
|
||||||
setRequestMessage({status: false, message: ''})
|
setRequestMessage({status: false, message: ''})
|
||||||
}, 2700);
|
}, 3000);
|
||||||
})
|
})
|
||||||
}else if(name=='offer'){ // RUNS THIS IF JOB IS SENT TO USER
|
}else if(name=='offer'){ // RUNS THIS IF JOB IS SENT TO USER
|
||||||
reqData = { ...pendingData };
|
reqData = { ...pendingData };
|
||||||
@@ -63,13 +63,13 @@ function PendingJobsPopout({ details, onClose, situation }) {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setPendingJobLoader({ extend: false, offer: false });
|
setPendingJobLoader({ extend: false, offer: false });
|
||||||
setRequestMessage({status: false, message: ''})
|
setRequestMessage({status: false, message: ''})
|
||||||
}, 2700);
|
}, 4000);
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
setRequestMessage('Try Again')
|
setRequestMessage('Try Again')
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setPendingJobLoader({ extend: false, offer: false });
|
setPendingJobLoader({ extend: false, offer: false });
|
||||||
setRequestMessage({status: false, message: ''})
|
setRequestMessage({status: false, message: ''})
|
||||||
}, 2700);
|
}, 3000);
|
||||||
})
|
})
|
||||||
} else return
|
} else return
|
||||||
// try {
|
// try {
|
||||||
|
|||||||
+1
-1
@@ -303,7 +303,7 @@ input[type="text"][dir="rtl"] {
|
|||||||
|
|
||||||
.sidebar-logo.enter {
|
.sidebar-logo.enter {
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
width: 100%;
|
width: 80%;
|
||||||
}
|
}
|
||||||
.sidebar-logo {
|
.sidebar-logo {
|
||||||
transform: scale(0);
|
transform: scale(0);
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
export default function EmailValidator(email) {
|
||||||
|
let regEx = /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/;
|
||||||
|
if (regEx.test(email) == false) {
|
||||||
|
return false
|
||||||
|
}else{
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
export default function PasswordValidator(password) {
|
||||||
|
const regEx = /^[a-zA-Z0-9!@#$%^&*()_+{}\[\]:;<>,.?~\\/\-='"`|]+$/;
|
||||||
|
if (/[!@#$%^&*()_+{}\[\]:;<>,.?~\\/\-='"`|]/.test(password) == false || /[0-9]/.test(password)==false || /[A-Z]/.test(password)==false || /[a-z]/.test(password)==false) {
|
||||||
|
return false
|
||||||
|
}else{
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -7,12 +7,11 @@ export default function MyPendingJobsPage() {
|
|||||||
let { commonHeadBanner } = useSelector((state) => state.commonHeadBanner);
|
let { commonHeadBanner } = useSelector((state) => state.commonHeadBanner);
|
||||||
let { pendingListTable } = useSelector((state) => state.tableReload);
|
let { pendingListTable } = useSelector((state) => state.tableReload);
|
||||||
|
|
||||||
console.log('TESTING', pendingListTable)
|
|
||||||
|
|
||||||
const [MyJobList, setMyJobList] = useState({loading: true, data: []});
|
const [MyJobList, setMyJobList] = useState({loading: true, data: []});
|
||||||
const api = new usersService();
|
const api = new usersService();
|
||||||
|
|
||||||
const getMyJobList = async () => {
|
const getMyJobList = async () => {
|
||||||
|
setMyJobList({loading: true, data: []});
|
||||||
try {
|
try {
|
||||||
const res = await api.getMyPendingJobList();
|
const res = await api.getMyPendingJobList();
|
||||||
setMyJobList({loading: false, data: res.data});
|
setMyJobList({loading: false, data: res.data});
|
||||||
|
|||||||
Reference in New Issue
Block a user