Compare commits

...

10 Commits

13 changed files with 482 additions and 124 deletions
+2
View File
@@ -68,6 +68,7 @@ import FamilyWalletPage from "./views/FamilyWalletPage";
import FamilyActivitiesPage from "./views/FamilyActivitiesPage";
import FamGamesPage from "./views/FamGamesPage";
import FamilyRoutesPage from "./views/FamilyRoutesPage";
import PromoPage from "./views/PromoPage";
export default function Routers() {
return (
@@ -93,6 +94,7 @@ export default function Routers() {
<Route exact path="/outmessage" element={<VerifyYouPagesTwo />} />
<Route exact path="/eoffer" element={<LoginPageTwo />} />
<Route exact path="/invite" element={<LoginPageTwo />} />
<Route exact path="/promo/:name/:id" element={<PromoPage />} />
</>
) : (
<>
+210
View File
@@ -0,0 +1,210 @@
import React, {useState, useEffect} from 'react'
import { Link, useParams, useNavigate } from "react-router-dom";
import { useDispatch } from "react-redux";
import { updateUserDetails } from "../../../store/UserDetails";
import usersService from "../../../services/UsersService";
import PromoPageLayout from '../PromoPageLayout'
import InputCom from "../../Helpers/Inputs/InputCom";
import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
import LoadingSpinner from '../../../components/Spinners/LoadingSpinner'
export default function Promo() {
const api = new usersService()
const {name, id} = useParams() // PARAMETERS COMING FROM THE LINK
// console.log(name, id)
const navigate = useNavigate()
const dispatch = useDispatch();
const [requestStatus, setRequestStatus] = useState({loading:true, data:{}})
const [completeSignUp, setCompleteSignUp] = useState({loading:false, status:false, message: ''});
const [showPassword, setShowPassword] = useState(false);
const [password, setPassword] = useState("");
const handlePassword = (e) => {
setPassword(e.target.value);
};
// To Show and Hide Password
const togglePasswordVisibility = () => {
setShowPassword(!showPassword);
};
const handleContinue = () => {
let reqData = { // API REQUEST DATA/PAYLOAD
username: requestStatus?.data?.email,
promo: name,
promo_owner: id,
password: password,
sessionid: '24271A99426'
}
setCompleteSignUp({loading:true, status:false, message: ''})
if(!password){ // CHECKS FOR EMPTY PASSWORD
setCompleteSignUp({loading:false, status:false, message: 'Please Enter Password'})
return setTimeout(()=>{
setCompleteSignUp({loading:false, status:false, message: ''})
},2000)
}
api.loginPromo(reqData).then(res => { //loginPromo
console.log('RES', res)
if(res.data?.internal_return < 0 || !res?.data?.member_id || !res?.data?.uid || !res?.data?.session || res?.data?.status_message == 'VALID_LINK_NOT_FOUND'){
setCompleteSignUp({loading:false, status:false, message: 'Unable to login'})
return setTimeout(()=>{
setCompleteSignUp({loading:false, status:false, message: ''})
},4000)
}
// Do LOGIN HERE
localStorage.setItem("member_id", `${res.data.member_id}`);
localStorage.setItem("uid", `${res.data.uid}`);
localStorage.setItem("session_token", `${res.data.session}`);
localStorage.setItem("wallet_available_status", `${res.data.wallet_available_status}`);
if (res.data?.account_type == "FAMILY") {
sessionStorage.setItem("family_uid", res.data?.family_uid);
sessionStorage.setItem("parent_uid", res.data?.parent_uid);
}
dispatch(updateUserDetails({ ...res.data }));
setTimeout(() => {
navigate("/", { replace: true });
setCompleteSignUp({loading:false, status:true, message: ''})
}, 2000);
}).catch(err => {
setCompleteSignUp({loading:false, status:false, message: 'Opps! try again'})
setTimeout(()=>{
setCompleteSignUp({loading:false, status:false, message: ''})
},4000)
})
}
useEffect(()=>{
let reqData = { // API REQUEST DATA/PAYLOAD
promo: name,
promo_owner: id,
sessionid: '79970A12501'
}
api.verifyPromo(reqData).then(res => {
if(res?.data?.internal_return < 0 || !res?.data?.email || res?.data?.status_message != 'VALID_LINK_FOUND'){
return setRequestStatus({loading:false, data:{}})
}
setRequestStatus({loading:false, data:res?.data})
}).catch(err => {
setRequestStatus({loading:false, data:{}})
})
},[])
return (
<PromoPageLayout>
<div className="w-full">
<div className="mb-5">
<Link to="#">
<img
src={WrenchBoard}
alt="wrenchboard"
className="h-10 mx-auto"
/>
</Link>
</div>
{requestStatus.loading ?
<div className='flex flex-col justify-center items-center'>
<LoadingSpinner height='h-40' size='8' />
<p>Loading...</p>
<p>please do not refresh</p>
</div>
: Object.keys(requestStatus.data).length > 0 ?
<div className="flex place-content-center">
<div className="w-10/12 pb-3">
<div className="p-6 input-area login-area border-2 border-[#4687ba] rounded-2xl">
<div className="input-item mb-5">
<InputCom
labelClass="tracking-wider"
fieldClass="sm:px-6 px-2"
value={requestStatus?.data?.email}
// inputHandler={handleEmail}
placeholder="Your Email"
label="Email"
name="email"
type="email"
iconName="message"
disable={true}
/>
</div>
<div className="input-item mb-5">
<InputCom
labelClass="tracking-wider"
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
value={password}
inputHandler={handlePassword}
placeholder="● ● ● ● ● ●"
label="Set Password"
name="password"
type={showPassword ? "text" : "password"}
onClick={togglePasswordVisibility}
passIcon={showPassword ? "password" : "password"}
forgotPassword
/>
</div>
{completeSignUp.message && (
<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]">
{completeSignUp.message}
</div>
)}
<div className="flex justify-center">
<button
name="full"
onClick={handleContinue}
type="button"
disabled={completeSignUp.loading}
className={`btn-login rounded-full text-xl text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center text-[15px]`}
>
{completeSignUp.loading ? (
<div className="signup btn-loader"></div>
) : (
<>Continue</>
)}
</button>
</div>
</div>
</div>
</div>
:
<ErrorComponent onClick={() => navigate("/login")} />
}
</div>
</PromoPageLayout>
)
}
const ErrorComponent = ({ onClick }) => (
<div className="input-area">
<div className="my-5">
<p className="text-[14px] leading-[19px] text-center text-[#181c32]">
This error occurs because you have already verified this link or the
link has expired. Try login or reset password. If none worked, try to
create the account from the start.
</p>
</div>
<div className="signin-area flex justify-center mb-3.5">
<button
onClick={onClick}
type="button"
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-[#009ef7] hover:text-white flex justify-center bg-[#f1faff] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
>
<span>Return Home</span>
</button>
</div>
</div>
);
@@ -0,0 +1,80 @@
import React, { useContext } from "react";
import { Link } from "react-router-dom";
import { localImgLoad } from "../../lib";
import DarkModeContext from "../Contexts/DarkModeContext";
export default function PromoPageLayout({ children }) {
const bgImg = localImgLoad("images/left-wrenchboard.jpg");
const bgImgNig = localImgLoad("images/wrench-home-back-nigeria.jpg");
const bgImgCom = localImgLoad("images/wrench-home-back-common.jpg");
const { countryMode } = useContext(DarkModeContext);
return (
<div
className={`min-h-screen overflow-y-auto bg-cover bg-center flex flex-col justify-between items-center`}
style={{
backgroundImage: `url(${countryMode == "NG" ? bgImgNig : bgImgCom})`,
}}
>
<div className={`w-full grid grid-cols-1`}>
{/* <div
className={`auth-bg hidden xl:block bg-blue-50 relative bg-cover bg-no-repeat border-0 after:content-[''] after:absolute after:inset-0`}
style={{backgroundImage: `url(${bgImg})`}}
>
</div> */}
<div className="p-5 sm:p-7 flex place-content-center">
<div className="py-5 w-full sm:w-11/12 max-w-[550px] shadow-md bg-slate-50 dark:bg-dark-white rounded-[0.475rem]">
<div className="w-full flex justify-center items-center">
{children && children}
</div>
</div>
</div>
</div>
<div className='hidden w-full shadow-md bg-slate-50 dark:bg-dark-white'>
<div className="w-full flex flex-col md:flex-row justify-center items-center px-10 py-2">
<div className="flex justify-center items-center">
<div className="flex items-center">
<a
href="https://www.wrenchboard.com/about-us"
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
target="_blank"
rel="noreferrer"
>
About
</a>
<a
href="https://www.wrenchboard.com/service"
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
target="_blank"
rel="noreferrer"
>
Services
</a>
<a
href="https://www.wrenchboard.com/contact"
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
target="_blank"
rel="noreferrer"
>
Contact Us
</a>
</div>
</div>
<p className="text-black text-[15px] px-2 font-medium flex items-center gap-1">
<span className="dark:text-white">
&copy; {new Date().getFullYear()} -
</span>
<Link to="/" className="text-[#009ef7] ml-1">
WrenchBoard
</Link>{" "}
</p>
</div>
</div>
</div>
);
}
+3 -10
View File
@@ -28,21 +28,14 @@ export default function VerifyYou() {
</span>
</div>
<div className="input-area">
<div className="mb-5">
<div className="mb-5">
<p className="text-[14px] leading-[19px] text-center text-[#181c32]">
<b>Verify Email.</b> Help us secure your WrenchBoard account
by verifying your email registration address. Verification
will let you access all of WrenchBoard's features.
Please <span className="font-semibold tracking-wide">verify your email</span> to secure your account.
</p>
</div>
<div className="mb-5">
<p className="text-[14px] leading-[19px] text-center text-[#181c32]">
If you do not receive the confirmation message within a few
minutes of signing up, please check your Junk E-mail folder
just in case the confirmation email got delivered there
instead of your inbox. If so, select the confirmation
message and click Not Junk, which will allow future messages
to get through.
If you don't see the confirmation email, check your <span className='font-semibold tracking-wide'>Junk</span> or <span className='font-semibold tracking-wide'>Spam</span> folder and mark it as "Not Junk"
</p>
</div>
</div>
+145 -103
View File
@@ -7,6 +7,7 @@ import LoadingSpinner from "../Spinners/LoadingSpinner";
import { Form, Formik } from "formik";
import * as Yup from "yup";
import ReferralTable from "../MyWallet/WalletComponent/ReferralTable";
import TabButton from "../customTabs/TabButton";
const validationSchema = Yup.object().shape({
ref_email: Yup.string()
@@ -105,13 +106,27 @@ function ReferralDisplay() {
sendReferralMsg({...values}); // FUNCTION TO SEND REFERRAL MESSAGE
};
const [selectedTab, setSelectedTab] = useState("Send Referral");
const tabs = [ //STATE FOR SWITCHING BETWEEN TABS
{
id: 1,
title: "Send Referral",
iconName: "history",
},
{
id: 2,
title: "Referral List",
iconName: "history",
},
]
useEffect(() => {
allReferrals();
}, [refHistoryReload]);
return (
<div className="content-wrapper w-full lg:flex xl:space-x-8 bottomMargin">
<div className="lg:w-2/2 w-full mb-10 lg:mb-0">
<>
<div className='w-full'>
<div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
@@ -119,111 +134,138 @@ function ReferralDisplay() {
</h1>
</div>
</div>
<div className="referral w-full md:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl shadow">
<h2 className="mb-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
Send Referral
</h2>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleSubmit}
>
{(props) => (
<Form className="referral-info">
<div className="block md:mb-6 md:flex gap-10">
{/* Firstname */}
<div className="field w-full mb-6 md:mb-0">
<InputCom
fieldClass="px-6"
label="Firstname"
type="text"
name="ref_firstname"
placeholder="Firstname"
value={props.values.ref_firstname}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.ref_firstname &&
props.touched.ref_firstname && (
<p className="text-sm text-red-500">
{props.errors.ref_firstname}
</p>
)}
</div>
{/* Lastname */}
<div className="field w-full mb-6 md:mb-0">
<InputCom
fieldClass="px-6"
label="Lastname"
type="text"
name="ref_lastname"
placeholder="Lastname"
value={props.values.ref_lastname}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.ref_lastname &&
props.touched.ref_lastname && (
<p className="text-sm text-red-500">
{props.errors.ref_lastname}
</p>
)}
</div>
</div>
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="Email"
type="text"
name="ref_email"
placeholder="Email"
value={props.values.ref_email}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.ref_email && props.touched.ref_email && (
<p className="text-sm text-red-500">
{props.errors.ref_email}
</p>
)}
</div>
<hr />
{error.message != "" && (
<p className="text-base text-red-500 py-2">{error.message}</p>
)}
<div className="referral-btn flex justify-end items-center py-4 border-b-4">
{error.loading ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<button
type="submit"
className="px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Send Message
</button>
)}
</div>
</Form>
)}
</Formik>
</div>
<div className="w-full h-full p-4 bg-white dark:bg-dark-white rounded-2xl section-shadow lg:flex lg:px-10 px-4 justify-between">
<div className="content-tab-items lg:w-[230px] w-full mr-2">
<div className='overflow-hidden mb-5 lg:mb-0 py-2 lg:py-8'>
{tabs.map((item) => (
<div key={item.id} className='w-full'>
<TabButton
key={item.id}
item={item.title}
iconName={item.iconName}
selectedTab={selectedTab}
setSelectedTab={setSelectedTab}
/>
</div>
))}
</div>
</div>
<div className="w-[1px] bg-[#E3E4FE] dark:bg-[#a7a9b533] mr-10"></div>
<div className="flex-1 overflow-y-auto min-h-[520px]">
<>
{selectedTab == 'Send Referral' &&
<div className="referral w-full p-4">
<h2 className="mb-4 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
Send Referral
</h2>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleSubmit}
>
{(props) => (
<Form className="referral-info">
<div className="block md:mb-6 md:flex gap-10">
{/* Firstname */}
<div className="field w-full mb-6 md:mb-0">
<InputCom
fieldClass="px-6"
label="Firstname"
type="text"
name="ref_firstname"
placeholder="Firstname"
value={props.values.ref_firstname}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.ref_firstname &&
props.touched.ref_firstname && (
<p className="text-sm text-red-500">
{props.errors.ref_firstname}
</p>
)}
</div>
<div className="w-full md:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl shadow">
<h2 className="mb-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
Referral List
</h2>
{referralList.loading ? (
<LoadingSpinner size="32" color="sky-blue" />
) : (
<ReferralTable history={referralList} />
)}
{/* Lastname */}
<div className="field w-full mb-6 md:mb-0">
<InputCom
fieldClass="px-6"
label="Lastname"
type="text"
name="ref_lastname"
placeholder="Lastname"
value={props.values.ref_lastname}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.ref_lastname &&
props.touched.ref_lastname && (
<p className="text-sm text-red-500">
{props.errors.ref_lastname}
</p>
)}
</div>
</div>
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="Email"
type="text"
name="ref_email"
placeholder="Email"
value={props.values.ref_email}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
{props.errors.ref_email && props.touched.ref_email && (
<p className="text-sm text-red-500">
{props.errors.ref_email}
</p>
)}
</div>
<hr />
{error.message != "" && (
<p className="text-base text-red-500 py-2">{error.message}</p>
)}
<div className="referral-btn flex justify-end items-center py-4">
{error.loading ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<button
type="submit"
className="px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Send Message
</button>
)}
</div>
</Form>
)}
</Formik>
</div>
}
{selectedTab == 'Referral List' &&
<>
<div className="w-full p-4">
<h2 className="mb-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
Referral List
</h2>
{referralList.loading ? (
<LoadingSpinner size="22" color="sky-blue" />
) : (
<ReferralTable history={referralList} />
)}
</div>
</>
}
</>
</div>
</div>
</div>
</>
);
}
@@ -344,11 +344,11 @@ function NewJobListPopout({
{selectedTab == 'family' ?
'Assign to family'
: selectedTab == 'public' ?
'Offer this job to public'
'Place in Market'
: selectedTab == 'individual' ?
'Offer this job to individual'
'Assign to individual'
: selectedTab == 'group' ?
'Offer this job to your Group'
'Preferred List'
:
null
}
@@ -48,7 +48,7 @@ export default function AssignToFamily({
</div>
<div className="mt-3 mb-1 flex justify-end items-center">
<button
className={`px-4 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white`}
className={`uppercase px-4 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white`}
type="submit"
name='family'
>
@@ -48,14 +48,14 @@ export default function AssignToGroup({
</div>
<div className="mt-3 mb-1 flex justify-end items-center">
<button
className={`px-4 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white`}
className={`uppercase px-4 h-11 flex justify-center items-center btn-gradient text-sm rounded-full text-white`}
type="submit"
name='group'
>
{loader?.jobFields ?
<LoadingSpinner size={5} />
:
'Send Order to Group'
'Send Task to Group'
}
</button>
</div>
@@ -53,7 +53,7 @@ export default function AssignToIndividual({
</div>
<div className="mt-3 mb-1 flex justify-end items-center">
<button
className={`px-4 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white`}
className={`uppercase px-4 h-11 flex justify-center items-center btn-gradient text-sm rounded-full text-white`}
type="submit"
name='individual'
>
@@ -102,14 +102,14 @@ export default function AssignToPublic({
</div>
<div className="mt-3 mb-1 flex justify-end items-center">
<button
className={`px-4 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white`}
className={`uppercase px-4 h-11 flex justify-center items-center btn-gradient text-sm rounded-full text-white`}
type="submit"
name='public'
>
{loader?.jobFields ?
<LoadingSpinner size={5} />
:
'Show Task to Public'
'Place Task to the Market'
}
</button>
</div>
+4 -1
View File
@@ -278,5 +278,8 @@ export const apiConst = {
PAY_MODE_CCARD: 1,
PAY_MODE_BONUS: 9,
APPROVED_BALANCE: 5,
DISAPROVE_BALANCE: 3
DISAPROVE_BALANCE: 3,
WRENCHBOARD_VERIFY_PROMO: 55056,
WRENCHBOARD_LOGIN_PROMO: 55057,
};
+19 -1
View File
@@ -208,7 +208,7 @@ class usersService {
// }
getHeroJBanners() {
var postData = {
uuid: localStorage.getItem("uid"),
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
page: 0,
@@ -1493,6 +1493,24 @@ class usersService {
return this.postAuxEnd("/verifycompleted", postData);
}
// API FUNCTION TO VERIFY PROMO LINK
verifyPromo(reqData) {
var postData = {
action: apiConst.WRENCHBOARD_VERIFY_PROMO,
...reqData
};
return this.postAuxEnd("/promoverify", postData);
}
// API FUNCTION TO LOGIN USER THROUGH PROMO LINK
loginPromo(reqData) {
var postData = {
action: apiConst.WRENCHBOARD_LOGIN_PROMO,
...reqData
};
return this.postAuxEnd("/loginpromo", postData);
}
/*
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(username)
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(password)
+10
View File
@@ -0,0 +1,10 @@
import React from 'react'
import Promo from '../components/AuthPages/Promo/Promo'
export default function PromoPage() {
return (
<>
<Promo />
</>
)
}