diff --git a/.env b/.env index 878b89b..1d8c1e2 100644 --- a/.env +++ b/.env @@ -95,4 +95,7 @@ REACT_APP_GOOGLE_RECAPTCHA_SITEKEY=6Ld_qKooAAAAADNL1TPzRLmcBA8vlpvx__39Rj39 #FAMILY MEMBER MINIMUM AGE REACT_APP_FAMILY_MINIMUM_AGE=4 -REACT_APP_FAMILY_MAXIMUM_AGE=18 \ No newline at end of file +REACT_APP_FAMILY_MAXIMUM_AGE=18 + +#CHANGE LOGIN LAYOUT +REACT_APP_NEW_LOGIN_LAYOUT=1 \ No newline at end of file diff --git a/.env.development b/.env.development index 6795a1f..1649df2 100644 --- a/.env.development +++ b/.env.development @@ -63,4 +63,7 @@ REACT_APP_GOOGLE_RECAPTCHA_SITEKEY=6Ld_qKooAAAAADNL1TPzRLmcBA8vlpvx__39Rj39 #FAMILY MEMBER MINIMUM AGE REACT_APP_FAMILY_MINIMUM_AGE=4 -REACT_APP_FAMILY_MAXIMUM_AGE=18 \ No newline at end of file +REACT_APP_FAMILY_MAXIMUM_AGE=18 + +#CHANGE LOGIN LAYOUT +REACT_APP_NEW_LOGIN_LAYOUT=1 \ No newline at end of file diff --git a/.env.production b/.env.production index 59c8eaf..229be6f 100644 --- a/.env.production +++ b/.env.production @@ -70,3 +70,6 @@ REACT_APP_GOOGLE_RECAPTCHA_SITEKEY=6Ld_qKooAAAAADNL1TPzRLmcBA8vlpvx__39Rj39 #FAMILY MEMBER MINIMUM AGE REACT_APP_FAMILY_MINIMUM_AGE=4 REACT_APP_FAMILY_MAXIMUM_AGE=18 + +#CHANGE LOGIN LAYOUT +REACT_APP_NEW_LOGIN_LAYOUT=0 diff --git a/src/Routers.jsx b/src/Routers.jsx index 6df72d5..033053a 100644 --- a/src/Routers.jsx +++ b/src/Routers.jsx @@ -8,9 +8,11 @@ import AcitveBidsPage from "./views/AcitveBidsPage"; import AuthProfilePage from "./views/AuthProfilePage"; import CollectionItemPage from "./views/CollectionItemPage"; import ForgotPasswordPages from "./views/ForgotPasswordPages"; +import ForgotPasswordPagesTwo from "./views/ForgotPasswordPagesTwo"; import HistoryPage from "./views/HistoryPage"; import HomePages from "./views/HomePages"; import LoginPage from "./views/LoginPage"; +import LoginPageTwo from "./views/LoginPageTwo"; import MarketPlacePage from "./views/MarketPlacePage"; import MyWalletPage from "./views/MyWalletPage"; import SavedPage from "./views/SavedPage"; @@ -18,11 +20,15 @@ import SellPage from "./views/SellPage"; import SettingsPage from "./views/SettingsPage"; import ShopDetailsPage from "./views/ShopDetailsPage"; import SignupPage from "./views/SignupPage"; +import SignupPageTwo from "./views/SignupPageTwo"; import UpdatePasswordPages from "./views/UpdatePasswordPages"; +import UpdatePasswordPagesTwo from "./views/UpdatePasswordPagesTwo"; import UploadProductPage from "./views/UploadProductPage"; import UserProfilePage from "./views/UserProfilePage"; import VerifyYouPages from "./views/VerifyYouPages"; +import VerifyYouPagesTwo from "./views/VerifyYouPagesTwo"; import VerifyPasswordPages from "./views/VerifyPasswordPages"; +import VerifyPasswordPagesTwo from "./views/VerifyPasswordPagesTwo"; import RemindersPage from './views/RemindersPage'; import TrackingPage from "./views/TrackingPage"; import CalendarPage from "./views/CalendarPage"; @@ -31,6 +37,7 @@ import MyTaskPage from "./views/MyTaskPage"; import MyJobsPage from "./views/MyJobsPage"; import ReferralPage from "./views/ReferralPage"; import VerifyLinkPages from "./views/VerifyLinkPages"; +import VerifyLinkPagesTwo from "./views/VerifyLinkPagesTwo"; import MyActiveJobsPage from "./views/MyActiveJobsPage"; import FamilyAccPage from "./views/FamilyAccPage"; import StartJob from "./components/MyJobs/StartJob"; @@ -60,27 +67,34 @@ export default function Routers() { {/* guest routes */} - } /> - } /> - } /> - - } /> + {process.env.REACT_APP_NEW_LOGIN_LAYOUT == 1 ? + <> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + : + <> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + } } /> } /> } /> - } - /> - } - /> - } /> - } /> - } /> } /> } /> diff --git a/src/components/AuthPages/AuthLayout2.jsx b/src/components/AuthPages/AuthLayout2.jsx new file mode 100644 index 0000000..6cd4865 --- /dev/null +++ b/src/components/AuthPages/AuthLayout2.jsx @@ -0,0 +1,62 @@ +import React, { lazy } from "react"; +import { Link } from "react-router-dom"; +import { localImgLoad } from "../../lib"; + +export default function LoginLayout({ slogan, children }) { + const bgImg = localImgLoad('images/left-myft.jpg') + + return ( +
+
+ +
+
+
+ {children && children} +
+
+ +

