Compare commits

..

84 Commits

Author SHA1 Message Date
victorAnumudu db03242886 active task header count down added 2023-06-06 15:51:36 +01:00
ameye 07c20fd927 Merge branch 'market-item-view-popup' of WrenchBoard/Users-Wrench into master 2023-06-06 10:39:39 +00:00
Ebube c706b5c143 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into market-item-view-popup 2023-06-06 11:07:31 +01:00
Ebube 294f6af6e4 Complete 2023-06-06 11:07:08 +01:00
ameye 76603294a3 Merge branch 'market-item-view-popup' of WrenchBoard/Users-Wrench into master 2023-06-06 01:37:41 +00:00
Ebube 5ff9876681 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into market-item-view-popup 2023-06-06 01:35:15 +01:00
Ebube aba23e82a1 . 2023-06-06 01:34:48 +01:00
ameye 7175c217b2 Merge branch 'home_current_task' of WrenchBoard/Users-Wrench into master 2023-06-05 20:58:26 +00:00
victorAnumudu 8a81e6da54 user currect task due time implementation 2023-06-05 19:24:54 +01:00
ameye 36ee1e8987 Merge branch 'market-item-view-popup' of WrenchBoard/Users-Wrench into master 2023-06-05 10:55:18 +00:00
Ebube b73a6afeac Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into market-item-view-popup 2023-06-05 11:45:08 +01:00
Ebube 721c5a588f . 2023-06-05 11:44:40 +01:00
ameye a2431ff825 Merge branch 'no-family-display' of WrenchBoard/Users-Wrench into master 2023-06-05 08:36:45 +00:00
victorAnumudu 692fe461c3 No family display design added 2023-06-05 03:12:46 +01:00
ameye 3f84eef132 Merge branch 'multi-upload' of WrenchBoard/Users-Wrench into master 2023-06-05 01:50:31 +00:00
victorAnumudu 119f48642d implemented multi file upload 2023-06-05 02:48:22 +01:00
ameye 1a0f97030f Merge branch 'market-item-view-popup' of WrenchBoard/Users-Wrench into master 2023-06-05 01:08:38 +00:00
CHIEFSOFT\ameye 71d1b61bbd Single file send 2023-06-04 17:43:38 -04:00
Ebube 17ffe957e8 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into market-item-view-popup 2023-06-04 20:40:18 +01:00
Ebube e23aa95685 . 2023-06-04 20:32:29 +01:00
ameye 1c1293989b Merge branch 'width-adjustment' of WrenchBoard/Users-Wrench into master 2023-06-04 18:27:25 +00:00
victorAnumudu 63448429b2 width adjusted 2023-06-04 19:14:08 +01:00
ameye 8d1eac9ff6 Merge branch 'familytasks' of WrenchBoard/Users-Wrench into master 2023-06-04 17:21:21 +00:00
Ebube 25e5c3f47a Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into familytasks 2023-06-04 15:01:03 +01:00
Ebube 9f9c36ec85 . 2023-06-04 14:59:54 +01:00
CHIEFSOFT\ameye 05eb1a020d Activities on home page 2023-06-04 08:40:38 -04:00
ameye 30d344833c Merge branch 'pending-jobs-pop-apis' of WrenchBoard/Users-Wrench into master 2023-06-04 12:14:58 +00:00
CHIEFSOFT\ameye acdf167a69 List page 2023-06-03 22:56:27 -04:00
Ebube fd00113aab Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into pending-jobs-pop-apis 2023-06-04 02:23:49 +01:00
Ebube 8765329256 . 2023-06-04 02:13:00 +01:00
Ebube 3b9c0987b8 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into pending-jobs-pop-apis 2023-06-04 00:40:05 +01:00
Ebube 0304eaa328 . 2023-06-04 00:39:17 +01:00
ameye 85ac8d183c Merge branch 'fileupload_implementation' of WrenchBoard/Users-Wrench into master 2023-06-03 16:26:04 +00:00
victorAnumudu 1aa0fc6016 file upload implementation 2023-06-03 17:20:04 +01:00
Ebube 18b85e0ec9 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into pending-jobs-pop-apis 2023-06-03 17:08:13 +01:00
Ebube 024c8bbed1 . 2023-06-03 17:07:34 +01:00
ameye 865c61f393 Merge branch 'upload-API' of WrenchBoard/Users-Wrench into master 2023-06-03 12:15:19 +00:00
victorAnumudu bb79342762 Added the upload API to user services and changed class to classname 2023-06-03 12:54:43 +01:00
ameye 413e8e0361 Merge branch 'icon-replacements' of WrenchBoard/Users-Wrench into master 2023-06-02 16:39:41 +00:00
victorAnumudu ce5438ff85 icons on right sidebar replaced 2023-06-02 17:35:51 +01:00
ameye cf644d6349 Merge branch 'offerlist-show_hidden' of WrenchBoard/Users-Wrench into master 2023-06-02 16:11:58 +00:00
victorAnumudu 0f6a49246c shows offerlist only when offer exist 2023-06-02 17:03:48 +01:00
ameye 6c690fe897 Merge branch 'pending-jobs-pop-apis' of WrenchBoard/Users-Wrench into master 2023-06-01 13:15:24 +00:00
Ebube 1895b47b76 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into pending-jobs-pop-apis 2023-06-01 14:10:29 +01:00
Ebube 442fb36578 . 2023-06-01 14:06:19 +01:00
ameye cf157df31e Merge branch 'height-unified' of WrenchBoard/Users-Wrench into master 2023-06-01 12:06:10 +00:00
victorAnumudu 99359d7568 Height changed for textarea and upload area, max single file upload set to 1mb 2023-06-01 12:53:30 +01:00
Olusesan Ameye 0e09b84be2 Disable eslint in production envrionment 2023-06-01 09:32:02 +00:00
Olusesan Ameye bbedfbd801 fix 2023-06-01 09:24:29 +00:00
ameye 3d940a8629 Merge branch 'manage-active-job-tab' of WrenchBoard/Users-Wrench into master 2023-05-31 19:52:46 +00:00
victorAnumudu 6c38c6b44c created tab for message and files 2023-05-31 20:23:59 +01:00
ameye aeb22d7f28 Merge branch 'newlayout-manage-activejob' of WrenchBoard/Users-Wrench into master 2023-05-31 14:55:25 +00:00
victorAnumudu 1d50790cc1 manage active job layout changed 2023-05-31 15:14:34 +01:00
CHIEFSOFT\ameye 172c4b7e6f Dash work 2023-05-31 08:47:05 -04:00
CHIEFSOFT\ameye 3ea0737341 Home banners set up 2023-05-31 08:04:13 -04:00
ameye bb0c8c9f34 Merge branch 'task-table-loading' of WrenchBoard/Users-Wrench into master 2023-05-31 10:20:27 +00:00
Ebube 9139f637cf . 2023-05-31 10:54:08 +01:00
Ebube 16401cc3a2 . 2023-05-31 10:35:08 +01:00
ameye 93f26fcfba Merge branch 'enable-and-active-jobs' of WrenchBoard/Users-Wrench into master 2023-05-31 08:42:34 +00:00
Ebube ced9c523ad added suspense to familymanagetabs 2023-05-31 09:39:54 +01:00
Ebube 759269cd74 . 2023-05-31 05:59:45 +01:00
Ebube fb27a0d156 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into enable-and-active-jobs 2023-05-31 05:53:57 +01:00
Ebube 03da0e211b added qr code and print function 2023-05-31 05:53:31 +01:00
CHIEFSOFT\ameye c00d702a6b slider styles 2023-05-30 20:47:26 -04:00
CHIEFSOFT\ameye 206f292dd9 slider cards 2023-05-30 20:14:48 -04:00
CHIEFSOFT\ameye abb2329795 package added 2023-05-30 12:09:28 -04:00
ameye a92a9f961d Merge branch 'sliderCom-fix' of WrenchBoard/Users-Wrench into master 2023-05-30 14:07:54 +00:00
victorAnumudu f90a6e6687 fixed width added to back btn 2023-05-30 14:37:27 +01:00
victorAnumudu b44c039bbf fixed width added to back btn 2023-05-30 14:36:34 +01:00
victorAnumudu 09e0661e48 sliderCom item repeat fix 2023-05-30 14:28:57 +01:00
ameye af2c2d66a3 Merge branch 'myjoblist-moved' of WrenchBoard/Users-Wrench into master 2023-05-30 10:35:45 +00:00
victorAnumudu b2bfa6cd54 moved user joblist into it's own slice, to avoid unneccessary side menu display recalculation 2023-05-30 07:29:57 +01:00
ameye 577212eb19 Merge branch 'enable-and-active-jobs' of WrenchBoard/Users-Wrench into master 2023-05-30 02:34:59 +00:00
Ebube f5bf5997d6 addded email fix 2023-05-30 02:20:58 +01:00
Ebube 42c3676bcf . 2023-05-30 02:11:51 +01:00
Ebube 9c00badcf6 . 2023-05-30 01:42:36 +01:00
Ebube 85899a72d2 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into enable-and-active-jobs 2023-05-29 23:59:18 +01:00
Ebube 9cd3ef273b . 2023-05-29 23:58:55 +01:00
CHIEFSOFT\ameye 918575d802 Family member task layout 2023-05-29 18:23:57 -04:00
ameye f2070ae31d Merge branch 'correct-sidemenu-display' of WrenchBoard/Users-Wrench into master 2023-05-29 22:02:45 +00:00
victorAnumudu 4d9f0adf0c side menu display bug fixed 2023-05-29 22:41:29 +01:00
ameye e9271e649f Merge branch 'offerlist-display' of WrenchBoard/Users-Wrench into master 2023-05-29 20:00:37 +00:00
victorAnumudu f4e5ba1586 reverted offerlist to display only when there is offer 2023-05-29 20:53:17 +01:00
ameye 3ee01736db Merge branch 'button-name-display' of WrenchBoard/Users-Wrench into master 2023-05-29 19:39:36 +00:00
47 changed files with 2071 additions and 836 deletions
+4
View File
@@ -18,6 +18,7 @@ REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/svs/user"
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
REACT_APP_SESSION_EXPIRE_MINUTES=300000
REACT_APP_SESSION_EXPIRE_MINUTES_FAMILY=600000
REACT_APP_SESSION_EXPIRE_CHECKER=60000
REACT_APP_LOGIN_ERROR_TIMEOUT=7000
@@ -45,6 +46,9 @@ REACT_APP_FACEBOOK_CLIENT_ID=390204307987009
REACT_APP_FACEBOOK_CLIENT_SECRET=19f778e312f2ab96d147bacb612910c2
REACT_APP_FACEBOOK_CLIENT_SCOPE="email, public_profile"
REACT_APP_MAX_FILE_SIZE=1000000
REACT_APP_TOTAL_NUM_FILE=4
#apigate.lotus.g1.wrenchboard.com:76.209.103.227
#apigate.orion.g1.wrenchboard.com:76.209.103.227
+5 -1
View File
@@ -18,6 +18,7 @@ REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/svs/user"
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
REACT_APP_SESSION_EXPIRE_MINUTES=300000
REACT_APP_SESSION_EXPIRE_MINUTES_FAMILY=600000
REACT_APP_SESSION_EXPIRE_CHECKER=60000
REACT_APP_LOGIN_ERROR_TIMEOUT=7000
@@ -37,4 +38,7 @@ REACT_APP_ITEM_PER_PAGE=5
REACT_APP_GOOGLE_CLIENT_ID=817021856543-ad9nsjgdpsu2s2jrl63j3ihrv7lbf6ma.apps.googleusercontent.com
REACT_APP_GOOGLE_CLIENT_SECRET=aozK_2G8UjaCmLgPPkv9abIm
REACT_APP_GOOGLE_CLIENT_SCOPE="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
REACT_APP_GOOGLE_REDIRECT_URL=http://localhost:9082/login/auth/
REACT_APP_GOOGLE_REDIRECT_URL=http://localhost:9082/login/auth/
REACT_APP_MAX_FILE_SIZE=1000000
REACT_APP_TOTAL_NUM_FILE=4
+8 -1
View File
@@ -18,6 +18,7 @@ REACT_APP_USERS_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/svs/user"
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
REACT_APP_SESSION_EXPIRE_MINUTES=300000
REACT_APP_SESSION_EXPIRE_MINUTES_FAMILY=600000
REACT_APP_SESSION_EXPIRE_CHECKER=60000
REACT_APP_LOGIN_ERROR_TIMEOUT=7000
@@ -37,4 +38,10 @@ REACT_APP_ITEM_PER_PAGE=5
REACT_APP_GOOGLE_CLIENT_ID=817021856543-ad9nsjgdpsu2s2jrl63j3ihrv7lbf6ma.apps.googleusercontent.com
REACT_APP_GOOGLE_CLIENT_SECRET=aozK_2G8UjaCmLgPPkv9abIm
REACT_APP_GOOGLE_CLIENT_SCOPE="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
REACT_APP_GOOGLE_REDIRECT_URL=https://users.wrenchboard.com/login/auth/
REACT_APP_GOOGLE_REDIRECT_URL=https://users.wrenchboard.com/login/auth/
DISABLE_ESLINT_PLUGIN=true
REACT_APP_MAX_FILE_SIZE=1000000
REACT_APP_TOTAL_NUM_FILE=4
+8 -6
View File
@@ -14,17 +14,19 @@
"chartjs": "^0.3.24",
"cors": "^2.8.5",
"faker": "^6.6.6",
"flutterwave-react-v3": "^1.3.0",
"formik": "^2.2.9",
"react": "^18.2.0",
"react-chartjs-2": "^4.1.0",
"react-countup": "^6.2.0",
"react-router-dom": "^6.0.2",
"react-slick": "^0.29.0",
"react-toastify": "^9.0.1",
"flutterwave-react-v3": "^1.3.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-qr-code": "^2.0.11",
"react-redux": "^8.0.5",
"react-router-dom": "^6.0.2",
"react-scripts": "5.0.1",
"react-slick": "^0.29.0",
"react-to-print": "^2.14.12",
"react-toastify": "^9.0.1",
"redux": "^4.2.0",
"slick-carousel": "^1.8.1",
"web-vitals": "^1.0.1",
@@ -54,4 +56,4 @@
"last 1 safari version"
]
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 441 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

