Compare commits

...

35 Commits

Author SHA1 Message Date
victorAnumudu 0440b36f24 dashdata api removed 2024-09-25 13:13:19 +01:00
ameye de56fb601a Merge branch 'offerlist-display-bug' of WrenchBoard/Users-Wrench into master 2024-09-24 23:50:17 +00:00
victorAnumudu f286960bed top banner offer list display fixed 2024-09-25 00:45:54 +01:00
ameye a8a090c671 Merge branch 'offerlist-dark-color' of WrenchBoard/Users-Wrench into master 2024-09-24 21:13:03 +00:00
victorAnumudu 24e2a905d2 moved refer friend section 2024-09-24 22:07:33 +01:00
victorAnumudu 19c2500263 added dark color for offer list card 2024-09-24 21:13:03 +01:00
ameye 909c74b734 Merge branch 'dashboard-offerlist-position' of WrenchBoard/Users-Wrench into master 2024-09-24 20:09:14 +00:00
victorAnumudu 0ea988fcea repositioned offer list display 2024-09-24 21:05:01 +01:00
ameye db5eb85794 Merge branch 'blog-page-image' of WrenchBoard/Users-Wrench into master 2024-09-24 16:58:06 +00:00
victorAnumudu fb6a2767bc Merged with master 2024-09-24 17:34:00 +01:00
ameye c48ae540cc Merge branch 'changed-price-to-reward' of WrenchBoard/Users-Wrench into master 2024-09-24 15:56:46 +00:00
victorAnumudu c51693deb5 changed text price to reward 2024-09-24 15:36:38 +01:00
victorAnumudu b28d02b2f5 blog image fixed 2024-09-24 13:54:47 +01:00
ameye 74b395d99e Merge branch 'blog-id-fix' of WrenchBoard/Users-Wrench into master 2024-09-21 13:49:46 +00:00
victorAnumudu 21a2754fc9 blog id added 2024-09-21 14:47:22 +01:00
ameye 19282ad15a Merge branch 'home-page-image' of WrenchBoard/Users-Wrench into master 2024-09-21 11:45:46 +00:00
victorAnumudu f48b72b149 updated home page image 2024-09-21 12:15:10 +01:00
ameye 72d4af20aa Merge branch 'promo-page-update' of WrenchBoard/Users-Wrench into master 2024-09-21 09:52:42 +00:00
victorAnumudu e6f5746692 promo page download links added 2024-09-21 06:15:25 +01:00
CHIEFSOFT\ameye d0e7f58d5f Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench 2024-09-20 12:02:29 -04:00
CHIEFSOFT\ameye f4e21cb73e app links 2024-09-20 12:02:16 -04:00
ameye 6ad8ed34f5 Merge branch 'promo-login' of WrenchBoard/Users-Wrench into master 2024-09-19 18:24:42 +00:00
victorAnumudu b4bbe03bdd added promo login API 2024-09-19 19:21:15 +01:00
ameye 2c54aa36f8 Merge branch 'promo-page' of WrenchBoard/Users-Wrench into master 2024-09-18 18:54:19 +00:00
victorAnumudu 00c83b357f added promo page 2024-09-18 19:48:24 +01:00
ameye 0b7ec73409 Merge branch 'referal-page-header' of WrenchBoard/Users-Wrench into master 2024-09-13 16:53:31 +00:00
victorAnumudu f58e8834fb added referal page header 2024-09-13 10:22:04 +01:00
ameye 1a829789d4 Merge branch 'referral-page-update' of WrenchBoard/Users-Wrench into master 2024-09-13 07:26:35 +00:00
victorAnumudu 84dccfca50 updated referral page 2024-09-12 19:36:31 +01:00
ameye 49e3fc5810 Merge branch 'interest-count-added' of WrenchBoard/Users-Wrench into master 2024-09-07 11:54:02 +00:00
ameye e4b6391ed2 Merge branch 'assign-job-btn-harmonized' of WrenchBoard/Users-Wrench into master 2024-09-07 11:53:56 +00:00
victorAnumudu 3abbdd32eb interest count bug fixed 2024-09-06 21:03:58 +01:00
victorAnumudu e4a5c2682e interest count added 2024-09-06 20:53:45 +01:00
victorAnumudu 21abc93a04 made assign job btn name same as what is in mobile app 2024-09-02 20:21:31 +01:00
ameye d51bbdbc29 Merge branch 'timeline-default-value' of WrenchBoard/Users-Wrench into master 2024-08-26 19:38:54 +00:00
54 changed files with 1122 additions and 586 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

