Compare commits

...

8 Commits

7 changed files with 855 additions and 656 deletions
File diff suppressed because it is too large Load Diff
@@ -1,10 +1,16 @@
import React, { useState, useRef } from 'react' import React, { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import ModalCom from '../../Helpers/ModalCom' import ModalCom from '../../Helpers/ModalCom'
import LoadingSpinner from '../../Spinners/LoadingSpinner' import LoadingSpinner from '../../Spinners/LoadingSpinner'
import usersService from '../../../services/UsersService'
function CurrentTaskAction({jobDetails}) { function CurrentTaskAction({jobDetails}) {
const apiCall = new usersService()
const navigate = useNavigate()
const [checked, setChecked] = useState(false) const [checked, setChecked] = useState(false)
const [reqStatus, setReqStatus] = useState({loading:false, status: false, message: ''}) const [reqStatus, setReqStatus] = useState({loading:false, status: false, message: ''})
@@ -20,16 +26,37 @@ function CurrentTaskAction({jobDetails}) {
// FUNCTION TO HANDLE WHEN USER CLICKS ON SEND FOR REVIEW AND ACCEPTANCE // FUNCTION TO HANDLE WHEN USER CLICKS ON SEND FOR REVIEW AND ACCEPTANCE
const taskCompletedSubmit = () => { const taskCompletedSubmit = () => {
setReqStatus({loading:true, status: false, message: ''}) setReqStatus({loading:true, status: false, message: ''}) // Sets loading spinner active
if(!checked){ let reqData = {
contract: jobDetails.contract,
contract_uid: jobDetails.contract_uid,
job_action: 'NOTIFY_COMPLETE',
}
if(!checked){ // checks that checkbox is selected
setReqStatus({loading:false, status: false, message: 'Please check the box above'}) setReqStatus({loading:false, status: false, message: 'Please check the box above'})
return setTimeout(()=>{ return setTimeout(()=>{
setReqStatus({loading:false, status: false, message: ''}) setReqStatus({loading:false, status: false, message: ''})
}, 3000) }, 3000)
} }
setTimeout(()=>{
setReqStatus({loading:false, status: false, message: ''}) // API CALL TO MARK TASK AS COMPLETED BY WORKER
}, 3000) apiCall.taskCompleted(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: 'Task marked completed successfully'})
setTimeout(()=>{ // Sets popout to false and navigates user to /mytask after 3 seconds
popUpHandler()
navigate('/mytask', {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)
})
} }
return ( return (
@@ -1,9 +1,14 @@
import React,{useState} from 'react' import React,{useState} from 'react'
import ModalCom from '../../Helpers/ModalCom' import ModalCom from '../../Helpers/ModalCom'
import LoadingSpinner from '../../Spinners/LoadingSpinner' import LoadingSpinner from '../../Spinners/LoadingSpinner'
import { useNavigate } from 'react-router-dom'
import usersService from '../../../services/UsersService'
function PastDueJobAction({jobDetails}) { function PastDueJobAction({jobDetails}) {
const apiCall = new usersService()
const navigate = useNavigate()
const [checked, setChecked] = useState(false) const [checked, setChecked] = useState(false)
const [extendedTime, setExtendedTime] = useState('') // VALUE OF NEW EXTENDED TIME const [extendedTime, setExtendedTime] = useState('') // VALUE OF NEW EXTENDED TIME
@@ -21,7 +26,7 @@ function PastDueJobAction({jobDetails}) {
setPopUp(prev => !prev) setPopUp(prev => !prev)
} }
// FUNCTION TO HANDLE WHEN USER CLICKS ON SEND FOR REVIEW AND ACCEPTANCE // FUNCTION TO HANDLE WHEN OWNER CANCELS JOB
const cancelTask = () => { const cancelTask = () => {
setAction('cancel') setAction('cancel')
setReqStatus({loading:true, status: false, message: ''}) setReqStatus({loading:true, status: false, message: ''})
@@ -37,21 +42,41 @@ function PastDueJobAction({jobDetails}) {
}, 3000) }, 3000)
} }
// FUNCTION TO HANDLE WHEN USER CLICKS ON SEND FOR REVIEW AND ACCEPTANCE // FUNCTION TO HANDLE WHEN USER/OWNER CLICKS ON EXTEND TIMELINE FOR A JOB
const extendTime = () => { const extendTime = () => {
setAction('extend') setAction('extend')
setReqStatus({loading:true, status: false, message: ''}) setReqStatus({loading:true, status: false, message: ''}) // Sets loading spinner active
let reqData = {
if(!extendedTime){ // CHECKS IF EXTENDED TIME IS SELECTED contract: jobDetails.contract,
setReqStatus({loading:false, status: false, message: 'Please select extension duration'}) contract_uid: jobDetails.contract_uid,
job_action: 'EXTEND_TIMELINE',
duration: Number(extendedTime)
}
if(!extendedTime){ // checks that timeline duration is selected
setReqStatus({loading:false, status: false, message: 'Please select timeline duration'})
return setTimeout(()=>{ return setTimeout(()=>{
setReqStatus({loading:false, status: false, message: ''}) setReqStatus({loading:false, status: false, message: ''})
}, 3000) }, 3000)
} }
setTimeout(()=>{ // API CALL EXTEND TIMELINE BY OWNER
setReqStatus({loading:false, status: false, message: ''}) apiCall.extendJobTimeline(reqData).then((res)=>{
}, 3000) 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)
})
} }
return ( return (
@@ -149,7 +174,7 @@ function PastDueJobAction({jobDetails}) {
<option className='text-slate-500 text-lg' value='2'>1 days</option> <option className='text-slate-500 text-lg' value='2'>1 days</option>
<option className='text-slate-500 text-lg' value='3'>3 days</option> <option className='text-slate-500 text-lg' value='3'>3 days</option>
<option className='text-slate-500 text-lg' value='5'>5 days</option> <option className='text-slate-500 text-lg' value='5'>5 days</option>
<option className='text-slate-500 text-lg' value='1'>1 week</option> <option className='text-slate-500 text-lg' value='7'>1 week</option>
</select> </select>
</div> </div>
{reqStatus.loading && action=='extend' ? {reqStatus.loading && action=='extend' ?
@@ -1,17 +1,12 @@
import React, { useState } from "react"; import React, { useState } from "react";
import dataImage2 from "../../assets/images/data-table-user-2.png"; import dataImage2 from "../../assets/images/data-table-user-2.png";
import { useNavigate, useLocation } from "react-router-dom"; import { useNavigate, useLocation } from "react-router-dom";
import { handlePagingFunc } from "../Pagination/HandlePagination"; import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList"; import PaginatedList from "../Pagination/PaginatedList";
export default function MyActiveJobTable({ MyJobList, className }) { export default function MyActiveJobTable({ MyJobList, className }) {
const navigate = useNavigate(); const navigate = useNavigate();
let {pathname} = useLocation() let { pathname } = useLocation();
const filterCategories = ["All Categories", "Explore", "Featured"];
const [selectedCategory, setCategory] = useState(filterCategories[0]);
const [currentPage, setCurrentPage] = useState(0); const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage); const indexOfFirstItem = Number(currentPage);
@@ -44,82 +39,88 @@ export default function MyActiveJobTable({ MyJobList, className }) {
{ {
<> <>
{MyJobList && {MyJobList &&
MyJobList?.result_list && MyJobList?.result_list &&
MyJobList.result_list.length > 0 ? MyJobList.result_list.length > 0 ? (
currentActiveJobList.map((value, index) => ( currentActiveJobList.map((value, index) => {
<tr let deliveryDate = value?.delivery_date?.split(" ")[0];
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>
</td>
<td className="text-right py-4 px-2"> return (
<div className="flex justify-center items-center"> <tr
<button key={index}
type="button" className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
onClick={() => { >
navigate("/manage-active-job", { <td className=" py-4">
state: {...value, pathname}, <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
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white" src={dataImage2}
> alt="data"
View className="w-full h-full"
</button> />
</div> </div>
</td> <div className="flex flex-col flex-[0.9]">
</tr> <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>
<div className="flex gap-4 items-center">
<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:{" "}
<span className="text-purple">
{" "}
{deliveryDate}
</span>
</span>
<span className="text-sm text-thin-light-gray">
Send to:{" "}
<span className="text-purple">
{" "}
{value.job_to === null
? "public"
: value.job_to}
</span>
</span>
</div>
</div>
</div>
</td>
<td className="text-right py-4 px-2">
<div className="flex justify-center items-center">
<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"
>
View
</button>
</div>
</td>
</tr>
);
})
) : (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap"> <tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<td className="p-2"> <td className="p-2">No Active Task!</td>
No Active Task!
</td>
</tr> </tr>
} )}
</> </>
} }
</tbody> </tbody>
+1 -3
View File
@@ -12,9 +12,7 @@ export default function MyActiveJobs(props) {
console.log("AMEYE LOC1", props.MyJobList); console.log("AMEYE LOC1", props.MyJobList);
return ( return (
<Layout> <Layout>
<CommonHead <CommonHead commonHeadData={props.commonHeadData} />
commonHeadData={props.commonHeadData}
/>
<div className="notification-page w-full mb-10"> <div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full"> <div className="notification-wrapper w-full">
{/* heading */} {/* heading */}
+105 -102
View File
@@ -45,123 +45,126 @@ export default function MyJobTable({ className, ActiveJobList }) {
: "none", : "none",
}} }}
> >
{/* Adding this dark overlay in order to see the texts properly */}
{!ActiveJobList?.data.length && ( {!ActiveJobList?.data.length && (
<div class="absolute inset-0 bg-black opacity-30"></div> <div class="absolute inset-0 bg-black opacity-30"></div>
)} )}
{ActiveJobList.loading ? ( {ActiveJobList?.data.length > 0 && ActiveJobList.loading && (
<div className="w-full h-[520px] flex items-center justify-center"> <div className="w-full h-[520px] flex items-center justify-center">
<LoadingSpinner size="16" color="sky-blue" /> <LoadingSpinner size="16" color="sky-blue" />
</div> </div>
) : ( )}
<div className="relative w-full sm:rounded-lg">
<div className="h-auto w-full"> <div className="relative w-full sm:rounded-lg">
{ActiveJobList?.data?.length > 0 ? ( <div className="h-auto w-full">
currentTask?.map((task, idx) => ( {ActiveJobList?.data?.length > 0 &&
<div currentTask?.map((task, idx) => (
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] w-full flex justify-between items-center hover:bg-gray-50" <div
key={idx} className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] w-full flex justify-between items-center hover:bg-gray-50"
> key={idx}
<div className="py-4 max-w-[80%]"> >
<div className="flex space-x-2 items-center"> <div className="py-4 max-w-[80%]">
<div className="w-full min-w-[60px] max-w-[60px] flex-[0.1] h-[60px] rounded-full overflow-hidden flex justify-center items-center"> <div className="flex space-x-2 items-center">
<img <div className="w-full min-w-[60px] max-w-[60px] flex-[0.1] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
src={dataImage1} <img
alt="data" src={dataImage1}
className="w-full h-full" alt="data"
/> className="w-full h-full"
</div> />
<div className="flex flex-col flex-[0.9]"> </div>
<h1 className="font-bold text-xl text-dark-gray dark:text-white"> <div className="flex flex-col flex-[0.9]">
{task?.title} <h1 className="font-bold text-xl text-dark-gray dark:text-white">
</h1> {task?.title}
<span className="text-base text-gray-600"> </h1>
{task?.description} <span className="text-base text-gray-600">
{task?.description}
</span>
<span className="text-sm text-thin-light-gray">
Price:
<span className="text-purple ml-1">
{Number(task?.price) * 0.01}
</span> </span>
<span className="text-sm text-thin-light-gray"> </span>
Price: <span className="text-sm text-thin-light-gray">
<span className="text-purple ml-1"> Duration:
{Number(task?.price) * 0.01} <span className="text-purple ml-1">
</span> {Number(task?.timeline_days) === 1
? `${task?.timeline_days} day`
: `${task?.timeline_days} day(s)`}
</span> </span>
<span className="text-sm text-thin-light-gray"> </span>
Duration: <span className="text-sm text-thin-light-gray">
<span className="text-purple ml-1"> Due Date:
{Number(task?.timeline_days) === 1 <span className="text-purple ml-1">
? `${task?.timeline_days} day` {task?.delivery_date}
: `${task?.timeline_days} day(s)`}
</span>
</span> </span>
<span className="text-sm text-thin-light-gray"> </span>
Due Date: <span className="text-sm text-thin-light-gray">
<span className="text-purple ml-1"> Confirmation:
{task?.delivery_date} <span className="text-purple ml-1">
</span> {task?.contract}
</span> </span>
<span className="text-sm text-thin-light-gray"> </span>
Confirmation:
<span className="text-purple ml-1">
{task?.contract}
</span>
</span>
</div>
</div> </div>
</div> </div>
<div className="flex justify-center items-center py-4 px-2">
<button
type="button"
onClick={() => {
navigate("/manage-active-job", {
state: { ...task, pathname },
});
}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Manage
</button>
</div>
</div> </div>
))
) : ActiveJobList.status ? (
<div className="flex flex-col items-center justify-center gap-9 my-5">
<div className="p-2 font-bold text-3xl text-white whitespace-nowrap">
You currently have "0" task
</div>
<button
className="w-[115px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
onClick={navigateMarket}
>
{btnLoader ? (
<div className="signup btn-loader"></div>
) : (
"Find Task"
)}
</button>
</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>
)}
</div>
{/* PAGINATION BUTTON */} <div className="flex justify-center items-center py-4 px-2">
<PaginatedList <button
onClick={handlePagination} type="button"
prev={currentPage == 0 ? true : false} onClick={() => {
next={ navigate("/manage-active-job", {
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >= state: { ...task, pathname },
ActiveJobList?.data?.length });
? true }}
: false className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
} >
data={ActiveJobList?.data} Manage
start={indexOfFirstItem} </button>
stop={indexOfLastItem} </div>
/> </div>
{/* END OF PAGINATION BUTTON */} ))}
{ActiveJobList?.data?.length <= 0 && (
<div className="flex flex-col items-center justify-center gap-9 my-5">
<div className="p-2 font-bold text-3xl text-white whitespace-nowrap">
You currently have "0" task
</div>
<button
className="w-[115px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
onClick={navigateMarket}
>
{btnLoader ? (
<div className="signup btn-loader"></div>
) : (
"Find Task"
)}
</button>
</div>
)}
{ActiveJobList?.internal_return < 0 && (
<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>
)}
</div> </div>
)}
{/* PAGINATION BUTTON */}
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
ActiveJobList?.data?.length
? true
: false
}
data={ActiveJobList?.data}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
{/* END OF PAGINATION BUTTON */}
</div>
</div> </div>
); );
} }
+24
View File
@@ -653,6 +653,30 @@ class usersService {
return this.postAuxEnd("/offersresponse", postData); return this.postAuxEnd("/offersresponse", postData);
} }
// END POINT FOR WORKER TO MARK TASK AS COMPLETED
taskCompleted(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 14015,
...reqData,
};
return this.postAuxEnd("/activetaskstatus", postData);
}
// END POINT FOR OWNER TO EXTEND TIMELINE/DURATON OF JOB
extendJobTimeline(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 14015,
...reqData,
};
return this.postAuxEnd("/activejobstatus ", postData);
}
/* /*
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(username) - 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(username)
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(password) - 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(password)