+ © {new Date().getFullYear()} - + + WrenchBoard + {" "} +

+
+
+
+
+
+ ); +} diff --git a/src/components/AuthPages/ForgotPassword/index2.jsx b/src/components/AuthPages/ForgotPassword/index2.jsx new file mode 100644 index 0000000..032645e --- /dev/null +++ b/src/components/AuthPages/ForgotPassword/index2.jsx @@ -0,0 +1,211 @@ +import React, { useState } from "react"; +import { Link, useNavigate } from "react-router-dom"; +import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png"; +import usersService from "../../../services/UsersService"; +import InputCom from "../../Helpers/Inputs/InputCom"; +import AuthLayout from "../AuthLayout2"; +import EmailValidator from "../../../lib/EmailValidator"; +import ForgetPwdResponse from "../ForgetPwdResponse"; + +import ReCAPTCHA from "react-google-recaptcha"; + +export default function ForgotPassword() { + const [checked, setValue] = useState(false); + const [resetLoading, setResetLoading] = useState(false); + // email + const [email, setMail] = useState(""); + const [msgError, setMsgError] = useState(""); + const [msgSuccess, setMsgSuccess] = useState(null); + + const navigate = useNavigate(); + const userApi = new usersService(); + + const handleEmail = (e) => { + setMail(e?.target.value); + }; + + // const humanChecker = () => { + // setValue(!checked); + // }; + + function humanChecker(value) { + // console.log("Captcha value:", value); + if(value){ + setValue(true) + }else{ + setValue(false) + } + } + + const resetHandler = async () => { + if (email == "") { + setMsgError("An email is required"); + return setTimeout(() => { + setMsgError(null); + }, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT); + } + if (!checked) { + 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) { + const reqData = { email, action:11013 }; + setResetLoading(true); + try { + const res = await userApi.StartResetPassword(reqData); + if (res.status === 200) { + setMsgSuccess(true); + setMail(""); + setValue(false); + setResetLoading(false); + }else{ + setMsgSuccess(false); + } + } catch (error) { + setMsgSuccess(false); + setResetLoading(false); + setMail(""); + setMsgError("An error occurred"); + throw new Error(error); + } finally { + setTimeout(() => { + setMsgError(null); + }, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT); + } + } + }; + + return ( + <> + +
+
+ + wrenchboard + +
+
+
+ {msgSuccess == null ? + <> +
+

+ Forget Password +

+ + Enter your email to reset your password. + +
+
+
+ +
+ {/* hCaptha clone for the time being */} +
+ +
+ {/*
+
+
+ +
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
*/} + {msgError && ( +
+ {msgError} +
+ )} +
+
+ + +
+
+
+ + : + + } +
+
+
+
+ + ); +} diff --git a/src/components/AuthPages/Login/index2.jsx b/src/components/AuthPages/Login/index2.jsx new file mode 100644 index 0000000..afe5af2 --- /dev/null +++ b/src/components/AuthPages/Login/index2.jsx @@ -0,0 +1,591 @@ +import React, { useEffect, useLayoutEffect, useState } from "react"; +import { Link, useLocation, useNavigate } from "react-router-dom"; +import linkedInLogo from "../../../assets/images/Linkedin.png"; +import appleLogo from "../../../assets/images/apple-black.svg"; +import facebookLogo from "../../../assets/images/facebook-4.svg"; +import googleLogo from "../../../assets/images/google-logo.svg"; +import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png"; +import usersService from "../../../services/UsersService"; +import InputCom from "../../Helpers/Inputs/InputCom"; +import AuthLayout from "../AuthLayout2"; +// import { GoogleOAuthProvider } from '@react-oauth/google'; +import { useGoogleLogin } from "@react-oauth/google"; + +import { useDispatch } from "react-redux"; +import { updateUserDetails } from "../../../store/UserDetails"; + +import ReCAPTCHA from "react-google-recaptcha"; + +export default function Login() { + // eslint-disable-next-line no-restricted-globals + const queryParams = new URLSearchParams(location?.search); + // const sessionExpired = queryParams.get("sessionExpired"); + + const dispatch = useDispatch(); + const { state } = useLocation(); + + const [sessionExpired, setSessionExpired] = useState(queryParams.get("sessionExpired")) + + const [validCaptcha, setValidCaptcha] = useState({ show: false, valid: "" }); // FOR CAPTCHA + + let [loginType, setLoginType] = useState(""); + + const [loginLoading, setLoginLoading] = useState(false); + + const [showPassword, setShowPassword] = useState(false); + + //login error state + const [loginError, setLoginError] = useState(false); + // for the catch error + const [msgError, setMsgError] = useState(""); + + // To Show and Hide Password + const togglePasswordVisibility = () => { + setShowPassword(!showPassword); + }; + + //FUNCTION TO DETERMINE/CHANGE LOGIN COMPONENT + const handleLoginType = ({ target: { name } }) => { + setLoginType(name); + let currentDate = new Date(); + let expirationDate = new Date(currentDate.getTime() + 24 * 60 * 60 * 1000); + // Convert the expiration date to the appropriate format + let expirationDateString = expirationDate.toUTCString(); + document.cookie = `loginType=${name}; expires=${expirationDateString}; path=/;`; + }; + + // email + const [email, setMail] = useState(""); + const handleEmail = (e) => { + setMail(e.target.value); + }; + // password + const [password, setPassword] = useState(""); + const handlePassword = (e) => { + setPassword(e.target.value); + }; + const navigate = useNavigate(); + const userApi = new usersService(); + + // FUNCTION TO HANDLE USER LOGIN + const doLogin = ({ target: { name } }) => { + setMsgError(""); + setLoginError(false); + setLoginLoading(true); + let postData; // Post Data for API + if (!email || !password) { + setLoginLoading(false); + setMsgError("Please fill all the fields"); + setTimeout(() => { + setMsgError(""); + }, Number(process.env.REACT_APP_LOGIN_ERROR_TIMEOUT)); + return; + } + + if (name == "full") { + //checks if email is a valid email address + let regEx = /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/; + if (regEx.test(email) == false) { + setLoginLoading(false); + setMsgError("Invalid Email"); + return setTimeout(() => { + setMsgError(""); + }, 3000); + } + // Post Data Info for normal Login + postData = { + username: email, + password: password, + sessionid: "STARTING", + login_mode: 1100, + action: 11025, + }; + } else if (name == "family") { + // Post Data Info for family Login + postData = { + username: email, + pin: password, + sessionid: "20067A92714", + login_mode: 1105, + action: 11025, + }; + } else { + setLoginLoading(false); + setMsgError("Invalid Login Type. Consider refreshing the page"); + setTimeout(() => { + setMsgError(""); + }, Number(process.env.REACT_APP_LOGIN_ERROR_TIMEOUT)); + return; + } + if (name == "full" && !validCaptcha.valid && validCaptcha.show) { + // RUNS AND DISPLAYS CAPTCHA, IF ERROR OCCURED DURING LOGIN FOR FULL LOGIN ALONE + setMsgError("Please Verify Captcha"); + setLoginLoading(false); + setTimeout(() => { + setMsgError(""); + }, Number(process.env.REACT_APP_LOGIN_ERROR_TIMEOUT)); + return; + } + userApi + .logInUser(postData) + .then((res) => { + if ( + res.status != 200 || + res.data.internal_return < 0 || + !res.data.member_id || + !res.data.uid || + !res.data.session + ) { + // setMsgError("Wrong, email/password"); + setLoginError(true); + setLoginLoading(false); + setValidCaptcha((prev) => ({ ...prev, show: true })); // DISPLAYS CAPTCHA IF ERROR + return; + } + localStorage.setItem("member_id", `${res.data.member_id}`); + localStorage.setItem("uid", `${res.data.uid}`); + localStorage.setItem("session_token", `${res.data.session}`); + if (name === "family") { + sessionStorage.setItem("family_uid", res.data?.family_uid); + } + // localStorage.setItem("session", `${res.data.session}`); + dispatch(updateUserDetails({ ...res.data })); + setTimeout(() => { + navigate("/", { replace: true }); + setLoginLoading(false); + }, 2000); + }) + .catch((error) => { + setMsgError("Unable to login, try again"); + setLoginLoading(false); + setValidCaptcha((prev) => ({ ...prev, show: true })); // DISPLAYS CAPTCHA IF ERROR + }) + .finally(() => { + setTimeout(() => { + setLoginError(false); + setMsgError(""); + setLoginLoading(false); + }, Number(process.env.REACT_APP_LOGIN_ERROR_TIMEOUT)); + }); + }; + + function captchaChecker(value) { + // FUNCTION TO VALIDATE CAPTCHA + if (value) { + setValidCaptcha({ show: true, valid: value }); + } else { + setValidCaptcha({ show: true, valid: "" }); + } + } + + const googleLogin = useGoogleLogin({ + flow: "auth-code", + ux_mode: "redirect", + redirect_uri: process.env.REACT_APP_GOOGLE_REDIRECT_URL, + onSuccess: async (codeResponse) => { + console.log("GOOGLE LOGIN GOOD --- ", codeResponse); + }, + onError: (errorResponse) => console.log(errorResponse), + }); + + // In order to update the selected login type whenever the component renders + // useEffect(() => { + // Clear the loginType cookie if the user switches to loginfull + // document.cookie ="loginType=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; + // }, []); + + useLayoutEffect(() => { + // checks the cookie in order to set the login type before components mounts + // if(document.cookie.includes("loginType=family")){ + // setLoginType('family') + // }else if(document.cookie.includes("loginType=full")){ + // setLoginType('full') + // }else{ + // setLoginType('full') + // } + function readCookie(cname) { + // checks the cookie in order to set the login type before components mounts + let name = cname + "="; + let decoded_cookie = decodeURIComponent(document.cookie); + let carr = decoded_cookie.split(";"); + for (let i = 0; i < carr.length; i++) { + let c = carr[i]; + while (c.charAt(0) == " ") { + c = c.substring(1); + } + if (c.indexOf(name) == 0) { + return c.substring(name.length, c.length); + } + } + return "full"; + } + let loginValue = readCookie("loginType"); + setLoginType(loginValue); + + if (state?.error) { + //check if the login path has an error state indicating any social handle login with error + setMsgError("Unexpected Error, Please try again soon."); + setTimeout(() => { + setMsgError(""); + navigate("/login", { replace: true }); + }, 4000); + } + }, []); + + useEffect(() => { + setMail(""); + setPassword(""); + }, [loginType]); + + + // EFFECT TO CLEAR SESSION EXPIRY IF IT EXISTS AFTER SOME SECONDS + useEffect(()=>{ + let timer; + if(sessionExpired == "true"){ + timer = setTimeout(()=>{ + setSessionExpired(false) + },5000) + } + return () => { + clearTimeout(timer) + } + }, []) + + return ( + <> + +
+
+ + wrenchboard + +
+ {/*
*/} +
+
+ {/* HIDES THIS IF USER SESSION HAS EXPIRED */} + {sessionExpired != "true" && ( +
+ {/*

+ Sign In to WrenchBoard +

*/} + + New Here?{" "} + + Create an Account + + +
+ )} + + {/* SHOWS THIS IF USER SESSION HAS EXPIRED */} + {sessionExpired == "true" && ( +
+

+ Your session expired and will need to login again +

+
+ )} + + {/* switch login component */} +
+ + +
+ + {/* END of switch login component */} + + {/* for login component */} + { + loginType == "full" ? ( + //user login component +
+
+ +
+ +
+ +
+ + {/* hCaptha clone for the time being */} + {validCaptcha.show && ( +
+ +
+ )} + + {loginError && ( +
+ Invalid username or password- Please{" "} + + reset your password + {" "} + or{" "} + + create a new account + +
+ )} + {msgError && ( +
+ {msgError} +
+ )} +
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ ) : ( + // END of user login compoenent + // family login compoenent +
+
+ +
+ +
+ +
+ {loginError && ( +
+ Invalid username or password{" "} + {/* + reset your password + {" "} + or{" "} + + create a new account + */} +
+ )} + {msgError && ( +
+ {msgError} +
+ )} +
+
+ +
+
+
+ ) + // END of family login compoenent + } + {/* END of login component */} + + {loginType == "full" && ( +
+ This site is protected by a Captcha. Our Privacy Policy and + Terms of Service apply. +
+ )} +
+
+
+ + + ); +} + +const BrandBtn = ({ + link, + imgSrc, + brand, + onClick, + isAnchor = false, + style = { visibility: "visible" }, +}) => { + // const doGoogle = async () => { + // alert("start google"); + // }; + + // onSuccess: (codeResponse) => setUser(codeResponse), + + // const doGoogle = useGoogleLogin({ + // onSuccess: (codeResponse) => console.log('Login onSuccess:', codeResponse), + // onError: (error) => console.log('Login Failed:', error) + // }); + + // const doApple = async () => { + // alert("start apple"); + // }; + + // const doFacebook = async () => { + // alert("start facebook"); + // }; + return ( +
+ {isAnchor ? ( + + logo-icon(s) + + Continue with {brand} + + + ) : ( + + )} +
+ ); +}; diff --git a/src/components/AuthPages/SignUp/index2.jsx b/src/components/AuthPages/SignUp/index2.jsx new file mode 100644 index 0000000..2ee3637 --- /dev/null +++ b/src/components/AuthPages/SignUp/index2.jsx @@ -0,0 +1,404 @@ +import React, { useCallback, useEffect, useState } from "react"; +import { Link, useLocation, useNavigate } from "react-router-dom"; +import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png"; +import usersService from "../../../services/UsersService"; +import InputCom from "../../Helpers/Inputs/InputCom"; +import AuthLayout from "../AuthLayout2"; + +export default function SignUp() { + // eslint-disable-next-line no-restricted-globals + const queryParams = new URLSearchParams(location?.search); + const country = queryParams.get("cnt")?.toUpperCase(); + + const {pathname} = useLocation() + const currentPath = country ? `${pathname}?cnt=${country.toLowerCase()}`:pathname // Determines the new pathname is country query params exist + + const [signUpLoading, setSignUpLoading] = useState(false); + const [checked, setValue] = useState(false); + // for the catch error + const [msgError, setMsgError] = useState(""); + const [showPassword, setShowPassword] = useState(false); + const [countries, setCountries] = useState({loading:true, data:[]}); + + const [formData, setFormData] = useState({ + country: country? country : "", + first_name: "", + last_name: "", + email: "", + password: "", + }); + + const handleInputChange = (event) => { + const { name, value } = event?.target; + setFormData({ ...formData, [name]: value }); + }; + + // To Show and Hide Password + const togglePasswordVisibility = () => { + setShowPassword(!showPassword); + }; + + const rememberMe = () => { + setValue(!checked); + }; + + const navigate = useNavigate(); + const userApi = new usersService(); + + // Get Country Api + const getCountryList = useCallback(async () => { + + try { + const res = await userApi.getSignupCountryData(); + if (res.status === 200 && res.data.internal_return >= 0) { + const { result_list } = await res.data; + if(country){ // IF LINK/PATHNAME HAS CNT QUERY VALUE + let cnt = result_list.filter(item => item.code == country) // test to see country passed in query param exist from list of countries supplied by API + if(!cnt.length){ // IF CNT EMPTY, SET FORMDATA COUNTRY BACK TO EMPTY STRING: RE: THIS IS BCOS WE INITAIL SET COUNTRY VALUE IN FORMDATA, IF COUNTRY PARAM IS PRESENT IN LINK + setFormData(prev => ({...prev, country: ''})) + return setCountries({loading: false, data: result_list}); + } + return setCountries({loading: false, data: cnt}); + } + setCountries({loading: false, data:result_list}); + } else if (res.data.result !== 100) { + setCountries({loading: false, data:[]}); + } + } catch (error) { + throw new Error(error); + } + }, []); + + const handleSignUp = async () => { + let { country, first_name, last_name, email, password } = formData; + try { + if ( + email !== "" && + password !== "" && + first_name !== "" && + last_name !== "" && + country !== "" + ) { + //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) { + setMsgError("Invalid Email"); + return setTimeout(() => { + setMsgError(""); + }, 3000); + } + + //checks if terms and condition is checked + if (!checked) { + setMsgError("Terms and condition required"); + return setTimeout(() => { + setMsgError(""); + }, 3000); + } + + setSignUpLoading(true); + const reqData = { + country: country, + firstname: first_name, + lastname: last_name, + email: email, + username: email, + password: password, + terms: 1, + news: 1, + }; + + const res = await userApi.CreateUser(reqData); + + if (res.status === 200) { + const { data } = res; + if (data && data.acc === "DULPICATE") { + setMsgError( + "Unable to use this username. Please try another username." + ); + setSignUpLoading(false); + } + if (data && data.status === "1") { + setTimeout(() => { + navigate("/outmessage", { replace: true }); + setSignUpLoading(false); + }, 2000); + } + } else { + setSignUpLoading(false); + setMsgError("An error occurred"); + } + } else { + setMsgError("Please fill in fields"); + } + } catch (error) { + throw new Error(error); + } finally { + setTimeout(() => { + setMsgError(null); + }, process.env.REACT_APP_SIGNUP_ERROR_TIMEOUT); + } + }; + + useEffect(() => { + getCountryList(); + }, []); + + return ( + <> + +
+
+ + wrenchboard + +
+
+
+
+

