Compare commits

...

32 Commits

Author SHA1 Message Date
victorAnumudu b6ab3a6ee7 added new section to family acct dashboard 2024-02-19 14:09:20 +01:00
ameye f968cc5a50 Merge branch 'home-banners-dashboard' of WrenchBoard/Users-Wrench into master 2024-02-17 16:41:08 +00:00
Ebube 1ddb2fd903 remove mypage component from family 2024-02-17 16:27:09 +01:00
ameye 70f6ac4e24 Merge branch 'failedtopup-alert' of WrenchBoard/Users-Wrench into master 2024-02-15 18:50:06 +00:00
victorAnumudu 3d30481852 displays failed popout box for failed top up transaction 2024-02-15 13:49:05 +01:00
ameye 63c0b07f61 Merge branch 'home-banners-dashboard' of WrenchBoard/Users-Wrench into master 2024-02-03 23:31:58 +00:00
ameye 60568c42e8 Merge branch 'number-fix' of WrenchBoard/Users-Wrench into master 2024-02-03 23:31:51 +00:00
Ebube 77ac52820d added the email and offed the autocomplete attr for the component 2024-02-04 00:29:09 +01:00
victorAnumudu 240e075305 assign offer message updated 2024-02-03 22:49:15 +01:00
victorAnumudu bea41d8181 group count fixed 2024-02-03 22:09:25 +01:00
ameye 6268d68b67 Merge branch 'home-banners-dashboard' of WrenchBoard/Users-Wrench into master 2024-02-03 20:31:19 +00:00
Ebube f96b16b373 Added the number identifier for job list 2024-02-03 21:18:49 +01:00
ameye 9fb6a4db86 Merge branch 'download-app-links' of WrenchBoard/Users-Wrench into master 2024-02-02 11:26:36 +00:00
victorAnumudu 1aa3c79666 added download app links to signup page 2024-02-02 09:42:51 +01:00
ameye ecc2360dc4 Merge branch 'app-download-link' of WrenchBoard/Users-Wrench into master 2024-02-01 20:49:27 +00:00
victorAnumudu ca9bb1c211 changed class to classname 2024-02-01 19:43:36 +01:00
victorAnumudu 2f756d189a added app download links on login page 2024-02-01 19:34:01 +01:00
ameye d7acea769c Merge branch 'home-banners-dashboard' of WrenchBoard/Users-Wrench into master 2024-01-30 17:58:31 +00:00
Ebube 7ff5e2b6e0 . 2024-01-30 17:10:39 +01:00
Ebube 2f90c4a6c2 Different dashboards for Home Banner 2024-01-30 17:10:30 +01:00
ameye 29e0345e1c Merge branch 'Jobs-Manager-Side' of WrenchBoard/Users-Wrench into master 2024-01-27 00:26:56 +00:00
Ebube 129cdc8cba Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into Jobs-Manager-Side 2024-01-26 19:17:58 +01:00
Ebube 9d42ebebab added sidebar menu 2024-01-26 19:17:28 +01:00
ameye 6193f0b492 Merge branch 'Jobs-Manager-Side' of WrenchBoard/Users-Wrench into master 2024-01-26 18:03:56 +00:00
Ebube 1d86465812 Changed my pending jobs to offers and changed its routes 2024-01-26 17:44:24 +01:00
CHIEFSOFT\ameye 7a6f43ad20 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench 2024-01-26 10:31:56 -05:00
CHIEFSOFT\ameye 37b94a68ca new layout 2024-01-26 10:31:45 -05:00
ameye a1b63c5d0c Merge branch 'Jobs-Manager-Side' of WrenchBoard/Users-Wrench into master 2024-01-26 14:49:22 +00:00
Ebube e5162a2aaf refactored some things 2024-01-26 01:46:56 +01:00
Ebube 6ee9c7e7d8 added .toFixed(2)} 2024-01-26 01:08:07 +01:00
Ebube 5928ddb3c1 added the popup component 2024-01-26 01:07:20 +01:00
ameye 06c1e339b1 Merge branch 'login-box-fix' of WrenchBoard/Users-Wrench into master 2024-01-25 22:18:49 +00:00
42 changed files with 1220 additions and 454 deletions
+5 -1
View File
@@ -98,4 +98,8 @@ REACT_APP_FAMILY_MINIMUM_AGE=4
REACT_APP_FAMILY_MAXIMUM_AGE=18
#CHANGE LOGIN LAYOUT
REACT_APP_NEW_LOGIN_LAYOUT=1
REACT_APP_NEW_LOGIN_LAYOUT=1
#APP DOWNLOAD LINKS
REACT_APP_ANDROID_APP='https://play.google.com/store/apps/details?id=com.wrenchboard.users'
REACT_APP_APPLE_APP='https://itunes.apple.com/us/app/wrenchboard/id1435718367?ls=1&mt=8'
+5 -1
View File
@@ -66,4 +66,8 @@ REACT_APP_FAMILY_MINIMUM_AGE=4
REACT_APP_FAMILY_MAXIMUM_AGE=18
#CHANGE LOGIN LAYOUT
REACT_APP_NEW_LOGIN_LAYOUT=1
REACT_APP_NEW_LOGIN_LAYOUT=1
#APP DOWNLOAD LINKS
REACT_APP_ANDROID_APP='https://play.google.com/store/apps/details?id=com.wrenchboard.users'
REACT_APP_APPLE_APP='https://itunes.apple.com/us/app/wrenchboard/id1435718367?ls=1&mt=8'
+5 -1
View File
@@ -72,4 +72,8 @@ REACT_APP_FAMILY_MINIMUM_AGE=4
REACT_APP_FAMILY_MAXIMUM_AGE=18
#CHANGE LOGIN LAYOUT
REACT_APP_NEW_LOGIN_LAYOUT=0
REACT_APP_NEW_LOGIN_LAYOUT=1
#APP DOWNLOAD LINKS
REACT_APP_ANDROID_APP='https://play.google.com/store/apps/details?id=com.wrenchboard.users'
REACT_APP_APPLE_APP='https://itunes.apple.com/us/app/wrenchboard/id1435718367?ls=1&mt=8'
+3
View File
@@ -17,6 +17,9 @@
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>WrenchBoard</title>
<!-- FONT AWESOME -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v6.5.1/css/all.css"/>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
+16 -16
View File
@@ -1,22 +1,22 @@
import Toaster from "./components/Helpers/Toaster";
import Routers from "./Routers";
import Default from "./components/Partials/Default";
import { Navigate, useLocation } from "react-router-dom";
import Routers from "./Routers";
import Toaster from "./components/Helpers/Toaster";
import Default from "./components/Partials/Default";
function App() {
const {pathname} = useLocation()
return (
<Default>
<>
{pathname.startsWith('/@') ?
<Navigate to="/app" replace={true} />
:
<Routers />
}
<Toaster />
</>
</Default>
);
const { pathname } = useLocation();
return (
<Default>
<>
{pathname.startsWith("/@") ? (
<Navigate to="/app" replace={true} />
) : (
<Routers />
)}
<Toaster />
</>
</Default>
);
}
export default App;
+111 -76
View File
@@ -1,65 +1,61 @@
import { Route, Routes } from "react-router-dom";
import FourZeroFour from "./components/FourZeroFour";
import ScrollToTop from "./components/Helpers/ScrollToTop";
import MyCollection from "./components/MyCollection";
import StartJob from "./components/MyJobs/StartJob";
import Notification from "./components/Notification";
import AuthRoute from "./middleware/AuthRoute";
import AcitveBidsPage from "./views/AcitveBidsPage";
import AppDownloadPage from "./views/AppDownloadPage";
import AppleRedirectPage from "./views/AppleRedirectPage";
import AuthProfilePage from "./views/AuthProfilePage";
import AuthRedirect from "./views/AuthRedirect";
import BlogPage from "./views/BlogPage";
import CalendarPage from "./views/CalendarPage";
import CollectionItemPage from "./views/CollectionItemPage";
import FacebookRedirect from "./views/FacebookRedirect";
import FamilyAccPage from "./views/FamilyAccPage";
import FamilyManagePage from "./views/FamilyManagePage";
import FamilyMarketPage from "./views/FamilyMarketPage";
import FamilySettingsPage from "./views/FamilySettingsPage";
import ForgotPasswordPages from "./views/ForgotPasswordPages";
import ForgotPasswordPagesTwo from "./views/ForgotPasswordPagesTwo";
import HistoryPage from "./views/HistoryPage";
import HomePages from "./views/HomePages";
import JobGroupsPage from "./views/JobGroupsPage";
import LndPage from "./views/LndPage";
import LoginPage from "./views/LoginPage";
import LoginPageTwo from "./views/LoginPageTwo";
import ManageActiveJobs from "./views/ManageActiveJobs";
import ManageInterestOfferPage from "./views/ManageInterestOfferPage";
import MarketPlacePage from "./views/MarketPlacePage";
import MyActiveJobsPage from "./views/MyActiveJobsPage";
import MyCouponPage from "./views/MyCouponPage";
import MyJobsPage from "./views/MyJobsPage";
import MyOffersPage from "./views/MyOffersPage";
import MyPastDueJobsPage from "./views/MyPastDueJobsPage";
import MyReviewDueJobsPage from "./views/MyReviewDueJobsPage";
import MyTaskPage from "./views/MyTaskPage";
import MyWaitingJobsPage from "./views/MyWaitingJobsPage";
import MyWalletPage from "./views/MyWalletPage";
import OffersInterestPage from "./views/OffersInterestPage";
import ReferralPage from "./views/ReferralPage";
import RemindersPage from "./views/RemindersPage";
import ResourcePage from "./views/ResourcePage";
import SavedPage from "./views/SavedPage";
import SellPage from "./views/SellPage";
import SettingsPage from "./views/SettingsPage";
import ShopDetailsPage from "./views/ShopDetailsPage";
import SignupPage from "./views/SignupPage";
import SignupPageTwo from "./views/SignupPageTwo";
import TrackingPage from "./views/TrackingPage";
import UpdatePasswordPages from "./views/UpdatePasswordPages";
import UpdatePasswordPagesTwo from "./views/UpdatePasswordPagesTwo";
import UploadProductPage from "./views/UploadProductPage";
import UserProfilePage from "./views/UserProfilePage";
import VerifyYouPages from "./views/VerifyYouPages";
import VerifyYouPagesTwo from "./views/VerifyYouPagesTwo";
import VerifyPasswordPages from "./views/VerifyPasswordPages";
import VerifyPasswordPagesTwo from "./views/VerifyPasswordPagesTwo";
import RemindersPage from './views/RemindersPage';
import TrackingPage from "./views/TrackingPage";
import CalendarPage from "./views/CalendarPage";
import ResourcePage from "./views/ResourcePage";
import MyTaskPage from "./views/MyTaskPage";
import MyJobsPage from "./views/MyJobsPage";
import ReferralPage from "./views/ReferralPage";
import VerifyLinkPages from "./views/VerifyLinkPages";
import VerifyLinkPagesTwo from "./views/VerifyLinkPagesTwo";
import MyActiveJobsPage from "./views/MyActiveJobsPage";
import FamilyAccPage from "./views/FamilyAccPage";
import StartJob from "./components/MyJobs/StartJob";
import AddJobPage from "./views/AddJobPage";
import MyPendingJobsPage from "./views/MyPendingJobsPage";
import ManageActiveJobs from "./views/ManageActiveJobs";
import FamilyManagePage from "./views/FamilyManagePage";
import MyCouponPage from "./views/MyCouponPage";
import AuthRedirect from "./views/AuthRedirect";
import MyPastDueJobsPage from "./views/MyPastDueJobsPage";
import BlogPage from "./views/BlogPage";
import MyReviewDueJobsPage from "./views/MyReviewDueJobsPage";
import OffersInterestPage from "./views/OffersInterestPage";
import ManageInterestOfferPage from './views/ManageInterestOfferPage'
import MyWaitingJobsPage from "./views/MyWaitingJobsPage";
import FamilyMarketPage from "./views/FamilyMarketPage";
import FacebookRedirect from "./views/FacebookRedirect";
import AppleRedirectPage from "./views/AppleRedirectPage";
import LndPage from "./views/LndPage";
import FamilySettingsPage from "./views/FamilySettingsPage";
import AppDownloadPage from "./views/AppDownloadPage";
import JobGroupsPage from "./views/JobGroupsPage";
import VerifyPasswordPages from "./views/VerifyPasswordPages";
import VerifyPasswordPagesTwo from "./views/VerifyPasswordPagesTwo";
import VerifyYouPages from "./views/VerifyYouPages";
import VerifyYouPagesTwo from "./views/VerifyYouPagesTwo";
import YourPages from "./views/YourPage_";
export default function Routers() {
@@ -67,31 +63,47 @@ export default function Routers() {
<ScrollToTop>
<Routes>
{/* guest routes */}
{process.env.REACT_APP_NEW_LOGIN_LAYOUT == 1 ?
<>
<Route exact path="/login" element={<LoginPageTwo />} />
<Route exact path="/signup" element={<SignupPageTwo />} />
<Route exact path="/forgot-password" element={<ForgotPasswordPagesTwo />} />
<Route exact path="/update-password" element={<UpdatePasswordPagesTwo />} />
<Route path="/vemail" element={<VerifyLinkPagesTwo />} />
<Route path="/complereset" element={<VerifyPasswordPagesTwo />} />
<Route exact path="/outmessage" element={<VerifyYouPagesTwo />} />
<Route exact path="/eoffer" element={<LoginPageTwo />} />
<Route exact path="/invite" element={<LoginPageTwo />} />
</>
:
<>
<Route exact path="/login" element={<LoginPage />} />
<Route exact path="/signup" element={<SignupPage />} />
<Route exact path="/forgot-password" element={<ForgotPasswordPages />} />
<Route exact path="/update-password" element={<UpdatePasswordPages />} />
<Route path="/vemail" element={<VerifyLinkPages />} />
<Route path="/complereset" element={<VerifyPasswordPages />} />
<Route exact path="/outmessage" element={<VerifyYouPages />} />
<Route exact path="/eoffer" element={<LoginPage />} />
<Route exact path="/invite" element={<LoginPage />} />
</>
}
{process.env.REACT_APP_NEW_LOGIN_LAYOUT == 1 ? (
<>
<Route exact path="/login" element={<LoginPageTwo />} />
<Route exact path="/signup" element={<SignupPageTwo />} />
<Route
exact
path="/forgot-password"
element={<ForgotPasswordPagesTwo />}
/>
<Route
exact
path="/update-password"
element={<UpdatePasswordPagesTwo />}
/>
<Route path="/vemail" element={<VerifyLinkPagesTwo />} />
<Route path="/complereset" element={<VerifyPasswordPagesTwo />} />
<Route exact path="/outmessage" element={<VerifyYouPagesTwo />} />
<Route exact path="/eoffer" element={<LoginPageTwo />} />
<Route exact path="/invite" element={<LoginPageTwo />} />
</>
) : (
<>
<Route exact path="/login" element={<LoginPage />} />
<Route exact path="/signup" element={<SignupPage />} />
<Route
exact
path="/forgot-password"
element={<ForgotPasswordPages />}
/>
<Route
exact
path="/update-password"
element={<UpdatePasswordPages />}
/>
<Route path="/vemail" element={<VerifyLinkPages />} />
<Route path="/complereset" element={<VerifyPasswordPages />} />
<Route exact path="/outmessage" element={<VerifyYouPages />} />
<Route exact path="/eoffer" element={<LoginPage />} />
<Route exact path="/invite" element={<LoginPage />} />
</>
)}
<Route exact path="/login/auth" element={<AuthRedirect />} />
<Route exact path="/login/auth/flogin" element={<FacebookRedirect />} />
<Route exact path="/login/auth/apple" element={<AppleRedirectPage />} />
@@ -117,25 +129,48 @@ export default function Routers() {
<Route exact path="/market-place" element={<MarketPlacePage />} />
<Route exact path="/market" element={<MarketPlacePage />} />
<Route exact path="/familymarket" element={<FamilyMarketPage />} />
<Route exact path="/familysettings" element={<FamilySettingsPage />} />
<Route
exact
path="/familysettings"
element={<FamilySettingsPage />}
/>
<Route exact path="/notification" element={<Notification />} />
<Route exact path="/mytask" element={<MyTaskPage />} />
<Route exact path="/myjobs" element={<MyJobsPage />} />
{/* <Route exact path="/add-job" element={<AddJobPage />} /> */}
<Route exact path="/my-active-jobs" element={<MyActiveJobsPage />} />
<Route exact path="/my-pastdue-jobs" element={<MyPastDueJobsPage />} />
<Route exact path="/my-pending-jobs" element={<MyPendingJobsPage />} />
<Route exact path="/pend-interest" element={<MyWaitingJobsPage />} />
<Route exact path="/my-review-jobs" element={<MyReviewDueJobsPage />} />
<Route exact path="/acc-family" element={<FamilyAccPage />} />
<Route exact path="/manage-family" element={<FamilyManagePage />} />
<Route exact path="/start-job" element={<StartJob />} />
<Route exact path="/yourpage" element={<YourPages />} />
<Route exact path="/manage-active-job" element={<ManageActiveJobs />} />
<Route exact path="/blog-page" element={<BlogPage />} />
<Route exact path="/offer-interest" element={<OffersInterestPage />} />
<Route exact path="/manage-offer" element={<ManageInterestOfferPage />} />
<Route exact path="/my-active-jobs" element={<MyActiveJobsPage />} />
<Route
exact
path="/my-pastdue-jobs"
element={<MyPastDueJobsPage />}
/>
<Route exact path="/my-offers" element={<MyOffersPage />} />
<Route exact path="/pend-interest" element={<MyWaitingJobsPage />} />
<Route
exact
path="/my-review-jobs"
element={<MyReviewDueJobsPage />}
/>
<Route exact path="/acc-family" element={<FamilyAccPage />} />
<Route exact path="/manage-family" element={<FamilyManagePage />} />
<Route exact path="/start-job" element={<StartJob />} />
<Route exact path="/yourpage" element={<YourPages />} />
<Route
exact
path="/manage-active-job"
element={<ManageActiveJobs />}
/>
<Route exact path="/blog-page" element={<BlogPage />} />
<Route
exact
path="/offer-interest"
element={<OffersInterestPage />}
/>
<Route
exact
path="/manage-offer"
element={<ManageInterestOfferPage />}
/>
<Route
exact
+1 -1
View File
@@ -22,7 +22,7 @@ export default function LoginLayout({ slogan, children }) {
>
</div> */}
<div className="p-5 sm:p-7 flex place-content-center lg:col-start-2">
<div className="py-10 w-full sm:w-11/12 max-w-2xl shadow-md bg-slate-50 dark:bg-dark-white rounded-[0.475rem]">
<div className="py-5 w-full sm:w-11/12 max-w-2xl shadow-md bg-slate-50 dark:bg-dark-white rounded-[0.475rem]">
<div className="w-full flex justify-center items-center">
{children && children}
</div>
+29 -4
View File
@@ -520,11 +520,36 @@ export default function Login() {
}
{/* END of login component */}
{/* APP DOWNLOAD STORE */}
<div className="w-full mt-4">
<div className="w-full flex justify-center items-center gap-4">
<div className='w-28 lg:w-32'>
<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' 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>
</a>
</div>
<div className='w-28 lg:w-32'>
<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' 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>
</a>
</div>
</div>
</div>
{loginType == "full" && (
<div className="pt-5 text-[#181c32] text-center font-semibold text-[13.975px] leading-[20.9625px]">
This site is protected by a Captcha. Our Privacy Policy and
Terms of Service apply.
</div>
<>
<div className="pt-5 text-[#181c32] text-center font-semibold text-[13.975px] leading-[20.9625px]">
This site is protected by a Captcha. Our Privacy Policy and
Terms of Service apply.
</div>
</>
)}
</div>
</div>
+80 -40
View File
@@ -9,19 +9,21 @@ export default function SignUp() {
// eslint-disable-next-line no-restricted-globals
const queryParams = new URLSearchParams(location?.search);
const country = queryParams.get("cnt")?.toUpperCase();
const {pathname} = useLocation()
const currentPath = country ? `${pathname}?cnt=${country.toLowerCase()}`:pathname // Determines the new pathname is country query params exist
const { pathname } = useLocation();
const currentPath = country
? `${pathname}?cnt=${country.toLowerCase()}`
: pathname; // Determines the new pathname is country query params exist
const [signUpLoading, setSignUpLoading] = useState(false);
const [checked, setValue] = useState(false);
// for the catch error
const [msgError, setMsgError] = useState("");
const [showPassword, setShowPassword] = useState(false);
const [countries, setCountries] = useState({loading:true, data:[]});
const [countries, setCountries] = useState({ loading: true, data: [] });
const [formData, setFormData] = useState({
country: country? country : "",
country: country ? country : "",
first_name: "",
last_name: "",
email: "",
@@ -47,22 +49,23 @@ export default function SignUp() {
// Get Country Api
const getCountryList = useCallback(async () => {
try {
const res = await userApi.getSignupCountryData();
if (res.status === 200 && res.data.internal_return >= 0) {
const { result_list } = await res.data;
if(country){ // IF LINK/PATHNAME HAS CNT QUERY VALUE
let cnt = result_list.filter(item => item.code == country) // test to see country passed in query param exist from list of countries supplied by API
if(!cnt.length){ // IF CNT EMPTY, SET FORMDATA COUNTRY BACK TO EMPTY STRING: RE: THIS IS BCOS WE INITAIL SET COUNTRY VALUE IN FORMDATA, IF COUNTRY PARAM IS PRESENT IN LINK
setFormData(prev => ({...prev, country: ''}))
return setCountries({loading: false, data: result_list});
if (country) {
// IF LINK/PATHNAME HAS CNT QUERY VALUE
let cnt = result_list.filter((item) => item.code == country); // test to see country passed in query param exist from list of countries supplied by API
if (!cnt.length) {
// IF CNT EMPTY, SET FORMDATA COUNTRY BACK TO EMPTY STRING: RE: THIS IS BCOS WE INITAIL SET COUNTRY VALUE IN FORMDATA, IF COUNTRY PARAM IS PRESENT IN LINK
setFormData((prev) => ({ ...prev, country: "" }));
return setCountries({ loading: false, data: result_list });
}
return setCountries({loading: false, data: cnt});
return setCountries({ loading: false, data: cnt });
}
setCountries({loading: false, data:result_list});
setCountries({ loading: false, data: result_list });
} else if (res.data.result !== 100) {
setCountries({loading: false, data:[]});
setCountries({ loading: false, data: [] });
}
} catch (error) {
throw new Error(error);
@@ -113,9 +116,7 @@ export default function SignUp() {
if (res.status === 200) {
const { data } = res;
if (data && data.acc === "DULPICATE") {
setMsgError(
"Unable to use this username. Please try another username."
);
setMsgError("Duplicate username. Please try another email.");
setSignUpLoading(false);
}
if (data && data.status === "1") {
@@ -124,6 +125,11 @@ export default function SignUp() {
setSignUpLoading(false);
}, 2000);
}
if (data && data.status === "5") {
setMsgError("Something went wrong. Please try another email.");
setSignUpLoading(false);
}
} else {
setSignUpLoading(false);
setMsgError("An error occurred");
@@ -187,7 +193,9 @@ export default function SignUp() {
name="country"
value={formData.country}
inputHandler={handleInputChange}
disable={country && countries?.data?.length <= 1 ? true : false}
disable={
country && countries?.data?.length <= 1 ? true : false
}
/>
<div className="input-fl-name mb-4 sm:flex w-full sm:space-x-6 ">
<div className="input-item sm:w-1/2 w-full mb-4 sm:mb-0">
@@ -325,7 +333,7 @@ export default function SignUp() {
disabled={countries.loading}
type="button"
onClick={handleSignUp}
className={`rounded-full mb-6 text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center h-[42px] py-[0.8875rem] px-[1.81rem] text-[14.95px] btn-login`}
className={`rounded-full text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center h-[42px] py-[0.8875rem] px-[1.81rem] text-[14.95px] btn-login`}
>
{signUpLoading ? (
<div className="signup btn-loader"></div>
@@ -335,6 +343,44 @@ export default function SignUp() {
</button>
</div>
</div>
{/* APP DOWNLOAD STORE */}
<div className="w-full mt-4">
<div className="w-full flex justify-center items-center gap-4">
<div className="w-28 lg:w-32">
<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"
href={process.env.REACT_APP_APPLE_APP}
rel="noreferrer"
>
<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>
</a>
</div>
<div className="w-28 lg:w-32">
<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"
href={process.env.REACT_APP_ANDROID_APP}
rel="noreferrer"
>
<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>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
@@ -350,7 +396,7 @@ const SelectOption = ({
inputHandler,
value,
data, // passing the data from parent
disable
disable,
}) => {
return (
<div className="input-com mb-7">
@@ -364,39 +410,33 @@ const SelectOption = ({
</div>
<div>
<select
disabled={disable}
disabled={disable}
name={name}
id={name}
className="input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base focus-visible:border-transparent focus-visible:outline-0 focus-visible:ring-transparent "
onChange={inputHandler}
value={value}
>
{data?.data?.length > 1 ?
{data?.data?.length > 1 ? (
<>
<option value={""}>Select your Country</option>
{data?.data?.map((item) => (
<option value={item.code} key={item.uid}>
{item.country}
</option>
))}
<option value={""}>Select your Country</option>
{data?.data?.map((item) => (
<option value={item.code} key={item.uid}>
{item.country}
</option>
))}
</>
:
data?.data?.length == 1 ?
) : data?.data?.length == 1 ? (
data?.data?.map((item) => (
<option value={item.code} key={item.uid}>
{item.country}
</option>
))
:
data?.data?.length < 1 && data.loading ?
<option value=''>
Loading...
</option>
:
<option value=''>
No Country Found!
</option>
}
) : data?.data?.length < 1 && data.loading ? (
<option value="">Loading...</option>
) : (
<option value="">No Country Found!</option>
)}
</select>
</div>
</div>
+59 -55
View File
@@ -51,8 +51,7 @@ export default function VerifyLink() {
localStorage.setItem("member_id", `${data?.member_id}`);
localStorage.setItem("session_token", `${data?.session}`);
localStorage.setItem("session", `${data?.session}`);
localStorage.setItem("uid", data?.uid)
localStorage.setItem("uid", data?.uid);
navigate("/", { replace: true });
setLinkLoader(false);
@@ -80,19 +79,19 @@ export default function VerifyLink() {
};
// for verifying the incoming verification link and render the correct component
const verifyEmail = useCallback(async (code) => {
const verifyEmail = async (code) => {
try {
const verifyRes = await userApi.verifyEmail(code);
if (verifyRes.status === 200) {
let { data } = verifyRes;
console.log('TESTING VERIFY',data)
console.log("TESTING VERIFY", data);
if (
data &&
data.internal_return >= 0 &&
data.status == 0 &&
data.pending_id != '' &&
data.pending_uid != '' &&
data.username != '' &&
data.internal_return >= 0 &&
data.status == 0 &&
data.pending_id != "" &&
data.pending_uid != "" &&
data.username != "" &&
data.status_text === "Link Verified"
) {
setPageLoader(false);
@@ -106,12 +105,13 @@ export default function VerifyLink() {
setLinkSuccess(false);
throw new Error(error);
}
}, []);
};
// delay verify requests by 10000ms
const debouncedEmail = debounce(verifyEmail, 1000);
useEffect(() => {
setEmail("")
debouncedEmail(token);
}, []);
@@ -171,53 +171,57 @@ const SuccessfulComponent = ({
handleEmail,
msgErr,
loader,
}) => (
<div className="input-area">
{/* INPUT */}
<div className="mb-5">
<InputCom
fieldClass="px-6"
value={email}
inputHandler={handleEmail}
placeholder="support@mermsemr.com"
label="Email"
name="email"
type="email"
iconName="message"
/>
</div>
<div className="mb-5">
<InputCom
fieldClass="px-6"
value={password}
inputHandler={handlePassword}
placeholder="● ● ● ● ● ●"
label="Password"
name="password"
type="password"
iconName="password"
/>
</div>
{msgErr && (
<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]">
{msgErr}
}) => {
return (
<div className="input-area">
{/* INPUT */}
<div className="mb-5">
<InputCom
fieldClass="px-6"
value={email}
inputHandler={handleEmail}
placeholder="support@mermsemr.com"
label="Email"
name="email"
type="email"
iconName="message"
autoComplete="off"
/>
</div>
<div className="mb-5">
<InputCom
fieldClass="px-6"
value={password}
inputHandler={handlePassword}
placeholder="● ● ● ● ● ●"
label="Password"
name="password"
type="password"
iconName="password"
autoComplete="off"
/>
</div>
{msgErr && (
<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]">
{msgErr}
</div>
)}
<div className="signin-area mb-3.5">
<button
onClick={onSubmit}
type="button"
className={`btn-login rounded-[0.475rem] mb-6 text-xl text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center text-[15px]`}
>
{loader ? (
<div className="signup btn-loader"></div>
) : (
<span>Continue</span>
)}
</button>
</div>
)}
<div className="signin-area mb-3.5">
<button
onClick={onSubmit}
type="button"
className={`btn-login rounded-[0.475rem] mb-6 text-xl text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center text-[15px]`}
>
{loader ? (
<div className="signup btn-loader"></div>
) : (
<span>Continue</span>
)}
</button>
</div>
</div>
);
);
};
const ErrorComponent = ({ onClick }) => (
<div className="input-area">
+10 -8
View File
@@ -51,8 +51,7 @@ export default function VerifyLink() {
localStorage.setItem("member_id", `${data?.member_id}`);
localStorage.setItem("session_token", `${data?.session}`);
localStorage.setItem("session", `${data?.session}`);
localStorage.setItem("uid", data?.uid)
localStorage.setItem("uid", data?.uid);
navigate("/", { replace: true });
setLinkLoader(false);
@@ -85,16 +84,17 @@ export default function VerifyLink() {
const verifyRes = await userApi.verifyEmail(code);
if (verifyRes.status === 200) {
let { data } = verifyRes;
console.log('TESTING VERIFY',data)
console.log("TESTING VERIFY", data);
if (
data &&
data.internal_return >= 0 &&
data.status == 0 &&
data.pending_id != '' &&
data.pending_uid != '' &&
data.username != '' &&
data.internal_return >= 0 &&
data.status == 0 &&
data.pending_id != "" &&
data.pending_uid != "" &&
data.username != "" &&
data.status_text === "Link Verified"
) {
setEmail(data.username);
setPageLoader(false);
} else {
setPageLoader(false);
@@ -184,6 +184,7 @@ const SuccessfulComponent = ({
name="email"
type="email"
iconName="message"
autoComplete="off"
/>
</div>
<div className="mb-5">
@@ -196,6 +197,7 @@ const SuccessfulComponent = ({
name="password"
type="password"
iconName="password"
autoComplete="off"
/>
</div>
{msgErr && (
@@ -8,7 +8,7 @@ export default function HomeBannerOffersCard(props) {
useEffect(() => {
let { banner, banner_location } = props?.itemData;
if (banner_location === "LOCAL") {
const imagePath = require(`../../assets/images/${banner}`); // Replace with your directory path for local images
const imagePath = require(`../../assets/images/${banner}`);
setImageUrl(imagePath);
} else if (banner_location === "URL") setImageUrl(banner);
else return null;
@@ -0,0 +1,103 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { toast } from "react-toastify";
import heroBg from "../../assets/images/bg-sky-blue.jpg"; //hero-bg.svg";
import heroUser from "../../assets/images/hero-user.png";
import CountDown from "../Helpers/CountDown";
// import HomeSliders from "./HomeSliders";
import { useSelector } from "react-redux";
import HomeSliders from "../Home/HomeSliders";
export default function FamilyParentDashboard({ className, bannerList, nextDueTask }) {
const settings = {
autoplay: true,
dots: true,
arrows: false,
infinite: true,
swipe: true,
};
const sildeData = null;
const { userDetails } = useSelector((state) => state?.userDetails);
let loginDate = userDetails?.last_login.split(" ")[0];
let { firstname, lastname, email, profile_pic } = userDetails;
let userEmail = email.split("@")[0];
return (
<div
className={`w-full min-h-[400px] md:grid grid-cols-2 lg:p-8 p-4 justify-between items-center gap-2 rounded-2xl overflow-hidden bg-blue-500 ${
className || ""
}`}
style={{
// background: `url(${heroBg})`,
backgroundRepeat: "no-repeat",
backgroundSize: "cover",
}}
>
<div className="h-full flex flex-col justify-between mb-5 lg:mb-0">
{/* heading */}
<div>
<h1 className="lg:text-2xl text-xl font-medium text-white tracking-wide">
Welcome
</h1>
<span className="text-[18px] font-thin tracking-wide text-white">
Last Login : {loginDate}
</span>
</div>
{/* user */}
<div className="flex items-center space-x-3">
<div className="w-14 h-14 flex justify-center items-center rounded-full overflow-hidden">
<img src={profile_pic != "" ? profile_pic : heroUser} alt="" />
</div>
<div>
<p className="text-xl tracking-wide font-bold antise text-white">
{`${firstname} ${lastname}`}
</p>
<p className="text-sm tracking-wide text-white">@{userEmail}</p>
</div>
</div>
{/* countdown */}
{nextDueTask?.next_due && Object.keys(nextDueTask.next_due)?.length != 0 && (
<div className="w-full h-32 flex justify-evenly items-center sm:p-6 p-1 rounded-2xl border back-dark1 border-white-opacity">
<div className="flex flex-col justify-between">
<p className="text-base text-white tracking-wide">Current Task</p>
<p className="lg:text-2xl text-lg font-bold tracking-wide text-white">
{(nextDueTask.next_due.item_code).substr(0,4)+'...'}
</p>
<p className="text-base text-white tracking-wide">
{nextDueTask.next_due.price * 0.01} Naira
</p>
</div>
<div className="w-[1px] h-full bg-white-opacity"></div>
<div className="flex flex-col justify-between">
<p className="text-base text-white tracking-wide">Next due in</p>
<p className="lg:text-2xl text-lg font-bold tracking-wide text-white">
{/* <CountDown lastDate="2023-04-26 4:00:00" /> */}
<CountDown lastDate={nextDueTask.next_due.due_date} />
</p>
<div className="text-base text-white tracking-wide flex gap-[23px]">
<span>Hrs</span>
<span>Min</span>
<span>Sec</span>
</div>
</div>
</div>
)}
{/* action */}
<div className="flex lg:space-x-3 space-x-1 items-center">
<Link to="/mytask" className="text-white text-base">
<span className=" border-b dark:border-[#5356fb29] border-white">
{" "}
View All Task(s)
</span>
</Link>
</div>
</div>
<HomeSliders
settings={settings}
sideData={sildeData}
bannerList={bannerList}
/>
</div>
);
}
+103
View File
@@ -0,0 +1,103 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { toast } from "react-toastify";
import heroBg from "../../assets/images/bg-sky-blue.jpg"; //hero-bg.svg";
import heroUser from "../../assets/images/hero-user.png";
import CountDown from "../Helpers/CountDown";
// import HomeSliders from "./HomeSliders";
import { useSelector } from "react-redux";
import HomeSliders from "../Home/HomeSliders";
export default function HomeDashboard({ className, bannerList, nextDueTask }) {
const settings = {
autoplay: true,
dots: true,
arrows: false,
infinite: true,
swipe: true,
};
const sildeData = null;
const { userDetails } = useSelector((state) => state?.userDetails);
let loginDate = userDetails?.last_login.split(" ")[0];
let { firstname, lastname, email, profile_pic } = userDetails;
let userEmail = email.split("@")[0];
return (
<div
className={`w-full min-h-[400px] md:grid grid-cols-2 lg:p-8 p-4 justify-between items-center gap-2 rounded-2xl overflow-hidden ${
className || ""
}`}
style={{
background: `url(${heroBg})`,
backgroundRepeat: "no-repeat",
backgroundSize: "cover",
}}
>
<div className="h-full flex flex-col justify-between mb-5 lg:mb-0">
{/* heading */}
<div>
<h1 className="lg:text-2xl text-xl font-medium text-white tracking-wide">
Welcome
</h1>
<span className="text-[18px] font-thin tracking-wide text-white">
Last Login : {loginDate}
</span>
</div>
{/* user */}
<div className="flex items-center space-x-3">
<div className="w-14 h-14 flex justify-center items-center rounded-full overflow-hidden">
<img src={profile_pic != "" ? profile_pic : heroUser} alt="" />
</div>
<div>
<p className="text-xl tracking-wide font-bold antise text-white">
{`${firstname} ${lastname}`}
</p>
<p className="text-sm tracking-wide text-white">@{userEmail}</p>
</div>
</div>
{/* countdown */}
{nextDueTask?.next_due && Object.keys(nextDueTask.next_due)?.length != 0 && (
<div className="w-full h-32 flex justify-evenly items-center sm:p-6 p-1 rounded-2xl border back-dark1 border-white-opacity">
<div className="flex flex-col justify-between">
<p className="text-base text-white tracking-wide">Current Task</p>
<p className="lg:text-2xl text-lg font-bold tracking-wide text-white">
{(nextDueTask.next_due.item_code).substr(0,4)+'...'}
</p>
<p className="text-base text-white tracking-wide">
{nextDueTask.next_due.price * 0.01} Naira
</p>
</div>
<div className="w-[1px] h-full bg-white-opacity"></div>
<div className="flex flex-col justify-between">
<p className="text-base text-white tracking-wide">Next due in</p>
<p className="lg:text-2xl text-lg font-bold tracking-wide text-white">
{/* <CountDown lastDate="2023-04-26 4:00:00" /> */}
<CountDown lastDate={nextDueTask.next_due.due_date} />
</p>
<div className="text-base text-white tracking-wide flex gap-[23px]">
<span>Hrs</span>
<span>Min</span>
<span>Sec</span>
</div>
</div>
</div>
)}
{/* action */}
<div className="flex lg:space-x-3 space-x-1 items-center">
<Link to="/mytask" className="text-white text-base">
<span className=" border-b dark:border-[#5356fb29] border-white">
{" "}
View All Task(s)
</span>
</Link>
</div>
</div>
<HomeSliders
settings={settings}
sideData={sildeData}
bannerList={bannerList}
/>
</div>
);
}
@@ -0,0 +1,103 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { toast } from "react-toastify";
import heroBg from "../../assets/images/bg-sky-blue.jpg"; //hero-bg.svg";
import heroUser from "../../assets/images/hero-user.png";
import CountDown from "../Helpers/CountDown";
// import HomeSliders from "./HomeSliders";
import { useSelector } from "react-redux";
import HomeSliders from "../Home/HomeSliders";
export default function JobOwnerDashboard({ className, bannerList, nextDueTask }) {
const settings = {
autoplay: true,
dots: true,
arrows: false,
infinite: true,
swipe: true,
};
const sildeData = null;
const { userDetails } = useSelector((state) => state?.userDetails);
let loginDate = userDetails?.last_login.split(" ")[0];
let { firstname, lastname, email, profile_pic } = userDetails;
let userEmail = email.split("@")[0];
return (
<div
className={`w-full min-h-[400px] md:grid grid-cols-2 lg:p-8 p-4 justify-between items-center gap-2 rounded-2xl overflow-hidden bg-blue-800 ${
className || ""
}`}
style={{
// background: `url(${heroBg})`,
backgroundRepeat: "no-repeat",
backgroundSize: "cover",
}}
>
<div className="h-full flex flex-col justify-between mb-5 lg:mb-0">
{/* heading */}
<div>
<h1 className="lg:text-2xl text-xl font-medium text-white tracking-wide">
Welcome
</h1>
<span className="text-[18px] font-thin tracking-wide text-white">
Last Login : {loginDate}
</span>
</div>
{/* user */}
<div className="flex items-center space-x-3">
<div className="w-14 h-14 flex justify-center items-center rounded-full overflow-hidden">
<img src={profile_pic != "" ? profile_pic : heroUser} alt="" />
</div>
<div>
<p className="text-xl tracking-wide font-bold antise text-white">
{`${firstname} ${lastname}`}
</p>
<p className="text-sm tracking-wide text-white">@{userEmail}</p>
</div>
</div>
{/* countdown */}
{nextDueTask?.next_due && Object.keys(nextDueTask.next_due)?.length != 0 && (
<div className="w-full h-32 flex justify-evenly items-center sm:p-6 p-1 rounded-2xl border back-dark1 border-white-opacity">
<div className="flex flex-col justify-between">
<p className="text-base text-white tracking-wide">Current Task</p>
<p className="lg:text-2xl text-lg font-bold tracking-wide text-white">
{(nextDueTask.next_due.item_code).substr(0,4)+'...'}
</p>
<p className="text-base text-white tracking-wide">
{nextDueTask.next_due.price * 0.01} Naira
</p>
</div>
<div className="w-[1px] h-full bg-white-opacity"></div>
<div className="flex flex-col justify-between">
<p className="text-base text-white tracking-wide">Next due in</p>
<p className="lg:text-2xl text-lg font-bold tracking-wide text-white">
{/* <CountDown lastDate="2023-04-26 4:00:00" /> */}
<CountDown lastDate={nextDueTask.next_due.due_date} />
</p>
<div className="text-base text-white tracking-wide flex gap-[23px]">
<span>Hrs</span>
<span>Min</span>
<span>Sec</span>
</div>
</div>
</div>
)}
{/* action */}
<div className="flex lg:space-x-3 space-x-1 items-center">
<Link to="/mytask" className="text-white text-base">
<span className=" border-b dark:border-[#5356fb29] border-white">
{" "}
View All Task(s)
</span>
</Link>
</div>
</div>
<HomeSliders
settings={settings}
sideData={sildeData}
bannerList={bannerList}
/>
</div>
);
}
@@ -0,0 +1,103 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { toast } from "react-toastify";
import heroBg from "../../assets/images/bg-sky-blue.jpg"; //hero-bg.svg";
import heroUser from "../../assets/images/hero-user.png";
import CountDown from "../Helpers/CountDown";
// import HomeSliders from "./HomeSliders";
import { useSelector } from "react-redux";
import HomeSliders from "../Home/HomeSliders";
export default function WorkerDashboard({ className, bannerList, nextDueTask }) {
const settings = {
autoplay: true,
dots: true,
arrows: false,
infinite: true,
swipe: true,
};
const sildeData = null;
const { userDetails } = useSelector((state) => state?.userDetails);
let loginDate = userDetails?.last_login.split(" ")[0];
let { firstname, lastname, email, profile_pic } = userDetails;
let userEmail = email.split("@")[0];
return (
<div
className={`w-full min-h-[400px] md:grid grid-cols-2 lg:p-8 p-4 justify-between items-center gap-2 rounded-2xl overflow-hidden bg-blue-900 ${
className || ""
}`}
style={{
// background: `url(${heroBg})`,
backgroundRepeat: "no-repeat",
backgroundSize: "cover",
}}
>
<div className="h-full flex flex-col justify-between mb-5 lg:mb-0">
{/* heading */}
<div>
<h1 className="lg:text-2xl text-xl font-medium text-white tracking-wide">
Welcome
</h1>
<span className="text-[18px] font-thin tracking-wide text-white">
Last Login : {loginDate}
</span>
</div>
{/* user */}
<div className="flex items-center space-x-3">
<div className="w-14 h-14 flex justify-center items-center rounded-full overflow-hidden">
<img src={profile_pic != "" ? profile_pic : heroUser} alt="" />
</div>
<div>
<p className="text-xl tracking-wide font-bold antise text-white">
{`${firstname} ${lastname}`}
</p>
<p className="text-sm tracking-wide text-white">@{userEmail}</p>
</div>
</div>
{/* countdown */}
{nextDueTask?.next_due && Object.keys(nextDueTask.next_due)?.length != 0 && (
<div className="w-full h-32 flex justify-evenly items-center sm:p-6 p-1 rounded-2xl border back-dark1 border-white-opacity">
<div className="flex flex-col justify-between">
<p className="text-base text-white tracking-wide">Current Task</p>
<p className="lg:text-2xl text-lg font-bold tracking-wide text-white">
{(nextDueTask.next_due.item_code).substr(0,4)+'...'}
</p>
<p className="text-base text-white tracking-wide">
{nextDueTask.next_due.price * 0.01} Naira
</p>
</div>
<div className="w-[1px] h-full bg-white-opacity"></div>
<div className="flex flex-col justify-between">
<p className="text-base text-white tracking-wide">Next due in</p>
<p className="lg:text-2xl text-lg font-bold tracking-wide text-white">
{/* <CountDown lastDate="2023-04-26 4:00:00" /> */}
<CountDown lastDate={nextDueTask.next_due.due_date} />
</p>
<div className="text-base text-white tracking-wide flex gap-[23px]">
<span>Hrs</span>
<span>Min</span>
<span>Sec</span>
</div>
</div>
</div>
)}
{/* action */}
<div className="flex lg:space-x-3 space-x-1 items-center">
<Link to="/mytask" className="text-white text-base">
<span className=" border-b dark:border-[#5356fb29] border-white">
{" "}
View All Task(s)
</span>
</Link>
</div>
</div>
<HomeSliders
settings={settings}
sideData={sildeData}
bannerList={bannerList}
/>
</div>
);
}
+11
View File
@@ -0,0 +1,11 @@
import FamilyParentDashboard from "./FamilyParentDashboard";
import HomeDashboard from "./HomeDashboard";
import JobOwnerDashboard from "./JobOwnerDashboard";
import WorkerDashboard from "./WorkerDashboard";
export {
FamilyParentDashboard,
HomeDashboard,
JobOwnerDashboard,
WorkerDashboard,
};
@@ -27,6 +27,7 @@ export default function InputCom({
direction,
tabIndex,
error,
autoComplete="on"
}) {
const inputRef = useRef(null);
// Entry Validation
@@ -107,6 +108,7 @@ export default function InputCom({
readOnly={disable}
onBlur={blurHandler}
dir={direction}
autoComplete={autoComplete}
/>
{iconName && (
<div className="absolute right-6 bottom-3 z-10 flex gap-2">
+31 -2
View File
@@ -1,7 +1,8 @@
import React from "react";
import ParentWaiting from "../MyPendingJobs/ParentWaiting";
import ParentWaiting from "../MyOffers/ParentWaiting";
import MyOffersFamilyTable from "../MyTasks/MyOffersFamilyTable";
import FamilyActiveLSlde from "./FamilyActiveLSlde";
import { Link } from "react-router-dom";
export default function FamilyDash({ familyOffers, MyActiveJobList }) {
// console.log("PROPS IN FAMILY DASH->", familyOffers?.result_list);
@@ -11,6 +12,30 @@ export default function FamilyDash({ familyOffers, MyActiveJobList }) {
<div>
<div className="home-page-wrapper">
{/* <CommonHead commonHeadData={props.commonHeadData} /> */}
<div className="w-full mb-4 grid grid-cols-2 md:grid-cols-4 gap-2 md:gap-4">
{[1,2,3,4,5].map((item, index) => (
<Link to='/' className={`h-40 rounded-lg shadow-sm ${index%2==0 ? 'bg-red-200/50' : 'bg-sky-300/50'}`}>
<div >
</div>
</Link>
))}
</div>
<div className="my-4">
<h1 className="my-4 text-26 font-bold text-dark-gray dark:text-white tracking-wide">Resources</h1>
<div className="w-full grid grid-cols-2 md:grid-cols-3 gap-2 md:gap-4">
{[1,2,3,4,5].map((item, index) => (
<Link to='/' className={`h-40 rounded-lg shadow-sm ${index%2==0 ? 'bg-red-200/50' : 'bg-sky-300/50'}`}>
<div >
</div>
</Link>
))}
</div>
</div>
{familyOffers?.result_list && familyOffers?.result_list.length > 0 && (
<MyOffersFamilyTable
familyOffers={familyOffers?.result_list}
@@ -19,7 +44,11 @@ export default function FamilyDash({ familyOffers, MyActiveJobList }) {
/>
)}
{trending && trending.length > 0 && (
<FamilyActiveLSlde trending={trending} className="mb-10" image_server={familyOffers?.session_image_server} />
<FamilyActiveLSlde
trending={trending}
className="mb-10"
image_server={familyOffers?.session_image_server}
/>
)}
{/*<TopSellerTopBuyerSliderSection className="mb-10" />*/}
+47 -7
View File
@@ -4,22 +4,62 @@ import MyOffersTable from "../MyTasks/MyOffersTable";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import Hero from "./Hero";
import HomeActivities from "./HomeActivities";
import { FamilyParentDashboard, HomeDashboard, JobOwnerDashboard, WorkerDashboard } from "../Dashboards";
export default function FullAccountDash(props) {
// console.log("PROPS IN HOME->", props);
const { userDetails } = useSelector((state) => state?.userDetails);
const renderDashboard = () => {
switch (props.dashTypes) {
case "DEFAULT_HOME_DASH":
return (
<HomeDashboard
className="mb-10"
data={userDetails}
bannerList={props.bannerList}
nextDueTask={props.nextDueTask}
/>
);
case "FAMILY_PARENT_DASH":
return (
<FamilyParentDashboard
className="mb-10"
data={userDetails}
bannerList={props.bannerList}
nextDueTask={props.nextDueTask}
/>
);
case "WORKER_HOME_DASH":
return (
<WorkerDashboard
className="mb-10"
data={userDetails}
bannerList={props.bannerList}
nextDueTask={props.nextDueTask}
/>
);
case "JOBOWNER_HOME_DASH":
return (
<JobOwnerDashboard
className="mb-10"
data={userDetails}
bannerList={props.bannerList}
nextDueTask={props.nextDueTask}
/>
);
default:
return null;
}
};
return (
<>
<div className="home-page-wrapper">
<Hero
className="mb-10"
data={userDetails}
bannerList={props.bannerList}
nextDueTask={props.nextDueTask}
/>
{props.offersList?.data?.result_list?.length ? (
{renderDashboard()}
{props?.dashTypes !== "undefined" && props.offersList?.data?.result_list?.length ? (
<MyOffersTable
MyActiveOffersList={props.offersList?.data}
className="mb-10"
+1
View File
@@ -82,6 +82,7 @@ export default function Home(props) {
<FullAccountDash
nextDueTask={nextDueTask}
bannerList={props.bannerList}
dashTypes={props.dashTypes}
offersList={MyOffersList}
MyActiveJobList={MyActiveJobList}
/>
+163 -84
View File
@@ -1,5 +1,5 @@
import { useCallback, useEffect, useMemo, useState } from "react";
import { useSelector } from "react-redux";
import { useDispatch, useSelector } from "react-redux";
import usersService from "../../services/UsersService";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import SelectBox from "../Helpers/SelectBox";
@@ -11,9 +11,13 @@ import EditJobPopOut from "../jobPopout/EditJobPopout";
import DeleteIcon from "../../assets/images/icon-delete.svg";
import EditIcon from "../../assets/images/icon-edit.svg";
import { tableReload } from "../AddJob/settings";
import CreditPopup from "../MyWallet/Popup/CreditPopup";
import JobListPopout from "../jobPopout/JobListPopout";
export default function MyJobTable({ MyJobList, reloadJobList, className }) {
const dispatch = useDispatch();
// Getting the categories
const currentJobCart = MyJobList?.data?.categories;
// DropDown Box
@@ -23,21 +27,44 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
Object.keys(filterCategories)[0]
);
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
const [jobPopout, setJobPopout] = useState({ show: false, data: {} });
let [deleteJobPopout, setDeleteJobPopout] = useState({
const [deleteJobPopout, setDeleteJobPopout] = useState({
show: false,
data: {},
}); // STATE TO HOLD THE VALUE OF THE ITEM DETAILS TO DELETE AND DETERMINE WHEN TO SHOW
});
const [editJob, setEditJob] = useState({ show: false, data: {} });
const [myCountry, setCountries] = useState("");
const {
userDetails: { country },
} = useSelector((state) => state?.userDetails);
const userApi = useMemo(() => new usersService(), []);
const [creditPopup, setCreditPopup] = useState({ show: false, data: {} });
const [walletItem, setWalletItem] = useState(null);
/**
* Opens the credit popup.
* @param {Object} value - The value object.
*/
const openPopUp = (value) => {
setCreditPopup({
show: true,
data: { ...value },
});
};
/**
* Closes the credit popup and dispatches a table reload action.
*/
const closePopUp = () => {
setCreditPopup({ show: false, data: {} });
dispatch(tableReload({ type: "WALLETTABLE" }));
};
// Get Country Api
const getCountryList = useCallback(async () => {
try {
@@ -98,6 +125,121 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
}
};
const { MyJobListHeader, MyJobListTable } = myJobTableFeatures(
filterCategories,
selectedCategory,
handleSetCategory,
setDeleteJobPopout,
setEditJob,
setJobPopout,
MyJobList,
filteredCurrentJobList,
handlePagination,
currentPage,
currentJobList,
indexOfFirstItem,
indexOfLastItem
);
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px] ${
className || ""
}`}
>
<MyJobListHeader />
{MyJobList?.loading ? (
<LoadingSpinner size="16" color="sky-blue" />
) : (
<MyJobListTable />
)}
{/* Job List Popout */}
{jobPopout.show && (
<JobListPopout
details={jobPopout.data}
onClose={() => {
setJobPopout({ show: false, data: {} });
}}
setWalletItem={setWalletItem}
openWallet={openPopUp}
situation={jobPopout.show}
/>
)}
{/* End of Job List Popout */}
{/* Delete Job Popout */}
{deleteJobPopout.show && (
<DeleteJobPopout
details={deleteJobPopout.data}
onClose={() => {
setDeleteJobPopout({ show: false, data: {} });
}}
reloadJobList={reloadJobList}
situation={deleteJobPopout.show}
/>
)}
{/* END of Delete Job Popout */}
{editJob.show && (
<EditJobPopOut
details={editJob.data}
onClose={() => {
setEditJob({
show: false,
data: {},
});
}}
situation={editJob.show}
country={myCountry}
categories={currentJobCart}
/>
)}
{creditPopup.show && (
<CreditPopup
details={creditPopup.data}
walletItem={walletItem}
onClose={closePopUp}
situation={openPopUp}
/>
)}
</div>
);
}
function myJobTableFeatures(
filterCategories,
selectedCategory,
handleSetCategory,
setDeleteJobPopout,
setEditJob,
setJobPopout,
MyJobList,
filteredCurrentJobList,
handlePagination,
currentPage,
currentJobList,
indexOfFirstItem,
indexOfLastItem
) {
// List of job table features
const MyJobListHeader = () => (
<div className="header w-full flex justify-between items-center mb-5">
<div className="flex space-x-2 items-center">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
{filterCategories[selectedCategory]} Jobs
</h1>
</div>
<SelectBox
action={handleSetCategory}
datas={Object.values(filterCategories)}
className="Update-table-dropdown"
contentBodyClasses="w-auto min-w-max"
/>
</div>
);
const JobListItem = ({ value, index, image_server }) => {
let thePrice = PriceFormatter(
value?.price * 0.01,
@@ -187,7 +329,10 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
<button
type="button"
onClick={() => {
setJobPopout({ show: true, data: { thePrice, ...value } });
setJobPopout({
show: true,
data: { thePrice, ...value },
});
}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
@@ -198,32 +343,32 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
);
};
const NoJobsRow = ({ text }) => (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<td className="p-2">{text}</td>
</tr>
);
const MyJobListTable = () => (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between min-h-[520px]">
<table className="table-auto min-w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
<>
{MyJobList &&
MyJobList?.data?.result_list &&
MyJobList.data?.result_list.length > 0 ? (
filteredCurrentJobList?.length ? (
{MyJobList?.data?.result_list?.length > 0 ? (
filteredCurrentJobList.length > 0 ? (
filteredCurrentJobList.map((value, index) => (
<JobListItem
index={index}
key={index}
index={index}
value={value}
image_server={MyJobList?.data.session_image_server}
image_server={MyJobList.data.session_image_server}
/>
))
) : (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<td className="p-2">No Jobs Available In This Category!</td>
</tr>
<NoJobsRow text="No Jobs Available In This Category!" />
)
) : (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<td className="p-2">No Jobs Available!</td>
</tr>
<NoJobsRow text="No Jobs Available!" />
)}
</>
</tbody>
@@ -246,71 +391,5 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
{/* END OF PAGINATION BUTTON */}
</div>
);
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px] ${
className || ""
}`}
>
<div className="header w-full flex justify-between items-center mb-5">
<div className="flex space-x-2 items-center">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
{filterCategories[selectedCategory]} Jobs
</h1>
</div>
<SelectBox
action={handleSetCategory}
datas={Object.values(filterCategories)}
className="Update-table-dropdown"
contentBodyClasses="w-auto min-w-max"
/>
</div>
{MyJobList?.loading ? (
<LoadingSpinner size="16" color="sky-blue" />
) : (
<MyJobListTable />
)}
{/* Job List Popout */}
{jobPopout.show && (
<JobListPopout
details={jobPopout.data}
onClose={() => {
setJobPopout({ show: false, data: {} });
}}
situation={jobPopout.show}
/>
)}
{/* End of Job List Popout */}
{/* Delete Job Popout */}
{deleteJobPopout.show && (
<DeleteJobPopout
details={deleteJobPopout.data}
onClose={() => {
setDeleteJobPopout({ show: false, data: {} });
}}
reloadJobList={reloadJobList}
situation={deleteJobPopout.show}
/>
)}
{/* END of Delete Job Popout */}
{editJob.show && (
<EditJobPopOut
details={editJob.data}
onClose={() => {
setEditJob({
show: false,
data: {},
});
}}
situation={editJob.show}
country={myCountry}
categories={currentJobCart}
/>
)}
</div>
);
return { MyJobListHeader, MyJobListTable };
}
@@ -1,11 +1,10 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import Layout from "../Partials/Layout";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import CommonHead from "../UserHeader/CommonHead";
import MyPendingJobTable from "./MyPendingJobTable";
import LoadingSpinner from "../Spinners/LoadingSpinner";
export default function MyPendingJobs(props) {
export default function MyOffers(props) {
const [selectTab, setValue] = useState("today");
const filterHandler = (value) => {
setValue(value);
@@ -13,9 +12,7 @@ export default function MyPendingJobs(props) {
// console.log("AMEYE LOC1", props.MyJobList);
return (
<Layout>
<CommonHead
commonHeadData={props.commonHeadData}
/>
<CommonHead commonHeadData={props.commonHeadData} />
<div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full">
{/* heading */}
@@ -25,7 +22,7 @@ export default function MyPendingJobs(props) {
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
>
Pending Job(s)
Pending Offers
</span>
</h1>
</div>
@@ -36,13 +33,17 @@ export default function MyPendingJobs(props) {
></div>
</div>
</div>
{props.MyJobList.loading ?
<div className="bg-white">
<LoadingSpinner size='16' color='sky-blue' height='min-h-[300px]' />
</div>
:
<MyPendingJobTable MyJobList={props.MyJobList.data} />
}
{props.MyJobList.loading ? (
<div className="bg-white">
<LoadingSpinner
size="16"
color="sky-blue"
height="min-h-[300px]"
/>
</div>
) : (
<MyPendingJobTable MyJobList={props.MyJobList.data} />
)}
</div>
</div>
</Layout>
@@ -66,6 +66,8 @@ const initialValues = {
function AddFundDollars(props) {
let MaxNoOfCards = process.env.REACT_APP_MAX_CREDIT_CARDS; // HOLDS THE VALUE OF THE MAX NUMBER OF CARDS USER CAN ADD
let [loadingState, setLoadingState] = useState(false)
const apiCall = new usersService();
let countryWallet = props.walletItem.country;
const [selectedOption, setSelectedOption] = useState("previous");
@@ -162,10 +164,11 @@ function AddFundDollars(props) {
}
}
props.setConfirmCredit((prev) => ({
...prev,
show: { awaitConfirm: { loader: true } },
}));
// props.setConfirmCredit((prev) => ({
// ...prev,
// show: { awaitConfirm: { loader: true } },
// }));
setLoadingState(true)
// Extracting card_uid from the previous card details
const paymentCardValue = prevCardDetails["payment-card"];
@@ -193,6 +196,18 @@ function AddFundDollars(props) {
if (res.data.internal_return < 0) {
props.setInputError("An Error Occurred");
throw new Error("An Error Occurred");
// use commented code when you when to display pop for failed start credit API
// props.setConfirmCredit((prev) => ({
// ...prev,
// show: {
// awaitConfirm: { loader: false, state: false },
// acceptConfirm: { loader: false, state: true },
// },
// data: {internal_return: -1}
// }));
setLoadingState(false)
return
}
const _response = res.data;
@@ -204,6 +219,7 @@ function AddFundDollars(props) {
stateData = { ...stateData, ..._response };
setTimeout(() => {
setLoadingState(false)
props.setConfirmCredit({
show: {
awaitConfirm: { loader: false, state: true },
@@ -213,6 +229,7 @@ function AddFundDollars(props) {
});
}, 1500);
} catch (error) {
setLoadingState(false)
props.setInputError(error.message);
setTimeout(() => props.setInputError(""), 5000);
props.setConfirmCredit((prev) => ({
@@ -582,7 +599,7 @@ function AddFundDollars(props) {
type="submit"
className="px-4 py-1 h-11 max-w-[115px] w-full flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
{props.confirmCredit?.show?.awaitConfirm?.loader ? (
{loadingState ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<>
@@ -616,7 +633,7 @@ function AddFundDollars(props) {
type="button"
className="px-4 py-1 h-11 max-w-[115px] w-full flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
{props.confirmCredit?.show?.awaitConfirm?.loader ? (
{loadingState ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<span className="text-white">Continue</span>
@@ -86,6 +86,16 @@ function AddFundPop({
}));
setInputError("An Error Occurred");
setTimeout(() => setInputError(""), 5000);
// use commented code when you when to display pop for failed start credit API
// setConfirmCredit((prev) => ({
// ...prev,
// show: {
// awaitConfirm: { loader: false, state: false },
// acceptConfirm: { loader: false, state: true },
// },
// data: {internal_return: -1}
// }));
return;
}
@@ -70,7 +70,8 @@ function CompleteConfirmCredit({ onClose, confirmCredit }) {
}`}
</span>
</div>
{data?.curr_balance &&
<div className="flex items-center gap-8">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Wallet Balance
@@ -79,6 +80,7 @@ function CompleteConfirmCredit({ onClose, confirmCredit }) {
{data?.curr_balance * 0.01}
</span>
</div>
}
{isSuccess && (
<div className="flex items-center gap-8">
@@ -239,7 +239,8 @@ function ConfirmAddFund({
setConfirmCredit((prev) => ({
...prev,
show: {
acceptConfirm: { loader: false },
awaitConfirm: { loader: false, state: false },
acceptConfirm: { loader: false, state: true },
},
}));
return;
@@ -261,7 +262,8 @@ function ConfirmAddFund({
setConfirmCredit((prev) => ({
...prev,
show: {
acceptConfirm: { loader: false },
awaitConfirm: { loader: false, state: false },
acceptConfirm: { loader: false, state: true },
},
}));
console.log(error);
@@ -333,7 +335,8 @@ function ConfirmAddFund({
setConfirmCredit((prev) => ({
...prev,
show: {
acceptConfirm: { loader: false },
awaitConfirm: { loader: false, state: false },
acceptConfirm: { loader: false, state: true },
},
}));
setTimeout(() => onClose, 10000);
@@ -79,7 +79,7 @@ const CreditPopup = ({ details, onClose, situation, walletItem }) => {
<ConfirmAddFund
confirmCredit={confirmCredit}
setConfirmCredit={setConfirmCredit}
walletItem={walletItem}
walletItem={walletItem || details}
onClose={onClose}
/>
) : confirmCredit?.show?.acceptConfirm?.state ? (
+1 -1
View File
@@ -47,7 +47,7 @@ const WalletRoutes = () => {
}
setAllCountries((prev) => ({
loading: false,
data: res.data.result_list,
data: res?.data?.result_list,
}));
})
.catch((error) => {
+24 -23
View File
@@ -48,6 +48,7 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
// 9308RDR122
const handlerBalance = () => {
setbalanceValue.toggle();
if (notificationDropdown) {
@@ -238,9 +239,9 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
</div>
</button>
{/* balance */}
{/* My Page Button */}
<PageButton />
{userDetails.account_type === "FULL" ? <PageButton /> : null}
{/*<div className="lg:hidden block"></div>*/}
<WalletHeader
@@ -671,28 +672,28 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
);
}
const PageButton = () => {
return (
<Link to="/yourpage" className="lg:flex hidden user-balance cursor-pointer lg:w-[152px] w-[150px] h-[48px] items-center rounded-full relative bg-sky-blue pr-1.5 pl-4">
<div
className="flex items-center lg:justify-between justify-center w-full h-full"
>
<span className="lg:block hidden w-[25px]">
<Link
to="/yourpage"
className="lg:flex hidden user-balance cursor-pointer lg:w-[152px] w-[150px] h-[48px] items-center rounded-full relative bg-sky-blue pr-1.5 pl-4"
>
<div className="flex items-center lg:justify-between justify-center w-full h-full">
<span className="lg:block hidden w-[25px]">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 68 50" id="Page">
<path
fillRule="evenodd"
d="M0 13V2a2 2 0 0 1 2-2h64a2 2 0 0 1 2 2v11H0Zm0 4v31a2 2 0 0 0 2 2h20V17H0Zm26 33h40a2 2 0 0 0 2-2V17H26v33Z"
fill="#ffffff"
className="color000000 svgShape"
></path>
</svg>
</span>
<p className="lg:text-xl text-lg font-bold text-white">My Page</p>
<span className="lg:block hidden">
{/* <Icons name="deep-plus" /> */}
</span>
</div>
<path
fillRule="evenodd"
d="M0 13V2a2 2 0 0 1 2-2h64a2 2 0 0 1 2 2v11H0Zm0 4v31a2 2 0 0 0 2 2h20V17H0Zm26 33h40a2 2 0 0 0 2-2V17H26v33Z"
fill="#ffffff"
className="color000000 svgShape"
></path>
</svg>
</span>
<p className="lg:text-xl text-lg font-bold text-white">My Page</p>
<span className="lg:block hidden">
{/* <Icons name="deep-plus" /> */}
</span>
</div>
</Link>
)
}
);
};
+7 -2
View File
@@ -192,8 +192,13 @@ export default function MobileSidebar({
{[
{ name: "List", path: "/myjobs", iconName: "job-list" },
{
name: "Pending",
path: "/my-pending-jobs",
name: "Offers",
path: "/my-offers",
iconName: "pending-job",
},
{
name: "Waiting",
path: "/pend-interest",
iconName: "pending-job",
},
{
+1 -1
View File
@@ -190,7 +190,7 @@ export default function RightSideBar({myJobList}) {
{/* name */}
<div>
<p className="text-thin-light-gray text-base font-medium">
<NavLink to="/my-review-jobs">Review Pending</NavLink>
<NavLink to="/my-review-jobs">Review</NavLink>
</p>
</div>
</div>
+9 -5
View File
@@ -8,14 +8,13 @@ import {
import DarkModeContext from "../Contexts/DarkModeContext";
import Icons from "../Helpers/Icons";
export default function Sidebar({
sidebar,
action,
logoutModalHandler,
myJobList,
}) {
const darkMode = useContext(DarkModeContext);
const darkMode = useContext(DarkModeContext);
let { userDetails } = useSelector((state) => state.userDetails);
//const jobLists = getJobList(); // pass from upper - we need in a lot of places
@@ -218,8 +217,13 @@ export default function Sidebar({
iconName: "job-list",
},
{
name: "Pending",
path: "/my-pending-jobs",
name: "Waiting",
path: "/pend-interest",
iconName: "pending-job",
},
{
name: "Offers",
path: "/my-offers",
iconName: "pending-job",
},
{
@@ -291,7 +295,7 @@ export default function Sidebar({
className="signout-btn w-full flex items-center justify-center"
>
<span className="p-[1px] w-[40px] h-[40px] border border-purple rounded-full">
<Icons name='new-logout' />
<Icons name="new-logout" />
</span>
</button>
)}
+109 -80
View File
@@ -6,7 +6,6 @@ import usersService from "../../services/UsersService";
import { tableReload } from "../../store/TableReloads";
import InputCom from "../Helpers/Inputs/InputCom/index";
import ModalCom from "../Helpers/ModalCom";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import Detail from "./popoutcomponent/Detail";
@@ -23,7 +22,13 @@ const validationSchema = Yup.object().shape({
group: Yup.string(),
});
function JobListPopout({ details, onClose, situation }) {
function JobListPopout({
details,
onClose,
situation,
openWallet,
setWalletItem,
}) {
const [selectedTab, setSelectedTab] = useState("public");
const tabs = ["public", "individual", "group"];
@@ -65,6 +70,12 @@ function JobListPopout({ details, onClose, situation }) {
const taskWalletSelector = getWalletDetail(details?.currency);
const openCreditPopup = () => {
onClose();
setWalletItem(taskWalletSelector);
openWallet();
};
// member listing
const memberList = useCallback(async () => {
setLoader({ member: true, jobFields: false });
@@ -138,6 +149,7 @@ function JobListPopout({ details, onClose, situation }) {
job_uid,
job_description: textArea,
};
let reqData;
// for family input
@@ -183,18 +195,18 @@ function JobListPopout({ details, onClose, situation }) {
const res = await apiCall.assignJobTask(reqData);
let { status, data } = await res;
if (status != 200 || data.internal_return < 0) {
setRequestStatus({ message: "Unable to complete", status: false });
setRequestStatus({ message: data?.status ? data?.status : "Unable to assign offer", status: false });
return setTimeout(() => {
setLoader({ jobFields: false });
setRequestStatus({ message: "", status: false });
}, 3000);
}
dispatch(tableReload({ type: "JOBTABLE" }));
setRequestStatus({ message: "Successful", status: true });
setRequestStatus({ message: data?.status_msg ? data?.status_msg : "Offer Assigned Successful", status: true });
setTimeout(() => {
setLoader({ jobFields: false });
onClose();
throw new Response(data);
// throw new Response(data);
}, 3000);
} catch (error) {
setRequestStatus({ message: "Unable to complete", status: false });
@@ -238,7 +250,50 @@ function JobListPopout({ details, onClose, situation }) {
});
}, []);
console.log("wallet >> ", walletDetails, details, taskWalletSelector);
const DetailsSection = ({ label, value }) => (
<div className="my-3 md:flex">
<Detail label={label} value={value} />
</div>
);
const DetailsComponent = () => {
const detailsArray = [
{ label: "Description", value: details.description },
{ label: "Price", value: details.thePrice },
{ label: "Timeline", value: `${details.timeline_days} day(s)` },
{ label: "Created", value: new Date(details?.created).toDateString() },
];
return (
<div className="px-4 pb-3 w-full md:border-r-2">
{/* <p className='text-lg font-semibold text-slate-900 tracking-wide'>{details.title}</p> */}
{/* INPUT SECTION */}
{detailsArray.map((detail, index) => (
<DetailsSection
key={index}
label={detail.label}
value={detail.value}
/>
))}
<div className="">
<label className="w-full text-slate-900 dark:text-white tracking-wide font-semibold">
Delivery Detail
</label>
<textarea
className={`p-2 w-full text-sm text-slate-900 dark:text-white bg-transparent outline-none border border-slate-300 rounded-md`}
rows="7"
style={{ resize: "none" }}
value={textArea}
onChange={handleInputChange}
/>
<p>{errMsg.deliveryDetail}</p>
</div>
</div>
);
};
return (
<ModalCom action={onClose} situation={situation} className="">
<div className="logout-modal-wrapper w-[90%] md:w-[768px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
@@ -272,48 +327,9 @@ function JobListPopout({ details, onClose, situation }) {
</svg>
</button>
</div>
<div className="md:grid grid-cols-2 bg-white dark:bg-dark-white rounded-lg shadow-lg">
<div className="px-4 pb-3 w-full md:border-r-2">
{/* <p className='text-lg font-semibold text-slate-900 tracking-wide'>{details.title}</p> */}
{/* INPUT SECTION */}
<div className="my-3 md:flex">
<Detail label="Description" value={details.description} />
</div>
<div className="my-3 md:flex">
<Detail label="Price" value={details.thePrice} />
</div>
<div className="my-3 md:flex">
<Detail
label="Timeline"
value={`${details.timeline_days} day(s)`}
/>
</div>
<div className="my-3 md:flex">
<Detail
label="Created"
value={new Date(details?.created).toDateString()}
/>
</div>
<div className="">
<label className="w-full text-slate-900 dark:text-white tracking-wide font-semibold">
Delivery Detail
</label>
<textarea
className={`p-2 w-full text-sm text-slate-900 dark:text-white bg-transparent outline-none border border-slate-300 rounded-md`}
rows="7"
style={{ resize: "none" }}
value={textArea}
onChange={handleInputChange}
/>
<p>{errMsg.deliveryDetail}</p>
</div>
</div>
<DetailsComponent />
<>
{/* ACTION SECTION */}
{+taskWalletSelector.amount > +details.price ? (
@@ -324,26 +340,12 @@ function JobListPopout({ details, onClose, situation }) {
<div className="flex flex-col grow">
<div className="grid grid-cols-3 mt-4">
{tabs.map((item) => (
<button
// className={`px-4 py-1 rounded-t-2xl ${selectedTab == item ? 'btn-gradient border-[2px] text-white' : 'bg-white text-[#000] border-t-[2px]'}`}
className={`px-4 py-1 rounded-t-2xl border-t-[2px] transition-all duration-200 flex flex-col justify-center items-center ${
selectedTab == item
? "bg-red-50 dark:bg-[#D85A5A] text-slate-600 font-extrabold"
: "bg-white text-[#000]"
}`}
value={item}
name={item}
onClick={() => setSelectedTab(item)}
>
<div
className={`mb-[1px] h-6 w-6 border-4 rounded-full transition-all duration-200 ${
selectedTab == item
? "border-white bg-emerald-500"
: "border-red-50 dark:border-[#D85A5A] bg-white"
}`}
></div>
{item[0].toUpperCase() + item.slice(1)}
</button>
<TabButton
key={item}
item={item}
selectedTab={selectedTab}
setSelectedTab={setSelectedTab}
/>
))}
</div>
<div className="grow flex flex-col bg-red-50 dark:bg-[#D85A5A] rounded-b-2xl">
@@ -496,7 +498,10 @@ function JobListPopout({ details, onClose, situation }) {
</div>
</div>
) : (
<ZeroBalanceChecker {...taskWalletSelector} />
<ZeroBalanceChecker
{...taskWalletSelector}
openCreditPopup={openCreditPopup}
/>
)}
{/* END OF ACTION SECTION */}
@@ -570,11 +575,6 @@ const JobFieldInput = ({
{item?.name}
</option>
)}
{/* {inputName === "group" && (
<option value={item?.group_id} key={idx}>
{item?.group_name}
</option>
)} */}
</React.Fragment>
))}
</>
@@ -588,7 +588,11 @@ const JobFieldInput = ({
<option value="">{optionText}</option>
{data?.groups?.map((item, index) => (
<option value={item?.group_id} key={index}>
{item?.group_name}
{`${item?.group_name} (${
item?.member_count == null
? "0"
: ' ' + item.member_count + ' '
})`}
</option>
))}
</>
@@ -653,18 +657,43 @@ const publicArray = [
{ duration: 28, name: "4 weeks" },
];
const ZeroBalanceChecker = ({ amount, code, country }) => {
let thePrice = PriceFormatter(amount * 0.01, code, country);
const ZeroBalanceChecker = ({ amount, code, country, openCreditPopup }) => {
return (
<div className="px-4 pb-3 w-full flex flex-col gap-5 items-center">
<h1 className="text-lg mt-3 font-medium tracking-wide text-black dark:text-white">
Wallet Balance:{` ${code} ${amount}`}
Wallet Balance:{` ${code} ${(+amount * 0.01).toFixed(2)}`}
</h1>
<p className="font-semibold text-center text-red-500 text-lg">You do not have sufficient balance to assign this task</p>
<button className="btn-gradient w-48 h-[46px] text-white rounded-full text-base bg-pink flex justify-center items-center">
<p className="font-semibold text-center text-red-500 text-lg">
You do not have sufficient balance to assign this task
</p>
<button
onClick={openCreditPopup}
className="btn-gradient w-48 h-[46px] text-white rounded-full text-base bg-pink flex justify-center items-center"
>
Add Credit to Wallet
</button>
</div>
);
};
const TabButton = ({ item, selectedTab, setSelectedTab }) => (
<button
className={`px-4 py-1 rounded-t-2xl border-t-[2px] transition-all duration-200 flex flex-col justify-center items-center ${
selectedTab === item
? "bg-red-50 dark:bg-[#D85A5A] text-slate-600 font-extrabold"
: "bg-white text-[#000]"
}`}
value={item}
name={item}
onClick={() => setSelectedTab(item)}
>
<div
className={`mb-[1px] h-6 w-6 border-4 rounded-full transition-all duration-200 ${
selectedTab === item
? "border-white bg-emerald-500"
: "border-red-50 dark:border-[#D85A5A] bg-white"
}`}
></div>
{item[0].toUpperCase() + item.slice(1)}
</button>
);
+1 -1
View File
@@ -227,7 +227,7 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
console.log("ERROR ", error);
});
}, []);
//
//FUNCTION TO GET COMMON HEAD DATA
useEffect(() => {
apiCall
+7 -8
View File
@@ -1,18 +1,17 @@
import React, {useState, useEffect} from 'react'
import { useSelector } from "react-redux";
import Home from "../components/Home";
import usersService from "../services/UsersService";
import { useSelector } from 'react-redux';
export default function HomePages() {
const { commonHeadBanner } = useSelector((state) => state.commonHeadBanner);
const {commonHeadBanner} = useSelector(state => state.commonHeadBanner)
const bannerOptions = {
bannerList: commonHeadBanner?.result_list,
dashTypes: commonHeadBanner?.home_dash_type,
};
return (
<>
<Home
bannerList={commonHeadBanner?.result_list}
/>
<Home {...bannerOptions} />
</>
);
}
@@ -1,34 +1,34 @@
import React, { useContext, useState, useEffect } from "react";
import usersService from "../services/UsersService";
import MyPendingJobs from "../components/MyPendingJobs";
import React, { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import MyOffers from "../components/MyOffers";
import usersService from "../services/UsersService";
export default function MyPendingJobsPage() {
export default function MyOffersPage() {
let { commonHeadBanner } = useSelector((state) => state.commonHeadBanner);
let { pendingListTable } = useSelector((state) => state.tableReload);
const [MyJobList, setMyJobList] = useState({loading: true, data: []});
const [MyJobList, setMyJobList] = useState({ loading: true, data: [] });
const api = new usersService();
const getMyJobList = async () => {
setMyJobList({loading: true, data: []});
setMyJobList({ loading: true, data: [] });
try {
const res = await api.getMyPendingJobList();
setMyJobList({loading: false, data: res.data});
setMyJobList({ loading: false, data: res.data });
} catch (error) {
setMyJobList({loading: false, data: []});
setMyJobList({ loading: false, data: [] });
console.log("Error getting mode");
}
};
useEffect(() => {
getMyJobList();
getMyJobList();
}, [pendingListTable]);
// debugger;
return (
<>
<MyPendingJobs
<MyOffers
MyJobList={MyJobList}
commonHeadData={commonHeadBanner.result_list}
/>