+6 -11
View File
@@ -4,7 +4,9 @@ import InputCom from "../Helpers/Inputs/InputCom";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import usersService from "../../services/UsersService";
import { useSelector } from "react-redux";
import { useSelector, useDispatch } from "react-redux";
import { tableReload } from '../../store/TableReloads'
import { Field, Form, Formik } from "formik";
import * as Yup from "yup";
@@ -36,20 +38,12 @@ const validationSchema = Yup.object().shape({
.required("Timeline is required"),
});
// let initialValues = {
// // initial values for formik
// country: "NG",
// price: 0,
// title: "",
// description: "",
// job_detail: "",
// timeline_days: "",
// };
function AddJob() {
const ApiCall = new usersService();
const navigate = useNavigate();
let dispatch = useDispatch()
let { userDetails } = useSelector((state) => state.userDetails);
let [pageLoading, setPageLoading] = useState(true); // State used for knowing when the page is mounting
@@ -115,6 +109,7 @@ function AddJob() {
message: "Job Added Successfully",
});
setTimeout(() => {
dispatch(tableReload({type:'JOBTABLE'}))
navigate("/myjobs", { replace: true });
}, 1000);
})
+130 -86
View File
@@ -1,8 +1,10 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { Link, useNavigate, } from "react-router-dom";
import { toast } from "react-toastify";
import localImgLoad from "../../lib/localImgLoad";
import Icons from "../Helpers/Icons";
import MarketPopUp from "../MarketPlace/PopUp/MarketPopUp";
import usersService from "../../services/UsersService";
export default function AvailableJobsCard({
className,
@@ -11,7 +13,13 @@ export default function AvailableJobsCard({
}) {
//debugger;
const [addFavorite, setValue] = useState(datas.whishlisted);
const [options, setOption] = useState(false);
const [marketPopUp, setMarketPopUp] = useState({ show: false, data: {} });
const [manageInt, setManageInt] = useState(null)
const navigate = useNavigate();
const apiCall = useMemo(() => new usersService(), []);
const favoriteHandler = () => {
if (!addFavorite) {
setValue(true);
@@ -21,98 +29,134 @@ export default function AvailableJobsCard({
toast.warn("Remove to Favorite List");
}
};
const marketInterestData = useCallback(async() => {
let { offer_code } = datas;
let reqData = { offer_code };
try {
const manageInt = await apiCall.MarketInterest(reqData);
const manageIntRes = await manageInt?.data;
setManageInt(manageIntRes)
} catch (error) {
throw new Error(error)
}
}, [])
useEffect(() => {
if (!datas) {
navigate("/market", { replace: true });
}
marketInterestData()
}, [marketInterestData, datas])
return (
<div
className={`card-style-two w-full h-[426px] p-[20px] bg-white dark:bg-dark-white rounded-2xl section-shadow ${
className || ""
}`}
>
<div className="flex flex-col justify-between w-full h-full">
<Link to="/shop-details" className="mb-2.5">
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{datas.title}
</h1>
</Link>
<>
<div
className={`card-style-two w-full h-[426px] p-[20px] bg-white dark:bg-dark-white rounded-2xl section-shadow ${
className || ""
}`}
>
<div className="flex flex-col justify-between w-full h-full">
<Link to="/shop-details" className="mb-2.5">
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{datas.title}
</h1>
</Link>
<div className="card-two-info flex justify-between items-center">
<div className="owned-by flex space-x-2 items-center">
<div>
<p className="text-thin-light-gray text-sm leading-3">Added</p>
<p className="text-base text-dark-gray dark:text-white">
{datas.offer_added}
</p>
</div>
</div>
<div className="w-[1px] bg-light-purple dark:bg-dark-light-purple h-7"></div>
<div className="created-by flex space-x-2 items-center flex-row-reverse">
<div>
<p className="text-thin-light-gray text-sm leading-3 text-right">
Expires
</p>
<p className="text-base text-dark-gray dark:text-white text-right">
{datas.expire}
</p>
</div>
</div>
</div>
<div className="thumbnail-area w-full">
<div
className="w-full h-[236px] p-6 rounded-xl overflow-hidden"
style={{
background: `url(${localImgLoad(
`images/${datas.thumbnil}`
)}) 0% 0% / cover no-repeat`,
}}
>
<div className="flex justify-center">{datas.description}</div>
</div>
</div>
<div className="details-area">
<div className="product-two-options flex justify-between mb-5 relative">
{/* <div className="status">*/}
{/* {datas.isActive && (*/}
{/* <span className="text-xs px-3 py-1.5 tracking-wide rounded-full bg-gold text-white">*/}
{/* Active*/}
{/*</span>*/}
{/* )}*/}
{/* </div>*/}
{/*<div className=" review flex space-x-2">*/}
{/* <button*/}
{/* onClick={favoriteHandler}*/}
{/* type="button"*/}
{/* className={`w-7 h-7 bg-white rounded-full flex justify-center items-center ${*/}
{/* addFavorite ? "text-red-500" : "text-thin-light-gray"*/}
{/* }`}*/}
{/* >*/}
{/* <Icons name="star" />*/}
{/* </button>*/}
{/*</div>*/}
</div>
<div className="flex justify-between">
<div className="flex items-center space-x-2">
<div className="card-two-info flex justify-between items-center">
<div className="owned-by flex space-x-2 items-center">
<div>
<p className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white">
{datas.price * 0.01}
{datas.currency} | {datas.timeline_days} day(s)
</p>
<p className="text-sm text-lighter-gray">
( {datas.offer_code})
<p className="text-thin-light-gray text-sm leading-3">Added</p>
<p className="text-base text-dark-gray dark:text-white">
{datas.offer_added}
</p>
</div>
</div>
<div>
<button
type="button"
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
>
View
</button>
<div className="w-[1px] bg-light-purple dark:bg-dark-light-purple h-7"></div>
<div className="created-by flex space-x-2 items-center flex-row-reverse">
<div>
<p className="text-thin-light-gray text-sm leading-3 text-right">
Expires
</p>
<p className="text-base text-dark-gray dark:text-white text-right">
{datas.expire}
</p>
</div>
</div>
</div>
<div className="thumbnail-area w-full">
<div
className="w-full h-[236px] p-6 rounded-xl overflow-hidden"
style={{
background: `url(${localImgLoad(
`images/${datas.thumbnil}`
)}) 0% 0% / cover no-repeat`,
}}
>
<div className="flex justify-center">{datas.description}</div>
</div>
</div>
<div className="details-area">
<div className="product-two-options flex justify-between mb-5 relative">
{/* <div className="status">*/}
{/* {datas.isActive && (*/}
{/* <span className="text-xs px-3 py-1.5 tracking-wide rounded-full bg-gold text-white">*/}
{/* Active*/}
{/*</span>*/}
{/* )}*/}
{/* </div>*/}
{/*<div className=" review flex space-x-2">*/}
{/* <button*/}
{/* onClick={favoriteHandler}*/}
{/* type="button"*/}
{/* className={`w-7 h-7 bg-white rounded-full flex justify-center items-center ${*/}
{/* addFavorite ? "text-red-500" : "text-thin-light-gray"*/}
{/* }`}*/}
{/* >*/}
{/* <Icons name="star" />*/}
{/* </button>*/}
{/*</div>*/}
</div>
<div className="flex justify-between">
<div className="flex items-center space-x-2">
<div>
<p className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white">
{datas.price * 0.01}
{datas.currency} | {datas.timeline_days} day(s)
</p>
<p className="text-sm text-lighter-gray">
( {datas.offer_code})
</p>
</div>
</div>
<div>
<button
type="button"
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
onClick={() => {
setMarketPopUp({show: true, data: datas})
}}
>
View
</button>
</div>
</div>
</div>
</div>
</div>
</div>
{marketPopUp.show && (
<MarketPopUp
details={datas}
onClose={() => {
setMarketPopUp({ show: false, data: {} });
}}
situation={marketPopUp.show}
marketInt={manageInt}
/>
)}
</>
);
}
+21 -6
View File
@@ -3,24 +3,39 @@ import { Link } from "react-router-dom";
import localImgLoad from "../../lib/localImgLoad";
export default function HomeBannerOffersCard(props) {
console.log("HomeBannerOffersCard->",props.itemData)
console.log("HomeBannerOffersCard-> ##->",props)
const link_result = "/" + props.itemData.link_path;
var imgUrl = props.itemData.banner; // ? this.state.nextImgSrc : this.state.song.imgSrc;
console.log("IMAGE FOR BANNER->",imgUrl);
var divStyle = {
backgroundImage: 'url(' + imgUrl + ')'
}
var linkDivStyle = "item w-full block group banner-630-340 " + divStyle;
return (
<Link
to="/my-collection/collection-item"
className="item w-full block group banner-630-340"
to={link_result}
className={linkDivStyle}
>
<div className="flex flex-col justify-between h-full">
<div className="content flex justify-between items-center mb-5">
<div>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
<div className="siderCardHeader">
<h1 className="text-2xl font-bold text-dark-gray dark:text-white tracking-wide">
<>{props.itemData.title}</>
</h1>
</div>
{/*<SelectBox datas={filterDatas} action={dataSetHandler} />*/}
</div>
<div className="h-[233px]">
{props.itemData.description}
<div className="siderCardDescription">
{props.itemData.description}
</div>
<div className="siderCardButton">
[BUTTON HERE]
</div>
</div>
</div>
</Link>
);
+40 -25
View File
@@ -1,44 +1,59 @@
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import Layout from "../Partials/Layout";
import FamilyManageTabs from "./FamilyManageTabs";
import { useLocation } from "react-router-dom";
import FamilyManageTabs from "./Tabs/FamilyManageTabs";
import { useLocation, useNavigate } from "react-router-dom";
import LoadingSpinner from "../Spinners/LoadingSpinner";
export default function FamilyManage() {
const [selectTab, setValue] = useState("today");
let [pageLoading, setPageLoading] = useState(true);
let location = useLocation();
let accountDetails = location?.state
let navigate = useNavigate();
let accountDetails = location?.state;
// tab handler
const filterHandler = (value) => {
setValue(value);
};
useEffect(() => {
if (!accountDetails) {
navigate("/acc-family", { replace: true });
} else {
setPageLoading(false);
}
}, []);
return (
<Layout>
{/*<CommonHead />*/}
<div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full">
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
>
Manage Family
</span>
</h1>
</div>
<div className="slider-btns flex space-x-4">
<div
onClick={() => filterHandler("today")}
className="relative"
></div>
{pageLoading ? (
<LoadingSpinner size={8} color="sky-blue" />
) : (
<div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full">
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
>
Manage Family
</span>
</h1>
</div>
<div className="slider-btns flex space-x-4">
<div
onClick={() => filterHandler("today")}
className="relative"
></div>
</div>
</div>
<FamilyManageTabs accountDetails={accountDetails} />
</div>
<FamilyManageTabs accountDetails={accountDetails} />
</div>
</div>
)}
</Layout>
);
}
}
+31 -18
View File
@@ -5,7 +5,9 @@ import { useNavigate, useLocation, Link } from "react-router-dom";
import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList";
export default function FamilyTable({ className, familyList, loader }) {
import familyImage from '../../assets/images/no-family-side.png'
export default function FamilyTable({ className, familyList, loader, popUpHandler }) {
const filterCategories = ["All Categories", "Explore", "Featured"];
const [selectedCategory, setCategory] = useState(filterCategories[0]);
const navigate = useNavigate();
@@ -32,9 +34,11 @@ export default function FamilyTable({ className, familyList, loader }) {
<div className="h-full min-h-[500px] w-full overflow-hidden flex justify-center items-center">
<LoadingSpinner size="16" color="sky-blue" />
</div>
) : (
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400 relative">
<>
)
:
familyList?.length > 0 ?
(
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400 relative">
<thead className="sticky top-0">
<tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-bottom ">
<th className="py-4">Name</th>
@@ -44,9 +48,7 @@ export default function FamilyTable({ className, familyList, loader }) {
</tr>
</thead>
<tbody className="h-full">
<>
{familyList?.length > 0 ? (
currentFamilyList?.map((props, idx) => {
{currentFamilyList?.map((props, idx) => {
let {
firstname,
lastname,
@@ -115,18 +117,29 @@ export default function FamilyTable({ className, familyList, loader }) {
</tr>
);
})
) : (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<td className="p-2" colSpan="4">
No Family Accounts Found!
</td>
</tr>
)}
</>
}
</tbody>
</>
</table>
)}
</table>
)
:
(
<div className="font-bold text-center text-xl md:text-2xl lg:text-4xl text-dark-gray md:flex items-center justify-between">
<div className="p-2 w-full md:w-1/2">
<p className="mb-4 p-3 md:p-16">Add your family, assign tasks, and get the whole team engaged.</p>
<button
onClick={popUpHandler}
type="button"
className="text-white btn-gradient text-lg tracking-wide px-5 py-2 rounded-full"
>
Add Family
</button>
</div>
<div className="p-2 w-full md:w-1/2">
<img className='w-full' src={familyImage} alt="A Family" />
</div>
</div>
)
}
</div>
{/* PAGINATION BUTTON */}
<PaginatedList
-31
View File
@@ -1,31 +0,0 @@
import React, { useState } from "react";
import dataImage1 from "../../assets/images/data-table-user-1.png";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import { useNavigate, useLocation, Link } from "react-router-dom";
export default function FamilyTasks({ className, loader }) {
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow min-h-[520px] max-h-[600px] ${
className || ""
}`}
>
<div className="relative w-full overflow-x-auto sm:rounded-lg">
{loader ? (
<div className="h-full min-h-[500px] w-full overflow-hidden flex justify-center items-center">
<LoadingSpinner size="16" color="sky-blue" />
</div>
) : (
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400 relative">
<tr>
<td> Yes This are my tasks </td>
</tr>
</table>
)}
</div>
</div>
);
}
@@ -1,13 +1,17 @@
import React, {
Suspense,
forwardRef,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import profile from "../../assets/images/profile-info-profile.png";
import usersService from "../../services/UsersService";
import QRCode from "react-qr-code";
import { useReactToPrint } from "react-to-print";
import usersService from "../../../services/UsersService";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import profile from "../../../assets/images/profile-info-profile.png";
import FamilyTasks from "./FamilyTasks";
export default function FamilyManageTabs({
@@ -16,7 +20,16 @@ export default function FamilyManageTabs({
listReload,
loader,
}) {
const [familyDetails, setFamilyDetails] = useState(null);
const [details, setDetails] = useState({
familyDetails: {
loading: false,
data: null,
},
familyTasks: {
loading: false,
data: null,
},
});
const [errMsg, setErrMsg] = useState("");
// List of tabs
const tabs = [
@@ -34,7 +47,6 @@ export default function FamilyManageTabs({
},
];
const [tab, setTab] = useState(tabs[0].name);
const [manageLoader, setManageLoader] = useState(false);
const tabHandler = (value) => {
setTab(value);
};
@@ -54,28 +66,54 @@ export default function FamilyManageTabs({
imgReader.readAsDataURL(e.target.files[0]);
}
};
// Api call
const apiCall = useMemo(() => new usersService(), []);
// function for manage family
const familyManageHandler = useCallback(async () => {
setManageLoader(true);
const manageFamily = useCallback(async () => {
try {
setDetails({
familyDetails: { loading: true },
familyTasks: { loading: true },
});
let { family_uid } = accountDetails;
let reqData = { family_uid };
let res = await apiCall.ManageFamily(reqData);
let { data } = await res;
if (data?.internal_return < 0) return;
setFamilyDetails(data);
setManageLoader(false);
// the family response
const familyRes = await apiCall.ManageFamily(reqData);
const familyData = familyRes.data;
// the tasks response
const tasksRes = await apiCall.ManageTasks(reqData);
const tasksData = tasksRes.data;
// checking the internal return
if (familyData?.internal_return < 0 || tasksData?.internal_return < 0)
return;
setDetails({
familyDetails: { loading: false, data: familyData },
familyTasks: { loading: false, data: tasksData },
});
} catch (error) {
setDetails({
familyDetails: { loading: false },
familyTasks: { loading: false },
});
setErrMsg("An error occurred");
throw new Error(error);
}
}, [apiCall, accountDetails]);
useEffect(() => {
familyManageHandler();
}, [tab]);
manageFamily();
}, [tab, manageFamily]);
const accountRef = useRef();
// to handle printing
const useHandlePrint = useReactToPrint({
content: () => accountRef.current,
});
return (
<div
@@ -84,11 +122,13 @@ export default function FamilyManageTabs({
}`}
>
<div className="relative w-full overflow-x-auto sm:rounded-lg">
{loader ? (
<div className="h-full min-h-[500px] w-full overflow-hidden flex justify-center items-center">
<LoadingSpinner size="16" color="sky-blue" />
</div>
) : (
<Suspense
fallback={
<div className="h-full min-h-[500px] w-full overflow-hidden flex justify-center items-center">
<LoadingSpinner size="16" color="sky-blue" />
</div>
}
>
<div className="w-full h-full text-sm text-left text-gray-500 dark:text-gray-400 relative grid grid-cols-4 min-h-[520px]">
<div className="border-r border-[#E3E4FE] dark:border-[#a7a9b533] p-6 h-full">
<ProfileInfo
@@ -99,7 +139,7 @@ export default function FamilyManageTabs({
accountDetails={accountDetails}
/>
</div>
<div className="col-span-3 p-6 h-full w-full">
<div className="col-span-3 justify-self-end h-full w-full">
<div className="flex flex-col w-full">
<ul className="flex-[0.1] flex gap-2 items-center border-b border-b-[#FAFAF] w-full">
{tabs.map(({ name, id }) => (
@@ -123,20 +163,25 @@ export default function FamilyManageTabs({
<div
className={`${
tab === name ? "block" : "hidden"
} h-full p-4 border border-[#dbd9d9]`}
} h-full p-4 border border-[#dbd9d9] relative overflow-y-auto`}
key={id}
>
{manageLoader ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<>
{name === "Tasks" && <FamilyTasks className={className} loader={loader}/>}
{name === "Account" && (
<Account familyDetails={familyDetails} />
)}
{name === "Profile" && <Profile />}
</>
{name === "Tasks" && (
<FamilyTasks
className={className}
loader={details.familyTasks.loading}
familyData={details.familyTasks.data}
/>
)}
{name === "Account" && (
<Account
familyData={details.familyDetails.data}
myRef={accountRef}
loader={details.familyDetails.loading}
handlePrint={useHandlePrint}
/>
)}
{name === "Profile" && <Profile />}
</div>
);
})}
@@ -144,7 +189,7 @@ export default function FamilyManageTabs({
</div>
</div>
</div>
)}
</Suspense>
</div>
</div>
);
@@ -157,7 +202,6 @@ function ProfileInfo({
browseProfileImg,
accountDetails,
}) {
let { firstname, lastname, age } = accountDetails;
return (
<div className="flex flex-col items-center gap-6">
<div className="flex justify-center">
@@ -198,33 +242,70 @@ function ProfileInfo({
</div>
<div className="flex flex-col justify-center gap-3 items-center">
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{firstname}
{accountDetails?.firstname}
</h1>
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{lastname}
{accountDetails?.lastname}
</h1>
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{age}
{accountDetails?.age}
</h1>
</div>
</div>
);
}
function Account({ familyDetails }) {
const Account = forwardRef(({ familyData, myRef, handlePrint }, ref) => {
return (
<div className="w-full lg:min-h-[400px] h-full flex items-center justify-center">
<div className="flex flex-col">
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Username: <span className="ml-2 normal-case">{familyDetails?.username}</span>
</h2>
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Pin: <span className="ml-2 normal-case">{familyDetails?.pin}</span>
</h2>
<div
className="w-full lg:min-h-[500px] h-full flex flex-col items-center justify-center"
ref={myRef}
>
<div className="update-table w-full lg:min-h-[450px] h-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow ">
<div className="flex items-center justify-around h-[380px]">
<div className="flex flex-col">
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Username:{" "}
<span className="ml-2 normal-case">
{familyData?.username ? familyData?.username : "please wait..."}
</span>
</h2>
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Pin:{" "}
<span className="ml-2 normal-case">
{familyData?.pin ? familyData?.pin : "please wait..."}
</span>
</h2>
</div>
<span className="text-5xl text-gray-400 opacity-20 font-bold">
or
</span>
<div className="max-w-[200px]">
<p className="text-xl tracking-wide mb-[15px] text-center font-bold text-dark-gray dark:text-white">
Scan the code from mobile app
</p>
<QRCode
size={256}
style={{ height: "auto", maxWidth: "100%", width: "100%" }}
value={`https://www.google.com`}
viewBox={`0 0 256 256`}
/>
</div>
</div>
<div className="h-[50px] w-full flex justify-center items-center">
<button
className="btn-shine w-[116px] h-[46px] text-white rounded-full text-base bg-pink flex justify-center items-center"
onClick={handlePrint}
>
Print
</button>
</div>
</div>
</div>
);
}
});
function Profile() {
return <>Profile</>;
@@ -0,0 +1,142 @@
import React, { useState } from "react";
import dataImage2 from "../../../assets/images/data-table-user-2.png";
import { useNavigate, useLocation } from "react-router-dom";
import { handlePagingFunc } from "../../Pagination/HandlePagination";
import PaginatedList from "../../Pagination/PaginatedList";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import Icons from "../../Helpers/Icons";
export default function FamilyTasks({ familyData, className, loader }) {
const filterCategories = ["All Categories", "Explore", "Featured"];
const [selectedCategory, setCategory] = useState(filterCategories[0]);
let navigate = useNavigate();
let { pathname } = useLocation();
let data = ["1", "2", "3", "4", "5", "6"]; // to be replaced later by result from API CALL
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem =
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentTask = familyData?.result_list.slice(
indexOfFirstItem,
indexOfLastItem
);
const handlePagination = (e) => {
handlePagingFunc(e, setCurrentPage);
};
return (
<div
className={`update-table w-full bg-white dark:bg-dark-white h-full lg:min-h-[450px] overflow-hidden rounded-2xl section-shadow ${
className || ""
}`}
>
{loader ? (
<div className="w-full h-full flex justify-center items-center lg:min-h-[470px]">
<LoadingSpinner size={16} color="sky-blue" />
</div>
) : (
<>
{" "}
{familyData && familyData?.result_list && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{
<>
{familyData &&
familyData?.result_list &&
familyData.result_list.length > 0 &&
currentTask.map((value, index) => {
// find due date
const dueDate = value?.delivery_date.split(" ")[0]
return (
<tr
key={index}
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
>
<td className=" py-4">
<div className="flex space-x-2 items-center w-full">
<div className="w-full h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1] max-w-[60px] min-w-[60px]">
<img
src={dataImage2}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col flex-[0.9]">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
{value.title}
</h1>
<div className="flex gap-4 items-center">
<span className="text-sm text-thin-light-gray">
Price:{" "}
<span className="text-purple">
{value.price * 0.01}
</span>
</span>
<span className="text-sm text-thin-light-gray">
Duration:{" "}
<span className="text-purple">
{" "}
{value.timeline_days} day(s)
</span>
</span>
<span className="text-sm text-thin-light-gray">
Due Date:{" "}
<span className="text-purple">
{" "}
{dueDate}
</span>
</span>
</div>
</div>
</div>
</td>
<td className="text-right py-4 px-2">
<button
type="button"
onClick={() => {
navigate("/manage-active-job", {
state: { ...value, pathname },
});
}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
<Icons name="right-arrow" />
</button>
</td>
</tr>
)
})}
</>
}
</tbody>
</table>
{/* PAGINATION BUTTON */}
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
familyData?.result_list.length
? true
: false
}
data={familyData?.result_list}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
{/* END OF PAGINATION BUTTON */}
</div>
)}
</>
)}
</div>
);
}
+1 -1
View File
@@ -158,7 +158,7 @@ export default function FamilyAcc() {
></div>
</div>
</div>
<FamilyTable familyList={familyList} loader={loader} />
<FamilyTable familyList={familyList} loader={loader} popUpHandler={popUpHandler} />
</div>
</div>
{popUp && (
+15
View File
@@ -468,6 +468,21 @@ export default function Icons({ name }) {
>
<rect y="0.823242" width="20" height="2.35294" rx="1.17647" />
</svg>
) : name === "right-arrow" ? (
<svg
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg"
// enableBackground="new 0 0 24 24"
viewBox="0 0 24 24"
className="fill-black dark:fill-white"
id="right-arrow"
>
<path
d="M15.5,11.3L9.9,5.6c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l4.9,4.9l-4.9,4.9c-0.2,0.2-0.3,0.4-0.3,0.7c0,0.6,0.4,1,1,1
c0.3,0,0.5-0.1,0.7-0.3l5.7-5.7c0,0,0,0,0,0C15.9,12.3,15.9,11.7,15.5,11.3z"
></path>
</svg>
) : (
""
)}
-12
View File
@@ -51,8 +51,6 @@ export default function HistoryTable({ className }) {
<td className="py-4 text-center">Value</td>
<td className="py-4 text-center">USD</td>
<td className="py-4 text-center">24H%</td>
<td className="py-4 text-center">Bits</td>
<td className="py-4 text-center">Time</td>
<td className="py-4 text-right">Status</td>
</tr>
@@ -165,16 +163,6 @@ export default function HistoryTable({ className }) {
-24.75 (11.5%)
</span>
</td>
<td className="text-right py-4 px-2">
<span className="text-base text-dark-gray dark:text-white font-medium">
343
</span>
</td>
<td className="text-right py-4 px-2">
<span className="text-base text-thin-light-gray">
2 Hours 1 min 30s
</span>
</td>
<td className="text-right py-4 px-2">
<button
type="button"
+2 -2
View File
@@ -217,7 +217,7 @@ export default function History() {
{/* PURCHASE SECTION */}
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full max-h-[700px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Purchases</h2>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">Purchases</h1>
{purchaseHistory.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
@@ -230,7 +230,7 @@ export default function History() {
{/* RECENT ACTIVITY SECTION */}
<div className="lg:w-1/2 w-full mb-10 lg:mb-0">
<div className="wallet w-full md:p-8 p-4 h-full max-h-[700px] bg-white dark:bg-dark-white overflow-y-auto rounded-2xl shadow">
<h2 className='text-slate-900 dark:text-white text-xl lg:text-2xl font-medium'>Recent Activity</h2>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">Recent Activity</h1>
{/* <p className='text-base text-slate-500 dark:text-white'>Activity Report</p> */}
{paymentHistory.loading ?
<LoadingSpinner size='16' color='sky-blue' />
+17 -10
View File
@@ -1,11 +1,13 @@
import React from "react";
import datas from "../../data/product_data.json";
import Hero from "./Hero";
import HomeTaskDisplay from "./HomeTaskDisplay";
// import HomeTaskDisplay from "./HomeTaskDisplay";
import usersService from "../../services/UsersService";
import { useSelector } from "react-redux";
// import SellHistoryMarketVisitorAnalytic from './SellHistoryMarketVisitorAnalytic';
// import TopSellerTopBuyerSliderSection from "./TopSellerTopBuyerSliderSection";
//import UpdateTable from "./UpdateTable";
import HomeActivities from "./HomeActivities";
export default function FullAccountDash(props) {
@@ -13,9 +15,8 @@ export default function FullAccountDash(props) {
const trending = datas.datas;
const jobData = datas.datas; // api calls or cache
//getHomeDate
const userApi = new usersService();
const homeData = userApi.getHomeDate();
const {userDetails} = useSelector((state) => state?.userDetails)
@@ -25,12 +26,18 @@ export default function FullAccountDash(props) {
<Hero className="mb-10"
data={userDetails}
bannerList={props.bannerList}
nextDueTask={props.nextDueTask}
/>
<HomeTaskDisplay
jobData={jobData}
className="mb-10"
bannerList={props.bannerList}
/>
<HomeActivities className="mb-10"/>
{/*<UpdateTable className="mb-10"/>*/}
{/*<SellHistoryMarketVisitorAnalytic className="mb-10"/>*/}
{/*<TopSellerTopBuyerSliderSection className="mb-10" />*/}
{/*<HomeTaskDisplay*/}
{/* jobData={jobData}*/}
{/* className="mb-10"*/}
{/* bannerList={props.bannerList}*/}
{/*/>*/}
</div>
</div>
);
+26 -21
View File
@@ -11,7 +11,7 @@ import SliderCom from "../Helpers/SliderCom";
import HomeSliders from "./HomeSliders";
import { useSelector } from "react-redux";
export default function Hero({ className,bannerList }) {
export default function Hero({ className, bannerList, nextDueTask }) {
const settings = {
autoplay: true,
dots: true,
@@ -71,27 +71,32 @@ export default function Hero({ className,bannerList }) {
</div>
</div>
{/* countdown */}
<div className="w-full h-32 flex justify-evenly items-center sm:p-6 p-1 rounded-2xl border 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">
ABCDEFGH01
</p>
<p className="text-base text-white tracking-wide">773.69 USD</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" />
</p>
<div className="text-base text-white tracking-wide flex gap-[23px]">
<span>Hrs</span>
<span>Min</span>
<span>Sec</span>
{ nextDueTask?.next_due && Object.keys(nextDueTask.next_due)?.length &&
(
<div className="w-full h-32 flex justify-evenly items-center sm:p-6 p-1 rounded-2xl border 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}
</p>
<p className="text-base text-white tracking-wide">{nextDueTask.next_due.price} 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>
</div>
</div>
)
}
{/* action */}
<div className="flex lg:space-x-3 space-x-1 items-center">
<Link
+267
View File
@@ -0,0 +1,267 @@
import React, { useState } from "react";
import dataImage1 from "../../assets/images/data-table-user-1.png";
import dataImage2 from "../../assets/images/data-table-user-2.png";
import dataImage3 from "../../assets/images/data-table-user-3.png";
import dataImage4 from "../../assets/images/data-table-user-4.png";
import SelectBox from "../Helpers/SelectBox";
export default function HomeActivities({ className }) {
const filterCategories = ["All Categories", "Explore", "Featured"];
const [selectedCategory, setCategory] = useState(filterCategories[0]);
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow relative min-h-[520px] ${
className || ""
}`}
>
<div className="header w-full sm:flex justify-between items-center mb-5">
<div className="flex space-x-2 items-center mb-2 sm:mb-0">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
Recent Activities
</h1>
</div>
</div>
<div className="relative w-full overflow-x-auto sm:rounded-lg">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{/* table heading */}
{/*<tr className="text-base text-thin-light-gray whitespace-nowrap px-2 border-b dark:border-[#5356fb29] default-border-b dark:border-[#5356fb29] ottom ">*/}
{/* <td className="py-4 w-[300px] block whitespace-nowrap">*/}
{/* All Product*/}
{/* </td>*/}
{/* <td className="py-4 whitespace-nowrap text-center">.</td>*/}
{/* <td className="py-4 whitespace-nowrap text-center"></td>*/}
{/* <td className="py-4 whitespace-nowrap text-right"></td>*/}
{/*</tr>*/}
<tr className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
<td className=" py-4">
<div className="flex space-x-2 items-center">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img
src={dataImage1}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
Mullican Computer Joy
</h1>
<span className="text-sm text-thin-light-gray">
Owned by <span className="text-purple">Xoeyam</span>
</span>
</div>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span>
<svg
width="18"
height="18"
viewBox="0 0 18 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9 18C13.9706 18 18 13.9706 18 9C18 4.02944 13.9706 0 9 0C4.02944 0 0 4.02944 0 9C0 13.9706 4.02944 18 9 18Z"
fill="#627EEA"
/>
<path
d="M9.28125 2.25V7.23937L13.4983 9.12375L9.28125 2.25Z"
fill="white"
fillOpacity="0.602"
/>
<path
d="M9.28012 2.25L5.0625 9.12375L9.28012 7.23937V2.25Z"
fill="white"
/>
<path
d="M9.28125 12.3582V15.7483L13.5011 9.91016L9.28125 12.3582Z"
fill="white"
fillOpacity="0.602"
/>
<path
d="M9.28012 15.7483V12.3576L5.0625 9.91016L9.28012 15.7483Z"
fill="white"
/>
<path
d="M9.28125 11.572L13.4983 9.12348L9.28125 7.24023V11.572Z"
fill="white"
fillOpacity="0.2"
/>
<path
d="M5.0625 9.12348L9.28012 11.572V7.24023L5.0625 9.12348Z"
fill="white"
fillOpacity="0.602"
/>
</svg>
</span>
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
7473 ETH
</span>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7.55225 0C7.8457 0 8.13914 0 8.43205 0C8.44829 0.026534 8.47537 0.0151623 8.49756 0.0162453C9.28966 0.0649812 10.0606 0.220936 10.8013 0.505229C12.7699 1.26172 14.2323 2.58354 15.183 4.46638C15.5999 5.29218 15.8506 6.16997 15.9561 7.08891C15.9691 7.201 15.9621 7.3158 16 7.42465C16 7.80858 16 8.19251 16 8.57698C15.9778 8.5916 15.9854 8.61543 15.9838 8.63546C15.9475 9.10387 15.8744 9.56686 15.7515 10.0206C15.1787 12.1342 13.9524 13.7603 12.0818 14.8942C11.1516 15.4579 10.1397 15.8002 9.06064 15.941C8.89497 15.9626 8.72875 15.98 8.56308 15.9995C8.17217 15.9995 7.78127 15.9995 7.39036 16C7.3752 15.9789 7.35138 15.9865 7.33135 15.9848C6.96752 15.9545 6.60639 15.9009 6.25068 15.8197C4.77639 15.4829 3.48998 14.793 2.4131 13.7311C0.998917 12.3372 0.204656 10.6461 0.0270709 8.66687C0.0205739 8.59431 0.033568 8.51904 0 8.44972C0 8.15081 0 7.85244 0 7.55352C0.0265295 7.53403 0.0151597 7.50479 0.016784 7.47988C0.0730915 6.64162 0.251218 5.83044 0.564158 5.05066C1.10179 3.71043 1.93774 2.59058 3.07634 1.70142C4.33839 0.715876 5.77098 0.159745 7.36762 0.0270755C7.4288 0.0216604 7.49432 0.0341151 7.55225 0ZM7.24635 9.86252C7.24635 10.2383 7.24526 10.6147 7.24743 10.9905C7.24797 11.0457 7.23389 11.0679 7.17596 11.0593C7.09691 11.0479 7.01678 11.0446 6.93774 11.0338C6.26746 10.9461 5.63563 10.7371 5.03952 10.4192C5.00379 10.4002 4.97834 10.3802 4.9621 10.4425C4.81375 11.0176 4.66324 11.5926 4.51164 12.1666C4.50027 12.2094 4.51272 12.2278 4.54954 12.2473C4.66486 12.3096 4.78235 12.3665 4.90309 12.4152C5.5961 12.6968 6.31998 12.8408 7.06497 12.8842C7.14131 12.8885 7.16134 12.9112 7.1608 12.9865C7.15701 13.4159 7.16026 13.8453 7.15809 14.2747C7.15755 14.3397 7.17488 14.3619 7.2431 14.3614C7.69085 14.3581 8.13914 14.3576 8.5869 14.3614C8.66432 14.3619 8.67731 14.3359 8.67731 14.2666C8.67461 13.8026 8.67677 13.3385 8.67461 12.8744C8.67407 12.8089 8.68544 12.7786 8.76015 12.765C9.09962 12.7049 9.4288 12.6058 9.74228 12.4607C10.3498 12.1802 10.8408 11.7703 11.1603 11.1724C11.4288 10.6699 11.51 10.1327 11.4618 9.56957C11.4158 9.03239 11.2366 8.55207 10.8787 8.14431C10.5506 7.77121 10.1402 7.51129 9.69843 7.29522C9.39145 7.14523 9.07363 7.02284 8.75041 6.91129C8.7098 6.89721 8.67407 6.88693 8.67407 6.82736C8.67623 6.14993 8.67569 5.4725 8.67461 4.79507C8.67461 4.75121 8.68489 4.73117 8.73308 4.73767C8.87547 4.75717 9.01895 4.77016 9.16134 4.79236C9.634 4.86493 10.0796 5.02467 10.5116 5.22395C10.5717 5.25157 10.5945 5.24886 10.6123 5.17684C10.7434 4.6467 10.8771 4.1171 11.0162 3.58913C11.0379 3.5079 11.0244 3.47541 10.948 3.44076C10.2799 3.13751 9.57282 3.01025 8.8457 2.97614C8.78018 2.97289 8.76123 2.95556 8.76178 2.88896C8.76503 2.50232 8.76232 2.11568 8.76448 1.72904C8.76503 1.66785 8.75041 1.64727 8.68489 1.64727C8.23173 1.64998 7.77802 1.64998 7.32485 1.64727C7.26151 1.64673 7.24418 1.66406 7.24418 1.72742C7.24689 2.1433 7.24256 2.55972 7.24797 2.9756C7.24905 3.06116 7.2209 3.08661 7.14239 3.10285C6.73579 3.18679 6.34651 3.32271 5.98646 3.53281C5.20628 3.98822 4.72117 4.64724 4.61938 5.5586C4.51597 6.48837 4.83812 7.2427 5.57661 7.81778C6.05739 8.19251 6.60639 8.43781 7.1738 8.64683C7.2274 8.66633 7.24743 8.68907 7.24689 8.7481C7.24472 9.12066 7.24635 9.49159 7.24635 9.86252Z"
fill="#59BE59"
/>
<path
d="M7.2452 9.86252C7.2452 9.49158 7.24358 9.12119 7.24683 8.75026C7.24737 8.69123 7.22734 8.66903 7.17374 8.64899C6.60687 8.43997 6.05787 8.19467 5.57655 7.81994C4.8386 7.24486 4.51591 6.49053 4.61933 5.56076C4.72057 4.6494 5.20568 3.99092 5.98641 3.53497C6.34645 3.32486 6.73519 3.18894 7.14233 3.10501C7.22084 3.08876 7.24899 3.06277 7.24791 2.97775C7.2425 2.56187 7.24683 2.14545 7.24412 1.72957C7.24358 1.66621 7.2609 1.64888 7.32479 1.64943C7.77796 1.65213 8.23167 1.65213 8.68483 1.64943C8.7498 1.64888 8.76442 1.66946 8.76442 1.73119C8.76171 2.11783 8.76496 2.50447 8.76171 2.89111C8.76117 2.95717 8.78012 2.97504 8.84563 2.97829C9.57276 3.01295 10.2793 3.13966 10.948 3.44291C11.0243 3.47757 11.0373 3.51006 11.0162 3.59128C10.877 4.11926 10.7433 4.64885 10.6123 5.17899C10.5944 5.25156 10.5717 5.25372 10.5116 5.2261C10.079 5.02683 9.63394 4.86708 9.16128 4.79452C9.01889 4.77286 8.87595 4.75932 8.73302 4.73983C8.68483 4.73333 8.67455 4.75337 8.67455 4.79723C8.67563 5.47466 8.67617 6.15209 8.674 6.82952C8.674 6.88908 8.70974 6.89937 8.75034 6.91345C9.07303 7.02446 9.39138 7.14684 9.69837 7.29738C10.1396 7.51344 10.5506 7.77283 10.8787 8.14647C11.2365 8.55369 11.4157 9.03455 11.4618 9.57173C11.51 10.1349 11.4287 10.6726 11.1602 11.1746C10.8408 11.7724 10.3497 12.1818 9.74222 12.4629C9.42874 12.608 9.09956 12.7071 8.76009 12.7672C8.68483 12.7802 8.674 12.811 8.67455 12.8766C8.67671 13.3406 8.67455 13.8047 8.67725 14.2688C8.67779 14.3381 8.66426 14.3646 8.58684 14.3636C8.13908 14.3598 7.69079 14.3608 7.24304 14.3636C7.17536 14.3641 7.15803 14.3424 7.15803 14.2769C7.1602 13.8475 7.15695 13.4181 7.16074 12.9887C7.16128 12.9128 7.14179 12.8906 7.06491 12.8863C6.31992 12.843 5.59658 12.699 4.90303 12.4174C4.78229 12.3681 4.66426 12.3112 4.54948 12.2495C4.51321 12.23 4.50075 12.2116 4.51158 12.1688C4.66318 11.5943 4.81369 11.0197 4.96204 10.4446C4.97829 10.3824 5.00373 10.4024 5.03947 10.4214C5.63557 10.7387 6.2674 10.9477 6.93768 11.036C7.01672 11.0463 7.09685 11.0501 7.1759 11.0614C7.23383 11.0695 7.24737 11.0479 7.24737 10.9927C7.24412 10.6147 7.2452 10.2383 7.2452 9.86252ZM8.68537 9.36325C8.67942 9.37245 8.67455 9.37678 8.67455 9.38112C8.674 9.83978 8.67401 10.2984 8.67292 10.7571C8.67292 10.8177 8.70216 10.7928 8.72598 10.7755C8.82452 10.7046 8.90736 10.619 8.96691 10.5123C9.17698 10.1333 9.05679 9.63725 8.68537 9.36325ZM7.23871 6.11147C7.23871 5.75354 7.23871 5.40589 7.23871 5.05174C6.92522 5.33982 6.92522 5.77249 7.23871 6.11147Z"
fill="#FEFEFE"
/>
<path
d="M8.68433 9.36328C9.05574 9.63729 9.17539 10.1333 8.96586 10.5118C8.90631 10.619 8.82347 10.7046 8.72493 10.775C8.70111 10.7918 8.67188 10.8172 8.67188 10.7566C8.67242 10.2979 8.67296 9.83927 8.6735 9.38061C8.67404 9.37682 8.67891 9.37249 8.68433 9.36328Z"
fill="#59BE59"
/>
<path
d="M7.23882 6.11149C6.92533 5.77305 6.92587 5.33984 7.23882 5.05176C7.23882 5.40591 7.23882 5.75355 7.23882 6.11149Z"
fill="#59BE59"
/>
</svg>
</span>
<span className="text-base text-dark-gray dark:text-white font-medium">
6392.99$
</span>
</div>
</td>
<td className="text-right py-4">
<button
type="button"
className="text-sm text-white bg-purple px-2.5 py-1.5 rounded-full"
>
Active
</button>
</td>
</tr>
<tr className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
<td className=" py-4">
<div className="flex space-x-2 items-center">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img
src={dataImage2}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
Mullican Computer Joy
</h1>
<span className="text-sm text-thin-light-gray">
Owned by <span className="text-purple">Xoeyam</span>
</span>
</div>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span>
<svg
width="18"
height="18"
viewBox="0 0 18 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9 18C13.9706 18 18 13.9706 18 9C18 4.02944 13.9706 0 9 0C4.02944 0 0 4.02944 0 9C0 13.9706 4.02944 18 9 18Z"
fill="#627EEA"
/>
<path
d="M9.28125 2.25V7.23937L13.4983 9.12375L9.28125 2.25Z"
fill="white"
fillOpacity="0.602"
/>
<path
d="M9.28012 2.25L5.0625 9.12375L9.28012 7.23937V2.25Z"
fill="white"
/>
<path
d="M9.28125 12.3582V15.7483L13.5011 9.91016L9.28125 12.3582Z"
fill="white"
fillOpacity="0.602"
/>
<path
d="M9.28012 15.7483V12.3576L5.0625 9.91016L9.28012 15.7483Z"
fill="white"
/>
<path
d="M9.28125 11.572L13.4983 9.12348L9.28125 7.24023V11.572Z"
fill="white"
fillOpacity="0.2"
/>
<path
d="M5.0625 9.12348L9.28012 11.572V7.24023L5.0625 9.12348Z"
fill="white"
fillOpacity="0.602"
/>
</svg>
</span>
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
7473 ETH
</span>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7.55225 0C7.8457 0 8.13914 0 8.43205 0C8.44829 0.026534 8.47537 0.0151623 8.49756 0.0162453C9.28966 0.0649812 10.0606 0.220936 10.8013 0.505229C12.7699 1.26172 14.2323 2.58354 15.183 4.46638C15.5999 5.29218 15.8506 6.16997 15.9561 7.08891C15.9691 7.201 15.9621 7.3158 16 7.42465C16 7.80858 16 8.19251 16 8.57698C15.9778 8.5916 15.9854 8.61543 15.9838 8.63546C15.9475 9.10387 15.8744 9.56686 15.7515 10.0206C15.1787 12.1342 13.9524 13.7603 12.0818 14.8942C11.1516 15.4579 10.1397 15.8002 9.06064 15.941C8.89497 15.9626 8.72875 15.98 8.56308 15.9995C8.17217 15.9995 7.78127 15.9995 7.39036 16C7.3752 15.9789 7.35138 15.9865 7.33135 15.9848C6.96752 15.9545 6.60639 15.9009 6.25068 15.8197C4.77639 15.4829 3.48998 14.793 2.4131 13.7311C0.998917 12.3372 0.204656 10.6461 0.0270709 8.66687C0.0205739 8.59431 0.033568 8.51904 0 8.44972C0 8.15081 0 7.85244 0 7.55352C0.0265295 7.53403 0.0151597 7.50479 0.016784 7.47988C0.0730915 6.64162 0.251218 5.83044 0.564158 5.05066C1.10179 3.71043 1.93774 2.59058 3.07634 1.70142C4.33839 0.715876 5.77098 0.159745 7.36762 0.0270755C7.4288 0.0216604 7.49432 0.0341151 7.55225 0ZM7.24635 9.86252C7.24635 10.2383 7.24526 10.6147 7.24743 10.9905C7.24797 11.0457 7.23389 11.0679 7.17596 11.0593C7.09691 11.0479 7.01678 11.0446 6.93774 11.0338C6.26746 10.9461 5.63563 10.7371 5.03952 10.4192C5.00379 10.4002 4.97834 10.3802 4.9621 10.4425C4.81375 11.0176 4.66324 11.5926 4.51164 12.1666C4.50027 12.2094 4.51272 12.2278 4.54954 12.2473C4.66486 12.3096 4.78235 12.3665 4.90309 12.4152C5.5961 12.6968 6.31998 12.8408 7.06497 12.8842C7.14131 12.8885 7.16134 12.9112 7.1608 12.9865C7.15701 13.4159 7.16026 13.8453 7.15809 14.2747C7.15755 14.3397 7.17488 14.3619 7.2431 14.3614C7.69085 14.3581 8.13914 14.3576 8.5869 14.3614C8.66432 14.3619 8.67731 14.3359 8.67731 14.2666C8.67461 13.8026 8.67677 13.3385 8.67461 12.8744C8.67407 12.8089 8.68544 12.7786 8.76015 12.765C9.09962 12.7049 9.4288 12.6058 9.74228 12.4607C10.3498 12.1802 10.8408 11.7703 11.1603 11.1724C11.4288 10.6699 11.51 10.1327 11.4618 9.56957C11.4158 9.03239 11.2366 8.55207 10.8787 8.14431C10.5506 7.77121 10.1402 7.51129 9.69843 7.29522C9.39145 7.14523 9.07363 7.02284 8.75041 6.91129C8.7098 6.89721 8.67407 6.88693 8.67407 6.82736C8.67623 6.14993 8.67569 5.4725 8.67461 4.79507C8.67461 4.75121 8.68489 4.73117 8.73308 4.73767C8.87547 4.75717 9.01895 4.77016 9.16134 4.79236C9.634 4.86493 10.0796 5.02467 10.5116 5.22395C10.5717 5.25157 10.5945 5.24886 10.6123 5.17684C10.7434 4.6467 10.8771 4.1171 11.0162 3.58913C11.0379 3.5079 11.0244 3.47541 10.948 3.44076C10.2799 3.13751 9.57282 3.01025 8.8457 2.97614C8.78018 2.97289 8.76123 2.95556 8.76178 2.88896C8.76503 2.50232 8.76232 2.11568 8.76448 1.72904C8.76503 1.66785 8.75041 1.64727 8.68489 1.64727C8.23173 1.64998 7.77802 1.64998 7.32485 1.64727C7.26151 1.64673 7.24418 1.66406 7.24418 1.72742C7.24689 2.1433 7.24256 2.55972 7.24797 2.9756C7.24905 3.06116 7.2209 3.08661 7.14239 3.10285C6.73579 3.18679 6.34651 3.32271 5.98646 3.53281C5.20628 3.98822 4.72117 4.64724 4.61938 5.5586C4.51597 6.48837 4.83812 7.2427 5.57661 7.81778C6.05739 8.19251 6.60639 8.43781 7.1738 8.64683C7.2274 8.66633 7.24743 8.68907 7.24689 8.7481C7.24472 9.12066 7.24635 9.49159 7.24635 9.86252Z"
fill="#59BE59"
/>
<path
d="M7.2452 9.86252C7.2452 9.49158 7.24358 9.12119 7.24683 8.75026C7.24737 8.69123 7.22734 8.66903 7.17374 8.64899C6.60687 8.43997 6.05787 8.19467 5.57655 7.81994C4.8386 7.24486 4.51591 6.49053 4.61933 5.56076C4.72057 4.6494 5.20568 3.99092 5.98641 3.53497C6.34645 3.32486 6.73519 3.18894 7.14233 3.10501C7.22084 3.08876 7.24899 3.06277 7.24791 2.97775C7.2425 2.56187 7.24683 2.14545 7.24412 1.72957C7.24358 1.66621 7.2609 1.64888 7.32479 1.64943C7.77796 1.65213 8.23167 1.65213 8.68483 1.64943C8.7498 1.64888 8.76442 1.66946 8.76442 1.73119C8.76171 2.11783 8.76496 2.50447 8.76171 2.89111C8.76117 2.95717 8.78012 2.97504 8.84563 2.97829C9.57276 3.01295 10.2793 3.13966 10.948 3.44291C11.0243 3.47757 11.0373 3.51006 11.0162 3.59128C10.877 4.11926 10.7433 4.64885 10.6123 5.17899C10.5944 5.25156 10.5717 5.25372 10.5116 5.2261C10.079 5.02683 9.63394 4.86708 9.16128 4.79452C9.01889 4.77286 8.87595 4.75932 8.73302 4.73983C8.68483 4.73333 8.67455 4.75337 8.67455 4.79723C8.67563 5.47466 8.67617 6.15209 8.674 6.82952C8.674 6.88908 8.70974 6.89937 8.75034 6.91345C9.07303 7.02446 9.39138 7.14684 9.69837 7.29738C10.1396 7.51344 10.5506 7.77283 10.8787 8.14647C11.2365 8.55369 11.4157 9.03455 11.4618 9.57173C11.51 10.1349 11.4287 10.6726 11.1602 11.1746C10.8408 11.7724 10.3497 12.1818 9.74222 12.4629C9.42874 12.608 9.09956 12.7071 8.76009 12.7672C8.68483 12.7802 8.674 12.811 8.67455 12.8766C8.67671 13.3406 8.67455 13.8047 8.67725 14.2688C8.67779 14.3381 8.66426 14.3646 8.58684 14.3636C8.13908 14.3598 7.69079 14.3608 7.24304 14.3636C7.17536 14.3641 7.15803 14.3424 7.15803 14.2769C7.1602 13.8475 7.15695 13.4181 7.16074 12.9887C7.16128 12.9128 7.14179 12.8906 7.06491 12.8863C6.31992 12.843 5.59658 12.699 4.90303 12.4174C4.78229 12.3681 4.66426 12.3112 4.54948 12.2495C4.51321 12.23 4.50075 12.2116 4.51158 12.1688C4.66318 11.5943 4.81369 11.0197 4.96204 10.4446C4.97829 10.3824 5.00373 10.4024 5.03947 10.4214C5.63557 10.7387 6.2674 10.9477 6.93768 11.036C7.01672 11.0463 7.09685 11.0501 7.1759 11.0614C7.23383 11.0695 7.24737 11.0479 7.24737 10.9927C7.24412 10.6147 7.2452 10.2383 7.2452 9.86252ZM8.68537 9.36325C8.67942 9.37245 8.67455 9.37678 8.67455 9.38112C8.674 9.83978 8.67401 10.2984 8.67292 10.7571C8.67292 10.8177 8.70216 10.7928 8.72598 10.7755C8.82452 10.7046 8.90736 10.619 8.96691 10.5123C9.17698 10.1333 9.05679 9.63725 8.68537 9.36325ZM7.23871 6.11147C7.23871 5.75354 7.23871 5.40589 7.23871 5.05174C6.92522 5.33982 6.92522 5.77249 7.23871 6.11147Z"
fill="#FEFEFE"
/>
<path
d="M8.68433 9.36328C9.05574 9.63729 9.17539 10.1333 8.96586 10.5118C8.90631 10.619 8.82347 10.7046 8.72493 10.775C8.70111 10.7918 8.67188 10.8172 8.67188 10.7566C8.67242 10.2979 8.67296 9.83927 8.6735 9.38061C8.67404 9.37682 8.67891 9.37249 8.68433 9.36328Z"
fill="#59BE59"
/>
<path
d="M7.23882 6.11149C6.92533 5.77305 6.92587 5.33984 7.23882 5.05176C7.23882 5.40591 7.23882 5.75355 7.23882 6.11149Z"
fill="#59BE59"
/>
</svg>
</span>
<span className="text-base text-dark-gray dark:text-white font-medium">
6392.99$
</span>
</div>
</td>
<td className="text-right py-4">
<button
type="button"
className="text-sm text-white bg-light-green px-2.5 py-1.5 rounded-full"
>
Complated
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
);
}
+3 -3
View File
@@ -19,9 +19,9 @@ export default function HomeSliders(props) {
<div className="item w-full h-full bg-white dark:bg-dark-white rounded-2xl overflow-hidden">
<img src={slider2} alt="slider" className="w-full h-full" />
</div>
<div className="item w-full h-full bg-white dark:bg-dark-white rounded-2xl overflow-hidden">
<img src={slider3} alt="slider" className="w-full h-full" />
</div>
{/*<div className="item w-full h-full bg-white dark:bg-dark-white rounded-2xl overflow-hidden">*/}
{/* <img src={slider3} alt="slider" className="w-full h-full" />*/}
{/*</div>*/}
{props.bannerList.map((item, index) => (
<div className="item w-full h-full bg-white dark:bg-dark-white rounded-2xl overflow-hidden">
<HomeBannerOffersCard
+21 -5
View File
@@ -1,4 +1,4 @@
import React from "react";
import React, { useState, useEffect } from "react";
import datas from "../../data/product_data.json";
import Layout from "../Partials/Layout";
import usersService from "../../services/UsersService";
@@ -11,10 +11,10 @@ export default function Home(props) {
console.log("PROPS IN HOME->",props);
// const trending = datas.datas;
// const jobData = datas.datas; // api calls or cache
let [nextDueTask, setNextDueTask] = useState({})
const userApi = new usersService();
// const homeData = userApi.getHomeDate();
const {userDetails} = useSelector((state) => state?.userDetails)
const commonHeadData =()=>{
@@ -22,6 +22,22 @@ export default function Home(props) {
return 0;
}
// FUNCTION TO GET DASH DATA TO DETERMINE CURRENT TASK DUE TIME
const getHomeDate = () => {
userApi.getHomeDate().then(res => {
if(res.status != 200 || res.internal_return < 0){
return
}
setNextDueTask(res.data)
}).catch(error => {
console.log(error)
})
}
useEffect(()=>{
getHomeDate()
},[])
return (
<Layout>
<div className="home-page-wrapper">
@@ -29,7 +45,7 @@ export default function Home(props) {
<FamilyDash commonHeadData={commonHeadData} />
)}
{userDetails && userDetails?.account_type == "FULL" && (
<FullAccountDash bannerList={props.bannerList} />
<FullAccountDash nextDueTask={nextDueTask} bannerList={props.bannerList} />
)}
</div>
@@ -0,0 +1,206 @@
import React, { useCallback, useMemo, useState } from "react";
import ModalCom from "../../Helpers/ModalCom";
import { toast } from "react-toastify";
import { Form, Formik } from "formik";
import usersService from "../../../services/UsersService";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
const [marketMsg, setMarketMsg] = useState({
loading: false,
data: {},
state: undefined,
});
const [textValue, setTextValue] = useState("");
const handleInputChange = ({ target: { value } }) => {
setTextValue(value);
};
const apiCall = useMemo(() => new usersService(), []);
const marketCalls = useCallback(
async (e) => {
let nameOfCall = e?.target?.name;
let { offer_code } = details;
let reqData = { offer_code };
try {
if (nameOfCall === "market-message") {
// To manage the manage msg data
setMarketMsg({ loading: true });
reqData = { yourmessage: textValue, ...reqData };
const marketMessage = await apiCall.MarketMessage(reqData);
const marketMessageRes = await marketMessage?.data;
if (marketMessageRes?.internal_return < 0) {
setMarketMsg({ loading: false });
toast.warn("Something wrong happened", {
autoClose: 2000,
hideProgressBar: true,
});
onClose();
return;
}
toast.success("Message sent", {
autoClose: 2500,
hideProgressBar: true,
});
// To manage the manage msg data
setMarketMsg({ data: marketMessageRes, state: true });
}
} catch (error) {
throw new Error(error);
} finally {
setTimeout(() => {
onClose();
setTextValue("");
setMarketMsg({ loading: false });
}, 2000);
}
},
[apiCall, details, onClose, setMarketMsg, textValue]
);
// let addedIntDate = marketInt?.added?.split(" ")[0];
let expireIntDate = marketInt?.expire?.split(" ")[0];
return (
// className="job-popup"
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="logout-modal-header w-full flex items-center justify-end lg:p-6 px-[30px] py-[23px]">
<CloseIcon onClose={onClose} />
</div>
<div className="md:flex bg-white rounded-lg shadow-lg">
<div className="p-4 w-full md:w-3/4 md:border-r-1">
<div className="flex items-center gap-4 md:text-[16px] text-md tracking-wide text-dark-gray dark:text-white">
<p className="font-semibold text-slate-900">
{details.offer_code}
</p>
<p>
<span className="text-slate-900">{`Timeline: ${details.timeline_days} day(s) -- `}</span>
<span className="font-semibold text-slate-900">{`Budget: ${details.price} naira`}</span>
</p>
</div>
{/* INPUT SECTION */}
{[
{ name: "Title", content: details.title },
{ name: "Description", content: details.description },
{
name: "Detail",
content: details.job_description,
danger: true,
},
].map(({ name, content, danger }, idx) => (
<div className="my-3 md:flex" key={idx}>
<label className="w-full md:w-1/4 text-slate-900 tracking-wide font-semibold">
{name}
</label>
{danger ? (
<p
className={`w-full md:w-3/4 text-slate-900 `}
dangerouslySetInnerHTML={{
__html: danger && content?.replace(/"/g, ""),
}}
/>
) : (
<p className={`w-full md:w-3/4 text-slate-900 `}>
{content !== "Detail" ? content : null}
</p>
)}
</div>
))}
<hr />
<div className="my-3 w-full flex flex-col gap-3">
<div className="w-full">
<label className="w-full text-slate-900 tracking-wide">
If you have any questions about this task:
</label>
<textarea
className={`p-1 w-full text-sm text-slate-900 outline-none border border-slate-300 rounded-md`}
rows="5"
style={{ resize: "none" }}
placeholder="Enter message here ..."
value={textValue}
onChange={handleInputChange}
/>
</div>
<button
className="self-end w-[150px] h-[52px] rounded-md text-base bg-yellow-500 text-white"
name="market-message"
onClick={marketCalls}
>
{marketMsg.loading ? (
<LoadingSpinner size={5} color="white" />
) : !marketMsg.state ? (
"Send Message"
) : (
"Message Sent"
)}
</button>
</div>
</div>
<div className="w-full md:w-1/4 h-full">
<div className="w-[90%] mx-auto bg-[#f1f8ff] p-4 rounded-md">
<p className="w-full text-slate-900 tracking-wide my-1">
Interested in the task?
</p>
<div className="w-full flex flex-col justify-center py-4 gap-2">
<hr />
<button className="bg-[#57cd89] text-center text-lg font-semibold text-white py-2 px-4 rounded-md inline-flex flex-col items-center justify-center">
{" "}
<span>Send</span>
<span>Interest</span>
<span>Request</span>
</button>
<p>Error - {marketInt?.status}</p>
<p className="mt-2 flex items-center">
Interest: <b className="ml-1">{marketInt?.public_view}</b>
</p>
<hr />
</div>
<p className="my-10">Expire: {expireIntDate}</p>
</div>
</div>
{/* END OF ACTION SECTION */}
</div>
</div>
</ModalCom>
);
};
export default MarketPopUp;
const CloseIcon = ({ onClose }) => (
<button
type="button"
className="text-[#374557] dark:text-red-500"
onClick={onClose}
>
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
className="fill-current"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z"
fill=""
fillOpacity="0.6"
/>
<path
d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z"
fill="#"
fillOpacity="0.6"
/>
</svg>
</button>
);
@@ -31,7 +31,13 @@ export default function ActiveJobMessage({ activeJobMesList }) {
<tbody>
{currentActiveJobMesList.map((item, index) => (
<tr key={index} className='text-slate-500'>
<td className="p-2" dangerouslySetInnerHTML={{__html: item.message}}></td>
<td>
<div className="msg_box">
<div className="msg_header">{item.msg_date} {item.msg_firstname}</div>
<span className="p-2" dangerouslySetInnerHTML={{__html: item.message}}></span>
</div>
</td>
</tr>
))}
</tbody>
@@ -48,7 +54,7 @@ export default function ActiveJobMessage({ activeJobMesList }) {
:
<tbody>
<tr className='text-slate-500'>
<td className="p-2" colSpan={4}>No Purchase History Found!</td>
<td className="p-2" colSpan={4}>No Message Found!</td>
</tr>
</tbody>
}
+289 -120
View File
@@ -5,6 +5,8 @@ import { useNavigate } from "react-router-dom";
import ActiveJobMessage from "./ActiveJobMessage";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import CountDown from "../Helpers/CountDown";
import usersService from "../../services/UsersService";
function ActiveJobs(props) {
@@ -15,6 +17,10 @@ function ActiveJobs(props) {
let [messageToSend, setMessageToSend] = useState('') // State to hold the value of message to be sent
let [filesToSend, setFilesToSend] = useState([]) // State to hold the value of files to be sent
let [tab, setTab] = useState('message')
let [requestStatus, setRequestStatus] = useState({loading: false, status: false, message: ''})
// FUNCTION TO HANDLE MESSAGE CHANGE
@@ -22,6 +28,47 @@ function ActiveJobs(props) {
setMessageToSend(value)
}
// FUNCTION TO HANDLE FILE UPlOAD CHANGE
const handleFileChange = ({target:{files}}) => {
setRequestStatus({loading: false, status: false, message: ''}) // State to determine error state
if(!files[0]) { // IF NO FILE SELECTED RETURN
return
}
if(files[0].size > Number(process.env.REACT_APP_MAX_FILE_SIZE)){
setRequestStatus({loading: false, status: false, message: 'File must be <= 1mb'})
setTimeout(()=>{
setRequestStatus({loading: false, status: false, message: ''})
}, 5000)
return
}
if(filesToSend.length >= Number(process.env.REACT_APP_TOTAL_NUM_FILE)){
setRequestStatus({loading: false, status: false, message: `Total number of attachment is ${Number(process.env.REACT_APP_TOTAL_NUM_FILE)}`})
setTimeout(()=>{
setRequestStatus({loading: false, status: false, message: ''})
}, 5000)
return
}
// INCLUDE FILE IF NO ERROR
setFilesToSend(prev => ([...prev, files[0]]))
}
// FUNCTION TO CLEAR ALL TYPED MESSAGE OR FILES
const handleClearAll = ({target:{name}}) => {
if(tab == 'message'){
setMessageToSend('')
}else if(tab=='files'){
setFilesToSend([])
}else{
return
}
}
// FUNCTION TO REMOVE AND IMAGE
const handleRemoveImage = (imageToDelete) => {
setFilesToSend(prev => prev.filter(item => item.name != imageToDelete.name))
}
// FUNCTION TO SEND TASK MESSAGE
const sendTaskMessage = () => {
let reqData={message: messageToSend, msg_type: 'TEXT', contract:props.details.contract}
@@ -49,17 +96,67 @@ function ActiveJobs(props) {
})
}
// FUNCTION TO SEND FILES
const sendFile = async () => {
setRequestStatus({loading: true, status: false, message: ''})
if(!filesToSend.length){ // checks if file to send is empty
setRequestStatus({loading: false, status: false, message: 'No File(s) selected'})
return setTimeout(()=>{
setRequestStatus({loading: false, status: false, message: ''})
}, 5000)
}
for(let i=0; i<=filesToSend.length-1; i++){ // Loops through files to send array and trigger upload API call
const fileToBase64 = async () =>{ // Converts file data to base64 string
try {
const base64String = await convertFileToBase64(filesToSend[i]);
return base64String;
} catch (error) {
return false;
}
}
// if(await !fileToBase64()){
// return
// }
let reqData={file_name: filesToSend[i].name, file_size: filesToSend[i].size, file_type: 'image/png', file_data: await fileToBase64(), msg_type: 'FILE', contract:props.details.contract}
ApiCall.sendFiles(reqData).then((res)=>{
// if(res.status != 200 || res.data.internal_return < 0){
// setRequestStatus({loading: false, status: false, message: 'Files(s) could not be sent, try again later'})
// return
// }
// setRequestStatus({loading: false, status: true, message: 'File(s) Uploaded Successfully'})
// props.reloadActiveJobList(prev => !prev) // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
// setFilesToSend([]) // SETS FILES TO SEND TO SEND BACK TO EMPTY ARRAY
}).catch(error => {
// setRequestStatus({loading: false, status: false, message: 'Opps! something went wrong'})
}).finally(()=>{
if(i==filesToSend.length-1){
setRequestStatus({loading: false, status: true, message: 'File(s) Uploaded Successfully'})
setFilesToSend([]) // SETS FILES TO SEND TO SEND BACK TO EMPTY ARRAY
props.reloadActiveJobList(prev => !prev) // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
setTimeout(()=>{
setRequestStatus({loading: false, status: false, message: ''})
}, 5000)
}
})
}
}
return (
<Layout>
<div className="p-4 lg:flex justify-between items-start space-y-4 lg:space-x-4 lg:space-y-0 rounded-lg shadow-lg bg-slate-100">
<div className="w-full lg:w-1/2">
<div className="py-[20px] bg-white px-4 rounded-md shadow-md">
{/* back btn and title */}
<div className="w-full flex justify-start space-x-3 items-center">
<div className="py-[20px] bg-white px-4 rounded-2xl shadow-md md:flex justify-between items-start gap-8">
{/* job title */}
<div className="w-full md:w-8/12">
<div className="w-full flex justify-start space-x-3 items-start">
<button
type="button"
className="text-[#374557] border border-sky-blue p-1 rounded-full"
className="min-w-[45px] h-auto text-[#374557] border border-sky-blue p-1 rounded-full"
onClick={() => navigate(props.details.pathname, {replace: true})}
>
<svg
@@ -72,143 +169,196 @@ function ActiveJobs(props) {
<path d="M19 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H19v-2z" />
</svg>
</button>
<h1 className="text-lg font-bold text-dark-gray dark:text-white tracking-wide">
<h1 className="text-xl lg:text-2xl font-bold text-dark-gray dark:text-white tracking-wide">
{props.details?.title && props.details.title}
</h1>
</div>
{/* END of back btn and title */}
<div className="mt-2 w-full flex flex-col-reverse lg:flex-row lg:justify-between lg:items-start lg:space-x-2">
<div className="w-full lg:w-2/3 my-2 lg:my-0">
<p className="text-base text-slate-700 dark:text-black">
{props.details?.contract && props.details.contract}
</p>
<p className="text-base text-slate-700 dark:text-black">
<span className="font-semibold">Description: </span>
{props.details?.description && props.details.description}
</p>
<p className="text-base text-sky-blue">Delivery Detail</p>
<div className="">
<p className="text-base text-slate-700 dark:text-black">
<span className="font-semibold">Due: </span>
{props.details?.delivery_date &&
props.details.delivery_date.split(" ")[0]}
</p>
<p className="text-base text-slate-700 dark:text-black">
{props.details?.delivery_date &&
props.details.delivery_date.split(" ")[1]}
</p>
<p className="text-base text-slate-700 dark:text-black">
{props.details?.timeline_days && props.details.timeline_days} day(s)
</p>
</div>
</div>
<div className="w-full lg:w-1/3 lg:text-center">
<p className="text-base text-sky-blue">
{userDetails.firstname && userDetails.firstname}
</p>
<div className="w-full my-2">
<p className="w-full text-base text-right text-sky-blue">
{userDetails.firstname && userDetails.firstname}
</p>
<div className="text-base text-slate-700 dark:text-black tracking-wide">
<p className="font-semibold text-black">Description: </p>
<p className="p-2 border border-sky-blue">{props.details?.description && props.details.description}</p>
</div>
</div>
</div>
{/* end of job title */}
<div className="mt-5 bg-white p-4 rounded-md shadow-md">
<div className="">
<p className="relative py-2 my-2 text-lg font-bold text-slate-600 dark:text-black border-b-2 border-slate-300 tracking-wide after:absolute after:-bottom-0.5 after:content-[''] after:w-[100px] after:h-[2px] after:bg-sky-blue after:left-0">Message(s)</p>
<textarea
className="p-4 w-full text-base text-slate-600 border-y border-slate-300 outline-none"
rows="10"
style={{ resize: "none" }}
name='message'
onChange={handleMessageChange}
value={messageToSend}
/>
{/* job details */}
<div className="w-full md:w-4/12">
<p className="text-base text-sky-blue">Delivery Detail</p>
<div className="my-1 flex items-start gap-3">
<p className="font-semibold">Due: </p>
<div className="flex flex-col justify-between">
<p className="text-base text-slate-700 dark:text-black tracking-wide">
<CountDown lastDate={props.details.delivery_date} />
</p>
<div className="text-base text-slate-700 dark:text-black tracking-wide flex gap-[5px]">
<span>Hrs</span>
<span>Min</span>
<span>Sec</span>
</div>
</div>
</div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
<div className="w-full">
{/* error or success display */}
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
<div className="my-1 text-base text-slate-700 dark:text-black tracking-wide flex items-center gap-3">
<span className="font-semibold text-black">Duration: </span>
<span className="">{props.details?.timeline_days && props.details.timeline_days} day(s)</span>
</div>
<div className="my-1 text-base text-slate-700 dark:text-black tracking-wide flex items-center gap-3">
<span className="font-semibold text-black">No: </span>
<span className="">{props.details?.contract && props.details.contract}</span>
</div>
</div>
{/* end of job details */}
</div>
<div className="my-4 py-[20px] bg-white px-4 rounded-2xl shadow-md lg:flex justify-between items-start space-y-4 lg:space-x-4 lg:space-y-0">
<div className="w-full lg:w-1/2">
<div className="">
<h1 className="text-lg font-bold text-dark-gray dark:text-white tracking-wide">Actions</h1>
<p className="my-3 py-1 text-base">
Waiting for the completion message from the client before you can approve.
</p>
</div>
{/* TEXTAREA SECTION */}
<div className="mt-5">
<div className="">
{/* <p className="relative py-2 my-2 text-lg font-bold text-slate-600 dark:text-black border-b-2 border-slate-300 tracking-wide after:absolute after:-bottom-0.5 after:content-[''] after:w-[100px] after:h-[2px] after:bg-sky-blue after:left-0">Message(s)</p> */}
<div className="my-2 flex items-center border-b border-slate-300">
<button
name='message'
onClick={(e) => setTab(e.target.name)}
className={`p-2 text-lg font-bold text-slate-600 dark:text-black border ${tab == 'message'? 'border-sky-blue':'border-slate-300'} tracking-wide transition duration-200`}>
Send Message
</button>
<button
name='files'
onClick={(e) => setTab(e.target.name)}
className={`p-2 text-lg font-bold text-slate-600 dark:text-black border ${tab == 'files'? 'border-sky-blue':'border-slate-300'} tracking-wide transition duration-200`}>
Send Files
</button>
</div>
{tab == 'message' ?
(
<textarea
className="p-4 w-full h-[300px] text-base text-slate-600 border border-slate-300 outline-none"
// rows="10"
style={{ resize: "none" }}
name='message'
onChange={handleMessageChange}
value={messageToSend}
/>
)
:
<div className="p-4 w-full h-[300px] text-base text-slate-600 border border-slate-300">
<div className="files">
<label htmlFor="file" className="h-20 btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer">Select Files to Upload</label>
<input type="file" id='file' accept="image/*" style={{display: 'none'}} onChange={handleFileChange}/>
</div>
<div className="selected_file my-2">
{filesToSend.length > 0 &&
filesToSend.map((item, index)=> (
<p key={index} className="flex items-center space-x-2">
<span>{item.name}</span>
<button name='remove' onClick={()=>handleRemoveImage(item)} className="px-2 flex justify-center items-center rounded-full border border-red-500 text-red-500">x</button>
</p>
))
}
</div>
</div>
) : (
requestStatus.status && (
}
</div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
<div className="w-full">
{/* error or success display */}
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
</div>
{/* End of error or success display */}
) : (
requestStatus.status && (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
</div>
{/* End of error or success display */}
{/* Buttons Sections */}
<div className="py-2 mb-8 sm:flex sm:justify-center sm:items-center">
<div className="w-full sm:w-2/4 mb-5 sm:mb-0">
<button
onClick={()=>{console.log('working')}}
type="button"
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-md flex justify-center items-center"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill='white'>
<path d="M12 2L2 12h3v8h14v-8h3L12 2zm0 16v-6h-2v6H7l5-5 5 5h-3z"/>
</svg>
{/* Buttons Sections */}
<div className="py-2 sm:flex sm:justify-end sm:items-center">
<div className="w-full sm:w-2/4 flex justify-between items-center space-x-2">
<button
type="button"
onClick={handleClearAll}
className="border-gradient text-base tracking-wide px-4 py-3 rounded-full"
>
<span className="text-gradient">Clear</span>
</button>
{tab == 'files' ?
(
<button
onClick={sendFile}
type="button"
className="btn-gradient text-base tracking-wide px-4 py-3 rounded-full flex justify-center items-center"
>
{requestStatus.loading ?
<LoadingSpinner size='6' color='sky-blue' />
:
<>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill='white'>
<path d="M12 2L2 12h3v8h14v-8h3L12 2zm0 16v-6h-2v6H7l5-5 5 5h-3z"/>
</svg>
<span className="text-white">Upload Files</span>
</button>
</div>
<div className="w-full sm:w-2/4 flex justify-between items-center space-x-2">
<button
type="button"
className="bg-red-600 text-base text-white tracking-wide px-4 py-2 rounded-md hover:opacity-90"
>
<span className="text-white">Clear</span>
</button>
<button
onClick={sendTaskMessage}
type="button"
className="btn-gradient text-base text-white tracking-wide px-4 py-2 rounded-md"
>
{requestStatus.loading ?
<LoadingSpinner size='6' color='sky-blue' />
<span className="text-white">Upload Files</span>
</>
}
</button>
)
:
<span className="text-white">Send</span>
}
</button>
(
<button
onClick={sendTaskMessage}
type="button"
className="btn-gradient text-base text-white tracking-wide px-4 py-3 rounded-full"
>
{requestStatus.loading ?
<LoadingSpinner size='6' color='sky-blue' />
:
<span className="text-white">Send</span>
}
</button>
)
}
</div>
</div>
{/* end of Buttons Sections */}
</div>
{/* end of Buttons Sections */}
</div>
</div>
{/* ACTION SECTION */}
<div className="w-full lg:w-1/2 h-full">
<div className="py-[20px] bg-white px-4 rounded-md shadow-md">
<h1 className="text-lg font-bold text-dark-gray dark:text-white tracking-wide">Actions</h1>
<p className="my-3 py-1 text-base">
Waiting for the completion message from the client before you can approve.
</p>
{/* END OF TEXTAREA */}
</div>
<div className="mt-5 bg-white p-4 rounded-md shadow-md">
<div className="">
<p className="text-lg font-bold text-dark-gray dark:text-black tracking-wide">Message</p>
{props.activeJobMesList.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
<ActiveJobMessage activeJobMesList={props.activeJobMesList} />
}
</div>
{/* MESSAGE SECTION */}
<div className="w-full lg:w-1/2">
<p className="text-lg font-bold text-dark-gray dark:text-black tracking-wide">Message</p>
{props.activeJobMesList.loading ?
<LoadingSpinner size='16' color='sky-blue' />
:
<ActiveJobMessage activeJobMesList={props.activeJobMesList} />
}
</div>
</div>
{/* END OF MESSAGE */}
</div>
</Layout>
@@ -216,3 +366,22 @@ function ActiveJobs(props) {
}
export default ActiveJobs;
function convertFileToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const base64String = reader.result.split(',')[1];
resolve(base64String);
};
reader.onerror = error => {
reject(error);
};
reader.readAsDataURL(file);
});
}
-1
View File
@@ -44,7 +44,6 @@ export default function MyJobs(props) {
</div>
<MyJobTable
MyJobList={props.MyJobList}
reloadJobList={props.reloadJobList}
/>
</div>
</div>
+111 -111
View File
@@ -24,121 +24,121 @@ export default function MyPendingJobTable({ MyJobList, className }) {
};
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow ${
className || ""
}`}
>
{MyJobList && MyJobList?.result_list && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{/*<tr className="text-base text-thin-light-gray border-b dark:border-[#5356fb29] default-border-b dark:border-[#5356fb29] ottom ">*/}
{/* <td className="py-4">All Product</td>*/}
{/* <td className="py-4 text-right">.</td>*/}
{/*</tr>*/}
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow ${
className || ""
}`}
>
{MyJobList && MyJobList?.result_list && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{/*<tr className="text-base text-thin-light-gray border-b dark:border-[#5356fb29] default-border-b dark:border-[#5356fb29] ottom ">*/}
{/* <td className="py-4">All Product</td>*/}
{/* <td className="py-4 text-right">.</td>*/}
{/*</tr>*/}
{
<>
{MyJobList &&
MyJobList?.result_list &&
MyJobList.result_list.length > 0 &&
currentActiveJobList.map((value, index) => (
<tr
key={index}
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
>
<td className=" py-4">
<div className="flex space-x-2 items-center w-full">
<div className="w-full h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1] max-w-[60px]">
<img
src={dataImage2}
alt="data"
className="w-full h-full"
/>
{
<>
{MyJobList &&
MyJobList?.result_list &&
MyJobList.result_list.length > 0 &&
currentActiveJobList.map((value, index) => (
<tr
key={index}
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
>
<td className=" py-4">
<div className="flex space-x-2 items-center w-full">
<div className="w-full h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1] max-w-[60px]">
<img
src={dataImage2}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col flex-[0.9]">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
{value.title}
</h1>
<div>{value.description}</div>
<span className="text-sm text-thin-light-gray">
Price:{" "}
<span className="text-purple">
{value.price * 0.01}
</span>
</span>
<span className="text-sm text-thin-light-gray">
Duration:{" "}
<span className="text-purple">
{" "}
{value.timeline_days} day(s)
</span>
</span>
<span className="text-sm text-thin-light-gray">
Expire:{" "}
<span className="text-purple">
{" "}
{value.expire}
</span>
</span>
<span className="text-sm text-thin-light-gray">
Send to:{" "}
<span className="text-purple">
{" "}
{value.job_to}
</span>
</span>
</div>
</div>
<div className="flex flex-col flex-[0.9]">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
{value.title}
</h1>
<div>{value.description}</div>
<span className="text-sm text-thin-light-gray">
Price:{" "}
<span className="text-purple">
{value.price * 0.01}
</span>
</span>
<span className="text-sm text-thin-light-gray">
Duration:{" "}
<span className="text-purple">
{" "}
{value.timeline_days} day(s)
</span>
</span>
<span className="text-sm text-thin-light-gray">
Expire:{" "}
<span className="text-purple">
{" "}
{value.expire}
</span>
</span>
<span className="text-sm text-thin-light-gray">
Send to:{" "}
<span className="text-purple">
{" "}
{value.job_to}
</span>
</span>
</div>
</div>
</td>
</td>
<td className="text-right py-4 px-2">
<button
type="button"
onClick={() => {
setJobPopout({ show: true, data: value });
}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
</button>
</td>
</tr>
))}
</>
<td className="text-right py-4 px-2">
<button
type="button"
onClick={() => {
setJobPopout({ show: true, data: value });
}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
</button>
</td>
</tr>
))}
</>
}
</tbody>
</table>
{/* PAGINATION BUTTON */}
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
MyJobList?.result_list.length
? true
: false
}
</tbody>
</table>
{/* PAGINATION BUTTON */}
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
MyJobList?.result_list.length
? true
: false
}
data={MyJobList?.result_list}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
{/* END OF PAGINATION BUTTON */}
</div>
)}
data={MyJobList?.result_list}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
{/* END OF PAGINATION BUTTON */}
</div>
)}
{/* Active Job Popout */}
{jobPopout.show && (
<PendingJobsPopout
details={jobPopout.data}
onClose={() => {
setJobPopout({ show: false, data: {} });
}}
situation={jobPopout.show}
/>
)}
{/* End of Active Job Popout */}
</div>
{/* Active Job Popout */}
{jobPopout.show && (
<PendingJobsPopout
details={jobPopout.data}
onClose={() => {
setJobPopout({ show: false, data: {} });
}}
situation={jobPopout.show}
/>
)}
{/* End of Active Job Popout */}
</div>
);
}
+8 -26
View File
@@ -15,7 +15,7 @@ export default function MyOffersTable({ className, MyActiveOffersList}) {
const settings = {
arrows: false,
dots: false,
infinite: true,
infinite: MyActiveOffersList?.result_list?.length > 4,
autoplay: true,
slidesToShow: 4,
slidesToScroll: 1,
@@ -25,6 +25,7 @@ export default function MyOffersTable({ className, MyActiveOffersList}) {
settings: {
slidesToShow: 2,
slidesToScroll: 1,
infinite: MyActiveOffersList?.result_list?.length > 2,
},
},
],
@@ -50,9 +51,9 @@ export default function MyOffersTable({ className, MyActiveOffersList}) {
// }
};
// if ( !MyActiveOffersList || MyActiveOffersList?.result_list?.length == 0 ){
// return(''); // want blank or no appear when no items
// }
if ( !MyActiveOffersList || MyActiveOffersList?.result_list?.length == 0 ){
return(''); // want blank or no appear when no items
}
return (
<>
@@ -113,11 +114,9 @@ export default function MyOffersTable({ className, MyActiveOffersList}) {
</div>
<div className="slider-content">
<SliderCom settings={settings} selector={sellSlider}>
{ MyActiveOffersList.loading ?
<LoadingSpinner size={16} color='sky-blue' />
:
MyActiveOffersList?.data?.length > 0 ?
MyActiveOffersList.data.map((value, index) => (
{
MyActiveOffersList && MyActiveOffersList?.result_list?.length > 0 &&
MyActiveOffersList?.result_list?.map((value, index) => (
<div className="item" key={index}>
<div className="offer-slide-item flex flex-col justify-between items-center">
{/* title */}
@@ -155,23 +154,6 @@ export default function MyOffersTable({ className, MyActiveOffersList}) {
</div>
))
:
MyActiveOffersList.status ?
(
<div className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<div className="p-2">
No Tasks!
</div>
</div>
)
:
(
<div className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<p className="p-2">
Error Occurred! Unable to display Tasks!
</p>
</div>
)
}
+12 -4
View File
@@ -6,7 +6,11 @@ import CommonHead from "../UserHeader/CommonHead";
import TopSellerTopBuyerSliderSection from "../Home/TopSellerTopBuyerSliderSection";
import MyOffersTable from "./MyOffersTable";
export default function MyTasks({MyActiveOffersList, ActiveJobList, commonHeadData}) {
export default function MyTasks({
MyActiveOffersList,
ActiveJobList,
commonHeadData,
}) {
const [selectTab, setValue] = useState("today");
const filterHandler = (value) => {
setValue(value);
@@ -34,9 +38,13 @@ export default function MyTasks({MyActiveOffersList, ActiveJobList, commonHeadDa
></div>
</div>
</div>
<MyOffersTable
MyActiveOffersList={MyActiveOffersList}
className="mb-10" />
{MyActiveOffersList &&
MyActiveOffersList?.result_list?.length >= 0 && (
<MyOffersTable
MyActiveOffersList={MyActiveOffersList}
className="mb-10"
/>
)}
<MyJobTable ActiveJobList={ActiveJobList} />
</div>
</div>
+1 -1
View File
@@ -100,7 +100,7 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
// User Profile
let { firstname, lastname, email, profile_pic } = userDetails;
let userEmail = email.split("@")[0];
let userEmail = email?.split("@")[0];
return (
<>
+20 -22
View File
@@ -14,6 +14,7 @@ import usersService from "../../services/UsersService";
export default function Layout({ children }) {
const { drawer } = useSelector((state) => state.drawer);
const {userJobList} = useSelector((state) => state.userJobList)
const dispatch = useDispatch();
const [MobileSideBar, setMobileSidebar] = useToggle(false);
const [logoutModal, setLogoutModal] = useState(false);
@@ -35,29 +36,24 @@ export default function Layout({ children }) {
//---------------------------------------
/* LET U DEAL WITH JOB LIST - we need to centralize this list */
const {jobListTable} = useSelector((state) => state.tableReload)
const [MyJobList, setMyJobList] = useState({loading: true, data:[]});
const api = new usersService();
// const {jobListTable} = useSelector((state) => state.tableReload)
// const [myJobList, setMyJobList] = useState({loading: true, data:[]});
// const api = new usersService();
const getMyJobList = async () => {
setMyJobList({loading: true, data:[]})
try {
const res = await api.getMyJobList();
setMyJobList({loading: false, data:res.data})
// setMyJobList(res.data);
} catch (error) {
setMyJobList({loading: false, data:[]})
console.log("Error getting mode");
}
};
useEffect(() => {
getMyJobList();
}, [jobListTable]);
// const getJobList = ()=>{
// let jobLists = useSelector((state) => state.jobLists);
// return jobLists;
// }
//---------------------------------------
// const getMyJobList = async () => {
// setMyJobList({loading: true, data:[]})
// try {
// const res = await api.getMyJobList();
// setMyJobList({loading: false, data:res.data})
// // setMyJobList(res.data);
// } catch (error) {
// setMyJobList({loading: false, data:[]})
// console.log("Error getting mode");
// }
// };
// useEffect(() => {
// getMyJobList();
// }, [jobListTable]);
return (
<>
@@ -75,6 +71,7 @@ export default function Layout({ children }) {
logoutModalHandler={logoutModalHandler}
sidebar={drawer}
action={() => dispatch(drawerToggle())}
myJobList={userJobList}
/>
</div>
{MobileSideBar && (
@@ -92,6 +89,7 @@ export default function Layout({ children }) {
logoutModalHandler={logoutModalHandler}
sidebar={MobileSideBar}
action={() => setMobileSidebar.toggle()}
myJobList={userJobList}
/>
</div>
{/* end sidebar */}
+3 -3
View File
@@ -8,7 +8,7 @@ import {
import DarkModeContext from "../Contexts/DarkModeContext";
import Icons from "../Helpers/Icons";
export default function MobileSidebar({ sidebar, action, logoutModalHandler }) {
export default function MobileSidebar({ sidebar, action, logoutModalHandler, myJobList }) {
let { userDetails } = useSelector((state) => state.userDetails);
const darkMode = useContext(DarkModeContext);
@@ -180,7 +180,7 @@ export default function MobileSidebar({ sidebar, action, logoutModalHandler }) {
</div>
</div>
</div>
) : jobLists?.result_list?.length ? (
) : myJobList?.data?.result_list?.length ? (
<div className="setting-item">
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">
@@ -213,7 +213,7 @@ export default function MobileSidebar({ sidebar, action, logoutModalHandler }) {
</ul>
</div>
</div>
) : (
) : !myJobList?.loading && (
<div className="setting-item">
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">
+10 -72
View File
@@ -51,24 +51,11 @@ export default function RightSideBar() {
<div className="item flex space-x-3 items-center mb-4">
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg
width="40"
height="41"
viewBox="0 0 40 41"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<ellipse
cx="20"
cy="20.5745"
rx="20"
ry="19.9392"
fill="#FDD903"
/>
<path
d="M30.0432 20.1565C29.8181 20.2625 29.8101 20.5908 30.0328 20.7018C31.565 21.4629 32.3814 22.7261 32.4556 24.4068C32.5245 25.8708 32.4715 27.3349 32.4821 28.7989C32.4821 29.0738 32.3973 29.1636 32.1216 29.1636C30.0169 29.153 27.907 29.153 25.8023 29.1636C25.4524 29.1636 25.4471 28.9945 25.4471 28.7408C25.4524 27.5569 25.4524 26.3782 25.4471 25.1943C25.4418 23.91 24.9169 23.318 23.6287 23.3022C20.8825 23.2705 18.1417 23.2916 15.3955 23.2757C15.0615 23.2757 15.035 23.4237 15.035 23.688C15.0456 25.3476 15.0297 27.0072 15.0456 28.6668C15.0509 29.0526 14.9608 29.1742 14.5526 29.1689C12.5327 29.1478 10.5182 29.1478 8.49834 29.1689C8.09543 29.1742 8 29.0632 8 28.6668C8.0106 23.2123 8.0106 17.7578 8.0053 12.3034C8.0053 11.9757 8.03181 11.8013 8.44532 11.8013C14.1444 11.8171 19.8488 11.8066 25.5478 11.833C27.0216 11.8383 28.4901 11.9968 29.842 12.6469C31.5279 13.4609 32.3125 14.8562 32.2117 16.7748C32.1332 18.3693 31.4419 19.4977 30.0432 20.1565ZM19.6208 18.6035C20.909 18.6035 22.2026 18.6088 23.4909 18.5982C23.7877 18.5982 24.0952 18.5824 24.3868 18.5242C24.7791 18.4449 24.9965 18.186 25.0018 17.7737C25.0071 17.3509 24.8109 17.0549 24.3815 16.9809C24.0899 16.9281 23.7877 16.9016 23.4855 16.9016C21.084 16.8963 18.6771 16.8963 16.2756 16.8963C15.0191 16.8963 15.035 16.8963 15.0297 18.1701C15.0297 18.5295 15.1464 18.6088 15.4804 18.6035C16.864 18.5929 18.2424 18.6035 19.6208 18.6035Z"
fill="#020200"
/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="history">
<g data-name="14"><circle cx="9" cy="14" r="7" fill="#ffd54f"></circle>
<path fill="#ef6c00" d="M21 9H17a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2zM21 5H3A1 1 0 0 1 3 3H21a1 1 0 0 1 0 2zM21 13H19a1 1 0 0 1 0-2h2a1 1 0 0 1 0 2zM21 17H19a1 1 0 0 1 0-2h2a1 1 0 0 1 0 2zM21 21H17a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2z"></path><path fill="#ff8f00" d="M10,10a1,1,0,0,0-2,0v3.59L6.29,15.29a1,1,0,1,0,1.41,1.41l2-2A1,1,0,0,0,10,14Z">
</path>
</g>
</svg>
</div>
{/* name */}
@@ -83,37 +70,8 @@ export default function RightSideBar() {
<div className="item flex space-x-3 items-center mb-4">
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg
width="40"
height="41"
viewBox="0 0 40 41"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<ellipse
cx="20"
cy="20.4043"
rx="20"
ry="19.9392"
fill="url(#paint0_linear_249_2794)"
/>
<path
d="M16.7403 14.4243C17.8836 14.4243 19.0272 14.4261 20.1705 14.4233C20.5666 14.4226 20.9612 14.4431 21.3489 14.5184C22.272 14.698 23.0864 15.0843 23.742 15.7545C23.8172 15.8312 23.8625 15.8401 23.9512 15.7762C24.8988 15.091 25.9527 14.6419 27.1244 14.484C27.8811 14.3821 28.6353 14.4115 29.3836 14.5947C30.3403 14.829 31.1613 15.277 31.8103 16.0013C32.413 16.674 32.7934 17.4511 32.9361 18.3386C33.054 19.0731 32.9989 19.7955 32.8499 20.5197C32.6718 21.3867 32.5167 22.2578 32.3477 23.1265C32.1933 23.92 32.0337 24.7123 31.8768 25.5054C31.7749 26.0202 31.6807 26.5367 31.5694 27.0493C31.5198 27.2772 31.3745 27.371 31.1365 27.3713C29.9446 27.3727 28.7528 27.3742 27.561 27.3745C27.2971 27.3745 27.1996 27.273 27.2463 27.0252C27.3872 26.2776 27.5365 25.5313 27.6807 24.7844C27.8136 24.095 27.9428 23.4052 28.076 22.7158C28.2148 21.9976 28.356 21.2798 28.4958 20.5616C28.5601 20.2311 28.6272 19.9038 28.5196 19.5662C28.3527 19.0422 27.8877 18.7075 27.3171 18.667C26.2023 18.5882 25.2894 19.4682 25.1459 20.415C25.0269 21.2017 24.844 21.9788 24.6918 22.7609C24.5703 23.386 24.4546 24.0126 24.3319 24.6378C24.1727 25.4483 24.0125 26.2587 23.8446 27.0674C23.8026 27.2694 23.65 27.3749 23.4365 27.3752C22.2322 27.377 21.028 27.3774 19.8237 27.3763C19.5956 27.3759 19.4854 27.2393 19.5292 27.0142C19.6609 26.3365 19.7956 25.6591 19.9278 24.9814C20.0869 24.1649 20.2446 23.3481 20.4031 22.5312C20.5549 21.7495 20.7017 20.9671 20.8604 20.1868C21.013 19.4359 20.4038 18.7124 19.6179 18.6688C18.5688 18.6102 17.6843 19.3695 17.4934 20.2162C17.3587 20.8144 17.2583 21.42 17.1415 22.0225C16.9389 23.0648 16.7359 24.1067 16.5322 25.1486C16.4114 25.7681 16.2895 26.3873 16.1683 27.0067C16.1187 27.2602 15.9832 27.3798 15.7197 27.3802C13.4145 27.3816 11.1097 27.3816 8.8045 27.3795C8.47305 27.3791 8.20621 27.1083 8.20548 26.7866C8.20475 26.471 8.48911 26.192 8.82823 26.1902C9.56414 26.186 10.3 26.1916 11.0359 26.1863C11.4995 26.1828 11.7854 25.749 11.5864 25.3581C11.5003 25.1888 11.3524 25.0904 11.1641 25.0503C11.0078 25.0169 10.8491 25.0304 10.6914 25.0301C9.77293 25.029 8.85451 25.0304 7.93645 25.0287C7.58712 25.0279 7.36408 24.893 7.27063 24.636C7.12754 24.242 7.42395 23.8444 7.87878 23.8323C8.18869 23.8241 8.49897 23.8305 8.80925 23.8305C9.95253 23.8302 11.0962 23.8312 12.2395 23.8287C12.5326 23.828 12.7702 23.6388 12.8148 23.3814C12.867 23.0807 12.7301 22.839 12.4494 22.7243C12.3493 22.6835 12.2468 22.6885 12.1442 22.6885C11.2805 22.687 10.4169 22.687 9.55318 22.6863C9.25933 22.686 9.03557 22.5749 8.91766 22.3001C8.76471 21.944 8.9998 21.5713 9.39257 21.5209C10.0653 21.4346 10.7403 21.5028 11.4138 21.4793C11.5171 21.4758 11.6207 21.4804 11.7237 21.4719C12.0642 21.4435 12.2891 21.206 12.2814 20.8886C12.2741 20.5943 12.0037 20.3351 11.6861 20.3277C11.4127 20.3213 11.1385 20.3316 10.8651 20.3231C10.5895 20.3142 10.3292 20.098 10.2884 19.8601C10.2362 19.5556 10.365 19.3056 10.633 19.1849C10.7487 19.1327 10.871 19.1402 10.9914 19.1398C11.7211 19.1367 12.4512 19.1388 13.1809 19.1342C13.5488 19.1317 13.7376 19.0099 13.8482 18.7444C13.9891 18.4064 13.6992 18.0148 13.3919 17.9829C13.1791 17.9609 12.967 17.9687 12.7549 17.9683C11.8124 17.9673 10.8699 17.9729 9.92734 17.9744C9.65539 17.9747 9.39002 17.6992 9.37468 17.4074C9.35899 17.1096 9.62181 16.8153 9.93318 16.7865C10.0117 16.7794 10.0912 16.7826 10.1701 16.7826C11.5689 16.7823 12.9677 16.783 14.3665 16.7819C14.6666 16.7816 14.8754 16.6342 14.9535 16.3754C15.0312 16.1184 14.9316 15.8546 14.702 15.7112C14.5728 15.6303 14.4264 15.625 14.28 15.6246C13.8055 15.6235 13.3313 15.6285 12.8567 15.6221C12.4822 15.6171 12.2252 15.4088 12.1876 15.0964C12.1435 14.7271 12.4253 14.4282 12.8359 14.4254C13.5963 14.4204 14.3563 14.4236 15.1167 14.4236C15.658 14.4236 16.1993 14.4236 16.7407 14.4236C16.7403 14.424 16.7403 14.424 16.7403 14.4243Z"
fill="white"
/>
<defs>
<linearGradient
id="paint0_linear_249_2794"
x1="3"
y1="16.4165"
x2="26.9783"
y2="26.4379"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#E100C5" />
<stop offset="1" stopColor="#FF812B" />
</linearGradient>
</defs>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="add-user">
<path fill="#9bcb5b" d="M12 13.4c-2 0-3.7-1.6-3.7-3.6s1.6-3.7 3.6-3.7 3.7 1.6 3.7 3.6-1.6 3.6-3.6 3.7zm0-6.2c-1.4 0-2.6 1.1-2.6 2.6 0 1.4 1.1 2.6 2.6 2.6s2.6-1.1 2.6-2.6c-.1-1.5-1.2-2.6-2.6-2.6z"></path><path fill="#9bcb5b" d="M16.6 17.9c-.3 0-.5-.2-.6-.5 0-2.2-1.8-4-4-4s-4 1.8-4 4c0 .3-.3.5-.6.5-.2 0-.4-.2-.5-.5 0-2.8 2.3-5.1 5.1-5.1s5.1 2.3 5.1 5.1c0 .3-.2.5-.5.5z"></path><path fill="#0376bc" d="M12 23.7C5.5 23.7.3 18.4.3 12 .3 5.5 5.6.3 12 .3c2.6 0 5.1.9 7.2 2.5.2.2.2.6 0 .8-.2.2-.4.2-.7.1-1.9-1.4-4.1-2.2-6.5-2.2C6.2 1.4 1.4 6.2 1.4 12S6.2 22.6 12 22.6 22.6 17.8 22.6 12c0-2.4-.8-4.6-2.2-6.5-.2-.3-.1-.6.2-.8.2-.1.5-.1.7.1 1.6 2 2.5 4.6 2.4 7.2 0 6.4-5.3 11.7-11.7 11.7z"></path><circle cx="20.2" cy="20.3" r="2.4" fill="#fff"></circle><path fill="#9bcb5b" d="M18 18.1c.6-.6 1.4-.9 2.2-.9.8 0 1.6.3 2.2.9s1 1.4.9 2.2c0 .8-.3 1.6-.9 2.2s-1.4 1-2.2.9c-.8 0-1.6-.3-2.2-.9s-1-1.4-.9-2.2c-.1-.8.3-1.7.9-2.2zm3.8 2.5V20h-1.3v-1.3h-.6V20h-1.3v.6h1.3v1.3h.6v-1.3h1.3z"></path>
</svg>
</div>
{/* name */}
@@ -130,29 +88,9 @@ export default function RightSideBar() {
<div className="item flex space-x-3 items-center mb-4">
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg
width="40"
height="41"
viewBox="0 0 40 41"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<ellipse
cx="20"
cy="20.2341"
rx="20"
ry="19.9392"
fill="#5165FF"
/>
<path
d="M26.1647 27.2085C22.5316 27.2448 19.3317 24.2111 19.3359 20.2195C19.3402 16.4128 22.3393 13.2525 26.1704 13.2554C30.0813 13.2583 33.012 16.5264 33.0006 20.2501C32.9892 24.1456 29.8505 27.2492 26.1647 27.2085Z"
fill="white"
/>
<path
d="M20.5815 27.1983C20.5217 27.2245 20.4405 27.207 20.3607 27.207C16.0039 27.2085 11.647 27.2085 7.29019 27.2085C7.25742 27.2085 7.22465 27.2099 7.1933 27.2085C7.01094 27.2026 7.00951 27.2026 7.00381 27.0076C7.00239 26.9581 7.00381 26.9086 7.00381 26.8576C7.00381 22.4395 7.00381 18.0214 7.00381 13.6033C7.00381 13.5072 6.99099 13.4082 7.01236 13.334C11.5373 17.9559 16.0566 22.5749 20.5815 27.1983Z"
fill="white"
/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" id="InternationalUser">
<path fill="#e6e7f9" d="M38.5 31.1c2.1-1.1 3.9-2.5 5.4-4.4h-3.2c-.6 1.6-1.3 3.1-2.2 4.4zm-5.8 1.4c2-.7 3.7-2.8 4.9-5.8h-4.9v5.8zm8.8-8.6h4.2c.9-1.8 1.5-3.7 1.7-5.8h-5.1c-.1 2-.4 4-.8 5.8zm2.4-17.3c-1.5-1.8-3.3-3.3-5.4-4.4.8 1.2 1.6 2.7 2.2 4.4h3.2zm-5.3 2.9h-5.9v5.8h6.7c-.1-2.1-.4-4.1-.8-5.8zm3.7 5.8h5.1c-.2-2.1-.8-4-1.7-5.8h-4.2c.4 1.8.7 3.7.8 5.8zM32.7.8v5.8h4.9c-1.2-2.9-2.9-5.1-4.9-5.8zm6.7 17.3h-6.7v5.8h5.9c.4-1.8.7-3.8.8-5.8zM25 6.6h4.9V.8c-2 .7-3.7 2.9-4.9 5.8zm-1.8 8.7h6.7V9.5H24c-.4 1.7-.7 3.7-.8 5.8zm6.7 17.2v-5.8H25c1.2 3 2.9 5.1 4.9 5.8zM24.1 2.3c-2.1 1.1-3.9 2.5-5.4 4.4H22c.5-1.7 1.3-3.2 2.1-4.4zM24 23.9h5.9v-5.8h-6.7c.1 2 .4 4 .8 5.8z" className="colorc1e5ff svgShape"></path><path fill="#ff6699" d="M3.7 44.7c0 1.6 1.2 2.8 2.8 2.8 1.3 0 2.4-.9 2.7-2.2.3 1.3 1.4 2.2 2.7 2.2 1.5 0 2.8-1.3 2.8-2.8V30.1h3.1V18.8c0-4.2-3.3-7.5-7.4-7.5H8c-4.1 0-7.4 3.4-7.4 7.5v11.3h3.1v14.6z" className="colorff99b0 svgShape"></path><path fill="#998da0" d="M9.2 10.3c2.4 0 4.4-2.2 4.4-4.9S11.6.5 9.2.5C6.8.5 4.8 2.7 4.8 5.4s2 4.9 4.4 4.9z" className="colorffd499 svgShape"></path><path fill="#e6e7f9" d="M16.9 9.5c-.3.6-.5 1.2-.8 1.8 1.3 1 2.3 2.4 2.9 4h1.3c.1-2 .3-4 .8-5.8h-4.2zm2.9 9.3v5.1h1.4c-.4-1.8-.7-3.8-.8-5.8h-.6c-.1.2 0 .4 0 .7zm2.2 7.9h-2.2v1.2c1.3 1.3 2.7 2.4 4.4 3.2-.9-1.3-1.7-2.8-2.2-4.4z" className="colorc1e5ff svgShape"></path>
</svg>
</div>
{/* name */}
<div>
+3 -4
View File
@@ -8,11 +8,10 @@ import {
import DarkModeContext from "../Contexts/DarkModeContext";
import Icons from "../Helpers/Icons";
export default function Sidebar({ sidebar, action, logoutModalHandler }) {
export default function Sidebar({ sidebar, action, logoutModalHandler, myJobList }) {
const darkMode = useContext(DarkModeContext);
let { userDetails } = useSelector((state) => state.userDetails);
console.log('user-details for job',userDetails);
//const jobLists = getJobList(); // pass from upper - we need in a lot of places
let { jobLists } = useSelector((state) => state.jobLists);
const marketData = jobLists?.result_list;
@@ -200,7 +199,7 @@ export default function Sidebar({ sidebar, action, logoutModalHandler }) {
</div>
</div>
</div>
) : jobLists?.result_list?.length ? (
) : myJobList?.data?.result_list?.length ? (
<>
<div className="setting-item">
<div className="heading mb-5">
@@ -239,7 +238,7 @@ export default function Sidebar({ sidebar, action, logoutModalHandler }) {
</div>
</div>
</>
) : (
) : !myJobList?.loading && (
<div className="setting-item">
<div className="heading mb-5">
<h1 className="title text-xl font-bold text-purple">
+42 -15
View File
@@ -1,6 +1,6 @@
import React, { useCallback, useEffect, useMemo, useState } from "react";
import ModalCom from "../Helpers/ModalCom";
import { Form, Formik } from "formik";
import { Field, Form, Formik } from "formik";
import * as Yup from "yup";
import InputCom from "../Helpers/Inputs/InputCom";
import LoadingSpinner from "../Spinners/LoadingSpinner";
@@ -245,20 +245,34 @@ const EditJobPopOut = ({ details, onClose, situation, country }) => {
</div>
<div className="field w-full mb-6">
<InputCom
fieldClass="px-6"
label="Timeline"
labelClass="tracking-wide"
inputBg="bg-slate-100"
inputClass=" input-curve lg border border-[#dce4e9]"
type="text"
name="timeline_days"
spanTag=" - Expected duration of this task"
// placeholder="Please Enter Detail Description of Job"
value={props.values.timeline_days}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/>
<div className={`flex items-center justify-between mb-2.5`}>
<label
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
htmlFor="timeline_days"
>
Timeline
<span className="text-green-700 text-sm tracking-wide">
- Expected duration of this task
</span>
</label>
</div>
<Field
component="select"
name="timeline_days"
className="input-field p-2 mt-3 rounded-md 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"
value={props.values.timeline_days}
>
<option value="">Select Duration</option>
{publicArray.map(({ name, duration }, idx) => (
<option
className="text-slate-500 text-lg"
value={duration}
>
{name}
</option>
))}
</Field>
{props.errors.timeline_days &&
props.touched.timeline_days && (
<p className="text-sm text-red-500">
@@ -316,3 +330,16 @@ const EditJobPopOut = ({ details, onClose, situation, country }) => {
};
export default EditJobPopOut;
const publicArray = [
{ duration: 1, name: "1 day" },
{ duration: 2, name: "2 days" },
{ duration: 3, name: "3 days" },
{ duration: 4, name: "4 days" },
{ duration: 5, name: "5 days" },
{ duration: 6, name: "6 days" },
{ duration: 7, name: "1 week" },
{ duration: 14, name: "2 weeks" },
{ duration: 21, name: "3 weeks" },
{ duration: 28, name: "4 weeks" },
];
+68 -23
View File
@@ -69,28 +69,49 @@ function JobListPopout({ details, onClose, situation }) {
};
let [textArea, setTextArea] = useState(details?.job_detail);
const [errMsg, setErrMsg] = useState("")
const [errMsg, setErrMsg] = useState({
deliveryDetail: "",
jobFields: {
family: "",
public: "",
individual: "",
group: "",
},
});
const handleInputChange = ({ target: { value } }) => {
setTextArea(value);
};
const errorHandler = ({target: {name}}) => {
}
const errorHandler = ({ target: { name } }) => {
try {
if (name === "family")
setErrMsg({ jobFields: { family: "please select a family member" } });
else if (name === "public")
setErrMsg({ jobFields: { public: "please select duration" } });
else if (name === "individual")
setErrMsg({ jobFields: { individual: "please enter email" } });
else if (name === "group")
setErrMsg({ jobFields: { group: "please select a family member" } });
} finally {
setTimeout(() => {
setErrMsg({ jobFields: "" });
}, 3000);
}
};
const jobFieldHandler = async (values, helpers) => {
let { job_id, job_uid } = details;
if(!textArea) {
setErrMsg("delivery detail is required!")
return
if (!textArea) {
setErrMsg({ deliveryDetail: "delivery detail is required!" });
return;
}
let jobReq = {
job_id,
job_uid,
job_description: textArea
job_description: textArea,
};
let reqData;
@@ -131,8 +152,7 @@ function JobListPopout({ details, onClose, situation }) {
};
setLoader({ jobFields: { group: true } });
} else {
setErrMsg("err herre")
return
return;
}
try {
@@ -148,7 +168,7 @@ function JobListPopout({ details, onClose, situation }) {
};
return (
<ModalCom action={onClose} situation={situation} className="edit-popup">
<ModalCom action={onClose} situation={situation} className="job-popup">
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-base md:text-lg font-bold text-dark-gray dark:text-white tracking-wide">
@@ -218,7 +238,7 @@ function JobListPopout({ details, onClose, situation }) {
value={textArea}
onChange={handleInputChange}
/>
{/* <p>{errMsg}</p> */}
<p>{errMsg.deliveryDetail}</p>
</div>
</div>
@@ -231,7 +251,7 @@ function JobListPopout({ details, onClose, situation }) {
>
{(props) => {
return (
<Form>
<Form className="mb-4">
{/* Assign to Family */}
<JobFieldInput
label="Assign to family"
@@ -242,8 +262,14 @@ function JobListPopout({ details, onClose, situation }) {
btnText="Assign to family"
optionText="Select Family"
loader={loader?.jobFields.family}
errorHandler={errorHandler}
/>
{/* <p>{errMsg}</p> */}
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
{" "}
{props?.values.family === "" && (
<span>{errMsg.jobFields.family}</span>
)}
</p>{" "}
</Form>
);
}}
@@ -256,7 +282,7 @@ function JobListPopout({ details, onClose, situation }) {
>
{(props) => {
return (
<Form>
<Form className="mb-4">
{/* Offer this job to public input */}
<JobFieldInput
label="Offer this job to public"
@@ -267,8 +293,14 @@ function JobListPopout({ details, onClose, situation }) {
btnText="Show Task to Public"
optionText="Select Duration"
loader={loader?.jobFields.public}
errorHandler={errorHandler}
/>
{/* <p>{errMsg}</p> */}
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
{" "}
{props?.values.public === "" && (
<span>{errMsg.jobFields.public}</span>
)}
</p>{" "}
</Form>
);
}}
@@ -281,7 +313,7 @@ function JobListPopout({ details, onClose, situation }) {
>
{(props) => {
return (
<Form>
<Form className="mb-4">
{/* Offer this job to individual input */}
<JobFieldInput
label="Offer this job to individual"
@@ -292,8 +324,14 @@ function JobListPopout({ details, onClose, situation }) {
inputHandler={props?.handleChange}
btnText="Send Offer to Individual"
loader={loader?.jobFields.individual}
errorHandler={errorHandler}
/>
{/* <p>{errMsg}</p> */}
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
{" "}
{props?.values.individual === "" && (
<span>{errMsg.jobFields.individual}</span>
)}
</p>{" "}
</Form>
);
}}
@@ -306,7 +344,7 @@ function JobListPopout({ details, onClose, situation }) {
>
{(props) => {
return (
<Form>
<Form className="mb-4">
{/* Offer this job to your group input */}
<JobFieldInput
label="Offer this job to your Group"
@@ -316,13 +354,18 @@ function JobListPopout({ details, onClose, situation }) {
btnText="Send Order to Group"
optionText="Group"
loader={loader?.jobFields.group}
errorHandler={errorHandler}
/>
{/* <p>{errMsg}</p> */}
<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>
{/* END OF ACTION SECTION */}
</div>
@@ -346,11 +389,12 @@ const JobFieldInput = ({
btnText,
parentClass,
optionText,
errorHandler,
loader,
data,
}) => {
return (
<div className="field w-full p-3 mb-6 bg-red-50 rounded-md">
<div className="field w-full p-3 mb-2 bg-red-50 rounded-md">
{select && (
<>
<div className={`input-com ${parentClass}`}>
@@ -407,7 +451,7 @@ const JobFieldInput = ({
fieldClass="px-6"
label={label}
labelClass="tracking-wide"
type="text"
type="email"
name={inputName}
placeholder={placeholder}
value={value}
@@ -421,6 +465,7 @@ const JobFieldInput = ({
<button
type="submit"
name={inputName}
onClick={errorHandler}
className="px-2 py-1 text-sm text-white btn-gradient tracking-wide rounded-md"
>
{loader ? <LoadingSpinner size={5} /> : btnText}
+1 -1
View File
@@ -43,7 +43,7 @@ function OfferJobPopout({details, onClose, situation}) {
setRequestStatus({loading: false, status: true, message: `Offer ${name}ed Successfully`, trigger: ''})
setTimeout(()=>{
onClose()
dispatch(tableReload({type:'JOBTABLE'}))
dispatch(tableReload({type:'MYTASKTABLE'}))
navigate('/mytask', {replace:true})
setRequestStatus({loading: false, status: false, message: '', trigger: ''})
},2000)
+167 -77
View File
@@ -1,12 +1,64 @@
import React from 'react'
import Detail from './popoutcomponent/Detail'
import ModalCom from '../Helpers/ModalCom'
import React, { useCallback, useMemo, useState } from "react";
import Detail from "./popoutcomponent/Detail";
import ModalCom from "../Helpers/ModalCom";
import usersService from "../../services/UsersService";
import { toast } from "react-toastify";
import LoadingSpinner from "../Spinners/LoadingSpinner";
const showSuccessToast = (message) => {
toast.success(message, {
autoClose: 3000,
hideProgressBar: true,
});
};
function PendingJobsPopout({ details, onClose, situation }) {
const [pendingJobLoader, setPendingJobLoader] = useState({
extend: false,
offer: false,
});
const apiCall = useMemo(() => new usersService(), []);
const handlePendingJobsBtn = useCallback(
async ({ target: { name } }) => {
let { job_uid, offer_code } = details;
let reqData;
let pendingData = { job_uid, offer_code };
try {
if (name === "extend") {
setPendingJobLoader({ extend: true });
reqData = { ...pendingData };
// let { data } =
await apiCall.pendingJobExtend(reqData);
// console.log("This is for extend", data);
showSuccessToast("Job has been extended by a week!");
} else if (name === "offer") {
setPendingJobLoader({ offer: true });
reqData = { ...pendingData };
// let { data } =
await apiCall.pendingJobSendTome(reqData);
// console.log("This is for offer", data);
showSuccessToast("Offer sent, check your email");
} else return;
setTimeout(() => {
setPendingJobLoader({ extend: false, offer: false });
onClose();
}, 2700);
} catch (error) {
setPendingJobLoader({ extend: false, offer: false });
throw new Error(error);
}
},
[onClose, apiCall, details]
);
function PendingJobsPopout({details, onClose, situation}) {
return (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<ModalCom action={onClose} situation={situation} className="edit-popup">
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Manage Pending Item
@@ -37,93 +89,131 @@ function PendingJobsPopout({details, onClose, situation}) {
</svg>
</button>
</div>
<div className='md:flex bg-white rounded-lg shadow-lg'>
<div className='p-4 w-full md:w-3/4 md:border-r-2'>
<p className='text-base font-semibold text-slate-900 tracking-wide'>{details.title}</p>
<div className='my-2 p-2 flex justify-start items-center space-x-2 bg-red-100 border-2 border-red-300'>
<span className='w-8 h-8 text-center text-sm rounded-full flex justify-center items-center text-red-300 bg-yellow-100'>!</span>
<div className=''>
<p className='text-sm'>This Job have been sent to public view</p>
<p className='text-sm text-slate-600'>This Job will expire</p>
<div className="md:flex bg-white rounded-lg shadow-lg">
<div className="p-4 w-full md:w-3/4 md:border-r-2">
<p className="text-base font-semibold text-slate-900 tracking-wide">
{details.title}
</p>
<div className="my-2 p-2 flex justify-start items-center space-x-2 bg-red-100 border-2 border-red-300">
<span className="w-8 h-8 text-center text-sm rounded-full flex justify-center items-center text-red-300 bg-yellow-100">
!
</span>
<div className="">
<p className="text-sm">
This Job have been sent to public view
</p>
<p className="text-sm text-slate-600">This Job will expire</p>
</div>
</div>
{/* INPUT SECTION */}
<div className='my-2 md:flex'>
<Detail
label='Date Added'
value={details.offer_added || 'default'}
/>
</div>
<div className='my-2 md:flex'>
<Detail
label='Description'
value={details.description}
/>
</div>
<div className='my-2 md:flex'>
<Detail
label='Offer Expire'
value={details.expire && `${details.expire.split(' ')[0]} ${details.expire.split(' ')[1].split('.')[0]}`}
/>
</div>
<div className='my-2 md:flex'>
<Detail
label='Price'
value={`${details.price*0.01} ${details.currency}`}
/>
</div>
<div className='my-2 md:flex'>
<Detail
label='Duration'
value={`${details.timeline_days} day(s)`}
<div className="my-2 md:flex">
<Detail
label="Date Added"
value={details.offer_added || "default"}
/>
</div>
<div className='my-2 md:flex'>
<Detail
label='Detail'
value={details.job_description || details.description}
<div className="my-2 md:flex">
<Detail label="Description" value={details.description} />
</div>
<div className="my-2 md:flex">
<Detail
label="Offer Expire"
value={
details.expire &&
`${details.expire.split(" ")[0]} ${
details.expire.split(" ")[1].split(".")[0]
}`
}
/>
</div>
<div className='my-2 md:flex'>
<Detail
label='Public Link'
value='https://work.wrenchboard.com/plb/viewjob/218B4BWB83'
bg='bg-slate-200'
<div className="my-2 md:flex">
<Detail
label="Price"
value={`${details.price * 0.01} ${details.currency}`}
/>
</div>
<div className="my-2 md:flex">
<Detail
label="Duration"
value={`${details.timeline_days} day(s)`}
/>
</div>
<div className="my-2 md:flex">
<Detail
label="Detail"
value={details.job_description || details.description}
/>
</div>
<div className="my-2 md:flex">
<Detail
label="Public Link"
value="https://work.wrenchboard.com/plb/viewjob/218B4BWB83"
bg="bg-slate-200"
/>
</div>
</div>
{/* ACTION SECTION */}
<div className='p-4 w-full md:w-1/4 h-full'>
<p className='mb-6 text-sm'>Actions</p>
<div className='mb-3'>
<p className='px-2 py-1 text-sm bg-slate-100'>Job sent to public view</p>
<div className="p-4 w-full md:w-1/4 h-full">
<p className="mb-6 text-sm">Actions</p>
<div className="mb-3">
<p className="px-2 py-1 text-sm bg-slate-100">
Job sent to public view
</p>
</div>
<div className='my-3'>
<button className='px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white'>Extend by a week</button>
<div className="my-3">
<button
className="px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
onClick={handlePendingJobsBtn}
name="extend"
>
{pendingJobLoader.extend ? (
<div className="w-[136px] flex justify-center items-center h-full">
<LoadingSpinner size={5} color="sky-blue" />
</div>
) : (
"Extend by a week"
)}
</button>
</div>
<div className='my-3'>
<button className='px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white'>Send to me</button>
<div className="my-3">
<button
className="px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
onClick={handlePendingJobsBtn}
name="offer"
>
{pendingJobLoader.offer ? (
<div className="w-[96px] flex justify-center items-center h-full">
<LoadingSpinner size={5} color="sky-blue" />
</div>
) : (
"Send to me"
)}
</button>
</div>
<div className='mt-10 md:mt-32 md:flex md:justify-center'>
<button className='px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white'>Cancel Offer</button>
<div className="mt-10 md:mt-32 md:flex md:justify-center">
<button
className="px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
onClick={onClose}
>
Cancel Offer
</button>
</div>
</div>
</div>
{/* close button */}
{/* close button */}
<div className="p-6 flex justify-center">
<button
onClick={onClose}
@@ -134,9 +224,9 @@ function PendingJobsPopout({details, onClose, situation}) {
</button>
</div>
{/* end of close button */}
</div>
</ModalCom>
)
</div>
</ModalCom>
);
}
export default PendingJobsPopout
export default PendingJobsPopout;
+29 -1
View File
@@ -9,7 +9,31 @@
font-family: "Product Sans";
src: url("./assets/fonts/Product Sans Bold.ttf");
}
.msg_box{
background-color: aliceblue;
margin: 5px;
padding: 5px;
border-radius: 15px;
}
.msg_header{
background-color: #1a3544;
color: white;
font-weight: bold;
}
.siderCardHeader{
margin: 40px 40px 10px 40px;
font-size: 24px;
font-weight: bolder;
}
.siderCardDescription{
margin: 20px 45px 10px 45px;
font-size: 20px;
}
.siderCardButton{
margin-top: 10px;
width: 100%;
text-align: center;
}
.offer-slide-item{
background: rgb(2,0,36);
background: radial-gradient(circle, rgba(2,0,36,1) 0%, rgba(3,51,2,0.782125350140056) 0%, rgba(0,212,255,0.07904411764705888) 0%, rgba(153,182,201,1) 99%);
@@ -787,4 +811,8 @@ TODO: Responsive ===========================
.edit-popup{
top: 75px;
}
.job-popup{
top: 55px;
}
+41 -7
View File
@@ -5,27 +5,43 @@ import LoadingSpinner from "../components/Spinners/LoadingSpinner";
import { useDispatch, useSelector } from "react-redux";
import { updateUserDetails } from "../store/UserDetails";
import { updateJobs } from "../store/jobLists";
import { updateUserJobList } from "../store/userJobList";
const AuthRoute = ({ redirectPath = "/login", children }) => {
const apiCall = useMemo(() => new usersService(), []);
const dispatch = useDispatch();
const [lastActivityTime, setLastActivityTime] = useState(Date.now());
const [isLogin, setIsLogin] = useState({ loading: true, status: false });
const [loadProfileDetails, setLoadProfileDetails] = useState([]);
const navigate = useNavigate();
const { jobListTable } = useSelector((state) => state.tableReload);
useEffect(() => {
//Removing Data stored at localStorage after session expires
const expireSession = () => {
localStorage.clear();
localStorage.removeItem("uid");
localStorage.removeItem("member_id");
localStorage.removeItem("session_token");
navigate("/login", { replace: true }); // redirects user to login page after session expires
};
const checkInactivity = setInterval(() => {
if (
Date.now() - lastActivityTime >
process.env.REACT_APP_SESSION_EXPIRE_MINUTES
) {
expireSession();
let { account_type } = loadProfileDetails;
if (account_type === "FAMILY") {
if (
Date.now() - lastActivityTime >
process.env.REACT_APP_SESSION_EXPIRE_MINUTES_FAMILY
) {
expireSession();
}
} else {
if (
Date.now() - lastActivityTime >
process.env.REACT_APP_SESSION_EXPIRE_MINUTES
) {
expireSession();
}
}
}, process.env.REACT_APP_SESSION_EXPIRE_CHECKER); // Checks for inactivity every minute
@@ -62,6 +78,7 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
setIsLogin({ loading: false, status: false });
return;
}
setLoadProfileDetails(res.data);
dispatch(updateUserDetails(res.data));
setIsLogin({ loading: false, status: true });
})
@@ -73,6 +90,23 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
}
}, []);
useEffect(() => {
const getMyJobList = async () => {
dispatch(updateUserJobList({ loading: true, data: [] }));
try {
const res = await apiCall.getMyJobList();
// setMyJobList({loading: false, data:res.data})
// setMyJobList(res.data);
dispatch(updateUserJobList({ loading: false, data: res.data }));
} catch (error) {
dispatch(updateUserJobList({ loading: false, data: [] }));
// setMyJobList({loading: false, data:[]})
console.log("Error getting mode");
}
};
getMyJobList();
}, [jobListTable]);
useEffect(() => {
// Getting market data
const getMarketActiveJobList = async () => {
+83 -1
View File
@@ -16,9 +16,10 @@ class usersService {
return this.postAuxEnd("/completesignuplink", reqData);
}
// FUNCTION TO GET USER CURRENT TASK DUE TIME
getHomeDate() {
var postData = {
uuid: localStorage.getItem("uid"),
// uuid: localStorage.getItem("uid"),
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
@@ -212,6 +213,20 @@ class usersService {
return this.postAuxEnd("/familymanage", postData);
}
// Family Tasks
ManageTasks(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
limit: 30,
offset: 0,
action: 13008,
...reqData
};
return this.postAuxEnd("/jobmanageractive", postData);
}
// Task for the person doing the job
getMyActiveTaskList() {
var postData = {
@@ -452,6 +467,31 @@ class usersService {
return this.postAuxEnd("/accounttypes", postData);
}
// Manage Interest
MarketInterest(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
msg_type: 'JOB',
action: 13033,
...reqData
};
return this.postAuxEnd("/marketinterest", postData);
}
MarketMessage(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
msg_type: 'JOB',
action: 13036,
...reqData
};
return this.postAuxEnd("/marketmessage", postData);
}
// END POINT TO ACCEPT TERMS AND AGREEMENT
jobManagerAgree() {
var postData = {
@@ -486,6 +526,30 @@ class usersService {
return this.postAuxEnd("/jobmanagerupdatejob", postData);
}
pendingJobExtend(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
extend_days: 7,
action: 13041,
...reqData,
};
return this.postAuxEnd("/pendingjobextend", postData);
}
pendingJobSendTome(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
mode: 200,
action: 13042,
...reqData,
};
return this.postAuxEnd("/pendingjobsendtome", postData);
}
// FUNCTION TO GET ACTIVE JOB MESSAGE LIST
activeJobMesList(reqData) {
var postData = {
@@ -512,6 +576,24 @@ class usersService {
return this.postAuxEnd("/sendtaskmessage", postData);
}
// FUNCTION TO SEND FILE UPLOAD
sendFiles(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 14010,
...reqData,
};
const formData = new FormData();
for (let data in postData) {
formData.append(data, postData[data]);
}
// return this.postAuxEnd("/uploads", formData);
return this.postAuxEnd("/uploads", postData);
}
// END POINT TO DELETE A JOB
deleteJob(reqData) {
var postData = {
+5 -1
View File
@@ -2,7 +2,8 @@ import { createSlice } from "@reduxjs/toolkit";
const initialState = {
jobListTable: false,
pendingListTable: false
pendingListTable: false,
myTaskTable: false
};
export const tableReloadSlice = createSlice({
@@ -17,6 +18,9 @@ export const tableReloadSlice = createSlice({
case 'PENDINGTABLE' :
state.pendingListTable = !state.pendingListTable;
return
case 'MYTASKTABLE' :
state.myTaskTable = !state.myTaskTable;
return
default:
return state
}
+3 -1
View File
@@ -4,12 +4,14 @@ import drawerReducer from "./drawer";
import userDetailReducer from "./UserDetails";
import jobReducer from "./jobLists";
import tableReloadReducer from "./TableReloads";
import userJobListReducer from './userJobList'
export default configureStore({
reducer: {
drawer: drawerReducer,
userDetails: userDetailReducer,
jobLists: jobReducer,
tableReload: tableReloadReducer
tableReload: tableReloadReducer,
userJobList: userJobListReducer
},
});
+20
View File
@@ -0,0 +1,20 @@
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
userJobList: {loading: true, data: []}
};
export const userSlice = createSlice({
name: "userJobList",
initialState,
reducers: {
updateUserJobList: (state,action) => {
state.userJobList = {...action.payload}
},
},
});
// Action creators are generated for each case reducer function
export const { updateUserJobList } = userSlice.actions;
export default userSlice.reducer;
+20 -19
View File
@@ -12,32 +12,33 @@ export default function MyJobsPage() {
return 0;
};
const { jobListTable } = useSelector((state) => state.tableReload);
const {userJobList} = useSelector((state) => state.userJobList)
// const { jobListTable } = useSelector((state) => state.tableReload);
// const userApi = new usersService();
// const activeJobList = userApi.getMyJobList();
const [MyJobList, setMyJobList] = useState({ loading: true, data: [] });
const api = new usersService();
// const [myJobList, setMyJobList] = useState({ loading: true, data: [] });
// const api = new usersService();
const getMyJobList = async () => {
setMyJobList({ loading: true, data: [] });
try {
const res = await api.getMyJobList();
setMyJobList({ loading: false, data: res.data });
// setMyJobList(res.data);
} catch (error) {
setMyJobList({ loading: false, data: [] });
console.log("Error getting mode");
}
};
useEffect(() => {
getMyJobList();
}, [jobListTable]);
// const getMyJobList = async () => {
// setMyJobList({ loading: true, data: [] });
// try {
// const res = await api.getMyJobList();
// setMyJobList({ loading: false, data: res.data });
// // setMyJobList(res.data);
// } catch (error) {
// setMyJobList({ loading: false, data: [] });
// console.log("Error getting mode");
// }
// };
// useEffect(() => {
// getMyJobList();
// }, [jobListTable]);
// debugger;
return (
<>
<MyJobs MyJobList={MyJobList} commonHeadData={commonHeadData} />
<MyJobs MyJobList={userJobList} commonHeadData={commonHeadData} />
</>
);
}
+47 -39
View File
@@ -1,4 +1,4 @@
import React, { useContext,useState, useEffect } from "react";
import React, { useContext, useState, useEffect } from "react";
import MyTasks from "../components/MyTasks";
// import UsersService from "../services/UsersService";
import usersService from "../services/UsersService";
@@ -6,46 +6,54 @@ import usersService from "../services/UsersService";
import { useSelector } from "react-redux";
export default function MyTaskPage() {
const {jobListTable} = useSelector((state) => state.tableReload)
const { myTaskTable } = useSelector((state) => state.tableReload);
const [MyActiveJobList, setMyActiveJobList] = useState({loading: true, status:false, data:[]});
const [MyActiveOffersList, setMyActiveOffersList] = useState({loading: true, status:false, data:[]});
const api = new usersService();
const commonHeadData =()=>{
console.log("COMMON HEAD DATA ----------------=====---------------------");
const [MyActiveJobList, setMyActiveJobList] = useState({
loading: true,
status: false,
data: [],
});
const [MyActiveOffersList, setMyActiveOffersList] = useState([]);
const api = new usersService();
const commonHeadData = () => {
console.log("COMMON HEAD DATA ----------------=====---------------------");
return 0;
};
const getMyActiveJobList = async () => {
setMyActiveJobList({ loading: true, status: false, data: [] });
try {
const res = await api.getMyActiveTaskList();
setMyActiveJobList({
loading: false,
status: true,
data: res.data.result_list,
});
} catch (error) {
setMyActiveJobList({ loading: false, status: false, data: [] });
console.log("Error getting tasks");
}
const getMyActiveJobList = async () => {
setMyActiveJobList({loading: true, status:false, data:[]});
try {
const res = await api.getMyActiveTaskList();
setMyActiveJobList({loading: false, status:true, data:res.data.result_list});
} catch (error) {
setMyActiveJobList({loading: false, status:false, data:[]});
console.log("Error getting tasks");
}
};
const getMyActiveOffersList = async () => {
setMyActiveOffersList({loading: true, status:false, data:[]});
try {
const res = await api.getOffersList();
setMyActiveOffersList({loading: false, status:true, data:res.data.result_list});
} catch (error) {
setMyActiveOffersList({loading: false, status:false, data:[]});
console.log("Error getting offers");
}
};
useEffect(() => {
getMyActiveJobList();
getMyActiveOffersList();
}, [jobListTable]);
};
const getMyActiveOffersList = async () => {
// setMyActiveOffersList({loading: true, status:false, data:[]});
try {
const res = await api.getOffersList();
setMyActiveOffersList(res.data);
} catch (error) {
// setMyActiveOffersList({loading: false, status:false, data:[]});
console.log("Error getting offers");
}
};
useEffect(() => {
getMyActiveJobList();
getMyActiveOffersList();
}, [myTaskTable]);
//debugger;
return (
<>
<MyTasks ActiveJobList={MyActiveJobList}
MyActiveOffersList={MyActiveOffersList}
commonHeadData={commonHeadData}/>
</>
);
//debugger;
return (
<MyTasks
ActiveJobList={MyActiveJobList}
MyActiveOffersList={MyActiveOffersList}
commonHeadData={commonHeadData}
/>
);
}