+ Create Account +

+ + Already have an account?{" "} + + Sign in here + + +
+
+
+ + OR + +
+
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+ +
+ {msgError && ( +
+ {msgError} +
+ )} + +
+
+ + + I agree with all + + terms and condition + + +
+
+ + {/* Forgot Password */} + {/*
+
+ + + I agree with all + + terms and condition + + +
+
*/} +
+
+ +
+
+
+
+
+
+
+ + ); +} + +const SelectOption = ({ + label, + name, + inputHandler, + value, + data, // passing the data from parent + disable +}) => { + return ( +
+
+ +
+
+ +
+
+ ); +}; diff --git a/src/components/AuthPages/UpdatePassword/index2.jsx b/src/components/AuthPages/UpdatePassword/index2.jsx new file mode 100644 index 0000000..49567dc --- /dev/null +++ b/src/components/AuthPages/UpdatePassword/index2.jsx @@ -0,0 +1,81 @@ +import React, { useState } from "react"; +import titleShape from "../../../assets/images/shape/title-shape-two.svg"; +import InputCom from "../../Helpers/Inputs/InputCom"; +import AuthLayout from "../AuthLayout2"; +import ThankYou from "../ThankYou"; + +export default function UpdatePassword() { + const [updated, setValue] = useState(false); + const [message, setMessage] = useState(false); + const updatePassword = () => { + setValue(!updated); + setTimeout(() => { + setMessage(!message); + }, 100); + }; + + return ( + <> + + {updated === false ? ( +
+
+
+

+ Update Password +

+ {/* w-[341px] absolute top-14 left-12 */} +
+ shape +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ ) : ( + + )} +
+ + ); +} diff --git a/src/components/AuthPages/VerifyLink/index2.jsx b/src/components/AuthPages/VerifyLink/index2.jsx new file mode 100644 index 0000000..2e50339 --- /dev/null +++ b/src/components/AuthPages/VerifyLink/index2.jsx @@ -0,0 +1,245 @@ +import { useCallback, useEffect, useState } from "react"; +import { Link, useLocation, useNavigate } from "react-router-dom"; +import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png"; +import debounce from "../../../hooks/debounce"; +import usersService from "../../../services/UsersService"; +import InputCom from "../../Helpers/Inputs/InputCom"; +import AuthLayout from "../AuthLayout2"; + +export default function VerifyLink() { + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [msgError, setMsgError] = useState(""); + const [linkLoader, setLinkLoader] = useState(false); + const [pageLoader, setPageLoader] = useState(true); + const [linkSuccess, setLinkSuccess] = useState(true); + const navigate = useNavigate(); + const location = useLocation(); + const queryParams = new URLSearchParams(location?.search); + const token = queryParams.get("vlnk"); + const userApi = new usersService(); + + // email + const handleEmail = (e) => { + setEmail(e.target.value); + }; + // password + const handlePassword = (e) => { + setPassword(e.target.value); + }; + + // if verification is okay. set a complete signup form + const completeSignup = async () => { + try { + if (email !== "" && password !== "") { + setLinkLoader(true); + var postData = { + username: email, + password: password, + login_mode: 100, + sessionid: "STARTER-NOTREAL", + verify_link: token, + action: 11012, + }; + const res = await userApi?.CompleteSignUp(postData); + + if (res.status === 200) { + const { data } = res; + if ( + data?.status > 0 && + data?.internal_return == 100 && + data?.session != "" + ) { + localStorage.setItem("email", `${data?.email}`); + localStorage.setItem("member_id", `${data?.member_id}`); + localStorage.setItem("session_token", `${data?.session}`); + localStorage.setItem("session", `${data?.session}`); + localStorage.setItem("uid", data?.uid) + + + navigate("/", { replace: true }); + setLinkLoader(false); + } else { + setLinkLoader(false); + setMsgError("Invalid Link or Password Combination"); + } + } else { + setLinkLoader(false); + setLinkSuccess(false); + setMsgError("An error occurred"); + } + } else { + setMsgError("Please fill in fields"); + } + } catch (error) { + setLinkLoader(false); + setLinkSuccess(false); + throw new Error(error); + } finally { + setTimeout(() => { + setMsgError(null); + }, process.env.REACT_APP_SIGNUP_ERROR_TIMEOUT); + } + }; + + // for verifying the incoming verification link and render the correct component + const verifyEmail = useCallback(async (code) => { + try { + const verifyRes = await userApi.verifyEmail(code); + if (verifyRes.status === 200) { + let { data } = verifyRes; + console.log('TESTING VERIFY',data) + if ( + data && + data.internal_return >= 0 && + data.status == 0 && + data.pending_id != '' && + data.pending_uid != '' && + data.username != '' && + data.status_text === "Link Verified" + ) { + setPageLoader(false); + } else { + setPageLoader(false); + setLinkSuccess(false); + } + } + } catch (error) { + setPageLoader(false); + setLinkSuccess(false); + throw new Error(error); + } + }, []); + + // delay verify requests by 10000ms + const debouncedEmail = debounce(verifyEmail, 1000); + + useEffect(() => { + debouncedEmail(token); + }, []); + + return ( + <> + + {pageLoader ? ( + wrenchboard + ) : ( +
+
+ + wrenchboard + +
+
+
+
+