+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 />} />
</>
) : (
<>
Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

+1 -1
View File
@@ -162,7 +162,7 @@ function AddJob({ popUpHandler, categories }) {
<div className="field w-full mb-[5px] xl:mb-0">
<InputCom
fieldClass="px-6 text-right flex"
label="Price"
label="Reward"
labelClass=""
type="number"
name="price"
@@ -42,7 +42,7 @@ export default function ActivitiesTab({ className }) {
<div className="relative w-full overflow-x-auto sm:rounded-lg">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
<tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-b dark:border-[#5356fb29] ottom ">
<tr className="text-base text-thin-light-gray whitespace-nowrap border-b default-border-b dark:border-[#5356fb29] ottom ">
<td className="py-4 pr-12">List</td>
<td className="py-4 text-start px-2">Product Name</td>
<td className="py-4 text-start px-2">Price</td>
+252
View File
@@ -0,0 +1,252 @@
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'
import GoogleDownload from '../../../assets/images/download/andriod.jpg'
import IOSDownload from '../../../assets/images/download/apple.jpg'
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"}
/>
</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>
{/* APP DOWNLOAD STORE */}
<div className="w-full mt-4">
<div className="w-full flex justify-between items-center gap-10 sm:gap-32">
<div className="w-full">
<a
// className="px-1 py-1 lg:py-2 flex justify-center items-center gap-1 w-full rounded-md bg-black text-white hover:text-slate-500 hover:shadow-lg transition-all duration-300"
target="_blank"
rel="noreferrer"
href={process.env.REACT_APP_APPLE_APP}
>
{/* <i className="fa-brands fa-apple text-3xl"></i>
<div className="flex flex-col">
<span className="text-[11px]">Available on the</span>
<span className="text-[12px] lg:text-base">
App Store
</span>
</div> */}
<img src={IOSDownload} className='w-full h-auto' alt='IOS Download' />
</a>
</div>
<div className="w-full">
<a
// className="px-1 py-1 lg:py-2 flex justify-center items-center gap-1 w-full rounded-md bg-black text-white hover:text-slate-500 hover:shadow-lg transition-all duration-300"
target="_blank"
rel="noreferrer"
href={process.env.REACT_APP_ANDROID_APP}
>
{/* <i className="fa-brands fa-google-play text-2xl"></i>
<div className="flex flex-col">
<span className="text-[11px]">Available on the</span>
<span className="text-[12px] lg:text-base">
Google Play
</span>
</div> */}
<img src={GoogleDownload} className='w-full h-auto' alt='IOS Download' />
</a>
</div>
</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-promo-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" ? bgImgCom : 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>
);
}
@@ -42,10 +42,10 @@ export default function ActivitiesTab({ className }) {
<div className="relative w-full overflow-x-auto sm:rounded-lg">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
<tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-b dark:border-[#5356fb29] ottom ">
<tr className="text-base text-thin-light-gray whitespace-nowrap border-b default-border-b dark:border-[#5356fb29] ottom ">
<td className="py-4 pr-12">List</td>
<td className="py-4 text-start px-2">Product Name</td>
<td className="py-4 text-start px-2">Price</td>
<td className="py-4 text-start px-2">Reward</td>
<td className="py-4 text-start px-2">Quantity</td>
<td className="py-4 text-start px-2">From</td>
<td className="py-4 text-start px-2 pr-12">To</td>
+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>
+8 -2
View File
@@ -26,9 +26,11 @@ export default function BlogItem(props) {
const queryParams = new URLSearchParams(location?.search);
const blog_id = queryParams.get("blog_id");
// console.log('MUMU', 'meta_value', blogdata, blogdata.data.image_url)
useEffect(()=>{
if(!blog_id){
navigate('/',{replace:true})
return navigate('/',{replace:true})
}
apiCall.getSingleBlogData({blog_id}).then(res => {
setBlogdata({loading: false, data:res.data})
@@ -87,7 +89,11 @@ export default function BlogItem(props) {
<div className="slider-btns flex space-x-4">
</div>
</div> */}
<div dangerouslySetInnerHTML={{__html: blogdata.data?.blogdata?.[0]?.post_content}}>
{/* console.log('MUMU', 'meta_value', blogdata, blogdata.data.image_url) */}
<div className='w-full mb-8'>
<img src={`${blogdata.data.image_url}/${blogdata.data?.blogdata?.[0]?.meta_value}`} className='w-full h-auto' alt='Blog Image' />
</div>
<div dangerouslySetInnerHTML={{__html: blogdata.data?.blogdata?.[0]?.post_content}} className='prose leading-relaxed'>
</div>
</div>
:
+1 -1
View File
@@ -175,7 +175,7 @@ export default function AvailableJobsCard({
<div className="block sm:flex flex-wrap gap-4">
<p className="text-sm text-thin-light-gray flex flext-start gap-1 items-center">
{datas?.offer_depend_uid && <i className="fa-solid fa-lock p-1 text-red-500 text-[12px]"></i>}
Price: <span className="text-purple">{thePrice}</span>
Reward: <span className="text-purple">{thePrice}</span>
</p>
<p className="text-sm text-thin-light-gray">
Duration:{" "}
+160 -59
View File
@@ -1,10 +1,19 @@
import React from "react";
import React, { Suspense, lazy, useState } from "react";
import { Link } from "react-router-dom";
import VideoElement from '../../components/VideoCom/VideoElement'
import OfferJobPopout from '../../components/jobPopout/OfferJobPopout'
import { PriceFormatter } from "../Helpers/PriceFormatter";
import CountDown from '../Helpers/CountDown'
const AccountDashboard = ({ className, bannerList, offersList, imageServer }) => {
let [offerPopout, setOfferPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
let offersListLength = offersList?.length
const AccountDashboard = ({ className, bannerList }) => {
// getting the upper three banners for the home layout
const getUpperBanner = bannerList?.filter((value, idx) => idx <= 2);
const getLowerBanner = bannerList?.filter((value, idx) => idx > 2);
const getUpperBanner = bannerList?.filter((value, idx) => idx <= 2 - offersListLength);
const getLowerBanner = bannerList?.filter((value, idx) => !getUpperBanner?.map(item => item?.title)?.includes(value.title));
let getImage = ({ banner_location, banner }) => {
if (banner_location == "LOCAL") {
@@ -14,56 +23,90 @@ const AccountDashboard = ({ className, bannerList }) => {
}
};
console.log(getLowerBanner);
return (
<div
className={`w-full min-h-[450px] flex flex-col justify-between items-center gap-4 rounded-2xl overflow-hidden ${
className || ""
}`}
>
<div className="w-full grid xxs:grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 items-center justify-center gap-2 md:gap-4">
{getUpperBanner?.map((props, idx) => {
let image = getImage(props);
<>
<div
className={`w-full min-h-[450px] flex flex-col justify-between items-center gap-4 rounded-2xl overflow-hidden ${
className || ""
}`}
>
let { short_title, short_description, short_button_text, link_path } =
props;
<div className="w-full grid xxs:grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 items-center justify-center gap-2 md:gap-4">
return (
<div key={idx}>
<TopBanner
btn={short_button_text}
image={image}
title={short_title}
desc={short_description}
link_path={link_path}
/>
</div>
);
})}
{/* OFFER LIST DISPLAY */}
<>
{(offersList && offersList?.length > 0) &&
offersList.map((item, index) => {
let thePrice = PriceFormatter(
item?.price * 0.01,
item?.currency_code,
item?.currency
);
let image = `${imageServer}${localStorage.getItem("session_token")}/job/${item.job_uid}`
return (
<div key={item.id}>
<NewOfferCard datas={item} image={image} price={thePrice} setOfferPopout={setOfferPopout} />
</div>
)
})}
</>
{getUpperBanner?.map((props, idx) => {
let image = getImage(props);
let { short_title, short_description, short_button_text, link_path, card_type, blog_id } =
props;
return (
<div key={idx}>
<TopBanner
btn={short_button_text}
image={image}
title={short_title}
desc={short_description}
link_path={card_type=='BLOG' ? `${link_path}?blog_id=${blog_id}` : link_path}
/>
</div>
);
})}
</div>
<div className="w-full grid-cols-1 md:grid-cols-2 2xl::grid-cols-3 grid items-center justify-center gap-2 md:gap-4">
{getLowerBanner?.map((props, idx) => {
let image = getImage(props);
let { short_title, short_description, short_button_text, link_path, card_type, blog_id } =
props;
return (
<div key={idx}>
<LowerBanner
btn={short_button_text}
image={image}
title={short_title}
desc={short_description}
link_path={link_path}
card_type={card_type}
blog_id={blog_id}
/>
</div>
);
})}
</div>
</div>
<div className="w-full grid-cols-1 md:grid-cols-2 2xl::grid-cols-3 grid items-center justify-center gap-2 md:gap-4">
{getLowerBanner?.map((props, idx) => {
let image = getImage(props);
let { short_title, short_description, short_button_text, link_path, card_type, blog_id } =
props;
return (
<div key={idx}>
<LowerBanner
btn={short_button_text}
image={image}
title={short_title}
desc={short_description}
link_path={link_path}
card_type={card_type}
blog_id={blog_id}
/>
</div>
);
})}
</div>
</div>
{/* Offer Job Popout */}
{offerPopout.show && (
<OfferJobPopout
details={offerPopout.data}
onClose={() => {
setOfferPopout({ show: false, data: {} });
}}
situation={offerPopout.show}
/>
)}
{/* End of Offer Job Popout */}
</>
);
};
@@ -71,25 +114,25 @@ export default AccountDashboard;
const TopBanner = ({ image, title = "", desc = "", btn, link_path, key }) => {
return (
<div className="flex flex-col shadow-md rounded-xl dark:border-[#5356fb29]" key={key}>
<Link to={link_path} className="h-[12rem] rounded-t-xl">
<div className="flex flex-col shadow-md rounded-xl dark:border-[#5356fb29] overflow-hidden" key={key}>
<Link to={link_path} className="h-[12rem] bg-white">
<img
src={image}
alt="banner-img"
loading="lazy"
className="w-full h-full rounded-t-xl object-cover"
className="w-auto mx-auto h-full"
/>
</Link>
<div className="h-[7rem] rounded-b-xl bg-white dark:bg-dark-white">
<div className="rounded-b-xl bg-white dark:bg-dark-white">
<div className="border-b border-slate-300 px-2 py-1 h-[5.4rem] flex flex-col gap-2 dark:text-white">
<Link to={link_path} className="font-bold text-lg">
<Link to={link_path} className="font-bold text-lg line-clamp-1">
{title}
</Link>
<Link to={link_path} className="text-sm">
{desc}
</Link>
</div>
<div className="flex justify-between w-full px-2 items-center pt-[0.2rem]">
<div className="flex justify-between w-full p-1 items-center">
<Link to={link_path} className="text-slate-300 font-semibold text-sm">
{btn}
</Link>
@@ -104,6 +147,64 @@ const TopBanner = ({ image, title = "", desc = "", btn, link_path, key }) => {
);
};
const NewOfferCard = ({ datas, hidden = false, price, setOfferPopout, image }) => {
return (
<div className="flex flex-col shadow-md bg-red-50 dark:bg-dark-white rounded-xl dark:border-[#5356fb29] overflow-hidden">
<div className="h-[12rem] bg-transparent">
{/* thumbnail image/video */}
{datas.job_type == "MEDIA" ?
<Suspense fallback={<p>Loading...</p>}>
<VideoElement videoId={datas?.media_uid} />
</Suspense>
:
<div
className="thumbnail w-full h-full rounded-xl overflow-hidden px-4 pt-4"
style={{
background: `url(${image}) center / contain no-repeat`,
}}
>
{hidden && <div className="flex justify-center"></div>}
</div>
}
</div>
<div className="rounded-b-xl bg-transparent dark:bg-dark-transparent">
<div className="border-b border-slate-300 px-2 py-1 h-[5.4rem] flex flex-col gap-2 dark:text-white">
<h1 className="font-bold text-lg line-clamp-1 text-center">
{datas?.title}
</h1>
{/* <Link to={link_path} className="text-sm">
{desc}
</Link> */}
<div className="card-buttons flex justify-center items-center space-x-2">
<button
type="button"
onClick={() =>
setOfferPopout({ show: true, data: { ...datas, price, image } })
}
className="btn-shine w-2/3 h-[40px] text-white rounded-full text-sm bg-pink flex justify-center items-center"
>
Start Task
</button>
</div>
</div>
<div className="flex justify-between w-full p-1 items-center">
<div className="flex gap-1 items-center">
<p className="text-[12px] text-red-500 tracking-wide">Expires</p>
<p className="text-[12px] font-semibold tracking-wide text-dark-gray dark:text-white">
<CountDown lastDate={datas.expire} />
</p>
</div>
<button className="flex items-center justify-center gap-2">
<div className="w-[4px] h-[4px] bg-slate-400 rounded-full"></div>
<div className="w-[4px] h-[4px] bg-slate-400 rounded-full"></div>
<div className="w-[4px] h-[4px] bg-slate-400 rounded-full"></div>
</button>
</div>
</div>
</div>
);
};
const LowerBanner = ({ image, title = "", desc = "", btn, link_path, card_type, blog_id, key }) => {
const newLinkPath = card_type == 'BLOG' ? `${link_path}?blog_id=${blog_id}` : link_path
@@ -113,7 +214,7 @@ const LowerBanner = ({ image, title = "", desc = "", btn, link_path, card_type,
className="flex flex-col bg-white shadow-md h-full rounded-xl dark:border-[#5356fb29] dark:bg-dark-white"
>
<div className="w-full xxs:flex justify-between items-center border-b border-slate-300 p-2">
<div className="min-h-[150px] sm:min-h-[130px] flex justify-between items-center">
<div className="min-h-[130px] sm:min-h-[100px] flex justify-between items-center">
<div className="px-2 flex flex-col gap-2 dark:text-white">
<Link to={newLinkPath} className="text-lg font-bold">
{title}
@@ -132,7 +233,7 @@ const LowerBanner = ({ image, title = "", desc = "", btn, link_path, card_type,
/>
</Link>
</div>
<div className="flex justify-between w-full px-2 items-center">
<div className="flex justify-between w-full p-1 items-center">
<Link to={newLinkPath} className="text-slate-300 font-semibold text-sm">
{btn}
</Link>
@@ -181,7 +282,7 @@ const BannerSection = ({ banners, variant }) => {
variant === "top"
? "rounded-b-xl bg-white"
: "border-b border-slate-300"
} h-[7rem]`}
}`}
>
<div className="border-b border-slate-300 px-2 py-1 h-[5.4rem] flex flex-col gap-2">
<Link to={link_path} className="font-bold text-lg">
@@ -191,7 +292,7 @@ const BannerSection = ({ banners, variant }) => {
{short_description}
</Link>
</div>
<div className="flex justify-between w-full px-2 items-center">
<div className="flex justify-between w-full p-1 items-center">
<Link to={link_path} className="text-slate-300 font-semibold">
{short_button_text}
</Link>
@@ -5,7 +5,6 @@ import { useSelector } from "react-redux";
export default function FamilyParentDashboard({
className,
bannerList,
nextDueTask,
}) {
const { userDetails } = useSelector((state) => state?.userDetails);
+1 -1
View File
@@ -2,7 +2,7 @@ import React from "react";
// import HomeSliders from "./HomeSliders";
import { useSelector } from "react-redux";
export default function HomeDashboard({ className, bannerList, nextDueTask }) {
export default function HomeDashboard({ className, bannerList }) {
const { userDetails } = useSelector((state) => state?.userDetails);
let loginDate = userDetails?.last_login.split(" ")[0];
@@ -5,7 +5,6 @@ import { useSelector } from "react-redux";
export default function JobOwnerDashboard({
className,
bannerList,
nextDueTask,
}) {
const { userDetails } = useSelector((state) => state?.userDetails);
@@ -5,7 +5,6 @@ import { useSelector } from "react-redux";
export default function WorkerDashboard({
className,
bannerList,
nextDueTask,
}) {
const { userDetails } = useSelector((state) => state?.userDetails);
@@ -74,7 +74,7 @@ export default function FamilyPending({ familyData }) {
</h1>
<div>{value.description}</div>
<span className="text-sm text-thin-light-gray flex items-start gap-1">
Price:{" "}
Reward:{" "}
<span className="text-purple">
{thePrice}
</span>
@@ -97,7 +97,7 @@ export default function FamilyNewTasks({
</h1>
<div className="flex flex-col sm:flex-row items-start gap-1 md:gap-4 md:items-center">
<span className="text-sm text-thin-light-gray flex flex-start gap-1">
Price:{" "}
Reward:{" "}
<span className="text-purple">
{thePrice}
</span>
@@ -83,7 +83,7 @@ export default function FamilyPending({
</h1>
<div>{value.description}</div>
<span className="text-sm text-thin-light-gray flex items-start gap-1">
Price:{" "}
Reward:{" "}
<span className="text-purple">
{thePrice}
</span>
@@ -87,7 +87,7 @@ export default function FamilyTasks({
</h1>
<div className="flex flex-col sm:flex-row items-start gap-1 md:gap-4 md:items-center">
<span className="text-sm text-thin-light-gray flex flex-start gap-1">
Price:{" "}
Reward:{" "}
<span className="text-purple">
{thePrice}
</span>
@@ -1,17 +1,16 @@
import React, { useEffect, useState } from "react";
import ModalCom from "../../../Helpers/ModalCom";
import InputCom from "../../../Helpers/Inputs/InputCom";
import { Form, Formik } from "formik";
import React, { useEffect, useState } from "react";
import * as Yup from "yup";
import InputCom from "../../../Helpers/Inputs/InputCom";
import ModalCom from "../../../Helpers/ModalCom";
import { AmountTo2DP } from "../../../Helpers/PriceFormatter";
import usersService from "../../../../services/UsersService";
import LoadingSpinner from "../../../Spinners/LoadingSpinner";
import { PriceFormatter } from "../../../Helpers/PriceFormatter";
import { tableReload } from "../../../../store/TableReloads";
import { useDispatch, useSelector } from "react-redux";
import { apiConst } from "../../../../lib/apiConst";
import usersService from "../../../../services/UsersService";
import { tableReload } from "../../../../store/TableReloads";
import { SocketValues } from "../../../Contexts/SocketIOContext";
import { AmountTo2DP } from "../../../Helpers/PriceFormatter";
import LoadingSpinner from "../../../Spinners/LoadingSpinner";
const validationSchema = Yup.object().shape({
// amount: Yup.string()
@@ -31,10 +30,9 @@ const validationSchema = Yup.object().shape({
});
function FamilyAddFundPopout({ action, situation, wallet, familyData }) {
const { userDetails } = useSelector((state) => state?.userDetails); // Gets User Detail
const {userDetails} = useSelector((state) => state?.userDetails); // Gets User Detail
const { parentAssignJobToKid } = SocketValues() // socket emit event from FULL account
const { parentAssignJobToKid } = SocketValues(); // socket emit event from FULL account
const dispatch = useDispatch();
@@ -60,7 +58,6 @@ function FamilyAddFundPopout({ action, situation, wallet, familyData }) {
};
// FUNCTION TO PERFORM FAMILY TRANSFER
const handleAddFund = (values) => {
setRequestStatus({ loading: true, status: false, message: "" });
let senderBal = startTransfer?.data?.origing_current_balance || ""; // SENDER'S ACCOUNT BALANCE
@@ -143,12 +140,12 @@ function FamilyAddFundPopout({ action, situation, wallet, familyData }) {
//SENDS MESSAGE TO SOCKET TO UPDATE CHILD ACCOUNT
// message, room
let socketMsg = {
"audience": "MEMBER",
"action": "REFRESH_WALLET",
"family_uid": reqData.family_uid,
}
let socketRoom = `FAMILY-${userDetails.uid}`
parentAssignJobToKid(socketMsg, socketRoom) //SENDS MESSAGE TO SOCKET TO UPDATE CHILD ACCOUNT
audience: "MEMBER",
action: "REFRESH_WALLET",
family_uid: reqData.family_uid,
};
let socketRoom = `FAMILY-${userDetails.uid}`;
parentAssignJobToKid(socketMsg, socketRoom); //SENDS MESSAGE TO SOCKET TO UPDATE CHILD ACCOUNT
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
@@ -189,14 +186,8 @@ function FamilyAddFundPopout({ action, situation, wallet, familyData }) {
<ModalCom action={action} situation={situation}>
<div className="relative logout-modal-wrapper lg:w-[500px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="modal-header-con">
<h1 className="modal-title">
Add Fund
</h1>
<button
type="button"
className="modal-close-btn"
onClick={action}
>
<h1 className="modal-title">Add Fund</h1>
<button type="button" className="modal-close-btn" onClick={action}>
<svg
width="36"
height="36"
@@ -94,7 +94,7 @@ export default function InputCom({
placeholder={placeholder}
value={value}
onChange={inputHandler}
className={`input-field placeholder:text-base text-dark-gray w-full h-full ${
className={`input-field placeholder:text-base text-dark-gray w-full h-full ${iconName && 'pr-6'} ${
inputBg && inputBg} tracking-wide focus:ring-0 focus:outline-none ${fieldClass}`}
type={type}
id={name}
+11 -12
View File
@@ -22,7 +22,6 @@ export default function FullAccountDash(props) {
className="mb-4"
data={userDetails}
bannerList={props.bannerList}
nextDueTask={props.nextDueTask}
/>
);
case "FAMILY_PARENT_DASH":
@@ -31,7 +30,6 @@ export default function FullAccountDash(props) {
className="mb-4"
data={userDetails}
bannerList={props.bannerList}
nextDueTask={props.nextDueTask}
/>
);
case "WORKER_HOME_DASH":
@@ -40,7 +38,6 @@ export default function FullAccountDash(props) {
className="mb-4"
data={userDetails}
bannerList={props.bannerList}
nextDueTask={props.nextDueTask}
/>
);
case "JOBOWNER_HOME_DASH":
@@ -49,7 +46,6 @@ export default function FullAccountDash(props) {
className="mb-4"
data={userDetails}
bannerList={props.bannerList}
nextDueTask={props.nextDueTask}
/>
);
default:
@@ -62,16 +58,19 @@ export default function FullAccountDash(props) {
<div className="home-page-wrapper">
{renderDashboard()}
{process.env.REACT_APP_SHOW_ACCOUNT_DASH == "1" && (
<AccountDashboard className="mb-4" bannerList={props.bannerList} />
<AccountDashboard className="mb-4" bannerList={props.bannerList} offersList={props.offersList} imageServer={props.imageServer} />
)}
{props?.dashTypes !== "undefined" &&
props.offersList?.data?.result_list?.length ? (
<MyOffersTable
MyActiveOffersList={props.offersList?.data}
className="mb-10"
/>
) : props.MyActiveJobList?.data?.length ? (
{
// props?.dashTypes !== "undefined" &&
// props.offersList?.data?.result_list?.length ? (
// <MyOffersTable
// MyActiveOffersList={props.offersList?.data}
// className="mb-10"
// />
// )
// :
props.MyActiveJobList?.data?.length ? (
<>
<div className="w-full mb-5 flex justify-between items-center gap-1">
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
+31 -32
View File
@@ -5,19 +5,16 @@ import usersService from "../../services/UsersService";
import { useSelector } from "react-redux";
import FamilyDash from "./FamilyDash";
import FullAccountDash from "./FullAccountDash";
import LoadingSpinner from '../../components/Spinners/LoadingSpinner'
export default function Home(props) {
// console.log("PROPS IN HOME->", props);
const userApi = new usersService();
const { commonHeadBanner } = useSelector((state) => state.commonHeadBanner);
let [nextDueTask, setNextDueTask] = useState({});
const [MyOffersList, setMyOffersList] = useState({loading: true, data: []});
const { userDetails } = useSelector((state) => state?.userDetails);
const [MyActiveJobList, setMyActiveJobList] = useState({loading:true, data:[]}); // STATE TO HOLD ACTIVE/CURRENT TASKS
// const [MyActiveJobList, setMyActiveJobList] = useState([]); // STATE TO HOLD ACTIVE/CURRENT TASKS
const getMyActiveJobList = async () => { // FUNCTION TO POPULATE ACTIVE/CURRENT TASK LIST
try {
@@ -32,41 +29,41 @@ export default function Home(props) {
};
// FUNCTION TO GET DASH DATA TO DETERMINE CURRENT TASK DUE TIME
const getHomeDate = () => {
userApi
.getHomeDate()
.then((res) => {
if (res.status != 200 || res.internal_return < 0) {
return;
}
setNextDueTask(res.data);
})
.catch((error) => {
console.log(error);
});
};
// const getHomeDate = () => {
// userApi
// .getHomeDate()
// .then((res) => {
// if (res.status != 200 || res.internal_return < 0) {
// return;
// }
// setNextDueTask(res.data);
// })
// .catch((error) => {
// console.log(error);
// });
// };
const getMyOffersList = async () => {
try {
const res = await userApi.getOffersList();
setMyOffersList({loading:false, data:res.data});
} catch (error) {
setMyOffersList({loading:false, data:[]});
console.log("Error getting offers", error);
}
};
// const getMyOffersList = async () => {
// try {
// const res = await userApi.getOffersList();
// setMyOffersList({loading:false, data:res.data});
// } catch (error) {
// setMyOffersList({loading:false, data:[]});
// console.log("Error getting offers", error);
// }
// };
useEffect(() => {
const fetchData = async () => {
await Promise.all([getHomeDate(), getMyOffersList(), getMyActiveJobList()]);
};
if(userDetails?.account_type == 'FULL'){
fetchData();
getMyActiveJobList();
}
}, []);
return (
<Layout>
{Object.keys(commonHeadBanner).length < 1 ?
<LoadingSpinner height='h-48' size='16' />
:
<div className="w-full">
{userDetails && userDetails?.account_type == "FAMILY" ? (
<FamilyDash
@@ -78,11 +75,12 @@ export default function Home(props) {
/>
) : userDetails && userDetails?.account_type == "FULL" ? (
<FullAccountDash
nextDueTask={nextDueTask}
bannerList={props.bannerList}
dashTypes={props.dashTypes}
offersList={MyOffersList}
// offersList={MyOffersList}
MyActiveJobList={MyActiveJobList}
offersList={props.offersList}
imageServer={props.imageServer}
/>
) : (
<div>
@@ -90,6 +88,7 @@ export default function Home(props) {
</div>
)}
</div>
}
</Layout>
);
}
+264 -235
View File
@@ -1,254 +1,283 @@
import React, {useEffect, useState} from 'react'
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import React, { useEffect, useState } from "react";
import usersService from "../../../services/UsersService";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
export default function LockJob({
details,
marketPlaceProduct,
ManageInterest,
manageInt,
handleInputChange,
MarketDetail,
marketMsg,
errMsg,
textValue,
}) {
const apiCall = new usersService();
export default function LockJob({details, marketPlaceProduct, ManageInterest, manageInt, handleInputChange, MarketDetail, marketMsg, errMsg, textValue}) {
const apiCall = new usersService()
const [completedTask, setCompletedTask] = useState({
loading: true,
data: [],
});
const [completedTask, setCompletedTask] = useState({
loading: true,
data: []
})
let thePrice = PriceFormatter(
details?.price * 0.01,
details?.currency_code,
details?.currency
);
let thePrice = PriceFormatter(
details?.price * 0.01,
details?.currency_code,
details?.currency
);
let cleanedText = details?.job_description
?.replace(/&lt;/g, "<")
.replace(/&gt;/g, ">")
.replace(/&quot;/g, '"')
.replace(/&amp;/g, "&");
let cleanedText = details?.job_description
?.replace(/&lt;/g, "<")
.replace(/&gt;/g, ">")
.replace(/&quot;/g, '"')
.replace(/&amp;/g, "&");
let dependOn = marketPlaceProduct?.filter(
(item) => item?.job_uid == details?.offer_depend_uid
)[0];
let dependOn = marketPlaceProduct?.filter(item => item?.job_uid == details?.offer_depend_uid)[0]
useEffect(() => {
apiCall
.getVerifyCompletedTask({ offer_depend_uid: details?.offer_depend_uid })
.then((res) => {
console.log("RES", res.data);
setCompletedTask({ loading: false, data: res?.data?.result_list });
})
.catch((err) => {
setCompletedTask({ loading: false, data: [] });
});
}, []);
useEffect(()=>{
apiCall.getVerifyCompletedTask({offer_depend_uid:details?.offer_depend_uid}).then(res => {
console.log('RES', res.data)
setCompletedTask({loading:false, data:res?.data?.result_list})
}).catch(err =>{
setCompletedTask({loading:false, data:[]})
})
},[])
return (
return (
<>
{completedTask.loading ? (
<div className="w-full md:col-span-4 flex justify-center items-center min-h-[500px]">
<LoadingSpinner size="10" />
</div>
) : (
<>
{completedTask.loading ?
<div className='w-full md:col-span-4 flex justify-center items-center min-h-[500px]'>
<LoadingSpinner
size='10'
/>
<div className="px-4 py-2 w-full md:col-span-3 md:border-r-1">
<div className="min-h-[200px]">
<h2 className="w-full flex gap-1 items-center font-semibold text-slate-900 dark:text-white tracking-wide">
{details?.offer_depend_uid && (
<i className="fa-solid fa-lock p-1 text-red-500 text-[12px]"></i>
)}
{details?.title}
</h2>
{/* INPUT SECTION */}
{[
{
name: "Description",
content: details.description,
},
{
name: "",
content: {
text: `Timeline: ${details.timeline_days} day(s) -- `,
bold: `Budget: ${thePrice}`,
},
},
// {
// name: "Delivery Detail",
// content: cleanedText,
// danger: true,
// },
].map(({ name, content, danger }, idx) => (
<div className={`my-1 flex flex-col items-start`} key={idx}>
<label className="py-1 job-label w-full">{name}</label>
<div
className={`w-full p-2 text-slate-900 dark:text-white market-pop rounded-2xl ${
name == "Description"
? "min-h-[100px] max-h-[100px] h-full overflow-y-auto break-words bg-slate-50"
: name == "Delivery Detail"
? " overflow-y-auto h-full min-h-[100px] max-h-[100px] bg-slate-50"
: "h-full flex items-center"
}`}
>
{danger ? (
<p
className={`dark:text-black`}
dangerouslySetInnerHTML={{
__html: danger && content,
}}
/>
) : (
<p className={`w-full text-slate-900 dark:text-black`}>
{name !== "Delivery Detail" ? (
<>
{typeof content !== "object" ? content : null}
{typeof content === "object" && (
<>
{/* <hr className="mb-1" /> */}
<span className="flex w-full mb-1 h-[1px] bg-slate-500"></span>
<span className="flex items-center gap-2 dark:text-white">
{content?.text}
<strong>{thePrice}</strong>
</span>
<span className="flex w-full mt-1 h-[1px] bg-slate-500"></span>
{/* <hr className="mt-1" /> */}
</>
)}
</>
) : (
""
)}
</p>
)}
</div>
</div>
))}
</div>
:
<>
<div className="px-4 py-2 w-full md:col-span-3 md:border-r-1">
<div className="min-h-[200px]">
<h2 className="w-full flex gap-1 items-center font-semibold text-slate-900 dark:text-white tracking-wide">
{details?.offer_depend_uid && <i className="fa-solid fa-lock p-1 text-red-500 text-[12px]"></i>}
{details?.title}
</h2>
{/* INPUT SECTION */}
{[
{
name: "Description",
content: details.description,
},
{
name: "",
content: {
text: `Timeline: ${details.timeline_days} day(s) -- `,
bold: `Budget: ${thePrice}`,
},
},
// {
// name: "Delivery Detail",
// content: cleanedText,
// danger: true,
// },
].map(({ name, content, danger }, idx) => (
<div className={`my-1 flex flex-col items-start`} key={idx}>
<label className="py-1 job-label w-full">
{name}
</label>
<div
className={`w-full p-2 text-slate-900 dark:text-white market-pop rounded-2xl ${
name == "Description"
? "min-h-[100px] max-h-[100px] h-full overflow-y-auto break-words bg-slate-50"
: name == "Delivery Detail" ? " overflow-y-auto h-full min-h-[100px] max-h-[100px] bg-slate-50"
: "h-full flex items-center"
}`}
>
{danger ? (
<p
className={`dark:text-black`}
dangerouslySetInnerHTML={{
__html: danger && content,
}}
/>
) : (
<p className={`w-full text-slate-900 dark:text-black`}>
{name !== "Delivery Detail" ? (
<>
{typeof content !== "object" ? content : null}
{typeof content === "object" && (
<>
{/* <hr className="mb-1" /> */}
<span className='flex w-full mb-1 h-[1px] bg-slate-500'></span>
<span className="flex items-center gap-2 dark:text-white">
{content?.text}
<strong>{thePrice}</strong>
</span>
<span className='flex w-full mt-1 h-[1px] bg-slate-500'></span>
{/* <hr className="mt-1" /> */}
</>
)}
</>
) : (
""
)}
</p>
)}
</div>
</div>
))}
</div>
{/* <hr className='my-3' /> */}
{completedTask.loading ?
<p className='py-3 w-full text-center text-lg'>Loading...</p>
:completedTask?.data?.filter(item => item?.job_uid == details.offer_depend_uid).length > 0 ?
<div className='w-full'>
<label className="job-label w-full flex gap-2 items-center">
If you have any questions about this task:
<span className={`text-sm ${marketMsg.state ? 'text-[#57cd89]' : 'text-red-500'}`}>
{marketMsg.state && "Message Sent!"}
{errMsg.market && "Failed to send"}
</span>
</label>
<div className="w-full flex items-center gap-3">
<div className="w-full">
<textarea
className={`p-1 w-full text-sm text-slate-900 dark:text-white ${
marketMsg.loading && "italic text-[#9CA3AF]"
} bg-transparent outline-none border-2 border-slate-300 rounded-md`}
rows="3"
style={{ resize: "none" }}
placeholder="Enter message here ..."
value={marketMsg.loading ? "Sending..." : textValue}
onChange={handleInputChange}
/>
</div>
<div className="relative flex flex-col">
<button
className="rounded-full flex justify-center items-center w-12 h-11 bg-yellow-500 text-white"
name="market-message"
onClick={MarketDetail}
disabled={marketMsg.loading}
>
{marketMsg.loading ? (
<LoadingSpinner size={5} color="white" />
) : (
// "Send Message"
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 11 20"
id="Arrow"
className="w-[0.7rem]"
>
<path
fillRule="evenodd"
d="M.366 19.708c.405.39 1.06.39 1.464 0l8.563-8.264a1.95 1.95 0 0 0 0-2.827L1.768.292A1.063 1.063 0 0 0 .314.282a.976.976 0 0 0-.011 1.425l7.894 7.617a.975.975 0 0 1 0 1.414L.366 18.295a.974.974 0 0 0 0 1.413"
// fill=""
className="color000000 svgShape fill-[#fff]"
></path>
</svg>
)}
</button>
</div>
</div>
</div>
:
<div className='w-full'>
<h1 className='text-red-600 text-lg'>This task depends on the task below</h1>
<div className='rounded-2xl bg-red-50'>
<div className='my-1 w-full'>
<h2 className="p-2 w-full flex gap-1 items-center font-semibold text-slate-900 dark:text-black tracking-wide">
{dependOn?.offer_depend_uid && <i className="fa-solid fa-lock p-1 text-red-500 text-[12px]"></i>}
{dependOn?.title}
</h2>
</div>
<div className={`p-2 flex flex-col items-start`}>
<p className="py-1 job-label w-full dark:text-black">Description</p>
<div className={`w-full p-2 text-slate-900 dark:text-black market-pop rounded-2xl bg-white break-words min-h-[100px] max-h-[100px]`}>
{dependOn?.description}
</div>
</div>
</div>
</div>
}
</div>
<div className="py-2 w-full md:col-span-1 h-full flex flex-col rounded-2xl">
<div className="mx-auto bg-[#f1f8ff] dark:bg-[#C2C8D3] px-4 rounded-md w-full h-full md:min-h-[420px] flex flex-col justify-between">
<div className="w-full flex flex-col justify-center pb-4 gap-2">
<p className="job-label w-full">
Interested?
</p>
<hr />
{completedTask.loading ?
<p className='py-3 w-full text-center text-lg'>Loading...</p>
:completedTask?.data?.filter(item => item?.job_uid == details.offer_depend_uid).length > 0 ?
{/* <hr className='my-3' /> */}
{completedTask.loading ? (
<p className="py-3 w-full text-center text-lg">Loading...</p>
) : completedTask?.data?.filter(
(item) => item?.job_uid == details.offer_depend_uid
).length > 0 ? (
<div className="w-full">
<label className="job-label w-full flex gap-2 items-center">
If you have any questions about this task:
<span
className={`text-sm ${
marketMsg.state ? "text-[#57cd89]" : "text-red-500"
}`}
>
{marketMsg.state && "Message Sent!"}
{errMsg.market && "Failed to send"}
</span>
</label>
<div className="w-full flex items-center gap-3">
<div className="w-full">
<textarea
className={`p-1 w-full text-sm text-slate-900 dark:text-white ${
marketMsg.loading && "italic text-[#9CA3AF]"
} bg-transparent outline-none border-2 border-slate-300 rounded-md`}
rows="3"
style={{ resize: "none" }}
placeholder="Enter message here ..."
value={marketMsg.loading ? "Sending..." : textValue}
onChange={handleInputChange}
/>
</div>
<div className="relative flex flex-col">
<button
className="btn-gradient text-white px-2 py-2 border-4 border-slate-300 text-lg lg:text-xl font-medium rounded-2xl"
name="market-interest"
onClick={ManageInterest}
className="rounded-full flex justify-center items-center w-12 h-11 bg-yellow-500 text-white"
name="market-message"
onClick={MarketDetail}
disabled={marketMsg.loading}
>
{" "}
<div className="flex md:flex-col justify-center gap-2">
<span>Notify</span>
<span>Owner</span>
</div>
{marketMsg.loading ? (
<LoadingSpinner size={5} color="white" />
) : (
// "Send Message"
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 11 20"
id="Arrow"
className="w-[0.7rem]"
>
<path
fillRule="evenodd"
d="M.366 19.708c.405.39 1.06.39 1.464 0l8.563-8.264a1.95 1.95 0 0 0 0-2.827L1.768.292A1.063 1.063 0 0 0 .314.282a.976.976 0 0 0-.011 1.425l7.894 7.617a.975.975 0 0 1 0 1.414L.366 18.295a.974.974 0 0 0 0 1.413"
// fill=""
className="color000000 svgShape fill-[#fff]"
></path>
</svg>
)}
</button>
:
<h1 className='text-red-600 text-base font-bold'>This task depends on completion of another task</h1>
}
<>
{manageInt.loading ? (
<p className="text-sm italic">please wait...</p>
) : (
<>
{manageInt?.msg !== "" && (
<p
className={`text-sm italic ${
manageInt?.state ? "text-green-500" : "text-red-500"
}`}
>
{manageInt?.msg}
</p>
)}
</>
)}
</>
</div>
</div>
</div>
) : (
<div className="w-full">
<h1 className="text-red-600 text-lg">
This task depends on the task below
</h1>
<div className="rounded-2xl bg-red-50">
<div className="my-1 w-full">
<h2 className="p-2 w-full flex gap-1 items-center font-semibold text-slate-900 dark:text-black tracking-wide">
{dependOn?.offer_depend_uid && (
<i className="fa-solid fa-lock p-1 text-red-500 text-[12px]"></i>
)}
{dependOn?.title}
</h2>
</div>
<div className={`p-2 flex flex-col items-start`}>
<p className="py-1 job-label w-full dark:text-black">
Description
</p>
<div
className={`w-full p-2 text-slate-900 dark:text-black market-pop rounded-2xl bg-white break-words min-h-[100px] max-h-[100px]`}
>
{dependOn?.description}
</div>
</div>
</div>
</div>
)}
</div>
<div className="text-slate-900">
<p className="flex items-center tracking-wide">
<span className="job-label">Interest: </span> <b className="ml-1">{details.interest_count}</b>
</p>
<hr />
<p className="my-1 flex flex-col">
<span className="job-label">Expire: </span>
<span> {new Date(details.expire).toLocaleString()} </span>
</p>
<div className="py-2 w-full md:col-span-1 h-full flex flex-col rounded-2xl">
<div className="mx-auto bg-[#f1f8ff] dark:bg-[#C2C8D3] px-4 rounded-md w-full h-full md:min-h-[420px] flex flex-col justify-between">
<div className="w-full flex flex-col justify-center pb-4 gap-2">
<p className="job-label w-full">Interested?</p>
<hr />
{completedTask.loading ? (
<p className="py-3 w-full text-center text-lg">Loading...</p>
) : completedTask?.data?.filter(
(item) => item?.job_uid == details.offer_depend_uid
).length > 0 ? (
<button
className="btn-gradient text-white px-2 py-2 border-4 border-slate-300 text-lg lg:text-xl font-medium rounded-2xl"
name="market-interest"
onClick={ManageInterest}
>
{" "}
<div className="flex md:flex-col justify-center gap-2">
<span>Notify</span>
<span>Owner</span>
</div>
</div>
</div>
</>
}
</button>
) : (
<h1 className="text-red-600 text-base font-bold">
This task depends on completion of another task
</h1>
)}
<>
{manageInt.loading ? (
<p className="text-sm italic">please wait...</p>
) : (
<>
{manageInt?.msg !== "" && (
<p
className={`text-sm italic ${
manageInt?.state ? "text-green-500" : "text-red-500"
}`}
>
{manageInt?.msg}
</p>
)}
</>
)}
</>
</div>
<div className="text-slate-900">
<p className="flex items-center tracking-wide">
<span className="job-label">Interest: </span>{" "}
<b className="ml-1">{details.interest_count}</b>
</p>
<hr />
<p className="my-1 flex flex-col">
<span className="job-label">Expire: </span>
<span> {new Date(details.expire).toLocaleString()} </span>
</p>
</div>
</div>
</div>
</>
)
)}
</>
);
}
@@ -1,4 +1,5 @@
import { useEffect, useMemo, useState } from "react";
import { useSelector } from "react-redux";
import { toast } from "react-toastify";
import usersService from "../../../services/UsersService";
import ModalCom from "../../Helpers/ModalCom";
@@ -9,6 +10,11 @@ import LockJob from "./LockJob";
const MarketPopUp = ({ details, onClose, situation, marketInt, marketPlaceProduct }) => {
let { jobLists } = useSelector((state) => state.jobLists);
const interestCount = jobLists?.interest_list?.filter(item => item.job_uid == details.job_uid);
// console.log('interestList', interest_count)
// console.log('MEMO', jobLists?.interest_list, datas.job_uid)
let {sendJobInterestToOwner} = SocketValues() // function to emit job interest request
const emitOfferInterest = () => {
let message = {
@@ -326,7 +332,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt, marketPlaceProduc
<div className="text-slate-900">
<p className="flex items-center tracking-wide">
<span className="job-label">Interest: </span> <b className="ml-1">{details.interest_count}</b>
<span className="job-label">Interest: </span> <b className="ml-1">{interestCount.length > 0 ? interestCount[0].interest_count : '0'}</b>
</p>
<hr />
<p className="my-1 flex flex-col">
+1 -1
View File
@@ -364,7 +364,7 @@ function ActiveJobs(props) {
<div className="my-1 text-base text-slate-700 tracking-wide flex items-center gap-3">
<span className="font-semibold text-black dark:text-white">
Price:{" "}
Reward:{" "}
</span>
<span className="">{thePrice}</span>
</div>
@@ -68,7 +68,7 @@ export default function MyActiveJobTable({ MyJobList, className }) {
</h1>
<div>{value.description}</div>
<span className="text-sm text-thin-light-gray flex flext-start gap-1">
Price:{" "}
Reward:{" "}
<span className="text-purple">
{thePrice}
</span>
@@ -68,7 +68,7 @@ export default function MyPastDueTaskTable({ MyJobList, className }) {
</h1>
<div>{value.description}</div>
<span className="text-sm text-thin-light-gray flex flext-start gap-1">
Price:{" "}
Reward:{" "}
<span className="text-purple">
{thePrice}
</span>
+1 -1
View File
@@ -277,7 +277,7 @@ function myJobTableFeatures(
</h1>
<div>{value.description}</div>
<span className="text-sm text-thin-light-gray flex items-start gap-1">
Price: <span className="text-purple">{thePrice}</span>
Reward: <span className="text-purple">{thePrice}</span>
</span>
<span className="text-sm text-thin-light-gray">
Duration:{" "}
@@ -69,7 +69,7 @@ export default function MyPendingJobTable({ MyJobList, className }) {
</h1>
<div>{value.description}</div>
<span className="text-sm text-thin-light-gray flex items-start gap-1">
Price:{" "}
Reward:{" "}
<span className="text-purple">
{thePrice}
</span>
+1 -1
View File
@@ -94,7 +94,7 @@ export default function MyJobTable({ className, ActiveJobList, Account, imageSer
{task?.description}
</span>
<span className="text-sm text-thin-light-gray flex flext-start gap-1">
Price:
Reward:
<span className="text-purple ml-1">{thePrice}</span>
</span>
<div className="flex flex-col sm:flex-row items-start gap-1 md:gap-4 md:items-center">
@@ -65,7 +65,7 @@ export default function MyWaitingJobTable({ MyJobList, className }) {
</h1>
<div>{value.description}</div>
<span className="text-sm text-thin-light-gray flex items-start gap-1">
Price:{" "}
Reward:{" "}
<span className="text-purple">
{thePrice}
</span>
+66 -53
View File
@@ -1,12 +1,7 @@
import { useSelector } from "react-redux";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import WalletItemCard from "./WalletItemCard";
import WalletItemCardFamily from "./WalletItemCardFamily";
import { useEffect, useState } from "react";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import SearchCom from "../Helpers/SearchCom";
import { localImgLoad } from "../../lib";
import background from "../../assets/images/bg-sky-blue.jpg";
import { localImgLoad } from "../../lib";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import FamilyWalletRedeemOptions from "./FamilyWalletRedeemOptions";
/**
@@ -14,29 +9,32 @@ import FamilyWalletRedeemOptions from "./FamilyWalletRedeemOptions";
*/
export default function FamilyWalletBox({ wallet, payment }) {
// const { loading, data } = wallet;
// const { userDetails } = useSelector((state) => state.userDetails);
// const accountType = userDetails?.account_type === "FAMILY";
const [selectedWallet, setSelectedWallet] = useState('')
const [activeWalletBtn, setActiveWalletBtn] = useState('')
const handleChangeWallet = ({target:{name}}) => { // FUNCTION TO SWITCH WALLET IF USER HAS MORE THAN TWO WALLETS
const currentWalletSelected = wallet?.data?.filter((item) => item.code == name);
setSelectedWallet(currentWalletSelected[0])
setActiveWalletBtn(name)
const [selectedWallet, setSelectedWallet] = useState("");
const [activeWalletBtn, setActiveWalletBtn] = useState("");
const handleChangeWallet = ({ target: { name } }) => {
// FUNCTION TO SWITCH WALLET IF USER HAS MORE THAN TWO WALLETS
const currentWalletSelected = wallet?.data?.filter(
(item) => item.code == name
);
setSelectedWallet(currentWalletSelected[0]);
setActiveWalletBtn(name);
// console.log(name, currentWalletSelected)
}
};
const image = selectedWallet?.code
? `${selectedWallet?.code.toLowerCase()}.svg`
: "default.png";
? `${selectedWallet?.code.toLowerCase()}.svg`
: "default.png";
useEffect(()=>{
setSelectedWallet(wallet.data[0])
setActiveWalletBtn(wallet?.data[0]?.code)
},[wallet])
useEffect(() => {
setSelectedWallet(wallet.data[0]);
setActiveWalletBtn(wallet?.data[0]?.code);
}, [wallet]);
return (
<div className="w-full">
@@ -44,31 +42,38 @@ export default function FamilyWalletBox({ wallet, payment }) {
<div className="main-wrapper w-full mb-10">
<div className="w-full mb-10 sm:grid grid-cols-2 gap-4">
<div className="w-full mb-4 sm:mb-0 rounded-2xl bg-white dark:bg-dark-white overflow-hidden">
{wallet?.loading ?
{wallet?.loading ? (
<div className="w-full h-full flex items-center justify-center bg-white">
<LoadingSpinner size="16" color="sky-blue" height='min-h-[240px]' />
<LoadingSpinner
size="16"
color="sky-blue"
height="min-h-[240px]"
/>
</div>
: wallet?.data.length > 0 ?
) : wallet?.data.length > 0 ? (
<>
{wallet?.data?.length > 1 &&
<div className="wal-selection px-5 py-2 text-black dark:text-white flex items-center gap-2">
{wallet?.data?.map(item =>(
<button
className={`py-0.5 px-1 mb-1 rounded-lg border border-orange-500 ${activeWalletBtn == item?.code && 'bg-orange-500'}`}
key={item?.wallet_uid}
name={item?.code}
onClick={handleChangeWallet}
>
{item?.description}
</button>
))}
</div>
}
<div className="p-5 bg-white-opacity min-h-[240px]"
style={{
background: `url(${background}) 0% 0% / cover no-repeat`,
}}
>
{wallet?.data?.length > 1 && (
<div className="wal-selection px-5 py-2 text-black dark:text-white flex items-center gap-2">
{wallet?.data?.map((item) => (
<button
className={`py-0.5 px-1 mb-1 rounded-lg border border-orange-500 ${
activeWalletBtn == item?.code && "bg-orange-500"
}`}
key={item?.wallet_uid}
name={item?.code}
onClick={handleChangeWallet}
>
{item?.description}
</button>
))}
</div>
)}
<div
className="p-5 bg-white-opacity min-h-[240px]"
style={{
background: `url(${background}) 0% 0% / cover no-repeat`,
}}
>
{/* image */}
<div className="min-w-[100px] min-h-[100px] max-w-min md:max-w-[100px] max-h-min md:max-h-[100px] rounded-full bg-[#e3e3e3] flex justify-center items-center">
<img
@@ -77,21 +82,30 @@ export default function FamilyWalletBox({ wallet, payment }) {
alt="currency-icon"
/>
</div>
<p className="text-base sm:text-lg text-white opacity-[70%] tracking-wide my-3">Current Balance</p>
<p className="text-base sm:text-lg text-white opacity-[70%] tracking-wide my-3">
Current Balance
</p>
<p className="text-[44px] lg:text-[62px] font-bold text-white tracking-wide leading-10">
{PriceFormatter(selectedWallet?.amount/100, selectedWallet?.code, undefined, "text-[2rem]")}
{Formatter(
selectedWallet?.amount / 100,
selectedWallet?.code,
undefined,
"text-[2rem]"
)}
</p>
</div>
</>
:
) : (
<div className="w-full h-full flex justify-center items-center rounded-2xl bg-white">
<p>No Wallet Record Found</p>
</div>
}
)}
</div>
<div className="p-5 w-full rounded-2xl bg-white dark:bg-dark-white text-black dark:text-white h-full min-h-[240px] max-h-96">
<h1 className="text-xl font-bold text-black dark:text-white">
Recent Activities
</h1>
</div>
<div className="p-5 w-full rounded-2xl bg-white dark:bg-dark-white text-black dark:text-white h-full min-h-[240px] max-h-96">
<h1 className="text-xl font-bold text-black dark:text-white">Recent Activities</h1>
</div>
</div>
</div>
<div className="w-full">
@@ -102,7 +116,6 @@ export default function FamilyWalletBox({ wallet, payment }) {
);
}
// data.length>0 && data.map((item) => (
// <div key={item.wallet_uid} className="w-full h-full mb-10 ">
// {/* <WalletItemCardFamily walletItem={item} payment={payment} countries={countries} /> */}
@@ -126,8 +126,8 @@ export default function OffersInterestTable({offerInterestList, className}) {
)
:
(
<div className="font-bold text-center text-xl md:text-2xl lg:text-4xl text-dark-gray md:flex items-center justify-between">
<p className="mb-4 p-3">No list avaliable.</p>
<div className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<p className="p-2">No list avaliable.</p>
</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>
</>
);
}
+1 -1
View File
@@ -119,7 +119,7 @@ function DeleteJobPopout({ details, onClose, situation }) {
{details.title}
</p>
<p className="text-lg tracking-wide text-dark-gray dark:text-white flex items-start gap-1">
<span className="job-label">Price: </span>{details.thePrice}
<span className="job-label">Reward: </span>{details.thePrice}
</p>
<p className="text-lg tracking-wide text-dark-gray dark:text-white">
<span className="job-label">Duration: </span>{details.timeline_days} day(s)
+1 -1
View File
@@ -273,7 +273,7 @@ const EditJobPopOut = ({
<div className="field w-full">
<InputCom
fieldClass="px-6 text-right"
label="Price"
label="Reward"
labelClass="tracking-wide"
inputBg="bg-slate-100"
inputClass="input-curve lg border border-light-purple"
@@ -274,7 +274,7 @@ const EditJobPopoutNew = ({
<div className="field w-full mb-[0.5rem] sm:mb-0">
<InputCom
fieldClass="px-6 text-right"
label="Price"
label="Reward"
labelClass="tracking-wide"
inputBg="bg-slate-100"
inputClass="input-curve lg border border-light-purple"
@@ -186,7 +186,7 @@ function FamilyOfferJobPopout({ details, onClose, situation }) {
</div>
<div className="my-2 md:flex">
<Detail label="Price" value={details.thePrice} />
<Detail label="Reward" value={details.thePrice} />
</div>
<div className="my-2 md:flex">
+1 -1
View File
@@ -263,7 +263,7 @@ function JobListPopout({
const DetailsComponent = () => {
const detailsArray = [
{ label: "Description", value: details.description },
{ label: "Price", value: details.thePrice },
{ label: "Reward", value: details.thePrice },
{ label: "Timeline", value: `${details.timeline_days} day(s)` },
{ label: "Created", value: new Date(details?.created).toDateString() },
];
@@ -246,7 +246,7 @@ function NewJobListPopout({
const DetailsComponent = () => {
const detailsArray = [
{ label: "Description", value: details.description },
{ label: "Price", value: details.thePrice },
{ label: "Reward", value: details.thePrice },
{ label: "Timeline", value: `${details.timeline_days} day(s)` },
{ label: "Created", value: new Date(details?.created).toDateString() },
];
@@ -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
}
+1 -1
View File
@@ -162,7 +162,7 @@ function OfferJobPopout({ details, onClose, situation }) {
</div>
<div className="my-2 md:flex">
<Detail label="Price" value={details.thePrice} />
<Detail label="Reward" value={details.thePrice} />
</div>
<div className="my-2 md:flex">
+5 -12
View File
@@ -3,13 +3,12 @@ import { useNavigate } from "react-router-dom";
import { toast } from "react-toastify";
import usersService from "../../services/UsersService";
import ModalCom from "../Helpers/ModalCom";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import Detail from "./popoutcomponent/Detail";
import { useDispatch } from "react-redux";
import { tableReload } from "../../store/TableReloads";
import { NewDateTimeFormatter } from "../../lib/NewDateTimeFormatter";
import { tableReload } from "../../store/TableReloads";
const showSuccessToast = (message) => {
toast.success(message, {
@@ -73,7 +72,7 @@ function PendingJobsPopout({ details, onClose, situation }) {
setRequestMessage({ status: true, message: res.data.status });
dispatch(tableReload({ type: "PENDINGTABLE" }));
setTimeout(() => {
onClose()
onClose();
setPendingJobLoader({ extend: false, offer: false });
setRequestMessage({ status: false, message: "" });
}, 4000);
@@ -140,14 +139,8 @@ function PendingJobsPopout({ details, onClose, situation }) {
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper w-[90%] md:w-[768px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="modal-header-con">
<h1 className="modal-title">
Manage Pending Item
</h1>
<button
type="button"
className="modal-close-btn"
onClick={onClose}
>
<h1 className="modal-title">Manage Pending Item</h1>
<button type="button" className="modal-close-btn" onClick={onClose}>
<svg
width="36"
height="36"
@@ -214,7 +207,7 @@ function PendingJobsPopout({ details, onClose, situation }) {
<div className="my-2 md:flex">
<Detail
label="Price"
label="Reward"
// value={`${details.price * 0.01} ${details.currency}`}
value={PriceFormatter(
details.price * 0.01,
@@ -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)
+2
View File
@@ -7,6 +7,8 @@ export default function HomePages() {
const bannerOptions = {
bannerList: commonHeadBanner?.result_list,
dashTypes: commonHeadBanner?.home_dash_type,
offersList: commonHeadBanner?.offers_list,
imageServer: commonHeadBanner?.session_image_server
};
return (
+10
View File
@@ -0,0 +1,10 @@
import React from 'react'
import Promo from '../components/AuthPages/Promo/Promo'
export default function PromoPage() {
return (
<>
<Promo />
</>
)
}