diff --git a/src/components/MyActiveJobs/JobActions/PastDueTaskAction.jsx b/src/components/MyActiveJobs/JobActions/PastDueTaskAction.jsx index 5bd83f3..065202d 100644 --- a/src/components/MyActiveJobs/JobActions/PastDueTaskAction.jsx +++ b/src/components/MyActiveJobs/JobActions/PastDueTaskAction.jsx @@ -1,26 +1,136 @@ -import React from 'react' +import React,{useState} from 'react' +import ModalCom from '../../Helpers/ModalCom' +import LoadingSpinner from '../../Spinners/LoadingSpinner' +import { useNavigate } from 'react-router-dom' +import usersService from '../../../services/UsersService' + +function PastDueTaskAction({jobDetails}) { + + const apiCall = new usersService() + const navigate = useNavigate() + + const [checked, setChecked] = useState(false) + + const [extendedTime, setExtendedTime] = useState('') // VALUE OF NEW EXTENDED TIME + + const [action, setAction] = useState('') // VALUE OF NEW EXTENDED TIME + + const [reqStatus, setReqStatus] = useState({loading:false, status: false, message: ''}) + + let [popUp, setPopUp] = useState(false) + + const popUpHandler = () => { + if(popUp){ + setChecked(false) + } + setPopUp(prev => !prev) + } + + // FUNCTION TO HANDLE WHEN OWNER CANCELS JOB + const cancelTask = () => { + setAction('cancel') + setReqStatus({loading:true, status: false, message: ''}) + + let reqData = { // API PAYLOADS + contract: jobDetails.contract, + contract_uid: jobDetails.contract_uid, + job_action: 'CANCEL_CONTRACT', + } + + if(!checked){ // CHECKS IF CHECKBOX IS SELECTED + setReqStatus({loading:false, status: false, message: 'Please check the box above'}) + return setTimeout(()=>{ + setReqStatus({loading:false, status: false, message: ''}) + }, 3000) + } + // API CALL TO ACCEPT COMPLETION BY OWNER + setReqStatus({loading:false, status: false, message: 'No api added yet'}) + setTimeout(()=>{ + setReqStatus({loading:false, status: false, message: ''}) + },1000) + // apiCall.ownerJobAction(reqData).then((res)=>{ + // if(res.status != 200 || res.data.internal_return < 0){ + // setReqStatus({loading:false, status: false, message: 'unable to complete request. Try again'}) + // return + // } + // setReqStatus({loading:false, status: true, message: 'job cancelled successfully'}) + // setTimeout(()=>{ // Sets popout to false and navigates user to /my-pastdue-jobs after 3 seconds + // popUpHandler() + // navigate('/my-pastdue-jobs', {replace: true}) + // }, 3000) + // }).catch(err => { + // setReqStatus({loading:false, status: false, message: 'Opps! Network error. Try again'}) + // }).finally(()=>{ + // setTimeout(()=>{ + // setReqStatus({loading:false, status: false, message: ''}) + // }, 3000) + // }) + } + + // FUNCTION TO HANDLE WHEN USER/OWNER CLICKS ON EXTEND TIMELINE FOR A JOB + const extendTime = () => { + setAction('extend') + setReqStatus({loading:true, status: false, message: ''}) // Sets loading spinner active + let reqData = { + contract: jobDetails.contract, + contract_uid: jobDetails.contract_uid, + job_action: 'EXTEND_TIMELINE', + extension: Number(extendedTime) + } + if(!extendedTime){ // checks that timeline duration is selected + setReqStatus({loading:false, status: false, message: 'Please select timeline duration'}) + return setTimeout(()=>{ + setReqStatus({loading:false, status: false, message: ''}) + }, 3000) + } + + // API CALL EXTEND TIMELINE BY OWNER + setReqStatus({loading:false, status: false, message: 'No api added yet'}) + setTimeout(()=>{ + setReqStatus({loading:false, status: false, message: ''}) + },1000) + // apiCall.ownerJobAction(reqData).then((res)=>{ + // if(res.status != 200 || res.data.internal_return < 0){ + // setReqStatus({loading:false, status: false, message: 'unable to complete request. Try again'}) + // return + // } + // setReqStatus({loading:false, status: true, message: 'Timeline extended successfully'}) + // setTimeout(()=>{ // Sets popout to false and navigates user to /my-pastdue-jobs after 3 seconds + // popUpHandler() + // navigate('/my-pastdue-jobs', {replace: true}) + // }, 3000) + // }).catch(err => { + // setReqStatus({loading:false, status: false, message: 'Opps! Network error. Try again'}) + // }).finally(()=>{ + // setTimeout(()=>{ + // setReqStatus({loading:false, status: false, message: ''}) + // }, 3000) + // }) + } -function PastDueTaskAction() { return ( -
+
- +
-
+
You have missed the allocated time
- {/*
*/}
-
@@ -28,6 +138,124 @@ function PastDueTaskAction() {
+ + {popUp && ( + +
+
+

+ Past Due Task +

+ +
+
+
+
+ {setChecked(prev => !prev)}} + className='w-6 h-6 text-sky-blue bg-gray-100 focus:ring-sky-blue' + /> +

I am ready to cancel this task

+
+ +
+ {reqStatus.loading && action=='cancel'? + + : + + } +
+ + {/* EXTEND TIMELINE SECTION */} +
+
+

Extend the timeline by:

+ +
+ {reqStatus.loading && action=='extend' ? + + : +
+ +
+} +
+ + {/* FOR SUCCESS/ERROR DISPLAY SECTION*/} +
+ {reqStatus.message != "" && + (!reqStatus.status ? ( +
+ {reqStatus.message} +
+ ) : ( + reqStatus.status && ( +
+ {reqStatus.message} +
+ ) + ))} +
+ {/* END OF FOR SUCCESS/ERROR DISPLAY SECTION*/} +
+ +
+ {/* cancel btn */} +
+ +
+
+
+ )}
) } diff --git a/src/components/MyTasks/RecentPastDueTable.jsx b/src/components/MyTasks/RecentPastDueTable.jsx new file mode 100644 index 0000000..b862a65 --- /dev/null +++ b/src/components/MyTasks/RecentPastDueTable.jsx @@ -0,0 +1,225 @@ +import { useState } from "react"; +import dataImage1 from "../../assets/images/data-table-user-1.png"; +import PaginatedList from "../Pagination/PaginatedList"; +import { handlePagingFunc } from "../Pagination/HandlePagination"; +import LoadingSpinner from "../Spinners/LoadingSpinner"; +import { useNavigate, useLocation } from "react-router-dom"; +import { PriceFormatter } from "../Helpers/PriceFormatter"; +import localImgLoad from "../../lib/localImgLoad"; + +const noTasksBg = require("../../assets/images/no-task-background.jpg"); +const noFamilyTasksBg = require("../../assets/images/family-no-task-background.jpg"); + +export default function RecentPastDueTable({ className, recentPastDue, Account, imageServer }) { + let navigate = useNavigate(); + let { pathname } = useLocation(); + + const [currentPage, setCurrentPage] = useState(0); + const indexOfFirstItem = Number(currentPage); + const indexOfLastItem = + Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE); + const currentTask = recentPastDue?.data?.result_list?.slice( + indexOfFirstItem, + indexOfLastItem + ); + + const handlePagination = (e) => { + handlePagingFunc(e, setCurrentPage); + }; + + let accountType = Account?.account_type == "FULL" + + // To navigate to task + const [btnLoader, setBtnLoader] = useState(false); + const navigateMarket = () => { + setBtnLoader(true); + const timeoutId = setTimeout(() => { + navigate(accountType ? "/market" : "/familymarket", { replace: true }); + setBtnLoader(false); + }, 2500); + return () => clearTimeout(timeoutId); + }; + + return ( +
+ {/* Adding this dark overlay in order to see the texts properly */} + {!recentPastDue?.data?.result_list?.length && accountType && ( +
+ )} + {recentPastDue?.loading ? +
+ +
+ : +
+
+ {recentPastDue?.data?.result_list?.length > 0 ? + currentTask?.map((task, idx) => { + // find due date + const dueDate = task?.delivery_date.split(" ")[0]; + let thePrice = PriceFormatter( + task?.price * 0.01, + task?.currency_code, + task?.currency + ); + let image = `${imageServer}${localStorage.getItem('session_token')}/job/${task.origin_job_uid}` + return ( +
+
+
+
+ data +
+
+

+ {task?.title} +

+ + {task?.description} + + + Reward: + {thePrice} + +
+ + Duration: + + {Number(task?.timeline_days) === 1 + ? `${task?.timeline_days} day` + : `${task?.timeline_days} day(s)`} + + + + Due Date: + {dueDate} + + + Confirmation: + + {task?.contract} + + +
+
+
+
+ +
+ {accountType ? + + : + + } +
+
+ ); + }) + : +
+
+ You currently have {accountType ? '"0"' : "no"} Past due task +
+
+ +
+
+ } +
+ + {/* PAGINATION BUTTON */} + = + recentPastDue?.data?.result_list?.length + ? true + : false + } + data={recentPastDue?.data?.result_list} + start={indexOfFirstItem} + stop={indexOfLastItem} + /> + {/* END OF PAGINATION BUTTON */} +
+ } +
+ ); +} diff --git a/src/components/MyTasks/RecentlyPastDue.jsx b/src/components/MyTasks/RecentlyPastDue.jsx new file mode 100644 index 0000000..2ed9404 --- /dev/null +++ b/src/components/MyTasks/RecentlyPastDue.jsx @@ -0,0 +1,76 @@ +import React, { useState } from "react"; +import Layout from "../Partials/Layout"; +import RecentPastDueTable from "./RecentPastDueTable"; +import CommonHead from "../UserHeader/CommonHead"; +import { useSelector } from "react-redux"; +import { useNavigate } from "react-router-dom"; +import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb"; + +export default function RecentlyPastDue({ + imageServer, + recentPastDue, + commonHeadData, +}) { + const { userDetails } = useSelector( + (state) => state?.userDetails + ); + + const navigate = useNavigate() + + const [selectTab, setValue] = useState("today"); + const filterHandler = (value) => { + setValue(value); + }; + + let accountType = userDetails?.account_type == "FULL" + + return ( + + {userDetails?.account_type == 'FULL' && + + } + +
+
+
+ + {/* } */} + + {/*
+ <> + + Past Due + + + {ActiveJobList?.data?.length > 0 && userDetails.account_type == 'FAMILY' && + + } + +
*/} +
+ + +
+
+
+ ); +} diff --git a/src/components/MyTasks/index.jsx b/src/components/MyTasks/index.jsx index ac8c78e..ffb404e 100644 --- a/src/components/MyTasks/index.jsx +++ b/src/components/MyTasks/index.jsx @@ -5,7 +5,7 @@ import CommonHead from "../UserHeader/CommonHead"; // import TopSellerTopBuyerSliderSection from "../Home/TopSellerTopBuyerSliderSection"; import MyOffersTable from "./MyOffersTable"; import { useSelector } from "react-redux"; -import { useNavigate } from "react-router-dom"; +import { useNavigate, Link } from "react-router-dom"; import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb"; export default function MyTasks({ @@ -94,18 +94,32 @@ export default function MyTasks({ } /> {/* } */} +
+ <> + { + // navigate(`/mytask?tab=pastdue`); + // }} + to='/mytask?tab=pastdue' + className="px-4 h-10 flex justify-center items-center text-lg md:text-xl rounded-xl text-red-600" + > + Past Due + + + {ActiveJobList?.data?.length > 0 && userDetails.account_type == 'FAMILY' && + + } + +
- {ActiveJobList?.data?.length > 0 && userDetails.account_type == 'FAMILY' && - - }
diff --git a/src/services/UsersService.js b/src/services/UsersService.js index 4cf0de5..be59eae 100644 --- a/src/services/UsersService.js +++ b/src/services/UsersService.js @@ -1521,6 +1521,17 @@ class usersService { }; return this.postAuxEnd("/learnmore", postData); } + + // API FUNCTION RECENTLY PAST DUE + getRecentPastDueList() { + var postData = { + member_uid: localStorage.getItem("uid"), + member_id: localStorage.getItem("member_id"), + sessionid: localStorage.getItem("session_token"), + // action: apiConst.WRENCHBOARD_LOGIN_PROMO, + }; + return this.postAuxEnd("/recentpastdue", postData); + } /* - 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(username) diff --git a/src/views/MyTaskPage.jsx b/src/views/MyTaskPage.jsx index bfc33d3..29dbfdb 100644 --- a/src/views/MyTaskPage.jsx +++ b/src/views/MyTaskPage.jsx @@ -4,8 +4,13 @@ import MyTasks from "../components/MyTasks"; import usersService from "../services/UsersService"; import { useSelector } from "react-redux"; +import RecentlyPastDue from "../components/MyTasks/RecentlyPastDue"; export default function MyTaskPage() { + const api = new usersService(); + const queryParams = new URLSearchParams(location?.search); + const tab = queryParams.get("tab")?.toLowerCase(); + const { myTaskTable } = useSelector((state) => state.tableReload); let { commonHeadBanner } = useSelector((state) => state.commonHeadBanner); @@ -16,7 +21,8 @@ export default function MyTaskPage() { data: [], }); const [MyActiveOffersList, setMyActiveOffersList] = useState([]); - const api = new usersService(); + + const [recentPastDue, setRecentPastDue] = useState({loading: true, data: {}}); const getMyActiveJobList = async () => { setMyActiveJobList({ loading: true, status: false, data: [] }); @@ -32,6 +38,7 @@ export default function MyTaskPage() { console.log("Error getting tasks"); } }; + const getMyActiveOffersList = async () => { // setMyActiveOffersList({loading: true, status:false, data:[]}); try { @@ -42,6 +49,21 @@ export default function MyTaskPage() { console.log("Error getting offers"); } }; + + const getRecentPastDue = async () => { + try { + const res = await api.getRecentPastDueList(); + setRecentPastDue({loading: false, data:res?.data}); + } catch (error) { + setRecentPastDue({loading: false, data:{}}); + console.log("Error getting offers"); + } + }; + + useEffect(()=>{ + getRecentPastDue() + },[]) + useEffect(() => { const fetchData = async () => { await Promise.all([getMyActiveJobList(), getMyActiveOffersList()]); @@ -52,10 +74,20 @@ export default function MyTaskPage() { //debugger; return ( - + <> + {tab == 'pastdue' ? + + : + + } + ); }