+ {linkSuccess + ? "Sign In to WrenchBoard" + : "Invalid verification link"} +

+
+ {/* If the verification was a success */} + {linkSuccess ? ( + + ) : ( + navigate("/login")} /> + )} +
+
+
+ )} +
+ + ); +} + +const SuccessfulComponent = ({ + onSubmit, + password, + handlePassword, + email, + handleEmail, + msgErr, + loader, +}) => ( +
+ {/* INPUT */} +
+ +
+
+ +
+ {msgErr && ( +
+ {msgErr} +
+ )} +
+ +
+
+); + +const ErrorComponent = ({ onClick }) => ( +
+
+

+ 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. +

+
+ +
+ +
+
+); diff --git a/src/components/AuthPages/VerifyPassword/index2.jsx b/src/components/AuthPages/VerifyPassword/index2.jsx new file mode 100644 index 0000000..70564e7 --- /dev/null +++ b/src/components/AuthPages/VerifyPassword/index2.jsx @@ -0,0 +1,269 @@ +import { useEffect, useState } from "react"; +import { Link, useLocation, useNavigate } from "react-router-dom"; +import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png"; +import usersService from "../../../services/UsersService"; +import InputCom from "../../Helpers/Inputs/InputCom"; +import AuthLayout from "../AuthLayout2"; +import ForgetPwdResponse from "../ForgetPwdResponse"; +import PasswordValidator from "../../../lib/PasswordValidator"; +import LoadingSpinner from "../../Spinners/LoadingSpinner"; + +const VerifyPassword = () => { + const [password, setPassword] = useState(""); + const [confirmPassword, setConfirmPassword] = useState(""); + const [requestStatus, setRequestStatus] = useState({loading: true, status:false, data: []}) + const [msgError, setMsgError] = useState(""); + const [linkLoader, setLinkLoader] = useState(false); + const [linkSuccess, setLinkSuccess] = useState(null); + const [showPassword, setShowPassword] = useState(false); + const navigate = useNavigate(); + const location = useLocation(); + const queryParams = new URLSearchParams(location?.search); + const token = queryParams.get("passlink"); + const userApi = new usersService(); + + // To Show and Hide Password + const togglePasswordVisibility = () => { + setShowPassword(!showPassword); + }; + + // Password + const handlePassword = (e) => { + let { name, value } = e?.target; + if (name == "password") setPassword(value); + if (name == "confirm_password") setConfirmPassword(value); + }; + + 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 { + setLinkLoader(true); + var reqData = { + sessionid: "DUMMY-CANNOT_BE_EMPTY", + reset_link: token, + newpass: password, + m_uid: requestStatus.data?.m_uid || '', + reset_uid: requestStatus.data?.reset_uid || '', + step: 300, + action: 730, + }; + const res = await userApi?.CompleteResetPassword(reqData); + + if (res.status == 200) { + const { data } = res; + if (data?.internal_return >= 0) { + // setTimeout(() => { + // navigate("/login", { replace: true }); + // setLinkLoader(false); + // }, 2000); + setLinkSuccess(true); + } else { + setLinkLoader(false); + setMsgError("An error occurred"); + setLinkSuccess(false); + } + } else { + setLinkLoader(false); + setLinkSuccess(false); + } + } catch (error) { + setLinkLoader(false); + setLinkSuccess(false); + throw new Error(error); + } finally { + setTimeout(() => { + setMsgError(null); + }, process.env.REACT_APP_SIGNUP_ERROR_TIMEOUT); + } + }; + + 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 ( + <> + +
+
+ + wrenchboard + +
+
+ {requestStatus.loading ? + + : + !requestStatus.loading && requestStatus.status ? +
+ {linkSuccess == null ? + <> +
+

+ Password Reset +

+ + Enter a new password to reset + + + We'll send an email to confirm reset + +
+
+

+ Must include a special, numeric, uppercase and lowercase character +

+
+ navigate("/login")} + /> + + : + + } +
+ : +
+ +
+ } +
+
+
+ + ); +}; + +export default VerifyPassword; + +const SuccessfulComponent = ({ + onSubmit, + navigateHandler, + showPassword, + onClick, + password, + confirmPassword, + handlePassword, + msgErr, + loader, +}) => ( +
+ {/* INPUT */} +
+ +
+
+ +
+ {msgErr && ( +
+ {msgErr} +
+ )} +
+ +
+
+ +
+
+); diff --git a/src/components/AuthPages/VerifyYou/index2.jsx b/src/components/AuthPages/VerifyYou/index2.jsx new file mode 100644 index 0000000..09d0635 --- /dev/null +++ b/src/components/AuthPages/VerifyYou/index2.jsx @@ -0,0 +1,64 @@ +import { useNavigate, Link } from "react-router-dom"; +import AuthLayout from "../AuthLayout2"; +import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png"; + +export default function VerifyYou() { + const navigate = useNavigate(); + return ( + <> + +
+
+ + wrenchboard + +
+
+
+
+

