Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b6ab3a6ee7 | |||
| f968cc5a50 | |||
| 1ddb2fd903 | |||
| 70f6ac4e24 | |||
| 3d30481852 | |||
| 63c0b07f61 | |||
| 60568c42e8 | |||
| 77ac52820d | |||
| 240e075305 | |||
| bea41d8181 | |||
| 6268d68b67 | |||
| f96b16b373 | |||
| 9fb6a4db86 | |||
| 1aa3c79666 | |||
| ecc2360dc4 | |||
| ca9bb1c211 | |||
| 2f756d189a | |||
| d7acea769c | |||
| 7ff5e2b6e0 | |||
| 2f90c4a6c2 | |||
| 29e0345e1c | |||
| 129cdc8cba | |||
| 9d42ebebab | |||
| 6193f0b492 | |||
| 1d86465812 | |||
| 7a6f43ad20 | |||
| 37b94a68ca | |||
| a1b63c5d0c | |||
| e5162a2aaf | |||
| 6ee9c7e7d8 | |||
| 5928ddb3c1 | |||
| 06c1e339b1 | |||
| 29cec58122 | |||
| d258158a13 | |||
| 1c47fa283a | |||
| d1b07e6e66 | |||
| 648f228e45 | |||
| 551a302ede | |||
| 108c82b2f8 | |||
| f46713ef00 | |||
| 992993b710 | |||
| 617df4200e | |||
| a47e398e87 | |||
| 281c4c7ab7 | |||
| 3c901e5d0d | |||
| 3bcbaae4c3 | |||
| 17e972d603 | |||
| 0e4b1af1ce |
@@ -98,4 +98,8 @@ REACT_APP_FAMILY_MINIMUM_AGE=4
|
|||||||
REACT_APP_FAMILY_MAXIMUM_AGE=18
|
REACT_APP_FAMILY_MAXIMUM_AGE=18
|
||||||
|
|
||||||
#CHANGE LOGIN LAYOUT
|
#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
@@ -66,4 +66,8 @@ REACT_APP_FAMILY_MINIMUM_AGE=4
|
|||||||
REACT_APP_FAMILY_MAXIMUM_AGE=18
|
REACT_APP_FAMILY_MAXIMUM_AGE=18
|
||||||
|
|
||||||
#CHANGE LOGIN LAYOUT
|
#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
@@ -72,4 +72,8 @@ REACT_APP_FAMILY_MINIMUM_AGE=4
|
|||||||
REACT_APP_FAMILY_MAXIMUM_AGE=18
|
REACT_APP_FAMILY_MAXIMUM_AGE=18
|
||||||
|
|
||||||
#CHANGE LOGIN LAYOUT
|
#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'
|
||||||
|
|||||||
@@ -17,6 +17,9 @@
|
|||||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||||
<title>WrenchBoard</title>
|
<title>WrenchBoard</title>
|
||||||
|
|
||||||
|
<!-- FONT AWESOME -->
|
||||||
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v6.5.1/css/all.css"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
|||||||
+16
-16
@@ -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 { Navigate, useLocation } from "react-router-dom";
|
||||||
|
import Routers from "./Routers";
|
||||||
|
import Toaster from "./components/Helpers/Toaster";
|
||||||
|
import Default from "./components/Partials/Default";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const {pathname} = useLocation()
|
const { pathname } = useLocation();
|
||||||
return (
|
return (
|
||||||
<Default>
|
<Default>
|
||||||
<>
|
<>
|
||||||
{pathname.startsWith('/@') ?
|
{pathname.startsWith("/@") ? (
|
||||||
<Navigate to="/app" replace={true} />
|
<Navigate to="/app" replace={true} />
|
||||||
:
|
) : (
|
||||||
<Routers />
|
<Routers />
|
||||||
}
|
)}
|
||||||
<Toaster />
|
<Toaster />
|
||||||
</>
|
</>
|
||||||
</Default>
|
</Default>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
+111
-76
@@ -1,65 +1,61 @@
|
|||||||
import { Route, Routes } from "react-router-dom";
|
import { Route, Routes } from "react-router-dom";
|
||||||
import FourZeroFour from "./components/FourZeroFour";
|
import FourZeroFour from "./components/FourZeroFour";
|
||||||
import ScrollToTop from "./components/Helpers/ScrollToTop";
|
import ScrollToTop from "./components/Helpers/ScrollToTop";
|
||||||
import MyCollection from "./components/MyCollection";
|
import StartJob from "./components/MyJobs/StartJob";
|
||||||
import Notification from "./components/Notification";
|
import Notification from "./components/Notification";
|
||||||
import AuthRoute from "./middleware/AuthRoute";
|
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 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 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 ForgotPasswordPages from "./views/ForgotPasswordPages";
|
||||||
import ForgotPasswordPagesTwo from "./views/ForgotPasswordPagesTwo";
|
import ForgotPasswordPagesTwo from "./views/ForgotPasswordPagesTwo";
|
||||||
import HistoryPage from "./views/HistoryPage";
|
import HistoryPage from "./views/HistoryPage";
|
||||||
import HomePages from "./views/HomePages";
|
import HomePages from "./views/HomePages";
|
||||||
|
import JobGroupsPage from "./views/JobGroupsPage";
|
||||||
|
import LndPage from "./views/LndPage";
|
||||||
import LoginPage from "./views/LoginPage";
|
import LoginPage from "./views/LoginPage";
|
||||||
import LoginPageTwo from "./views/LoginPageTwo";
|
import LoginPageTwo from "./views/LoginPageTwo";
|
||||||
|
import ManageActiveJobs from "./views/ManageActiveJobs";
|
||||||
|
import ManageInterestOfferPage from "./views/ManageInterestOfferPage";
|
||||||
import MarketPlacePage from "./views/MarketPlacePage";
|
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 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 SavedPage from "./views/SavedPage";
|
||||||
import SellPage from "./views/SellPage";
|
import SellPage from "./views/SellPage";
|
||||||
import SettingsPage from "./views/SettingsPage";
|
import SettingsPage from "./views/SettingsPage";
|
||||||
import ShopDetailsPage from "./views/ShopDetailsPage";
|
|
||||||
import SignupPage from "./views/SignupPage";
|
import SignupPage from "./views/SignupPage";
|
||||||
import SignupPageTwo from "./views/SignupPageTwo";
|
import SignupPageTwo from "./views/SignupPageTwo";
|
||||||
|
import TrackingPage from "./views/TrackingPage";
|
||||||
import UpdatePasswordPages from "./views/UpdatePasswordPages";
|
import UpdatePasswordPages from "./views/UpdatePasswordPages";
|
||||||
import UpdatePasswordPagesTwo from "./views/UpdatePasswordPagesTwo";
|
import UpdatePasswordPagesTwo from "./views/UpdatePasswordPagesTwo";
|
||||||
import UploadProductPage from "./views/UploadProductPage";
|
import UploadProductPage from "./views/UploadProductPage";
|
||||||
import UserProfilePage from "./views/UserProfilePage";
|
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 VerifyLinkPages from "./views/VerifyLinkPages";
|
||||||
import VerifyLinkPagesTwo from "./views/VerifyLinkPagesTwo";
|
import VerifyLinkPagesTwo from "./views/VerifyLinkPagesTwo";
|
||||||
import MyActiveJobsPage from "./views/MyActiveJobsPage";
|
import VerifyPasswordPages from "./views/VerifyPasswordPages";
|
||||||
import FamilyAccPage from "./views/FamilyAccPage";
|
import VerifyPasswordPagesTwo from "./views/VerifyPasswordPagesTwo";
|
||||||
import StartJob from "./components/MyJobs/StartJob";
|
import VerifyYouPages from "./views/VerifyYouPages";
|
||||||
import AddJobPage from "./views/AddJobPage";
|
import VerifyYouPagesTwo from "./views/VerifyYouPagesTwo";
|
||||||
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 YourPages from "./views/YourPage_";
|
import YourPages from "./views/YourPage_";
|
||||||
|
|
||||||
export default function Routers() {
|
export default function Routers() {
|
||||||
@@ -67,31 +63,47 @@ export default function Routers() {
|
|||||||
<ScrollToTop>
|
<ScrollToTop>
|
||||||
<Routes>
|
<Routes>
|
||||||
{/* guest routes */}
|
{/* guest routes */}
|
||||||
{process.env.REACT_APP_NEW_LOGIN_LAYOUT == 1 ?
|
{process.env.REACT_APP_NEW_LOGIN_LAYOUT == 1 ? (
|
||||||
<>
|
<>
|
||||||
<Route exact path="/login" element={<LoginPageTwo />} />
|
<Route exact path="/login" element={<LoginPageTwo />} />
|
||||||
<Route exact path="/signup" element={<SignupPageTwo />} />
|
<Route exact path="/signup" element={<SignupPageTwo />} />
|
||||||
<Route exact path="/forgot-password" element={<ForgotPasswordPagesTwo />} />
|
<Route
|
||||||
<Route exact path="/update-password" element={<UpdatePasswordPagesTwo />} />
|
exact
|
||||||
<Route path="/vemail" element={<VerifyLinkPagesTwo />} />
|
path="/forgot-password"
|
||||||
<Route path="/complereset" element={<VerifyPasswordPagesTwo />} />
|
element={<ForgotPasswordPagesTwo />}
|
||||||
<Route exact path="/outmessage" element={<VerifyYouPagesTwo />} />
|
/>
|
||||||
<Route exact path="/eoffer" element={<LoginPageTwo />} />
|
<Route
|
||||||
<Route exact path="/invite" element={<LoginPageTwo />} />
|
exact
|
||||||
</>
|
path="/update-password"
|
||||||
:
|
element={<UpdatePasswordPagesTwo />}
|
||||||
<>
|
/>
|
||||||
<Route exact path="/login" element={<LoginPage />} />
|
<Route path="/vemail" element={<VerifyLinkPagesTwo />} />
|
||||||
<Route exact path="/signup" element={<SignupPage />} />
|
<Route path="/complereset" element={<VerifyPasswordPagesTwo />} />
|
||||||
<Route exact path="/forgot-password" element={<ForgotPasswordPages />} />
|
<Route exact path="/outmessage" element={<VerifyYouPagesTwo />} />
|
||||||
<Route exact path="/update-password" element={<UpdatePasswordPages />} />
|
<Route exact path="/eoffer" element={<LoginPageTwo />} />
|
||||||
<Route path="/vemail" element={<VerifyLinkPages />} />
|
<Route exact path="/invite" element={<LoginPageTwo />} />
|
||||||
<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" 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" element={<AuthRedirect />} />
|
||||||
<Route exact path="/login/auth/flogin" element={<FacebookRedirect />} />
|
<Route exact path="/login/auth/flogin" element={<FacebookRedirect />} />
|
||||||
<Route exact path="/login/auth/apple" element={<AppleRedirectPage />} />
|
<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-place" element={<MarketPlacePage />} />
|
||||||
<Route exact path="/market" element={<MarketPlacePage />} />
|
<Route exact path="/market" element={<MarketPlacePage />} />
|
||||||
<Route exact path="/familymarket" element={<FamilyMarketPage />} />
|
<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="/notification" element={<Notification />} />
|
||||||
<Route exact path="/mytask" element={<MyTaskPage />} />
|
<Route exact path="/mytask" element={<MyTaskPage />} />
|
||||||
<Route exact path="/myjobs" element={<MyJobsPage />} />
|
<Route exact path="/myjobs" element={<MyJobsPage />} />
|
||||||
{/* <Route exact path="/add-job" element={<AddJobPage />} /> */}
|
{/* <Route exact path="/add-job" element={<AddJobPage />} /> */}
|
||||||
<Route exact path="/my-active-jobs" element={<MyActiveJobsPage />} />
|
<Route exact path="/my-active-jobs" element={<MyActiveJobsPage />} />
|
||||||
<Route exact path="/my-pastdue-jobs" element={<MyPastDueJobsPage />} />
|
<Route
|
||||||
<Route exact path="/my-pending-jobs" element={<MyPendingJobsPage />} />
|
exact
|
||||||
<Route exact path="/pend-interest" element={<MyWaitingJobsPage />} />
|
path="/my-pastdue-jobs"
|
||||||
<Route exact path="/my-review-jobs" element={<MyReviewDueJobsPage />} />
|
element={<MyPastDueJobsPage />}
|
||||||
<Route exact path="/acc-family" element={<FamilyAccPage />} />
|
/>
|
||||||
<Route exact path="/manage-family" element={<FamilyManagePage />} />
|
<Route exact path="/my-offers" element={<MyOffersPage />} />
|
||||||
<Route exact path="/start-job" element={<StartJob />} />
|
<Route exact path="/pend-interest" element={<MyWaitingJobsPage />} />
|
||||||
<Route exact path="/yourpage" element={<YourPages />} />
|
<Route
|
||||||
<Route exact path="/manage-active-job" element={<ManageActiveJobs />} />
|
exact
|
||||||
<Route exact path="/blog-page" element={<BlogPage />} />
|
path="/my-review-jobs"
|
||||||
<Route exact path="/offer-interest" element={<OffersInterestPage />} />
|
element={<MyReviewDueJobsPage />}
|
||||||
<Route exact path="/manage-offer" element={<ManageInterestOfferPage />} />
|
/>
|
||||||
|
<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
|
<Route
|
||||||
exact
|
exact
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 206 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 245 KiB |
@@ -1,20 +1,28 @@
|
|||||||
import React, { lazy } from "react";
|
import React, { lazy, useContext } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { localImgLoad } from "../../lib";
|
import { localImgLoad } from "../../lib";
|
||||||
|
|
||||||
|
import DarkModeContext from "../Contexts/DarkModeContext";
|
||||||
|
|
||||||
export default function LoginLayout({ slogan, children }) {
|
export default function LoginLayout({ slogan, children }) {
|
||||||
const bgImg = localImgLoad('images/left-wrenchboard.jpg')
|
const bgImg = localImgLoad('images/left-wrenchboard.jpg')
|
||||||
|
const bgImgNig = localImgLoad('images/wrench-home-back-nigeria.jpg')
|
||||||
|
const bgImgCom = localImgLoad('images/wrench-home-back-common.jpg')
|
||||||
|
|
||||||
|
const {countryMode} = useContext(DarkModeContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`layout-wrapper login`}>
|
<div className={`h-screen overflow-y-auto bg-cover bg-center`}
|
||||||
<div className={`w-full min-h-screen overflow-y-auto lg:grid grid-cols-2`}>
|
style={{backgroundImage: `url(${ countryMode == 'NG' ? bgImgNig : bgImgCom})`}}
|
||||||
<div
|
>
|
||||||
|
<div className={`w-full grid grid-cols-1 lg:grid-cols-2`}>
|
||||||
|
{/* <div
|
||||||
className={`auth-bg hidden lg:block bg-blue-50 relative bg-cover bg-no-repeat border-0 after:content-[''] after:absolute after:inset-0`}
|
className={`auth-bg hidden lg:block bg-blue-50 relative bg-cover bg-no-repeat border-0 after:content-[''] after:absolute after:inset-0`}
|
||||||
style={{backgroundImage: `url(${bgImg})`}}
|
style={{backgroundImage: `url(${bgImg})`}}
|
||||||
>
|
>
|
||||||
</div>
|
</div> */}
|
||||||
<div className="p-5 sm:p-7 flex place-content-center">
|
<div className="p-5 sm:p-7 flex place-content-center lg:col-start-2">
|
||||||
<div className="py-10 w-11/12 h-full flex flex-col justify-between items-center content-wrapper login shadow-md xl:bg-white 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">
|
<div className="w-full flex justify-center items-center">
|
||||||
{children && children}
|
{children && children}
|
||||||
</div>
|
</div>
|
||||||
@@ -48,7 +56,7 @@ export default function LoginLayout({ slogan, children }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className="py-1 text-black text-[15px] px-2 font-medium flex items-center gap-1">
|
<p className="py-1 text-black text-[15px] px-2 font-medium flex items-center gap-1">
|
||||||
<span className="">© {new Date().getFullYear()} -</span>
|
<span className="dark:text-white">© {new Date().getFullYear()} -</span>
|
||||||
<Link to="/" className="text-[#009ef7] ml-1">
|
<Link to="/" className="text-[#009ef7] ml-1">
|
||||||
WrenchBoard
|
WrenchBoard
|
||||||
</Link>{" "}
|
</Link>{" "}
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ export default function ForgotPassword() {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex place-content-center">
|
<div className="flex place-content-center">
|
||||||
<div className="w-11/12 sm:max-w-[400px]">
|
<div className="w-10/12">
|
||||||
{msgSuccess == null ?
|
{msgSuccess == null ?
|
||||||
<>
|
<>
|
||||||
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ export default function Login() {
|
|||||||
</div>
|
</div>
|
||||||
{/* <div className="content-wrapper login shadow-md w-10/12 mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5"> */}
|
{/* <div className="content-wrapper login shadow-md w-10/12 mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5"> */}
|
||||||
<div className="flex place-content-center">
|
<div className="flex place-content-center">
|
||||||
<div className="w-11/12 sm:max-w-[530px]">
|
<div className="w-10/12">
|
||||||
{/* HIDES THIS IF USER SESSION HAS EXPIRED */}
|
{/* HIDES THIS IF USER SESSION HAS EXPIRED */}
|
||||||
{sessionExpired != "true" && (
|
{sessionExpired != "true" && (
|
||||||
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
||||||
@@ -520,11 +520,36 @@ export default function Login() {
|
|||||||
}
|
}
|
||||||
{/* END of login component */}
|
{/* 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" && (
|
{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
|
<div className="pt-5 text-[#181c32] text-center font-semibold text-[13.975px] leading-[20.9625px]">
|
||||||
Terms of Service apply.
|
This site is protected by a Captcha. Our Privacy Policy and
|
||||||
</div>
|
Terms of Service apply.
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,19 +9,21 @@ export default function SignUp() {
|
|||||||
// eslint-disable-next-line no-restricted-globals
|
// eslint-disable-next-line no-restricted-globals
|
||||||
const queryParams = new URLSearchParams(location?.search);
|
const queryParams = new URLSearchParams(location?.search);
|
||||||
const country = queryParams.get("cnt")?.toUpperCase();
|
const country = queryParams.get("cnt")?.toUpperCase();
|
||||||
|
|
||||||
const {pathname} = useLocation()
|
const { pathname } = useLocation();
|
||||||
const currentPath = country ? `${pathname}?cnt=${country.toLowerCase()}`:pathname // Determines the new pathname is country query params exist
|
const currentPath = country
|
||||||
|
? `${pathname}?cnt=${country.toLowerCase()}`
|
||||||
|
: pathname; // Determines the new pathname is country query params exist
|
||||||
|
|
||||||
const [signUpLoading, setSignUpLoading] = useState(false);
|
const [signUpLoading, setSignUpLoading] = useState(false);
|
||||||
const [checked, setValue] = useState(false);
|
const [checked, setValue] = useState(false);
|
||||||
// for the catch error
|
// for the catch error
|
||||||
const [msgError, setMsgError] = useState("");
|
const [msgError, setMsgError] = useState("");
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
const [countries, setCountries] = useState({loading:true, data:[]});
|
const [countries, setCountries] = useState({ loading: true, data: [] });
|
||||||
|
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
country: country? country : "",
|
country: country ? country : "",
|
||||||
first_name: "",
|
first_name: "",
|
||||||
last_name: "",
|
last_name: "",
|
||||||
email: "",
|
email: "",
|
||||||
@@ -47,22 +49,23 @@ export default function SignUp() {
|
|||||||
|
|
||||||
// Get Country Api
|
// Get Country Api
|
||||||
const getCountryList = useCallback(async () => {
|
const getCountryList = useCallback(async () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await userApi.getSignupCountryData();
|
const res = await userApi.getSignupCountryData();
|
||||||
if (res.status === 200 && res.data.internal_return >= 0) {
|
if (res.status === 200 && res.data.internal_return >= 0) {
|
||||||
const { result_list } = await res.data;
|
const { result_list } = await res.data;
|
||||||
if(country){ // IF LINK/PATHNAME HAS CNT QUERY VALUE
|
if (country) {
|
||||||
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 LINK/PATHNAME HAS CNT QUERY VALUE
|
||||||
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
|
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
|
||||||
setFormData(prev => ({...prev, country: ''}))
|
if (!cnt.length) {
|
||||||
return setCountries({loading: false, data: result_list});
|
// 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) {
|
} else if (res.data.result !== 100) {
|
||||||
setCountries({loading: false, data:[]});
|
setCountries({ loading: false, data: [] });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
@@ -113,9 +116,7 @@ export default function SignUp() {
|
|||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const { data } = res;
|
const { data } = res;
|
||||||
if (data && data.acc === "DULPICATE") {
|
if (data && data.acc === "DULPICATE") {
|
||||||
setMsgError(
|
setMsgError("Duplicate username. Please try another email.");
|
||||||
"Unable to use this username. Please try another username."
|
|
||||||
);
|
|
||||||
setSignUpLoading(false);
|
setSignUpLoading(false);
|
||||||
}
|
}
|
||||||
if (data && data.status === "1") {
|
if (data && data.status === "1") {
|
||||||
@@ -124,6 +125,11 @@ export default function SignUp() {
|
|||||||
setSignUpLoading(false);
|
setSignUpLoading(false);
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data && data.status === "5") {
|
||||||
|
setMsgError("Something went wrong. Please try another email.");
|
||||||
|
setSignUpLoading(false);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
setSignUpLoading(false);
|
setSignUpLoading(false);
|
||||||
setMsgError("An error occurred");
|
setMsgError("An error occurred");
|
||||||
@@ -158,7 +164,7 @@ export default function SignUp() {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex place-content-center">
|
<div className="flex place-content-center">
|
||||||
<div className="w-11/12 sm:max-w-[530px]">
|
<div className="w-10/12">
|
||||||
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
||||||
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
|
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
|
||||||
Create Account
|
Create Account
|
||||||
@@ -187,7 +193,9 @@ export default function SignUp() {
|
|||||||
name="country"
|
name="country"
|
||||||
value={formData.country}
|
value={formData.country}
|
||||||
inputHandler={handleInputChange}
|
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-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">
|
<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}
|
disabled={countries.loading}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleSignUp}
|
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 ? (
|
{signUpLoading ? (
|
||||||
<div className="signup btn-loader"></div>
|
<div className="signup btn-loader"></div>
|
||||||
@@ -335,6 +343,44 @@ export default function SignUp() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -350,7 +396,7 @@ const SelectOption = ({
|
|||||||
inputHandler,
|
inputHandler,
|
||||||
value,
|
value,
|
||||||
data, // passing the data from parent
|
data, // passing the data from parent
|
||||||
disable
|
disable,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className="input-com mb-7">
|
<div className="input-com mb-7">
|
||||||
@@ -364,39 +410,33 @@ const SelectOption = ({
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<select
|
<select
|
||||||
disabled={disable}
|
disabled={disable}
|
||||||
name={name}
|
name={name}
|
||||||
id={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 "
|
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}
|
onChange={inputHandler}
|
||||||
value={value}
|
value={value}
|
||||||
>
|
>
|
||||||
{data?.data?.length > 1 ?
|
{data?.data?.length > 1 ? (
|
||||||
<>
|
<>
|
||||||
<option value={""}>Select your Country</option>
|
<option value={""}>Select your Country</option>
|
||||||
{data?.data?.map((item) => (
|
{data?.data?.map((item) => (
|
||||||
<option value={item.code} key={item.uid}>
|
<option value={item.code} key={item.uid}>
|
||||||
{item.country}
|
{item.country}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
:
|
) : data?.data?.length == 1 ? (
|
||||||
data?.data?.length == 1 ?
|
|
||||||
data?.data?.map((item) => (
|
data?.data?.map((item) => (
|
||||||
<option value={item.code} key={item.uid}>
|
<option value={item.code} key={item.uid}>
|
||||||
{item.country}
|
{item.country}
|
||||||
</option>
|
</option>
|
||||||
))
|
))
|
||||||
:
|
) : data?.data?.length < 1 && data.loading ? (
|
||||||
data?.data?.length < 1 && data.loading ?
|
<option value="">Loading...</option>
|
||||||
<option value=''>
|
) : (
|
||||||
Loading...
|
<option value="">No Country Found!</option>
|
||||||
</option>
|
)}
|
||||||
:
|
|
||||||
<option value=''>
|
|
||||||
No Country Found!
|
|
||||||
</option>
|
|
||||||
}
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export default function UpdatePassword() {
|
|||||||
<AuthLayout slogan="Welcome to myFit">
|
<AuthLayout slogan="Welcome to myFit">
|
||||||
{updated === false ? (
|
{updated === false ? (
|
||||||
<div className="flex place-content-center">
|
<div className="flex place-content-center">
|
||||||
<div className="w-11/12 sm:max-w-[600px]">
|
<div className="w-10/12">
|
||||||
<div className="title-area relative flex flex-col justify-center items-center mb-7">
|
<div className="title-area relative flex flex-col justify-center items-center mb-7">
|
||||||
<h1 className="sm:text-5xl text-4xl font-bold leading-[74px] text-dark-gray dark:text-white">
|
<h1 className="sm:text-5xl text-4xl font-bold leading-[74px] text-dark-gray dark:text-white">
|
||||||
Update Password
|
Update Password
|
||||||
|
|||||||
@@ -51,8 +51,7 @@ export default function VerifyLink() {
|
|||||||
localStorage.setItem("member_id", `${data?.member_id}`);
|
localStorage.setItem("member_id", `${data?.member_id}`);
|
||||||
localStorage.setItem("session_token", `${data?.session}`);
|
localStorage.setItem("session_token", `${data?.session}`);
|
||||||
localStorage.setItem("session", `${data?.session}`);
|
localStorage.setItem("session", `${data?.session}`);
|
||||||
localStorage.setItem("uid", data?.uid)
|
localStorage.setItem("uid", data?.uid);
|
||||||
|
|
||||||
|
|
||||||
navigate("/", { replace: true });
|
navigate("/", { replace: true });
|
||||||
setLinkLoader(false);
|
setLinkLoader(false);
|
||||||
@@ -80,19 +79,19 @@ export default function VerifyLink() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// for verifying the incoming verification link and render the correct component
|
// for verifying the incoming verification link and render the correct component
|
||||||
const verifyEmail = useCallback(async (code) => {
|
const verifyEmail = async (code) => {
|
||||||
try {
|
try {
|
||||||
const verifyRes = await userApi.verifyEmail(code);
|
const verifyRes = await userApi.verifyEmail(code);
|
||||||
if (verifyRes.status === 200) {
|
if (verifyRes.status === 200) {
|
||||||
let { data } = verifyRes;
|
let { data } = verifyRes;
|
||||||
console.log('TESTING VERIFY',data)
|
console.log("TESTING VERIFY", data);
|
||||||
if (
|
if (
|
||||||
data &&
|
data &&
|
||||||
data.internal_return >= 0 &&
|
data.internal_return >= 0 &&
|
||||||
data.status == 0 &&
|
data.status == 0 &&
|
||||||
data.pending_id != '' &&
|
data.pending_id != "" &&
|
||||||
data.pending_uid != '' &&
|
data.pending_uid != "" &&
|
||||||
data.username != '' &&
|
data.username != "" &&
|
||||||
data.status_text === "Link Verified"
|
data.status_text === "Link Verified"
|
||||||
) {
|
) {
|
||||||
setPageLoader(false);
|
setPageLoader(false);
|
||||||
@@ -106,12 +105,13 @@ export default function VerifyLink() {
|
|||||||
setLinkSuccess(false);
|
setLinkSuccess(false);
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
}
|
}
|
||||||
}, []);
|
};
|
||||||
|
|
||||||
// delay verify requests by 10000ms
|
// delay verify requests by 10000ms
|
||||||
const debouncedEmail = debounce(verifyEmail, 1000);
|
const debouncedEmail = debounce(verifyEmail, 1000);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
setEmail("")
|
||||||
debouncedEmail(token);
|
debouncedEmail(token);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -171,53 +171,57 @@ const SuccessfulComponent = ({
|
|||||||
handleEmail,
|
handleEmail,
|
||||||
msgErr,
|
msgErr,
|
||||||
loader,
|
loader,
|
||||||
}) => (
|
}) => {
|
||||||
<div className="input-area">
|
return (
|
||||||
{/* INPUT */}
|
<div className="input-area">
|
||||||
<div className="mb-5">
|
{/* INPUT */}
|
||||||
<InputCom
|
<div className="mb-5">
|
||||||
fieldClass="px-6"
|
<InputCom
|
||||||
value={email}
|
fieldClass="px-6"
|
||||||
inputHandler={handleEmail}
|
value={email}
|
||||||
placeholder="support@mermsemr.com"
|
inputHandler={handleEmail}
|
||||||
label="Email"
|
placeholder="support@mermsemr.com"
|
||||||
name="email"
|
label="Email"
|
||||||
type="email"
|
name="email"
|
||||||
iconName="message"
|
type="email"
|
||||||
/>
|
iconName="message"
|
||||||
</div>
|
autoComplete="off"
|
||||||
<div className="mb-5">
|
/>
|
||||||
<InputCom
|
</div>
|
||||||
fieldClass="px-6"
|
<div className="mb-5">
|
||||||
value={password}
|
<InputCom
|
||||||
inputHandler={handlePassword}
|
fieldClass="px-6"
|
||||||
placeholder="● ● ● ● ● ●"
|
value={password}
|
||||||
label="Password"
|
inputHandler={handlePassword}
|
||||||
name="password"
|
placeholder="● ● ● ● ● ●"
|
||||||
type="password"
|
label="Password"
|
||||||
iconName="password"
|
name="password"
|
||||||
/>
|
type="password"
|
||||||
</div>
|
iconName="password"
|
||||||
{msgErr && (
|
autoComplete="off"
|
||||||
<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>
|
||||||
|
{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>
|
||||||
)}
|
|
||||||
<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>
|
||||||
</div>
|
);
|
||||||
);
|
};
|
||||||
|
|
||||||
const ErrorComponent = ({ onClick }) => (
|
const ErrorComponent = ({ onClick }) => (
|
||||||
<div className="input-area">
|
<div className="input-area">
|
||||||
|
|||||||
@@ -51,8 +51,7 @@ export default function VerifyLink() {
|
|||||||
localStorage.setItem("member_id", `${data?.member_id}`);
|
localStorage.setItem("member_id", `${data?.member_id}`);
|
||||||
localStorage.setItem("session_token", `${data?.session}`);
|
localStorage.setItem("session_token", `${data?.session}`);
|
||||||
localStorage.setItem("session", `${data?.session}`);
|
localStorage.setItem("session", `${data?.session}`);
|
||||||
localStorage.setItem("uid", data?.uid)
|
localStorage.setItem("uid", data?.uid);
|
||||||
|
|
||||||
|
|
||||||
navigate("/", { replace: true });
|
navigate("/", { replace: true });
|
||||||
setLinkLoader(false);
|
setLinkLoader(false);
|
||||||
@@ -85,16 +84,17 @@ export default function VerifyLink() {
|
|||||||
const verifyRes = await userApi.verifyEmail(code);
|
const verifyRes = await userApi.verifyEmail(code);
|
||||||
if (verifyRes.status === 200) {
|
if (verifyRes.status === 200) {
|
||||||
let { data } = verifyRes;
|
let { data } = verifyRes;
|
||||||
console.log('TESTING VERIFY',data)
|
console.log("TESTING VERIFY", data);
|
||||||
if (
|
if (
|
||||||
data &&
|
data &&
|
||||||
data.internal_return >= 0 &&
|
data.internal_return >= 0 &&
|
||||||
data.status == 0 &&
|
data.status == 0 &&
|
||||||
data.pending_id != '' &&
|
data.pending_id != "" &&
|
||||||
data.pending_uid != '' &&
|
data.pending_uid != "" &&
|
||||||
data.username != '' &&
|
data.username != "" &&
|
||||||
data.status_text === "Link Verified"
|
data.status_text === "Link Verified"
|
||||||
) {
|
) {
|
||||||
|
setEmail(data.username);
|
||||||
setPageLoader(false);
|
setPageLoader(false);
|
||||||
} else {
|
} else {
|
||||||
setPageLoader(false);
|
setPageLoader(false);
|
||||||
@@ -132,7 +132,7 @@ export default function VerifyLink() {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex place-content-center">
|
<div className="flex place-content-center">
|
||||||
<div className="w-11/12 sm:max-w-[500px]">
|
<div className="w-10/12">
|
||||||
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
||||||
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
|
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
|
||||||
{linkSuccess
|
{linkSuccess
|
||||||
@@ -184,6 +184,7 @@ const SuccessfulComponent = ({
|
|||||||
name="email"
|
name="email"
|
||||||
type="email"
|
type="email"
|
||||||
iconName="message"
|
iconName="message"
|
||||||
|
autoComplete="off"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-5">
|
<div className="mb-5">
|
||||||
@@ -196,6 +197,7 @@ const SuccessfulComponent = ({
|
|||||||
name="password"
|
name="password"
|
||||||
type="password"
|
type="password"
|
||||||
iconName="password"
|
iconName="password"
|
||||||
|
autoComplete="off"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{msgErr && (
|
{msgErr && (
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ const VerifyPassword = () => {
|
|||||||
{requestStatus.loading ? (
|
{requestStatus.loading ? (
|
||||||
<LoadingSpinner color="sky-blue" size="16" height="h-300px" />
|
<LoadingSpinner color="sky-blue" size="16" height="h-300px" />
|
||||||
) : !requestStatus.loading && requestStatus.status ? (
|
) : !requestStatus.loading && requestStatus.status ? (
|
||||||
<div className="w-11/12 sm:max-w-[500px]">
|
<div className="w-10/12">
|
||||||
{linkSuccess == null ? (
|
{linkSuccess == null ? (
|
||||||
<>
|
<>
|
||||||
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export default function VerifyYou() {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex place-content-center">
|
<div className="flex place-content-center">
|
||||||
<div className="w-11/12 sm:max-w-[500px]">
|
<div className="w-10/12">
|
||||||
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
|
||||||
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
|
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
|
||||||
Let's verify your email now
|
Let's verify your email now
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default function HomeBannerOffersCard(props) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let { banner, banner_location } = props?.itemData;
|
let { banner, banner_location } = props?.itemData;
|
||||||
if (banner_location === "LOCAL") {
|
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);
|
setImageUrl(imagePath);
|
||||||
} else if (banner_location === "URL") setImageUrl(banner);
|
} else if (banner_location === "URL") setImageUrl(banner);
|
||||||
else return null;
|
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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
|
};
|
||||||
@@ -38,7 +38,7 @@ const validationSchema = Yup.object().shape({
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export default function InviteRelative({action, situation, setReloadRelList}) {
|
export default function InviteRelative({action, situation, setReloadRelList, relativeList}) {
|
||||||
|
|
||||||
const api = new usersService()
|
const api = new usersService()
|
||||||
|
|
||||||
@@ -49,8 +49,6 @@ export default function InviteRelative({action, situation, setReloadRelList}) {
|
|||||||
}); // STATE FOR KNOWING WHEN A REQUEST IS MADE TO THE SERVER
|
}); // STATE FOR KNOWING WHEN A REQUEST IS MADE TO THE SERVER
|
||||||
|
|
||||||
const handleInvite = (values) => {
|
const handleInvite = (values) => {
|
||||||
// delete values.firstname
|
|
||||||
// delete values.lasttname
|
|
||||||
setRequestStatus({loading: true, status: false, message: ""})
|
setRequestStatus({loading: true, status: false, message: ""})
|
||||||
api.inviteFamilyRelative(values).then(response => {
|
api.inviteFamilyRelative(values).then(response => {
|
||||||
let {status, data} = response
|
let {status, data} = response
|
||||||
@@ -169,7 +167,7 @@ export default function InviteRelative({action, situation, setReloadRelList}) {
|
|||||||
|
|
||||||
{/* Type */}
|
{/* Type */}
|
||||||
<div className="md:flex md:space-x-7 items-end mb-6">
|
<div className="md:flex md:space-x-7 items-end mb-6">
|
||||||
<div className="field w-full mb-6 md:mb-0">
|
{/* <div className="field w-full mb-6 md:mb-0">
|
||||||
<InputCom
|
<InputCom
|
||||||
fieldClass="px-6"
|
fieldClass="px-6"
|
||||||
label="Type"
|
label="Type"
|
||||||
@@ -181,6 +179,52 @@ export default function InviteRelative({action, situation, setReloadRelList}) {
|
|||||||
blurHandler={props.handleBlur}
|
blurHandler={props.handleBlur}
|
||||||
error={(props.errors.family_type && props.touched.family_type) ? props.errors.family_type : '' }
|
error={(props.errors.family_type && props.touched.family_type) ? props.errors.family_type : '' }
|
||||||
/>
|
/>
|
||||||
|
</div> */}
|
||||||
|
<div className="field w-full mb-6 xl:mb-0">
|
||||||
|
<label
|
||||||
|
htmlFor="family_type"
|
||||||
|
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex item-center gap-1"
|
||||||
|
>
|
||||||
|
Family Type
|
||||||
|
{props.errors.family_type && props.touched.family_type && (
|
||||||
|
<span className="text-[12px] text-red-500">
|
||||||
|
{props.errors.family_type}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
id="family_type"
|
||||||
|
name="family_type"
|
||||||
|
value={props.values.family_type}
|
||||||
|
className={`input-field p-2 mt-3 rounded-full placeholder:text-base text-dark-gray dark:text-white w-full h-10 bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none border`}
|
||||||
|
onChange={props.handleChange}
|
||||||
|
onBlur={props.handleBlur}
|
||||||
|
>
|
||||||
|
{relativeList?.loading ? (
|
||||||
|
<option className="text-slate-500 text-lg" value="">
|
||||||
|
Loading...
|
||||||
|
</option>
|
||||||
|
) : relativeList?.family_types?.length ? (
|
||||||
|
<>
|
||||||
|
<option className="text-slate-500 text-lg" value="">
|
||||||
|
Select Family Type
|
||||||
|
</option>
|
||||||
|
{relativeList?.family_types?.map((item, index) => (
|
||||||
|
<option
|
||||||
|
key={index}
|
||||||
|
className="text-slate-500 text-lg"
|
||||||
|
value={item?.ty}
|
||||||
|
>
|
||||||
|
{item?.ty}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<option className="text-slate-500 text-lg" value="">
|
||||||
|
No Options Found! Try Again
|
||||||
|
</option>
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div className="field w-full flex justify-end">
|
<div className="field w-full flex justify-end">
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
|
|||||||
@@ -24,21 +24,22 @@ export default function RelativeTable({relativeList}) {
|
|||||||
{relativeList && relativeList?.length > 0 ? (
|
{relativeList && relativeList?.length > 0 ? (
|
||||||
currentRelativeList.map((value, index) => (
|
currentRelativeList.map((value, index) => (
|
||||||
<tr key={value.uid || index} className="border-b dark:border-[#5356fb29] hover:bg-gray-50">
|
<tr key={value.uid || index} className="border-b dark:border-[#5356fb29] hover:bg-gray-50">
|
||||||
<td className='py-2'>
|
<td className='p-2'>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
|
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
|
||||||
{/* {value.firstname && value.firstname} {value.lastname && value.lastname} */} Firstname Lastname
|
{value.firstname && value.firstname} {value.lastname && value.lastname}
|
||||||
</h1>
|
</h1>
|
||||||
<span className="text-sm text-thin-light-gray">
|
<span className="text-sm text-thin-light-gray">
|
||||||
{/* {value.email && value.email} */} email.gmail.com
|
{value.email && value.email}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className='py-2'>
|
<td className='p-2'>
|
||||||
family type
|
{/* <span>Family Type</span> */}
|
||||||
|
<span>{value.family_type && value.family_type.toUpperCase()}</span>
|
||||||
</td>
|
</td>
|
||||||
<td className='py-2 text-right'>
|
<td className='p-2 text-right'>
|
||||||
{0}
|
{value.status && value.status}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const Relatives = () => {
|
|||||||
|
|
||||||
const [invitePopout, setInvitePopout] = useState(false)
|
const [invitePopout, setInvitePopout] = useState(false)
|
||||||
|
|
||||||
const [relativeList, setRelativeList] = useState({loading: true, data:[]})
|
const [relativeList, setRelativeList] = useState({loading: true, result_list:[], family_types:[]})
|
||||||
|
|
||||||
const showInviteMemberPopout = () => {
|
const showInviteMemberPopout = () => {
|
||||||
setInvitePopout(true)
|
setInvitePopout(true)
|
||||||
@@ -21,10 +21,14 @@ const Relatives = () => {
|
|||||||
const getRelativeList = () => {
|
const getRelativeList = () => {
|
||||||
setRelativeList(prev => ({...prev, loading: true}))
|
setRelativeList(prev => ({...prev, loading: true}))
|
||||||
api.getFamilyRelativeList().then(response => {
|
api.getFamilyRelativeList().then(response => {
|
||||||
setRelativeList({loading:false, data:response.data.family_types})
|
let {status, data} = response
|
||||||
// console.log('RESPONSE',response.data)
|
if(status != 200 || !data){
|
||||||
|
setRelativeList({loading:false, result_list:[], family_types:[]})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setRelativeList({loading:false, result_list:data?.result_list, family_types:data?.family_types})
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
setRelativeList({loading:false, data:[]})
|
setRelativeList({loading:false, result_list:[], family_types:[]})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +47,7 @@ const Relatives = () => {
|
|||||||
{relativeList.loading ?
|
{relativeList.loading ?
|
||||||
<LoadingSpinner size='8' height='h-full' />
|
<LoadingSpinner size='8' height='h-full' />
|
||||||
:
|
:
|
||||||
<RelativeTable relativeList={relativeList.data} />
|
<RelativeTable relativeList={relativeList.result_list} />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -54,6 +58,7 @@ const Relatives = () => {
|
|||||||
action={()=>setInvitePopout(false)}
|
action={()=>setInvitePopout(false)}
|
||||||
situation={invitePopout}
|
situation={invitePopout}
|
||||||
setReloadRelList={setReloadRelList}
|
setReloadRelList={setReloadRelList}
|
||||||
|
relativeList={relativeList}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
{/* END OF INVITE RELATIVE POPOUT */}
|
{/* END OF INVITE RELATIVE POPOUT */}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export default function InputCom({
|
|||||||
direction,
|
direction,
|
||||||
tabIndex,
|
tabIndex,
|
||||||
error,
|
error,
|
||||||
|
autoComplete="on"
|
||||||
}) {
|
}) {
|
||||||
const inputRef = useRef(null);
|
const inputRef = useRef(null);
|
||||||
// Entry Validation
|
// Entry Validation
|
||||||
@@ -107,6 +108,7 @@ export default function InputCom({
|
|||||||
readOnly={disable}
|
readOnly={disable}
|
||||||
onBlur={blurHandler}
|
onBlur={blurHandler}
|
||||||
dir={direction}
|
dir={direction}
|
||||||
|
autoComplete={autoComplete}
|
||||||
/>
|
/>
|
||||||
{iconName && (
|
{iconName && (
|
||||||
<div className="absolute right-6 bottom-3 z-10 flex gap-2">
|
<div className="absolute right-6 bottom-3 z-10 flex gap-2">
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import ParentWaiting from "../MyPendingJobs/ParentWaiting";
|
import ParentWaiting from "../MyOffers/ParentWaiting";
|
||||||
import MyOffersFamilyTable from "../MyTasks/MyOffersFamilyTable";
|
import MyOffersFamilyTable from "../MyTasks/MyOffersFamilyTable";
|
||||||
import FamilyActiveLSlde from "./FamilyActiveLSlde";
|
import FamilyActiveLSlde from "./FamilyActiveLSlde";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
export default function FamilyDash({ familyOffers, MyActiveJobList }) {
|
export default function FamilyDash({ familyOffers, MyActiveJobList }) {
|
||||||
// console.log("PROPS IN FAMILY DASH->", familyOffers?.result_list);
|
// console.log("PROPS IN FAMILY DASH->", familyOffers?.result_list);
|
||||||
@@ -11,6 +12,30 @@ export default function FamilyDash({ familyOffers, MyActiveJobList }) {
|
|||||||
<div>
|
<div>
|
||||||
<div className="home-page-wrapper">
|
<div className="home-page-wrapper">
|
||||||
{/* <CommonHead commonHeadData={props.commonHeadData} /> */}
|
{/* <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 && (
|
{familyOffers?.result_list && familyOffers?.result_list.length > 0 && (
|
||||||
<MyOffersFamilyTable
|
<MyOffersFamilyTable
|
||||||
familyOffers={familyOffers?.result_list}
|
familyOffers={familyOffers?.result_list}
|
||||||
@@ -19,7 +44,11 @@ export default function FamilyDash({ familyOffers, MyActiveJobList }) {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{trending && trending.length > 0 && (
|
{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" />*/}
|
{/*<TopSellerTopBuyerSliderSection className="mb-10" />*/}
|
||||||
|
|||||||
@@ -4,22 +4,62 @@ import MyOffersTable from "../MyTasks/MyOffersTable";
|
|||||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
import Hero from "./Hero";
|
import Hero from "./Hero";
|
||||||
import HomeActivities from "./HomeActivities";
|
import HomeActivities from "./HomeActivities";
|
||||||
|
import { FamilyParentDashboard, HomeDashboard, JobOwnerDashboard, WorkerDashboard } from "../Dashboards";
|
||||||
|
|
||||||
export default function FullAccountDash(props) {
|
export default function FullAccountDash(props) {
|
||||||
// console.log("PROPS IN HOME->", props);
|
// console.log("PROPS IN HOME->", props);
|
||||||
|
|
||||||
const { userDetails } = useSelector((state) => state?.userDetails);
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="home-page-wrapper">
|
<div className="home-page-wrapper">
|
||||||
<Hero
|
{renderDashboard()}
|
||||||
className="mb-10"
|
|
||||||
data={userDetails}
|
{props?.dashTypes !== "undefined" && props.offersList?.data?.result_list?.length ? (
|
||||||
bannerList={props.bannerList}
|
|
||||||
nextDueTask={props.nextDueTask}
|
|
||||||
/>
|
|
||||||
{props.offersList?.data?.result_list?.length ? (
|
|
||||||
<MyOffersTable
|
<MyOffersTable
|
||||||
MyActiveOffersList={props.offersList?.data}
|
MyActiveOffersList={props.offersList?.data}
|
||||||
className="mb-10"
|
className="mb-10"
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ export default function Home(props) {
|
|||||||
<FullAccountDash
|
<FullAccountDash
|
||||||
nextDueTask={nextDueTask}
|
nextDueTask={nextDueTask}
|
||||||
bannerList={props.bannerList}
|
bannerList={props.bannerList}
|
||||||
|
dashTypes={props.dashTypes}
|
||||||
offersList={MyOffersList}
|
offersList={MyOffersList}
|
||||||
MyActiveJobList={MyActiveJobList}
|
MyActiveJobList={MyActiveJobList}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export default function DeleteGroup({action, situation, details}) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<p className="text-xl text-center tracking-wide text-dark-gray dark:text-white">
|
<p className="text-xl text-center tracking-wide text-dark-gray dark:text-white">
|
||||||
Are you sure, you want to delete <br /> <span>'{details?.group_name}'</span>
|
Are you sure, you want to delete <br /> <span>'{details?.group_name}'</span> group?
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex space-x-2.5">
|
<div className="flex space-x-2.5">
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export default function DeleteMember({action, situation, details}) {
|
|||||||
<div className="logout-modal-wrapper lg:w-[500px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
|
<div className="logout-modal-wrapper lg:w-[500px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
|
||||||
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b border-light-purple dark:border-[#5356fb29] ">
|
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b border-light-purple dark:border-[#5356fb29] ">
|
||||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
||||||
Delete Member
|
Remove Member
|
||||||
</h1>
|
</h1>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -73,7 +73,7 @@ export default function DeleteMember({action, situation, details}) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<p className="text-xl text-center tracking-wide text-dark-gray dark:text-white">
|
<p className="text-xl text-center tracking-wide text-dark-gray dark:text-white">
|
||||||
Are you sure, you want to delete <br /> <span>'{details?.firstname} {details.lastname}'</span>
|
Are you sure, you want to remove <br /> <span>'{details?.firstname} {details.lastname}'</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex space-x-2.5">
|
<div className="flex space-x-2.5">
|
||||||
@@ -92,7 +92,7 @@ export default function DeleteMember({action, situation, details}) {
|
|||||||
type="button"
|
type="button"
|
||||||
className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full"
|
className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full"
|
||||||
>
|
>
|
||||||
Confirm Delete
|
Remove
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,72 +1,104 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import InputCom from '../../components/Helpers/Inputs/InputCom/index'
|
import AddGroup from "./AddGroup";
|
||||||
import DeleteGroup from './DeleteGroup'
|
import DeleteGroup from "./DeleteGroup";
|
||||||
import AddGroup from './AddGroup'
|
import { localImgLoad } from "../../lib";
|
||||||
|
|
||||||
export default function GroupList({groupList, selectedGroup, changeSelectedGroup, setUpdateList}) {
|
export default function GroupList({
|
||||||
|
groupList,
|
||||||
|
selectedGroup,
|
||||||
|
changeSelectedGroup,
|
||||||
|
setUpdateList,
|
||||||
|
}) {
|
||||||
|
const [deletePopout, setDeletePopout] = useState({
|
||||||
|
status: false,
|
||||||
|
data: {},
|
||||||
|
});
|
||||||
|
|
||||||
const [deletePopout, setDeletePopout] = useState({
|
const [addGroupPopout, setAddGroupPopout] = useState(false);
|
||||||
status: false,
|
|
||||||
data: {}
|
|
||||||
})
|
|
||||||
|
|
||||||
const [addGroupPopout, setAddGroupPopout] = useState(false)
|
const handleAddGroup = () => {
|
||||||
|
setAddGroupPopout(true);
|
||||||
const handleAddGroup = () => {
|
};
|
||||||
setAddGroupPopout(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleDeleteGroup = (item) => {
|
|
||||||
setDeletePopout({
|
|
||||||
status: true,
|
|
||||||
data: {...item}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const handleDeleteGroup = (item) => {
|
||||||
|
setDeletePopout({
|
||||||
|
status: true,
|
||||||
|
data: { ...item },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className='p-5 w-full lg:w-[400px] min-h-[300px] bg-sky-100 dark:bg-dark-gray rounded-2xl'>
|
<div className="p-5 w-full lg:w-[400px] min-h-[300px] bg-sky-100 dark:bg-dark-gray rounded-2xl flex flex-col">
|
||||||
{/* <h1 className='mb-5 text-lg lg:text-2xl tracking-wide font-bold text-slate-900 dark:text-slate-100'>Jobs Groups</h1> */}
|
{/* <h1 className='mb-5 text-lg lg:text-2xl tracking-wide font-bold text-slate-900 dark:text-slate-100'>Jobs Groups</h1> */}
|
||||||
<div className='flex justify-end items-center'>
|
<div className="flex justify-end items-center">
|
||||||
<button onClick={handleAddGroup} className='py-2 px-4 flex justify-center items-center bg-sky-blue hover:bg-sky-600 text-base rounded-full text-white font-bold'>Add Group</button>
|
<button
|
||||||
</div>
|
onClick={handleAddGroup}
|
||||||
|
className="py-2 px-4 flex justify-center items-center bg-sky-blue hover:bg-sky-600 text-base rounded-full text-white font-bold"
|
||||||
{groupList && groupList.length < 1 ?
|
>
|
||||||
<h1 className='my-5 text-lg tracking-wide text-slate-900 dark:text-slate-100'>No Group Found!</h1>
|
Add Group
|
||||||
:
|
</button>
|
||||||
<div className='my-4 max-h-[400px] overflow-y-auto'>
|
|
||||||
<div className='flex flex-col'>
|
|
||||||
{groupList.map(item=> (
|
|
||||||
<div key={item.group_uid} className='p-2 flex gap-2 items-center justify-between w-full'>
|
|
||||||
<div className='flex gap-2 items-center'>
|
|
||||||
<input type='radio' name='grouplist' value={item.group_id} checked={selectedGroup?.id == item?.group_id} onChange={changeSelectedGroup} className='w-[20px] h-[20px] outline-none' />
|
|
||||||
<p className='text-sm lg:text-base text-slate-900 dark:text-slate-100'>{item.group_name}</p>
|
|
||||||
</div>
|
|
||||||
<button onClick={()=>{handleDeleteGroup(item)}} className='rounded-lg text-sm bg-red-500 hover:bg-red-400 text-white font-bold py-1 px-2.5 flex justify-center items-center'>X</button>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{deletePopout.status &&
|
|
||||||
<DeleteGroup
|
|
||||||
action={()=>setDeletePopout({status:false, data:{}})}
|
|
||||||
situation={deletePopout.status}
|
|
||||||
details={deletePopout.data}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
|
|
||||||
{addGroupPopout &&
|
{groupList && groupList.length < 1 ? (
|
||||||
<AddGroup
|
<h1 className="my-5 text-lg tracking-wide text-slate-900 dark:text-slate-100">
|
||||||
action={()=>setAddGroupPopout(false)}
|
No Group Found!
|
||||||
situation={addGroupPopout}
|
</h1>
|
||||||
setUpdateList={setUpdateList}
|
) : (
|
||||||
/>
|
<div className="my-4 max-h-[596px] bg-[#fffef6] rounded overflow-y-auto flex-1">
|
||||||
}
|
<div className="flex flex-col">
|
||||||
|
{groupList.map((item) => (
|
||||||
|
<div
|
||||||
|
key={item.group_uid}
|
||||||
|
className="p-2 flex gap-2 items-center justify-between w-full"
|
||||||
|
>
|
||||||
|
<div className="flex gap-2 items-center">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="grouplist"
|
||||||
|
value={item.group_id}
|
||||||
|
checked={selectedGroup?.id == item?.group_id}
|
||||||
|
onChange={changeSelectedGroup}
|
||||||
|
className="w-[20px] h-[20px] outline-none"
|
||||||
|
/>
|
||||||
|
<p className="text-sm lg:text-base text-slate-900 dark:text-slate-100">
|
||||||
|
{item.group_name}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
handleDeleteGroup(item);
|
||||||
|
}}
|
||||||
|
className="flex relative items-center justify-center border-0 w-6 h-6"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={localImgLoad("images/icons/remove_grp.svg")}
|
||||||
|
alt="remove-icon"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{deletePopout.status && (
|
||||||
|
<DeleteGroup
|
||||||
|
action={() => setDeletePopout({ status: false, data: {} })}
|
||||||
|
situation={deletePopout.status}
|
||||||
|
details={deletePopout.data}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{addGroupPopout && (
|
||||||
|
<AddGroup
|
||||||
|
action={() => setAddGroupPopout(false)}
|
||||||
|
situation={addGroupPopout}
|
||||||
|
setUpdateList={setUpdateList}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,98 +1,118 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from "react";
|
||||||
import { handlePagingFunc } from '../Pagination/HandlePagination';
|
import { handlePagingFunc } from "../Pagination/HandlePagination";
|
||||||
import PaginatedList from '../Pagination/PaginatedList';
|
import PaginatedList from "../Pagination/PaginatedList";
|
||||||
import DeleteMember from './DeleteMember';
|
import DeleteMember from "./DeleteMember";
|
||||||
|
import { localImgLoad } from "../../lib";
|
||||||
|
|
||||||
export default function GroupMemberTable({selectedList}) {
|
export default function GroupMemberTable({ selectedList }) {
|
||||||
|
// Handle Pagination
|
||||||
// Handle Pagination
|
const [currentPage, setCurrentPage] = useState(0);
|
||||||
const [currentPage, setCurrentPage] = useState(0);
|
const indexOfFirstItem = Number(currentPage);
|
||||||
const indexOfFirstItem = Number(currentPage);
|
const indexOfLastItem =
|
||||||
const indexOfLastItem =Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
||||||
|
|
||||||
const currentSelectedList = selectedList?.slice(indexOfFirstItem, indexOfLastItem);
|
const currentSelectedList = selectedList?.slice(
|
||||||
|
indexOfFirstItem,
|
||||||
const handlePagination = (e) => {
|
indexOfLastItem
|
||||||
handlePagingFunc(e, setCurrentPage);
|
);
|
||||||
};
|
|
||||||
|
|
||||||
const [deletePopout, setDeletePopout] = useState({
|
const handlePagination = (e) => {
|
||||||
status: false,
|
handlePagingFunc(e, setCurrentPage);
|
||||||
data: {}
|
};
|
||||||
})
|
|
||||||
|
|
||||||
const handleDeleteMember = (item) => {
|
const [deletePopout, setDeletePopout] = useState({
|
||||||
setDeletePopout({
|
status: false,
|
||||||
status: true,
|
data: {},
|
||||||
data: {...item}
|
});
|
||||||
})
|
|
||||||
}
|
const handleDeleteMember = (item) => {
|
||||||
|
setDeletePopout({
|
||||||
return (
|
status: true,
|
||||||
<div className={`w-full p-8 bg-white dark:bg-dark-gray overflow-hidden rounded-2xl section-shadow`}>
|
data: { ...item },
|
||||||
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between min-h-[400px]">
|
});
|
||||||
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
|
};
|
||||||
<tbody>
|
|
||||||
<>
|
return (
|
||||||
{selectedList && selectedList?.length > 0 ? (
|
<div
|
||||||
currentSelectedList.map((value, index) => (
|
className={`w-full p-8 dark:bg-dark-gray overflow-hidden rounded-2xl section-shado bg-[#fffef6]`}
|
||||||
<tr key={value.uid} className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
|
>
|
||||||
{/* <td className="p-1">{value?.firstname}</td>
|
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between min-h-[400px]">
|
||||||
|
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
|
||||||
|
<tbody>
|
||||||
|
<>
|
||||||
|
{selectedList && selectedList?.length > 0 ? (
|
||||||
|
currentSelectedList.map((value, index) => (
|
||||||
|
<tr
|
||||||
|
key={value.uid}
|
||||||
|
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
|
||||||
|
>
|
||||||
|
{/* <td className="p-1">{value?.firstname}</td>
|
||||||
<td className="p-1">{value?.lastname}</td>
|
<td className="p-1">{value?.lastname}</td>
|
||||||
<td className="p-1">{value?.email}</td>
|
<td className="p-1">{value?.email}</td>
|
||||||
<td className="p-1 text-right">
|
<td className="p-1 text-right">
|
||||||
<button onClick={()=>{handleDeleteMember(value)}} className='rounded-lg text-sm bg-red-500 hover:bg-red-400 text-white font-bold py-1 px-2.5'>X</button>
|
<button onClick={()=>{handleDeleteMember(value)}} className='rounded-lg text-sm bg-red-500 hover:bg-red-400 text-white font-bold py-1 px-2.5'>X</button>
|
||||||
</td> */}
|
</td> */}
|
||||||
<td className='py-2'>
|
<td className="py-2">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
|
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
|
||||||
{value.firstname && value.firstname} {value.lastname && value.lastname}
|
{value.firstname && value.firstname}{" "}
|
||||||
</h1>
|
{value.lastname && value.lastname}
|
||||||
<span className="text-sm text-thin-light-gray">
|
</h1>
|
||||||
{value.email && value.email}
|
<span className="text-sm text-thin-light-gray">
|
||||||
</span>
|
{value.email && value.email}
|
||||||
</div>
|
</span>
|
||||||
</td>
|
</div>
|
||||||
<td className='py-2 text-right'>
|
</td>
|
||||||
<button onClick={()=>{handleDeleteMember(value)}} className='rounded-lg text-sm bg-red-500 hover:bg-red-400 text-white font-bold py-1 px-2.5'>X</button>
|
<td className="py-2 text-right">
|
||||||
</td>
|
<button
|
||||||
</tr>
|
onClick={() => {
|
||||||
))
|
handleDeleteMember(value);
|
||||||
) : (
|
}}
|
||||||
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
|
className="flex relative items-center justify-center border-0 w-8 h-8"
|
||||||
<td className="p-2">No Members Found</td>
|
>
|
||||||
</tr>
|
<img
|
||||||
)}
|
src={localImgLoad("images/icons/remove_grp.svg")}
|
||||||
</>
|
alt="remove-icon"
|
||||||
</tbody>
|
/>
|
||||||
</table>
|
</button>
|
||||||
|
</td>
|
||||||
{/* PAGINATION BUTTON */}
|
</tr>
|
||||||
<PaginatedList
|
))
|
||||||
onClick={handlePagination}
|
) : (
|
||||||
prev={currentPage == 0 ? true : false}
|
<tr className="font-semibold text-xl text-dark-gray dark:text-white whitespace-nowrap">
|
||||||
next={
|
<td className="p-2">No Members Found. Please add</td>
|
||||||
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
|
</tr>
|
||||||
selectedList?.length
|
)}
|
||||||
? true
|
</>
|
||||||
: false
|
</tbody>
|
||||||
}
|
</table>
|
||||||
data={selectedList}
|
|
||||||
start={indexOfFirstItem}
|
{/* PAGINATION BUTTON */}
|
||||||
stop={indexOfLastItem}
|
<PaginatedList
|
||||||
/>
|
onClick={handlePagination}
|
||||||
{/* END OF PAGINATION BUTTON */}
|
prev={currentPage == 0 ? true : false}
|
||||||
</div>
|
next={
|
||||||
|
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
|
||||||
{/* DELETE MEMBER POPOUT */}
|
selectedList?.length
|
||||||
{deletePopout.status &&
|
? true
|
||||||
<DeleteMember
|
: false
|
||||||
action={()=>setDeletePopout({status:false, data:{}})}
|
}
|
||||||
situation={deletePopout.status}
|
data={selectedList}
|
||||||
details={deletePopout.data}
|
start={indexOfFirstItem}
|
||||||
/>
|
stop={indexOfLastItem}
|
||||||
}
|
/>
|
||||||
{/* END OF DELETE MEMBER POPOUT */}
|
{/* END OF PAGINATION BUTTON */}
|
||||||
</div>
|
</div>
|
||||||
);
|
|
||||||
};
|
{/* DELETE MEMBER POPOUT */}
|
||||||
|
{deletePopout.status && (
|
||||||
|
<DeleteMember
|
||||||
|
action={() => setDeletePopout({ status: false, data: {} })}
|
||||||
|
situation={deletePopout.status}
|
||||||
|
details={deletePopout.data}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{/* END OF DELETE MEMBER POPOUT */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,79 +1,119 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from "react";
|
||||||
import Layout from '../Partials/Layout'
|
import Layout from "../Partials/Layout";
|
||||||
|
|
||||||
import GroupList from './GroupList'
|
import GroupList from "./GroupList";
|
||||||
import MemberList from './MemberList'
|
import MemberList from "./MemberList";
|
||||||
import LoadingSpinner from '../Spinners/LoadingSpinner'
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
|
|
||||||
import usersService from '../../services/UsersService'
|
import usersService from "../../services/UsersService";
|
||||||
|
|
||||||
export default function JobGroups() {
|
export default function JobGroups() {
|
||||||
|
const userApi = new usersService();
|
||||||
|
|
||||||
const userApi = new usersService();
|
const [updateList, setUpdateList] = useState(false);
|
||||||
|
|
||||||
const [updateList, setUpdateList] = useState(false)
|
const [groupList, setGroupList] = useState({
|
||||||
|
loading: true,
|
||||||
|
groups: [],
|
||||||
|
members: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const [selectedGroup, setSelectedGroup] = useState({
|
||||||
const [groupList, setGroupList] = useState({
|
id: "",
|
||||||
loading:true,
|
name: "",
|
||||||
groups: [],
|
data: [],
|
||||||
members: []
|
});
|
||||||
})
|
|
||||||
|
|
||||||
const [selectedGroup, setSelectedGroup] = useState({id:'', name:'', data: []})
|
const changeSelectedGroup = (e) => {
|
||||||
|
let groupID = e.target.value;
|
||||||
|
const activeMembers = groupList?.members?.filter(
|
||||||
|
(item) => item.group_id == groupID
|
||||||
|
);
|
||||||
|
const activeGroup = groupList?.groups?.filter(
|
||||||
|
(item) => item.group_id == groupID
|
||||||
|
);
|
||||||
|
setSelectedGroup({
|
||||||
|
id: groupID,
|
||||||
|
name: activeGroup[0]?.group_name,
|
||||||
|
data: activeMembers,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const changeSelectedGroup = (e) => {
|
useEffect(() => {
|
||||||
let groupID = e.target.value
|
setGroupList({ loading: true, groups: [], members: [] });
|
||||||
const activeMembers = groupList?.members?.filter(item => item.group_id == groupID)
|
userApi
|
||||||
const activeGroup = groupList?.groups?.filter(item => item.group_id == groupID)
|
.jobGroupList({})
|
||||||
setSelectedGroup({id: groupID, name:activeGroup[0]?.group_name, data:activeMembers})
|
.then((res) => {
|
||||||
}
|
const { status, data } = res;
|
||||||
|
if (status != 200 || data?.internal_return < 0) {
|
||||||
useEffect(()=>{
|
setGroupList({ loading: false, groups: [], members: [] });
|
||||||
setGroupList({loading: true, groups: [], members: []})
|
return;
|
||||||
userApi.jobGroupList({}).then(res => {
|
}
|
||||||
const {status, data} = res
|
if (data.result_list.length < 0) {
|
||||||
if(status != 200 || data?.internal_return < 0){
|
setGroupList({ loading: false, groups: [], members: [] });
|
||||||
setGroupList({loading: false, groups: [], members: []})
|
return;
|
||||||
return
|
}
|
||||||
}
|
setGroupList({
|
||||||
if(data.result_list.length < 0){
|
loading: false,
|
||||||
setGroupList({loading: false, groups: [], members: []})
|
groups: data.result_list,
|
||||||
return
|
members: data.result_list_member,
|
||||||
}
|
});
|
||||||
setGroupList({loading: false, groups: data.result_list, members: data.result_list_member})
|
if (selectedGroup.id == "") {
|
||||||
if(selectedGroup.id == ''){
|
let activeGroupId = data.result_list[0].group_id;
|
||||||
let activeGroupId = data.result_list[0].group_id
|
let activeGroup = data.result_list[0].group_name;
|
||||||
let activeGroup = data.result_list[0].group_name
|
let activeMembers = data.result_list_member?.filter(
|
||||||
let activeMembers = data.result_list_member?.filter(item => item.group_id == activeGroupId)
|
(item) => item.group_id == activeGroupId
|
||||||
setSelectedGroup({id: activeGroupId, name:activeGroup, data:activeMembers})
|
);
|
||||||
}else{
|
setSelectedGroup({
|
||||||
let activeMembers = data.result_list_member?.filter(item => item.group_id == selectedGroup?.id)
|
id: activeGroupId,
|
||||||
setSelectedGroup({id: selectedGroup?.id, name:selectedGroup?.name, data:activeMembers})
|
name: activeGroup,
|
||||||
}
|
data: activeMembers,
|
||||||
}).catch(error => {
|
});
|
||||||
setGroupList({loading: false, groups: [], members: []})
|
} else {
|
||||||
console.log(error)
|
let activeMembers = data.result_list_member?.filter(
|
||||||
})
|
(item) => item.group_id == selectedGroup?.id
|
||||||
},[updateList])
|
);
|
||||||
|
setSelectedGroup({
|
||||||
|
id: selectedGroup?.id,
|
||||||
|
name: selectedGroup?.name,
|
||||||
|
data: activeMembers,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setGroupList({ loading: false, groups: [], members: [] });
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}, [updateList]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<div>
|
<div>
|
||||||
<h1 className='mb-5 text-lg lg:text-2xl tracking-wide font-bold text-slate-900 dark:text-slate-100'>Jobs Groups</h1>
|
<h1 className="mb-5 text-lg lg:text-2xl tracking-wide font-bold text-slate-900 dark:text-slate-100">
|
||||||
</div>
|
Job Groups
|
||||||
<div className='p-5 w-full min-h-[400px] flex flex-col lg:flex-row gap-3 lg:gap-6 rounded-lg shadow-md bg-white dark:bg-dark-white'>
|
</h1>
|
||||||
{groupList.loading ?
|
</div>
|
||||||
<div className='w-full h-[400px] flex justify-center items-center'>
|
<div className="p-5 w-full min-h-[400px] flex flex-col lg:flex-row gap-3 lg:gap-6 rounded-lg shadow-md bg-white dark:bg-dark-white">
|
||||||
<LoadingSpinner size='16' />
|
{groupList.loading ? (
|
||||||
</div>
|
<div className="w-full h-[400px] flex justify-center items-center">
|
||||||
:
|
<LoadingSpinner size="16" />
|
||||||
<>
|
</div>
|
||||||
<GroupList groupList={groupList?.groups} selectedGroup={selectedGroup} changeSelectedGroup={changeSelectedGroup} setUpdateList={setUpdateList} />
|
) : (
|
||||||
<MemberList groupList={groupList?.groups} selectedGroup={selectedGroup} setUpdateList={setUpdateList} />
|
<>
|
||||||
</>
|
<GroupList
|
||||||
}
|
groupList={groupList?.groups}
|
||||||
</div>
|
selectedGroup={selectedGroup}
|
||||||
|
changeSelectedGroup={changeSelectedGroup}
|
||||||
|
setUpdateList={setUpdateList}
|
||||||
|
/>
|
||||||
|
<MemberList
|
||||||
|
groupList={groupList?.groups}
|
||||||
|
selectedGroup={selectedGroup}
|
||||||
|
setUpdateList={setUpdateList}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import GroupMemberTable from "./GroupMemberTable";
|
|||||||
|
|
||||||
import EmailValidator from "../../lib/EmailValidator";
|
import EmailValidator from "../../lib/EmailValidator";
|
||||||
|
|
||||||
import usersService from "../../services/UsersService";
|
|
||||||
import { apiConst } from "../../lib/apiConst";
|
import { apiConst } from "../../lib/apiConst";
|
||||||
|
import usersService from "../../services/UsersService";
|
||||||
|
|
||||||
export default function MemberList({
|
export default function MemberList({
|
||||||
groupList,
|
groupList,
|
||||||
@@ -277,7 +277,7 @@ export default function MemberList({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="my-2 flex flex-col min-h-[300px]">
|
<div className="my-2 flex flex-col min-h-[300px] h-full">
|
||||||
{selectedGroup?.data?.length < 1 ? (
|
{selectedGroup?.data?.length < 1 ? (
|
||||||
<h1 className="my-5 text-lg lg:text-xl tracking-wide text-slate-900 dark:text-slate-100">
|
<h1 className="my-5 text-lg lg:text-xl tracking-wide text-slate-900 dark:text-slate-100">
|
||||||
No Member Found, Please Add
|
No Member Found, Please Add
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useLocation, useNavigate } from "react-router-dom";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import localImgLoad from "../../lib/localImgLoad";
|
|
||||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||||
import { handlePagingFunc } from "../Pagination/HandlePagination";
|
import { handlePagingFunc } from "../Pagination/HandlePagination";
|
||||||
import PaginatedList from "../Pagination/PaginatedList";
|
import PaginatedList from "../Pagination/PaginatedList";
|
||||||
|
|
||||||
export default function MyActiveJobTable({ MyJobList, className }) {
|
export default function MyActiveJobTable({ MyJobList, className }) {
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
let { pathname } = useLocation();
|
let { pathname } = useLocation();
|
||||||
|
|
||||||
@@ -45,7 +43,11 @@ export default function MyActiveJobTable({ MyJobList, className }) {
|
|||||||
value?.currency_code,
|
value?.currency_code,
|
||||||
value?.currency
|
value?.currency
|
||||||
);
|
);
|
||||||
let image = `${MyJobList.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
|
let image = `${
|
||||||
|
MyJobList.session_image_server
|
||||||
|
}${localStorage.getItem("session_token")}/job/${
|
||||||
|
value.job_uid
|
||||||
|
}`;
|
||||||
return (
|
return (
|
||||||
<tr
|
<tr
|
||||||
key={index}
|
key={index}
|
||||||
@@ -112,7 +114,7 @@ export default function MyActiveJobTable({ MyJobList, className }) {
|
|||||||
className="px-4 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
className="px-4 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||||
>
|
>
|
||||||
{value.owner_status == "OWNER"
|
{value.owner_status == "OWNER"
|
||||||
? "Manage"
|
? "Review"
|
||||||
: "Send Updates"}
|
: "Send Updates"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import dataImage2 from "../../assets/images/data-table-user-2.png";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import SelectBox from "../Helpers/SelectBox";
|
|
||||||
import DeleteJobPopout from "../jobPopout/DeleteJobPopout";
|
|
||||||
import JobListPopout from "../jobPopout/JobListPopout";
|
|
||||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
|
||||||
import { useSelector } from "react-redux";
|
|
||||||
import usersService from "../../services/UsersService";
|
import usersService from "../../services/UsersService";
|
||||||
|
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||||
|
import SelectBox from "../Helpers/SelectBox";
|
||||||
import { handlePagingFunc } from "../Pagination/HandlePagination";
|
import { handlePagingFunc } from "../Pagination/HandlePagination";
|
||||||
import PaginatedList from "../Pagination/PaginatedList";
|
import PaginatedList from "../Pagination/PaginatedList";
|
||||||
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
|
import DeleteJobPopout from "../jobPopout/DeleteJobPopout";
|
||||||
import EditJobPopOut from "../jobPopout/EditJobPopout";
|
import EditJobPopOut from "../jobPopout/EditJobPopout";
|
||||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
|
||||||
|
|
||||||
import EditIcon from "../../assets/images/icon-edit.svg";
|
|
||||||
import DeleteIcon from "../../assets/images/icon-delete.svg";
|
import DeleteIcon from "../../assets/images/icon-delete.svg";
|
||||||
import localImgLoad from "../../lib/localImgLoad";
|
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 }) {
|
export default function MyJobTable({ MyJobList, reloadJobList, className }) {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
// Getting the categories
|
// Getting the categories
|
||||||
const currentJobCart = MyJobList?.data?.categories;
|
const currentJobCart = MyJobList?.data?.categories;
|
||||||
// DropDown Box
|
// DropDown Box
|
||||||
@@ -25,24 +27,46 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
|
|||||||
Object.keys(filterCategories)[0]
|
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,
|
show: false,
|
||||||
data: {},
|
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 [editJob, setEditJob] = useState({ show: false, data: {} });
|
||||||
|
|
||||||
const [myCountry, setCountries] = useState("");
|
const [myCountry, setCountries] = useState("");
|
||||||
|
|
||||||
const {
|
const {
|
||||||
userDetails: { country },
|
userDetails: { country },
|
||||||
} = useSelector((state) => state?.userDetails);
|
} = useSelector((state) => state?.userDetails);
|
||||||
|
|
||||||
const userApi = useMemo(() => new usersService(), []);
|
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
|
// Get Country Api
|
||||||
const getCountryList = useCallback(async () => {
|
const getCountryList = useCallback(async () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await userApi.getSignupCountryData();
|
const res = await userApi.getSignupCountryData();
|
||||||
if (res.status === 200 && res.data.internal_return >= 0) {
|
if (res.status === 200 && res.data.internal_return >= 0) {
|
||||||
@@ -59,7 +83,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
|
|||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
}
|
}
|
||||||
}, [userApi, country]);
|
}, [userApi, country]);
|
||||||
console.log('MY COUNTRY', myCountry)
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getCountryList();
|
getCountryList();
|
||||||
}, [getCountryList]);
|
}, [getCountryList]);
|
||||||
@@ -101,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 }) => {
|
const JobListItem = ({ value, index, image_server }) => {
|
||||||
let thePrice = PriceFormatter(
|
let thePrice = PriceFormatter(
|
||||||
value?.price * 0.01,
|
value?.price * 0.01,
|
||||||
@@ -190,7 +329,10 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
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"
|
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||||
>
|
>
|
||||||
@@ -201,117 +343,53 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
const NoJobsRow = ({ text }) => (
|
||||||
<div
|
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
|
||||||
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px] ${
|
<td className="p-2">{text}</td>
|
||||||
className || ""
|
</tr>
|
||||||
}`}
|
);
|
||||||
>
|
|
||||||
<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" />
|
|
||||||
) : (
|
|
||||||
<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 ? (
|
|
||||||
filteredCurrentJobList.map((value, index) => (
|
|
||||||
<JobListItem
|
|
||||||
index={index}
|
|
||||||
key={index}
|
|
||||||
value={value}
|
|
||||||
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>
|
|
||||||
)
|
|
||||||
) : (
|
|
||||||
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
|
|
||||||
<td className="p-2">No Jobs Avaliable!</td>
|
|
||||||
</tr>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
{/* PAGINATION BUTTON */}
|
const MyJobListTable = () => (
|
||||||
<PaginatedList
|
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between min-h-[520px]">
|
||||||
onClick={handlePagination}
|
<table className="table-auto min-w-full text-sm text-left text-gray-500 dark:text-gray-400">
|
||||||
prev={currentPage == 0 ? true : false}
|
<tbody>
|
||||||
next={
|
<>
|
||||||
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
|
{MyJobList?.data?.result_list?.length > 0 ? (
|
||||||
currentJobList?.length
|
filteredCurrentJobList.length > 0 ? (
|
||||||
? true
|
filteredCurrentJobList.map((value, index) => (
|
||||||
: false
|
<JobListItem
|
||||||
}
|
key={index}
|
||||||
data={currentJobList}
|
index={index}
|
||||||
start={indexOfFirstItem}
|
value={value}
|
||||||
stop={indexOfLastItem}
|
image_server={MyJobList.data.session_image_server}
|
||||||
/>
|
/>
|
||||||
{/* END OF PAGINATION BUTTON */}
|
))
|
||||||
</div>
|
) : (
|
||||||
)}
|
<NoJobsRow text="No Jobs Available In This Category!" />
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<NoJobsRow text="No Jobs Available!" />
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
{/* Job List Popout */}
|
{/* PAGINATION BUTTON */}
|
||||||
{jobPopout.show && (
|
<PaginatedList
|
||||||
<JobListPopout
|
onClick={handlePagination}
|
||||||
details={jobPopout.data}
|
prev={currentPage == 0 ? true : false}
|
||||||
onClose={() => {
|
next={
|
||||||
setJobPopout({ show: false, data: {} });
|
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
|
||||||
}}
|
currentJobList?.length
|
||||||
situation={jobPopout.show}
|
? true
|
||||||
/>
|
: false
|
||||||
)}
|
}
|
||||||
{/* End of Job List Popout */}
|
data={currentJobList}
|
||||||
|
start={indexOfFirstItem}
|
||||||
{/* Delete Job Popout */}
|
stop={indexOfLastItem}
|
||||||
{deleteJobPopout.show && (
|
/>
|
||||||
<DeleteJobPopout
|
{/* END OF PAGINATION BUTTON */}
|
||||||
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>
|
</div>
|
||||||
);
|
);
|
||||||
|
return { MyJobListHeader, MyJobListTable };
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-5
@@ -6,9 +6,7 @@ import PendingJobsPopout from "../jobPopout/PendingJobsPopout";
|
|||||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||||
import localImgLoad from "../../lib/localImgLoad";
|
import localImgLoad from "../../lib/localImgLoad";
|
||||||
|
|
||||||
|
|
||||||
export default function MyPendingJobTable({ MyJobList, className }) {
|
export default function MyPendingJobTable({ MyJobList, className }) {
|
||||||
|
|
||||||
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
|
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
|
||||||
|
|
||||||
const [currentPage, setCurrentPage] = useState(0);
|
const [currentPage, setCurrentPage] = useState(0);
|
||||||
@@ -19,7 +17,7 @@ export default function MyPendingJobTable({ MyJobList, className }) {
|
|||||||
indexOfFirstItem,
|
indexOfFirstItem,
|
||||||
indexOfLastItem
|
indexOfLastItem
|
||||||
);
|
);
|
||||||
|
|
||||||
const handlePagination = (e) => {
|
const handlePagination = (e) => {
|
||||||
handlePagingFunc(e, setCurrentPage);
|
handlePagingFunc(e, setCurrentPage);
|
||||||
};
|
};
|
||||||
@@ -46,7 +44,11 @@ export default function MyPendingJobTable({ MyJobList, className }) {
|
|||||||
value?.currency_code,
|
value?.currency_code,
|
||||||
value?.currency
|
value?.currency
|
||||||
);
|
);
|
||||||
let image = `${MyJobList.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
|
let image = `${
|
||||||
|
MyJobList.session_image_server
|
||||||
|
}${localStorage.getItem("session_token")}/job/${
|
||||||
|
value.job_uid
|
||||||
|
}`;
|
||||||
return (
|
return (
|
||||||
<tr
|
<tr
|
||||||
key={index}
|
key={index}
|
||||||
@@ -107,7 +109,9 @@ export default function MyPendingJobTable({ MyJobList, className }) {
|
|||||||
}}
|
}}
|
||||||
className="px-4 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
className="px-4 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||||
>
|
>
|
||||||
{value.owner_status == 'OWNER' ? 'Manage' : 'Send Updates'}
|
{value.owner_status == "OWNER"
|
||||||
|
? "Manage"
|
||||||
|
: "View"}
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
import Layout from "../Partials/Layout";
|
import Layout from "../Partials/Layout";
|
||||||
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
import CommonHead from "../UserHeader/CommonHead";
|
import CommonHead from "../UserHeader/CommonHead";
|
||||||
import MyPendingJobTable from "./MyPendingJobTable";
|
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 [selectTab, setValue] = useState("today");
|
||||||
const filterHandler = (value) => {
|
const filterHandler = (value) => {
|
||||||
setValue(value);
|
setValue(value);
|
||||||
@@ -13,9 +12,7 @@ export default function MyPendingJobs(props) {
|
|||||||
// console.log("AMEYE LOC1", props.MyJobList);
|
// console.log("AMEYE LOC1", props.MyJobList);
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<CommonHead
|
<CommonHead commonHeadData={props.commonHeadData} />
|
||||||
commonHeadData={props.commonHeadData}
|
|
||||||
/>
|
|
||||||
<div className="notification-page w-full mb-10">
|
<div className="notification-page w-full mb-10">
|
||||||
<div className="notification-wrapper w-full">
|
<div className="notification-wrapper w-full">
|
||||||
{/* heading */}
|
{/* heading */}
|
||||||
@@ -25,7 +22,7 @@ export default function MyPendingJobs(props) {
|
|||||||
<span
|
<span
|
||||||
className={`${selectTab === "today" ? "block" : "hidden"}`}
|
className={`${selectTab === "today" ? "block" : "hidden"}`}
|
||||||
>
|
>
|
||||||
Pending Job(s)
|
Pending Offers
|
||||||
</span>
|
</span>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
@@ -36,13 +33,17 @@ export default function MyPendingJobs(props) {
|
|||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{props.MyJobList.loading ?
|
{props.MyJobList.loading ? (
|
||||||
<div className="bg-white">
|
<div className="bg-white">
|
||||||
<LoadingSpinner size='16' color='sky-blue' height='min-h-[300px]' />
|
<LoadingSpinner
|
||||||
</div>
|
size="16"
|
||||||
:
|
color="sky-blue"
|
||||||
<MyPendingJobTable MyJobList={props.MyJobList.data} />
|
height="min-h-[300px]"
|
||||||
}
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<MyPendingJobTable MyJobList={props.MyJobList.data} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
@@ -66,6 +66,8 @@ const initialValues = {
|
|||||||
function AddFundDollars(props) {
|
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 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();
|
const apiCall = new usersService();
|
||||||
let countryWallet = props.walletItem.country;
|
let countryWallet = props.walletItem.country;
|
||||||
const [selectedOption, setSelectedOption] = useState("previous");
|
const [selectedOption, setSelectedOption] = useState("previous");
|
||||||
@@ -162,10 +164,11 @@ function AddFundDollars(props) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
props.setConfirmCredit((prev) => ({
|
// props.setConfirmCredit((prev) => ({
|
||||||
...prev,
|
// ...prev,
|
||||||
show: { awaitConfirm: { loader: true } },
|
// show: { awaitConfirm: { loader: true } },
|
||||||
}));
|
// }));
|
||||||
|
setLoadingState(true)
|
||||||
|
|
||||||
// Extracting card_uid from the previous card details
|
// Extracting card_uid from the previous card details
|
||||||
const paymentCardValue = prevCardDetails["payment-card"];
|
const paymentCardValue = prevCardDetails["payment-card"];
|
||||||
@@ -193,6 +196,18 @@ function AddFundDollars(props) {
|
|||||||
if (res.data.internal_return < 0) {
|
if (res.data.internal_return < 0) {
|
||||||
props.setInputError("An Error Occurred");
|
props.setInputError("An Error Occurred");
|
||||||
throw new Error("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;
|
const _response = res.data;
|
||||||
@@ -204,6 +219,7 @@ function AddFundDollars(props) {
|
|||||||
stateData = { ...stateData, ..._response };
|
stateData = { ...stateData, ..._response };
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
setLoadingState(false)
|
||||||
props.setConfirmCredit({
|
props.setConfirmCredit({
|
||||||
show: {
|
show: {
|
||||||
awaitConfirm: { loader: false, state: true },
|
awaitConfirm: { loader: false, state: true },
|
||||||
@@ -213,6 +229,7 @@ function AddFundDollars(props) {
|
|||||||
});
|
});
|
||||||
}, 1500);
|
}, 1500);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
setLoadingState(false)
|
||||||
props.setInputError(error.message);
|
props.setInputError(error.message);
|
||||||
setTimeout(() => props.setInputError(""), 5000);
|
setTimeout(() => props.setInputError(""), 5000);
|
||||||
props.setConfirmCredit((prev) => ({
|
props.setConfirmCredit((prev) => ({
|
||||||
@@ -582,7 +599,7 @@ function AddFundDollars(props) {
|
|||||||
type="submit"
|
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"
|
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" />
|
<LoadingSpinner size="6" color="sky-blue" />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
@@ -616,7 +633,7 @@ function AddFundDollars(props) {
|
|||||||
type="button"
|
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"
|
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" />
|
<LoadingSpinner size="6" color="sky-blue" />
|
||||||
) : (
|
) : (
|
||||||
<span className="text-white">Continue</span>
|
<span className="text-white">Continue</span>
|
||||||
|
|||||||
@@ -86,6 +86,16 @@ function AddFundPop({
|
|||||||
}));
|
}));
|
||||||
setInputError("An Error Occurred");
|
setInputError("An Error Occurred");
|
||||||
setTimeout(() => setInputError(""), 5000);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,8 @@ function CompleteConfirmCredit({ onClose, confirmCredit }) {
|
|||||||
}`}
|
}`}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{data?.curr_balance &&
|
||||||
<div className="flex items-center gap-8">
|
<div className="flex items-center gap-8">
|
||||||
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
|
||||||
Wallet Balance
|
Wallet Balance
|
||||||
@@ -79,6 +80,7 @@ function CompleteConfirmCredit({ onClose, confirmCredit }) {
|
|||||||
{data?.curr_balance * 0.01}
|
{data?.curr_balance * 0.01}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
{isSuccess && (
|
{isSuccess && (
|
||||||
<div className="flex items-center gap-8">
|
<div className="flex items-center gap-8">
|
||||||
|
|||||||
@@ -239,7 +239,8 @@ function ConfirmAddFund({
|
|||||||
setConfirmCredit((prev) => ({
|
setConfirmCredit((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
show: {
|
show: {
|
||||||
acceptConfirm: { loader: false },
|
awaitConfirm: { loader: false, state: false },
|
||||||
|
acceptConfirm: { loader: false, state: true },
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
return;
|
return;
|
||||||
@@ -261,7 +262,8 @@ function ConfirmAddFund({
|
|||||||
setConfirmCredit((prev) => ({
|
setConfirmCredit((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
show: {
|
show: {
|
||||||
acceptConfirm: { loader: false },
|
awaitConfirm: { loader: false, state: false },
|
||||||
|
acceptConfirm: { loader: false, state: true },
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
console.log(error);
|
console.log(error);
|
||||||
@@ -333,7 +335,8 @@ function ConfirmAddFund({
|
|||||||
setConfirmCredit((prev) => ({
|
setConfirmCredit((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
show: {
|
show: {
|
||||||
acceptConfirm: { loader: false },
|
awaitConfirm: { loader: false, state: false },
|
||||||
|
acceptConfirm: { loader: false, state: true },
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
setTimeout(() => onClose, 10000);
|
setTimeout(() => onClose, 10000);
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ const CreditPopup = ({ details, onClose, situation, walletItem }) => {
|
|||||||
<ConfirmAddFund
|
<ConfirmAddFund
|
||||||
confirmCredit={confirmCredit}
|
confirmCredit={confirmCredit}
|
||||||
setConfirmCredit={setConfirmCredit}
|
setConfirmCredit={setConfirmCredit}
|
||||||
walletItem={walletItem}
|
walletItem={walletItem || details}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
/>
|
/>
|
||||||
) : confirmCredit?.show?.acceptConfirm?.state ? (
|
) : confirmCredit?.show?.acceptConfirm?.state ? (
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ const WalletRoutes = () => {
|
|||||||
}
|
}
|
||||||
setAllCountries((prev) => ({
|
setAllCountries((prev) => ({
|
||||||
loading: false,
|
loading: false,
|
||||||
data: res.data.result_list,
|
data: res?.data?.result_list,
|
||||||
}));
|
}));
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
|||||||
@@ -5,6 +5,13 @@ function Default({ children }) {
|
|||||||
// dark mode setup
|
// dark mode setup
|
||||||
const [theme, setTheme] = useState(null);
|
const [theme, setTheme] = useState(null);
|
||||||
|
|
||||||
|
// country mode setup
|
||||||
|
const [countryMode, setCountryMode] = useState(localStorage.getItem('cnt') ? localStorage.getItem('cnt')?.toUpperCase() : '')
|
||||||
|
|
||||||
|
|
||||||
|
const queryParams = new URLSearchParams(location?.search);
|
||||||
|
const country = queryParams.get("cnt")?.toUpperCase();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
||||||
setTheme("dark");
|
setTheme("dark");
|
||||||
@@ -24,9 +31,17 @@ function Default({ children }) {
|
|||||||
const handleThemeSwitch = () => {
|
const handleThemeSwitch = () => {
|
||||||
setTheme(theme === "dark" ? "light" : "dark");
|
setTheme(theme === "dark" ? "light" : "dark");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(country){
|
||||||
|
setCountryMode(country)
|
||||||
|
localStorage.setItem('cnt', country)
|
||||||
|
}
|
||||||
|
},[countryMode])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DarkModeContext.Provider value={{ theme, handleThemeSwitch }}>
|
<DarkModeContext.Provider value={{ theme, handleThemeSwitch, countryMode }}>
|
||||||
{children && children}
|
{children && children}
|
||||||
</DarkModeContext.Provider>
|
</DarkModeContext.Provider>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
|||||||
|
|
||||||
// 9308RDR122
|
// 9308RDR122
|
||||||
|
|
||||||
|
|
||||||
const handlerBalance = () => {
|
const handlerBalance = () => {
|
||||||
setbalanceValue.toggle();
|
setbalanceValue.toggle();
|
||||||
if (notificationDropdown) {
|
if (notificationDropdown) {
|
||||||
@@ -238,9 +239,9 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
|||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
{/* balance */}
|
{/* balance */}
|
||||||
|
|
||||||
{/* My Page Button */}
|
{/* My Page Button */}
|
||||||
<PageButton />
|
{userDetails.account_type === "FULL" ? <PageButton /> : null}
|
||||||
|
|
||||||
{/*<div className="lg:hidden block"></div>*/}
|
{/*<div className="lg:hidden block"></div>*/}
|
||||||
<WalletHeader
|
<WalletHeader
|
||||||
@@ -671,28 +672,28 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const PageButton = () => {
|
const PageButton = () => {
|
||||||
return (
|
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">
|
<Link
|
||||||
<div
|
to="/yourpage"
|
||||||
className="flex items-center lg:justify-between justify-center w-full h-full"
|
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"
|
||||||
>
|
>
|
||||||
<span className="lg:block hidden w-[25px]">
|
<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">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 68 50" id="Page">
|
||||||
<path
|
<path
|
||||||
fillRule="evenodd"
|
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"
|
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"
|
fill="#ffffff"
|
||||||
className="color000000 svgShape"
|
className="color000000 svgShape"
|
||||||
></path>
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
<p className="lg:text-xl text-lg font-bold text-white">My Page</p>
|
<p className="lg:text-xl text-lg font-bold text-white">My Page</p>
|
||||||
<span className="lg:block hidden">
|
<span className="lg:block hidden">
|
||||||
{/* <Icons name="deep-plus" /> */}
|
{/* <Icons name="deep-plus" /> */}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export default function Layout({ children }) {
|
|||||||
localStorage.removeItem("member_id");
|
localStorage.removeItem("member_id");
|
||||||
localStorage.removeItem("uid");
|
localStorage.removeItem("uid");
|
||||||
sessionStorage.removeItem("family_uid");
|
sessionStorage.removeItem("family_uid");
|
||||||
// localStorage.clear();
|
localStorage.clear();
|
||||||
// toast.success("Come Back Soon", {
|
// toast.success("Come Back Soon", {
|
||||||
// icon: `🙂`,
|
// icon: `🙂`,
|
||||||
// });
|
// });
|
||||||
|
|||||||
@@ -192,8 +192,13 @@ export default function MobileSidebar({
|
|||||||
{[
|
{[
|
||||||
{ name: "List", path: "/myjobs", iconName: "job-list" },
|
{ name: "List", path: "/myjobs", iconName: "job-list" },
|
||||||
{
|
{
|
||||||
name: "Pending",
|
name: "Offers",
|
||||||
path: "/my-pending-jobs",
|
path: "/my-offers",
|
||||||
|
iconName: "pending-job",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Waiting",
|
||||||
|
path: "/pend-interest",
|
||||||
iconName: "pending-job",
|
iconName: "pending-job",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ export default function RightSideBar({myJobList}) {
|
|||||||
{/* name */}
|
{/* name */}
|
||||||
<div>
|
<div>
|
||||||
<p className="text-thin-light-gray text-base font-medium">
|
<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>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,14 +8,13 @@ import {
|
|||||||
import DarkModeContext from "../Contexts/DarkModeContext";
|
import DarkModeContext from "../Contexts/DarkModeContext";
|
||||||
import Icons from "../Helpers/Icons";
|
import Icons from "../Helpers/Icons";
|
||||||
|
|
||||||
|
|
||||||
export default function Sidebar({
|
export default function Sidebar({
|
||||||
sidebar,
|
sidebar,
|
||||||
action,
|
action,
|
||||||
logoutModalHandler,
|
logoutModalHandler,
|
||||||
myJobList,
|
myJobList,
|
||||||
}) {
|
}) {
|
||||||
const darkMode = useContext(DarkModeContext);
|
const darkMode = useContext(DarkModeContext);
|
||||||
|
|
||||||
let { userDetails } = useSelector((state) => state.userDetails);
|
let { userDetails } = useSelector((state) => state.userDetails);
|
||||||
//const jobLists = getJobList(); // pass from upper - we need in a lot of places
|
//const jobLists = getJobList(); // pass from upper - we need in a lot of places
|
||||||
@@ -218,8 +217,13 @@ export default function Sidebar({
|
|||||||
iconName: "job-list",
|
iconName: "job-list",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Pending",
|
name: "Waiting",
|
||||||
path: "/my-pending-jobs",
|
path: "/pend-interest",
|
||||||
|
iconName: "pending-job",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Offers",
|
||||||
|
path: "/my-offers",
|
||||||
iconName: "pending-job",
|
iconName: "pending-job",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -291,7 +295,7 @@ export default function Sidebar({
|
|||||||
className="signout-btn w-full flex items-center justify-center"
|
className="signout-btn w-full flex items-center justify-center"
|
||||||
>
|
>
|
||||||
<span className="p-[1px] w-[40px] h-[40px] border border-purple rounded-full">
|
<span className="p-[1px] w-[40px] h-[40px] border border-purple rounded-full">
|
||||||
<Icons name='new-logout' />
|
<Icons name="new-logout" />
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { Field, Form, Formik } from "formik";
|
import { Field, Form, Formik } from "formik";
|
||||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import usersService from "../../services/UsersService";
|
import usersService from "../../services/UsersService";
|
||||||
|
import { tableReload } from "../../store/TableReloads";
|
||||||
import InputCom from "../Helpers/Inputs/InputCom/index";
|
import InputCom from "../Helpers/Inputs/InputCom/index";
|
||||||
import ModalCom from "../Helpers/ModalCom";
|
import ModalCom from "../Helpers/ModalCom";
|
||||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
import Detail from "./popoutcomponent/Detail";
|
import Detail from "./popoutcomponent/Detail";
|
||||||
import { tableReload } from "../../store/TableReloads";
|
|
||||||
import { useDispatch } from "react-redux";
|
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
family: Yup.string().required("This is required "),
|
family: Yup.string().required("This is required "),
|
||||||
@@ -22,14 +22,22 @@ const validationSchema = Yup.object().shape({
|
|||||||
group: Yup.string(),
|
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"];
|
||||||
|
|
||||||
const [selectedTab, setSelectedTab] = useState('public')
|
const dispatch = useDispatch();
|
||||||
const tabs = ['public', 'individual', 'group']
|
|
||||||
|
|
||||||
const dispatch = useDispatch()
|
const [requestStatus, setRequestStatus] = useState({
|
||||||
|
message: "",
|
||||||
const [requestStatus, setRequestStatus] = useState({message:'', status:false})
|
status: false,
|
||||||
|
});
|
||||||
|
|
||||||
const [familyList, setFamilyList] = useState([]);
|
const [familyList, setFamilyList] = useState([]);
|
||||||
let [loader, setLoader] = useState({
|
let [loader, setLoader] = useState({
|
||||||
@@ -43,6 +51,30 @@ const [requestStatus, setRequestStatus] = useState({message:'', status:false})
|
|||||||
});
|
});
|
||||||
|
|
||||||
const apiCall = useMemo(() => new usersService(), []);
|
const apiCall = useMemo(() => new usersService(), []);
|
||||||
|
const { walletDetails } = useSelector((state) => state.walletDetails);
|
||||||
|
|
||||||
|
const getWalletDetail = (currency) => {
|
||||||
|
// A FUNCTION TO GET USER BALANCE BASED ON TASK CURRENCY
|
||||||
|
const walletChecker = walletDetails?.data.find(
|
||||||
|
(item) => item.description === currency
|
||||||
|
);
|
||||||
|
return walletChecker
|
||||||
|
? {
|
||||||
|
description: walletChecker.description,
|
||||||
|
country: walletChecker.country,
|
||||||
|
code: walletChecker.code,
|
||||||
|
amount: walletChecker.amount,
|
||||||
|
}
|
||||||
|
: 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const taskWalletSelector = getWalletDetail(details?.currency);
|
||||||
|
|
||||||
|
const openCreditPopup = () => {
|
||||||
|
onClose();
|
||||||
|
setWalletItem(taskWalletSelector);
|
||||||
|
openWallet();
|
||||||
|
};
|
||||||
|
|
||||||
// member listing
|
// member listing
|
||||||
const memberList = useCallback(async () => {
|
const memberList = useCallback(async () => {
|
||||||
@@ -117,6 +149,7 @@ const [requestStatus, setRequestStatus] = useState({message:'', status:false})
|
|||||||
job_uid,
|
job_uid,
|
||||||
job_description: textArea,
|
job_description: textArea,
|
||||||
};
|
};
|
||||||
|
|
||||||
let reqData;
|
let reqData;
|
||||||
|
|
||||||
// for family input
|
// for family input
|
||||||
@@ -147,7 +180,7 @@ const [requestStatus, setRequestStatus] = useState({message:'', status:false})
|
|||||||
// for group input
|
// for group input
|
||||||
reqData = {
|
reqData = {
|
||||||
...jobReq,
|
...jobReq,
|
||||||
email: '',
|
email: "",
|
||||||
group_id: values?.group,
|
group_id: values?.group,
|
||||||
assign_mode: 110044,
|
assign_mode: 110044,
|
||||||
duration: details?.timeline_days,
|
duration: details?.timeline_days,
|
||||||
@@ -161,52 +194,106 @@ const [requestStatus, setRequestStatus] = useState({message:'', status:false})
|
|||||||
try {
|
try {
|
||||||
const res = await apiCall.assignJobTask(reqData);
|
const res = await apiCall.assignJobTask(reqData);
|
||||||
let { status, data } = await res;
|
let { status, data } = await res;
|
||||||
if(status != 200 || data.internal_return < 0){
|
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(()=>{
|
return setTimeout(() => {
|
||||||
setLoader({ jobFields: false });
|
setLoader({ jobFields: false });
|
||||||
setRequestStatus({message:'', status:false})
|
setRequestStatus({ message: "", status: false });
|
||||||
},3000)
|
}, 3000);
|
||||||
}
|
}
|
||||||
dispatch(tableReload({ type: "JOBTABLE" }));
|
dispatch(tableReload({ type: "JOBTABLE" }));
|
||||||
setRequestStatus({message:'Successful', status:true})
|
setRequestStatus({ message: data?.status_msg ? data?.status_msg : "Offer Assigned Successful", status: true });
|
||||||
setTimeout(()=>{
|
setTimeout(() => {
|
||||||
setLoader({ jobFields: false });
|
setLoader({ jobFields: false });
|
||||||
onClose();
|
onClose();
|
||||||
throw new Response(data);
|
// throw new Response(data);
|
||||||
},3000)
|
}, 3000);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setRequestStatus({message:'Unable to complete', status:false})
|
setRequestStatus({ message: "Unable to complete", status: false });
|
||||||
setTimeout(()=>{
|
setTimeout(() => {
|
||||||
setRequestStatus({message:'', status:false})
|
setRequestStatus({ message: "", status: false });
|
||||||
setLoader({ jobFields: false });
|
setLoader({ jobFields: false });
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
},3000)
|
}, 3000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const [groupList, setGroupList] = useState({loading: true, groups: [], members: []})
|
const [groupList, setGroupList] = useState({
|
||||||
|
loading: true,
|
||||||
|
groups: [],
|
||||||
|
members: [],
|
||||||
|
});
|
||||||
|
|
||||||
// FUNCTION TO POPULATE USER GROUP LIST
|
// FUNCTION TO POPULATE USER GROUP LIST
|
||||||
useEffect(()=>{
|
useEffect(() => {
|
||||||
// setGroupList({loading: true, groups: [], members: []})
|
// setGroupList({loading: true, groups: [], members: []})
|
||||||
apiCall.jobGroupList({}).then(res => {
|
apiCall
|
||||||
const {status, data} = res
|
.jobGroupList({})
|
||||||
if(status != 200 || data?.internal_return < 0){
|
.then((res) => {
|
||||||
setGroupList({loading: false, groups: [], members: []})
|
const { status, data } = res;
|
||||||
return
|
if (status != 200 || data?.internal_return < 0) {
|
||||||
|
setGroupList({ loading: false, groups: [], members: [] });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if(data.result_list.length < 0){
|
if (data.result_list.length < 0) {
|
||||||
setGroupList({loading: false, groups: [], members: []})
|
setGroupList({ loading: false, groups: [], members: [] });
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
setGroupList({loading: false, groups: data.result_list, members: data.result_list_member})
|
setGroupList({
|
||||||
}).catch(error => {
|
loading: false,
|
||||||
setGroupList({loading: false, groups: [], members: []})
|
groups: data.result_list,
|
||||||
})
|
members: data.result_list_member,
|
||||||
},[])
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setGroupList({ loading: false, groups: [], members: [] });
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
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>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
// console.log("Job List P >> ", details)
|
|
||||||
return (
|
return (
|
||||||
<ModalCom action={onClose} situation={situation} className="">
|
<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">
|
<div className="logout-modal-wrapper w-[90%] md:w-[768px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
||||||
@@ -240,211 +327,185 @@ const [requestStatus, setRequestStatus] = useState({message:'', status:false})
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="md:grid grid-cols-2 bg-white dark:bg-dark-white rounded-lg shadow-lg">
|
<div className="md:grid grid-cols-2 bg-white dark:bg-dark-white rounded-lg shadow-lg">
|
||||||
<div className="p-4 pb-3 w-full md:border-r-2">
|
<DetailsComponent />
|
||||||
{/* <p className='text-lg font-semibold text-slate-900 tracking-wide'>{details.title}</p> */}
|
<>
|
||||||
|
{/* ACTION SECTION */}
|
||||||
|
{+taskWalletSelector.amount > +details.price ? (
|
||||||
|
<div className="px-4 pb-3 w-full flex flex-col justify-between">
|
||||||
|
<h1 className="text-lg mt-3 font-medium tracking-wide text-black dark:text-white">
|
||||||
|
Send this Task to:
|
||||||
|
</h1>
|
||||||
|
<div className="flex flex-col grow">
|
||||||
|
<div className="grid grid-cols-3 mt-4">
|
||||||
|
{tabs.map((item) => (
|
||||||
|
<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">
|
||||||
|
{selectedTab == "family" && (
|
||||||
|
<Formik
|
||||||
|
initialValues={initialValues}
|
||||||
|
validationSchema={validationSchema.fields.family}
|
||||||
|
onSubmit={jobFieldHandler}
|
||||||
|
>
|
||||||
|
{(props) => {
|
||||||
|
return (
|
||||||
|
<Form className="hidden">
|
||||||
|
{/* Assign to Family */}
|
||||||
|
<JobFieldInput
|
||||||
|
label="Assign to family"
|
||||||
|
select={true}
|
||||||
|
inputName="family"
|
||||||
|
value={props?.values.family}
|
||||||
|
data={familyList}
|
||||||
|
btnText="Assign to family"
|
||||||
|
optionText="Select Family"
|
||||||
|
loader={loader?.jobFields?.family}
|
||||||
|
errorHandler={errorHandler}
|
||||||
|
parentClass="w-full flex flex-col gap-4"
|
||||||
|
/>
|
||||||
|
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
|
||||||
|
{" "}
|
||||||
|
{props?.values?.family === "" && (
|
||||||
|
<span>{errMsg?.jobFields?.family}</span>
|
||||||
|
)}
|
||||||
|
</p>{" "}
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Formik>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* INPUT SECTION */}
|
{selectedTab == "public" && (
|
||||||
<div className="my-3 md:flex">
|
<Formik
|
||||||
<Detail label="Description" value={details.description} />
|
initialValues={initialValues}
|
||||||
</div>
|
validationSchema={validationSchema.fields.public}
|
||||||
|
onSubmit={jobFieldHandler}
|
||||||
|
>
|
||||||
|
{(props) => {
|
||||||
|
return (
|
||||||
|
<Form className="">
|
||||||
|
{/* Offer this job to public input */}
|
||||||
|
<JobFieldInput
|
||||||
|
label="Offer this job to public"
|
||||||
|
select={true}
|
||||||
|
inputName="public"
|
||||||
|
value={props?.values.public}
|
||||||
|
data={publicArray}
|
||||||
|
btnText="Show Task to Public"
|
||||||
|
optionText="Select Duration"
|
||||||
|
loader={loader?.jobFields?.public}
|
||||||
|
errorHandler={errorHandler}
|
||||||
|
parentClass="w-full flex flex-col gap-4"
|
||||||
|
/>
|
||||||
|
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
|
||||||
|
{" "}
|
||||||
|
{props?.values.public === "" && (
|
||||||
|
<span>{errMsg?.jobFields?.public}</span>
|
||||||
|
)}
|
||||||
|
</p>{" "}
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Formik>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="my-3 md:flex">
|
{selectedTab == "individual" && (
|
||||||
<Detail label="Price" value={details.thePrice} />
|
<Formik
|
||||||
</div>
|
initialValues={initialValues}
|
||||||
|
validationSchema={validationSchema.fields.individual}
|
||||||
|
onSubmit={jobFieldHandler}
|
||||||
|
>
|
||||||
|
{(props) => {
|
||||||
|
return (
|
||||||
|
<Form className="">
|
||||||
|
{/* Offer this job to individual input */}
|
||||||
|
<JobFieldInput
|
||||||
|
label="Offer this job to individual"
|
||||||
|
input={true}
|
||||||
|
inputName="individual"
|
||||||
|
value={props?.values.individual}
|
||||||
|
placeholder="Enter email of individual"
|
||||||
|
inputHandler={props?.handleChange}
|
||||||
|
btnText="Send Offer to Individual"
|
||||||
|
loader={loader?.jobFields?.individual}
|
||||||
|
errorHandler={errorHandler}
|
||||||
|
parentClass="w-full flex flex-col gap-4"
|
||||||
|
/>
|
||||||
|
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
|
||||||
|
{" "}
|
||||||
|
{props?.values.individual === "" && (
|
||||||
|
<span>{errMsg?.jobFields?.individual}</span>
|
||||||
|
)}
|
||||||
|
</p>{" "}
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Formik>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="my-3 md:flex">
|
{/* { process.env.REACT_APP_SHOW_OFFER_GROUP_JOB != 0 && } */}
|
||||||
<Detail
|
{selectedTab == "group" && (
|
||||||
label="Timeline"
|
<Formik
|
||||||
value={`${details.timeline_days} day(s)`}
|
initialValues={initialValues}
|
||||||
/>
|
validationSchema={validationSchema.fields.group}
|
||||||
</div>
|
onSubmit={jobFieldHandler}
|
||||||
|
>
|
||||||
<div className="my-3 md:flex">
|
{(props) => {
|
||||||
<Detail
|
return (
|
||||||
label="Created"
|
<Form className="">
|
||||||
value={new Date(details?.created).toDateString()}
|
{/* Offer this job to your group input */}
|
||||||
/>
|
<JobFieldInput
|
||||||
</div>
|
label="Offer this job to your Group"
|
||||||
|
select={true}
|
||||||
<div className="">
|
inputName="group"
|
||||||
<label className="w-full text-slate-900 dark:text-white tracking-wide font-semibold">
|
value={props?.values.group}
|
||||||
Delivery Detail
|
btnText="Send Order to Group"
|
||||||
</label>
|
optionText="Select Group"
|
||||||
<textarea
|
loader={loader?.jobFields?.group}
|
||||||
className={`p-2 w-full text-sm text-slate-900 dark:text-white bg-transparent outline-none border border-slate-300 rounded-md`}
|
errorHandler={errorHandler}
|
||||||
rows="7"
|
data={groupList}
|
||||||
style={{ resize: "none" }}
|
parentClass="w-full flex flex-col gap-4"
|
||||||
value={textArea}
|
/>
|
||||||
onChange={handleInputChange}
|
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
|
||||||
/>
|
{" "}
|
||||||
<p>{errMsg.deliveryDetail}</p>
|
{props?.values.group === "" && (
|
||||||
</div>
|
<span>{errMsg?.jobFields?.group}</span>
|
||||||
</div>
|
)}
|
||||||
|
</p>
|
||||||
{/* ACTION SECTION */}
|
</Form>
|
||||||
<div className="p-4 w-ful flex flex-col justify-between">
|
);
|
||||||
<h1 className="text-lg mt-3 font-medium tracking-wide text-black dark:text-white">Send this Task to:</h1>
|
}}
|
||||||
<div className="flex flex-col grow">
|
</Formik>
|
||||||
<div className="grid grid-cols-3 mt-4">
|
)}
|
||||||
{tabs.map(item => (
|
<p
|
||||||
<button
|
className={`text-center w-full text-lg ${
|
||||||
// className={`px-4 py-1 rounded-t-2xl ${selectedTab == item ? 'btn-gradient border-[2px] text-white' : 'bg-white text-[#000] border-t-[2px]'}`}
|
requestStatus.status
|
||||||
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]'}`}
|
? "text-emerald-600"
|
||||||
value={item}
|
: "text-red-600"
|
||||||
name={item}
|
}`}
|
||||||
onClick={()=>setSelectedTab(item)}
|
>
|
||||||
>
|
{requestStatus.message && requestStatus.message}
|
||||||
<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>
|
</p>
|
||||||
{item[0].toUpperCase() + item.slice(1)}
|
</div>
|
||||||
</button>
|
</div>
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="grow flex flex-col bg-red-50 dark:bg-[#D85A5A] rounded-b-2xl">
|
) : (
|
||||||
{selectedTab == 'family' &&
|
<ZeroBalanceChecker
|
||||||
<Formik
|
{...taskWalletSelector}
|
||||||
initialValues={initialValues}
|
openCreditPopup={openCreditPopup}
|
||||||
validationSchema={validationSchema.fields.family}
|
/>
|
||||||
onSubmit={jobFieldHandler}
|
)}
|
||||||
>
|
|
||||||
{(props) => {
|
|
||||||
return (
|
|
||||||
<Form className="hidden">
|
|
||||||
{/* Assign to Family */}
|
|
||||||
<JobFieldInput
|
|
||||||
label="Assign to family"
|
|
||||||
select={true}
|
|
||||||
inputName="family"
|
|
||||||
value={props?.values.family}
|
|
||||||
data={familyList}
|
|
||||||
btnText="Assign to family"
|
|
||||||
optionText="Select Family"
|
|
||||||
loader={loader?.jobFields?.family}
|
|
||||||
errorHandler={errorHandler}
|
|
||||||
parentClass='w-full flex flex-col gap-4'
|
|
||||||
/>
|
|
||||||
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
|
|
||||||
{" "}
|
|
||||||
{props?.values?.family === "" && (
|
|
||||||
<span>{errMsg?.jobFields?.family}</span>
|
|
||||||
)}
|
|
||||||
</p>{" "}
|
|
||||||
</Form>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Formik>
|
|
||||||
}
|
|
||||||
|
|
||||||
{selectedTab == 'public' &&
|
|
||||||
<Formik
|
|
||||||
initialValues={initialValues}
|
|
||||||
validationSchema={validationSchema.fields.public}
|
|
||||||
onSubmit={jobFieldHandler}
|
|
||||||
>
|
|
||||||
{(props) => {
|
|
||||||
return (
|
|
||||||
<Form className="">
|
|
||||||
{/* Offer this job to public input */}
|
|
||||||
<JobFieldInput
|
|
||||||
label="Offer this job to public"
|
|
||||||
select={true}
|
|
||||||
inputName="public"
|
|
||||||
value={props?.values.public}
|
|
||||||
data={publicArray}
|
|
||||||
btnText="Show Task to Public"
|
|
||||||
optionText="Select Duration"
|
|
||||||
loader={loader?.jobFields?.public}
|
|
||||||
errorHandler={errorHandler}
|
|
||||||
parentClass='w-full flex flex-col gap-4'
|
|
||||||
/>
|
|
||||||
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
|
|
||||||
{" "}
|
|
||||||
{props?.values.public === "" && (
|
|
||||||
<span>{errMsg?.jobFields?.public}</span>
|
|
||||||
)}
|
|
||||||
</p>{" "}
|
|
||||||
</Form>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Formik>
|
|
||||||
}
|
|
||||||
|
|
||||||
{selectedTab == 'individual' &&
|
{/* END OF ACTION SECTION */}
|
||||||
<Formik
|
</>
|
||||||
initialValues={initialValues}
|
|
||||||
validationSchema={validationSchema.fields.individual}
|
|
||||||
onSubmit={jobFieldHandler}
|
|
||||||
>
|
|
||||||
{(props) => {
|
|
||||||
return (
|
|
||||||
<Form className="">
|
|
||||||
{/* Offer this job to individual input */}
|
|
||||||
<JobFieldInput
|
|
||||||
label="Offer this job to individual"
|
|
||||||
input={true}
|
|
||||||
inputName="individual"
|
|
||||||
value={props?.values.individual}
|
|
||||||
placeholder="Enter email of individual"
|
|
||||||
inputHandler={props?.handleChange}
|
|
||||||
btnText="Send Offer to Individual"
|
|
||||||
loader={loader?.jobFields?.individual}
|
|
||||||
errorHandler={errorHandler}
|
|
||||||
parentClass='w-full flex flex-col gap-4'
|
|
||||||
/>
|
|
||||||
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
|
|
||||||
{" "}
|
|
||||||
{props?.values.individual === "" && (
|
|
||||||
<span>{errMsg?.jobFields?.individual}</span>
|
|
||||||
)}
|
|
||||||
</p>{" "}
|
|
||||||
</Form>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Formik>
|
|
||||||
}
|
|
||||||
|
|
||||||
{/* { process.env.REACT_APP_SHOW_OFFER_GROUP_JOB != 0 && } */}
|
|
||||||
{selectedTab == 'group' &&
|
|
||||||
<Formik
|
|
||||||
initialValues={initialValues}
|
|
||||||
validationSchema={validationSchema.fields.group}
|
|
||||||
onSubmit={jobFieldHandler}
|
|
||||||
>
|
|
||||||
{(props) => {
|
|
||||||
return (
|
|
||||||
<Form className="">
|
|
||||||
{/* Offer this job to your group input */}
|
|
||||||
<JobFieldInput
|
|
||||||
label="Offer this job to your Group"
|
|
||||||
select={true}
|
|
||||||
inputName="group"
|
|
||||||
value={props?.values.group}
|
|
||||||
btnText="Send Order to Group"
|
|
||||||
optionText="Select Group"
|
|
||||||
loader={loader?.jobFields?.group}
|
|
||||||
errorHandler={errorHandler}
|
|
||||||
data={groupList}
|
|
||||||
parentClass='w-full flex flex-col gap-4'
|
|
||||||
/>
|
|
||||||
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
|
|
||||||
{" "}
|
|
||||||
{props?.values.group === "" && (
|
|
||||||
<span>{errMsg?.jobFields?.group}</span>
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
</Form>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Formik>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{requestStatus.message &&
|
|
||||||
<p className={`mt-4 w-full text-lg ${requestStatus.status ? 'text-emerald-600' : 'text-red-600'}`}>{requestStatus.message}</p>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
{/* END OF ACTION SECTION */}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ModalCom>
|
</ModalCom>
|
||||||
@@ -480,7 +541,7 @@ const JobFieldInput = ({
|
|||||||
>
|
>
|
||||||
{label && (
|
{label && (
|
||||||
<label
|
<label
|
||||||
className="input-label border-2 w-full border-sky-700 py-4 px-2 text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block tracking-wide"
|
className="input-label border-2 w-full border-sky-700 rounded py-4 px-2 text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block tracking-wide"
|
||||||
htmlFor={inputName}
|
htmlFor={inputName}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
@@ -497,51 +558,49 @@ const JobFieldInput = ({
|
|||||||
value={value}
|
value={value}
|
||||||
>
|
>
|
||||||
{/* <option value="">{optionText}</option> */}
|
{/* <option value="">{optionText}</option> */}
|
||||||
{(inputName == 'family' || inputName == 'public') &&
|
{(inputName == "family" || inputName == "public") &&
|
||||||
Array.isArray(data) &&
|
Array.isArray(data) && (
|
||||||
<>
|
|
||||||
<option value="">{optionText}</option>
|
|
||||||
{ data?.map((item, idx) => (
|
|
||||||
<React.Fragment key={idx}>
|
|
||||||
{inputName === "family" && item?.last_login !== "" && (
|
|
||||||
<option value={item?.family_uid} key={idx}>
|
|
||||||
{`${item?.firstname} ${item?.lastname}`}
|
|
||||||
</option>
|
|
||||||
)}
|
|
||||||
{inputName === "public" && (
|
|
||||||
<option value={item?.duration} key={idx}>
|
|
||||||
{item?.name}
|
|
||||||
</option>
|
|
||||||
)}
|
|
||||||
{/* {inputName === "group" && (
|
|
||||||
<option value={item?.group_id} key={idx}>
|
|
||||||
{item?.group_name}
|
|
||||||
</option>
|
|
||||||
)} */}
|
|
||||||
</React.Fragment>
|
|
||||||
))}
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
{(inputName == 'group') &&
|
|
||||||
<>
|
|
||||||
{data.loading ?
|
|
||||||
<option value={''}>
|
|
||||||
Loading...
|
|
||||||
</option>
|
|
||||||
: data?.groups?.length > 0 ?
|
|
||||||
<>
|
<>
|
||||||
<option value="">{optionText}</option>
|
<option value="">{optionText}</option>
|
||||||
{ data?.groups?.map((item, index)=>(
|
{data?.map((item, idx) => (
|
||||||
<option value={item?.group_id} key={index}>
|
<React.Fragment key={idx}>
|
||||||
{item?.group_name}
|
{inputName === "family" &&
|
||||||
</option>
|
item?.last_login !== "" && (
|
||||||
|
<option value={item?.family_uid} key={idx}>
|
||||||
|
{`${item?.firstname} ${item?.lastname}`}
|
||||||
|
</option>
|
||||||
|
)}
|
||||||
|
{inputName === "public" && (
|
||||||
|
<option value={item?.duration} key={idx}>
|
||||||
|
{item?.name}
|
||||||
|
</option>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
:
|
)}
|
||||||
<option value="">No Group Found</option>
|
{inputName == "group" && (
|
||||||
}
|
<>
|
||||||
</>
|
{data.loading ? (
|
||||||
}
|
<option value={""}>Loading...</option>
|
||||||
|
) : data?.groups?.length > 0 ? (
|
||||||
|
<>
|
||||||
|
<option value="">{optionText}</option>
|
||||||
|
{data?.groups?.map((item, index) => (
|
||||||
|
<option value={item?.group_id} key={index}>
|
||||||
|
{`${item?.group_name} (${
|
||||||
|
item?.member_count == null
|
||||||
|
? "0"
|
||||||
|
: ' ' + item.member_count + ' '
|
||||||
|
})`}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<option value="">No Group Found</option>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Field>
|
</Field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -597,3 +656,44 @@ const publicArray = [
|
|||||||
{ duration: 21, name: "3 weeks" },
|
{ duration: 21, name: "3 weeks" },
|
||||||
{ duration: 28, name: "4 weeks" },
|
{ duration: 28, name: "4 weeks" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
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 * 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
|
||||||
|
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>
|
||||||
|
);
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
|||||||
localStorage.removeItem("member_id");
|
localStorage.removeItem("member_id");
|
||||||
localStorage.removeItem("session_token");
|
localStorage.removeItem("session_token");
|
||||||
sessionStorage.removeItem("family_uid");
|
sessionStorage.removeItem("family_uid");
|
||||||
|
localStorage.clear();
|
||||||
navigate("/login", { replace: true }); // redirects user to login page after session expires
|
navigate("/login", { replace: true }); // redirects user to login page after session expires
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -226,7 +227,7 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
|||||||
console.log("ERROR ", error);
|
console.log("ERROR ", error);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
//
|
|
||||||
//FUNCTION TO GET COMMON HEAD DATA
|
//FUNCTION TO GET COMMON HEAD DATA
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
apiCall
|
apiCall
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
import React, {useState, useEffect} from 'react'
|
import { useSelector } from "react-redux";
|
||||||
import Home from "../components/Home";
|
import Home from "../components/Home";
|
||||||
import usersService from "../services/UsersService";
|
|
||||||
|
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
|
|
||||||
export default function HomePages() {
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<Home
|
<Home {...bannerOptions} />
|
||||||
bannerList={commonHeadBanner?.result_list}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,34 @@
|
|||||||
import React, { useContext, useState, useEffect } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import usersService from "../services/UsersService";
|
|
||||||
import MyPendingJobs from "../components/MyPendingJobs";
|
|
||||||
import { useSelector } from "react-redux";
|
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 { commonHeadBanner } = useSelector((state) => state.commonHeadBanner);
|
||||||
let { pendingListTable } = useSelector((state) => state.tableReload);
|
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 api = new usersService();
|
||||||
|
|
||||||
const getMyJobList = async () => {
|
const getMyJobList = async () => {
|
||||||
setMyJobList({loading: true, data: []});
|
setMyJobList({ loading: true, data: [] });
|
||||||
try {
|
try {
|
||||||
const res = await api.getMyPendingJobList();
|
const res = await api.getMyPendingJobList();
|
||||||
setMyJobList({loading: false, data: res.data});
|
setMyJobList({ loading: false, data: res.data });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setMyJobList({loading: false, data: []});
|
setMyJobList({ loading: false, data: [] });
|
||||||
console.log("Error getting mode");
|
console.log("Error getting mode");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getMyJobList();
|
getMyJobList();
|
||||||
}, [pendingListTable]);
|
}, [pendingListTable]);
|
||||||
|
|
||||||
// debugger;
|
// debugger;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MyPendingJobs
|
<MyOffers
|
||||||
MyJobList={MyJobList}
|
MyJobList={MyJobList}
|
||||||
commonHeadData={commonHeadBanner.result_list}
|
commonHeadData={commonHeadBanner.result_list}
|
||||||
/>
|
/>
|
||||||
Reference in New Issue
Block a user