+ Let's verify your email now +

+ + Check your email. + +
+
+
+

+ Verify Email. Help us secure your WrenchBoard account + by verifying your email registration address. Verification + will let you access all of WrenchBoard's features. +

+
+
+

+ If you do not receive the confirmation message within a few + minutes of signing up, please check your Junk E-mail folder + just in case the confirmation email got delivered there + instead of your inbox. If so, select the confirmation + message and click Not Junk, which will allow future messages + to get through. +

+
+
+
+ +
+
+
+
+
+ + ); +} diff --git a/src/index.css b/src/index.css index 49b06f4..f032f00 100644 --- a/src/index.css +++ b/src/index.css @@ -955,6 +955,21 @@ TODO: Responsive =========================== padding-inline: 1rem; } +.auth-bg { + border: none; + /* box-shadow: inset 0 0 10px 20px #fff; */ +} + +.auth-bg::after { + background: linear-gradient( + to right, + transparent 0%, + transparent 50%, + transparent 95%, + rgb(255, 255, 255) 100% + ); +} + /* For IE10 */ .content-wrapper select::-ms-expand { display: none; diff --git a/src/views/ForgotPasswordPagesTwo.jsx b/src/views/ForgotPasswordPagesTwo.jsx new file mode 100644 index 0000000..3271c5c --- /dev/null +++ b/src/views/ForgotPasswordPagesTwo.jsx @@ -0,0 +1,10 @@ +import React from "react"; +import ForgotPassword from "../components/AuthPages/ForgotPassword/index2"; + +export default function ForgotPasswordPagesTwo() { + return ( + <> + + + ); +} diff --git a/src/views/LoginPageTwo.jsx b/src/views/LoginPageTwo.jsx new file mode 100644 index 0000000..4c002d1 --- /dev/null +++ b/src/views/LoginPageTwo.jsx @@ -0,0 +1,12 @@ +import React from "react"; +import Login from "../components/AuthPages/Login/index2"; + +function LoginPageTwo() { + return ( + <> + + + ); +} + +export default LoginPageTwo; diff --git a/src/views/SignupPageTwo.jsx b/src/views/SignupPageTwo.jsx new file mode 100644 index 0000000..f5543d3 --- /dev/null +++ b/src/views/SignupPageTwo.jsx @@ -0,0 +1,12 @@ +import React from "react"; +import SignUp from "../components/AuthPages/SignUp/index2"; + +function SignupPageTwo() { + return ( + <> + + + ); +} + +export default SignupPageTwo; diff --git a/src/views/UpdatePasswordPagesTwo.jsx b/src/views/UpdatePasswordPagesTwo.jsx new file mode 100644 index 0000000..9f1881a --- /dev/null +++ b/src/views/UpdatePasswordPagesTwo.jsx @@ -0,0 +1,10 @@ +import React from "react"; +import UpdatePassword from "../components/AuthPages/UpdatePassword/index2"; + +export default function UpdatePasswordPagesTwo() { + return ( + <> + + + ); +} diff --git a/src/views/VerifyLinkPagesTwo.jsx b/src/views/VerifyLinkPagesTwo.jsx new file mode 100644 index 0000000..90a1cc0 --- /dev/null +++ b/src/views/VerifyLinkPagesTwo.jsx @@ -0,0 +1,5 @@ +import VerifyLink from "../components/AuthPages/VerifyLink/index2"; + +export default function VerifyLinkPagesTwo() { + return ; +} diff --git a/src/views/VerifyPasswordPagesTwo.jsx b/src/views/VerifyPasswordPagesTwo.jsx new file mode 100644 index 0000000..1908b22 --- /dev/null +++ b/src/views/VerifyPasswordPagesTwo.jsx @@ -0,0 +1,6 @@ +import React from "react"; +import VerifyPassword from "../components/AuthPages/VerifyPassword/index2"; + +export default function VerifyPasswordPagesTwo() { + return ; +} diff --git a/src/views/VerifyYouPagesTwo.jsx b/src/views/VerifyYouPagesTwo.jsx new file mode 100644 index 0000000..dd9bda5 --- /dev/null +++ b/src/views/VerifyYouPagesTwo.jsx @@ -0,0 +1,6 @@ +import React from "react"; +import VerifyYou from "../components/AuthPages/VerifyYou/index2"; + +export default function VerifyYouPagesTwo() { + return ; +}