Compare commits

..

2 Commits

Author SHA1 Message Date
victorAnumudu 13da84099c lock job popout 2024-08-23 15:52:16 +01:00
ameye 3b6f2a4ca0 Merge branch 'job-lock' of WrenchBoard/Users-Wrench into master 2024-08-22 14:11:14 +00:00
6 changed files with 456 additions and 171 deletions
@@ -10,6 +10,7 @@ export default function AvailableJobsCard({
hidden = false,
contentDisplay,
image_server,
marketPlaceProduct
}) {
//debugger;
const [marketPopUp, setMarketPopUp] = useState({ show: false, data: {} });
@@ -222,6 +223,7 @@ export default function AvailableJobsCard({
setMarketPopUp({ show: false, data: {} });
}}
situation={marketPopUp.show}
marketPlaceProduct={marketPlaceProduct}
/>
)}
@@ -150,6 +150,7 @@ export default function MainSection({
contentDisplay={contentDisplay}
image_server={image_server}
datas={datum}
marketPlaceProduct={marketPlaceProduct}
/>
</div>
))
@@ -0,0 +1,252 @@
import React, {useEffect, useState} from 'react'
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import usersService from "../../../services/UsersService";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
export default function LockJob({details, marketPlaceProduct, ManageInterest, manageInt, handleInputChange, MarketDetail, marketMsg, errMsg, textValue}) {
const apiCall = new usersService()
const [completedTask, setCompletedTask] = useState({
loading: true,
data: []
})
let thePrice = PriceFormatter(
details?.price * 0.01,
details?.currency_code,
details?.currency
);
let cleanedText = details?.job_description
?.replace(/&lt;/g, "<")
.replace(/&gt;/g, ">")
.replace(/&quot;/g, '"')
.replace(/&amp;/g, "&");
let dependOn = marketPlaceProduct?.filter(item => item?.job_uid == details?.offer_depend_uid)[0]
useEffect(()=>{
apiCall.getVerifyCompletedTask({offer_depend_uid:details?.offer_depend_uid}).then(res => {
console.log('RES', res.data)
setCompletedTask({loading:false, data:res?.data?.result_list})
}).catch(err =>{
setCompletedTask({loading:false, data:[]})
})
},[])
return (
<>
{completedTask.loading ?
<div className='w-full md:col-span-4 flex justify-center items-center min-h-[500px]'>
<LoadingSpinner
size='10'
/>
</div>
:
<>
<div className="px-4 py-1 w-full md:col-span-3 md:border-r-1">
<div className="min-h-[300px]">
<h2 className="w-full flex gap-1 items-center font-semibold text-slate-900 dark:text-white tracking-wide">
{details?.offer_depend_uid && <i className="fa-solid fa-lock p-1 text-red-500 text-[12px]"></i>}
{details?.title}
</h2>
{/* INPUT SECTION */}
{[
{
name: "Description",
content: details.description,
},
{
name: "",
content: {
text: `Timeline: ${details.timeline_days} day(s) -- `,
bold: `Budget: ${thePrice}`,
},
},
{
name: "Delivery Detail",
content: cleanedText,
danger: true,
},
].map(({ name, content, danger }, idx) => (
<div className={`my-1 flex flex-col items-start`} key={idx}>
<label className="py-1 job-label w-full">
{name}
</label>
<div
className={`w-full p-2 text-slate-900 dark:text-white market-pop rounded-2xl ${
name == "Description"
? "min-h-[100px] max-h-[100px] h-full overflow-y-auto break-words bg-slate-50"
: name == "Delivery Detail" ? " overflow-y-auto h-full min-h-[100px] max-h-[100px] bg-slate-50"
: "h-full flex items-center"
}`}
>
{danger ? (
<p
className={`dark:text-white`}
dangerouslySetInnerHTML={{
__html: danger && content,
}}
/>
) : (
<p className={`w-full text-slate-900 dark:text-white`}>
{name !== "Delivery Detail" ? (
<>
{typeof content !== "object" ? content : null}
{typeof content === "object" && (
<>
{/* <hr className="mb-1" /> */}
<span className='flex w-full mb-1 h-[1px] bg-slate-500'></span>
<span className="flex items-center gap-2 dark:text-white">
{content?.text}
<strong>{thePrice}</strong>
</span>
<span className='flex w-full mt-1 h-[1px] bg-slate-500'></span>
{/* <hr className="mt-1" /> */}
</>
)}
</>
) : (
""
)}
</p>
)}
</div>
</div>
))}
</div>
<hr className='my-3' />
{completedTask.loading ?
<p className='py-3 w-full text-center text-lg'>Loading...</p>
:completedTask?.data?.filter(item => item?.job_uid == details.offer_depend_uid).length > 0 ?
<div className='w-full'>
<label className="job-label w-full flex gap-2 items-center">
If you have any questions about this task:
<span className={`text-sm ${marketMsg.state ? 'text-[#57cd89]' : 'text-red-500'}`}>
{marketMsg.state && "Message Sent!"}
{errMsg.market && "Failed to send"}
</span>
</label>
<div className="w-full flex items-center gap-3">
<div className="w-full">
<textarea
className={`p-1 w-full text-sm text-slate-900 dark:text-white ${
marketMsg.loading && "italic text-[#9CA3AF]"
} bg-transparent outline-none border-2 border-slate-300 rounded-md`}
rows="3"
style={{ resize: "none" }}
placeholder="Enter message here ..."
value={marketMsg.loading ? "Sending..." : textValue}
onChange={handleInputChange}
/>
</div>
<div className="relative flex flex-col">
<button
className="rounded-full flex justify-center items-center w-12 h-11 bg-yellow-500 text-white"
name="market-message"
onClick={MarketDetail}
disabled={marketMsg.loading}
>
{marketMsg.loading ? (
<LoadingSpinner size={5} color="white" />
) : (
// "Send Message"
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 11 20"
id="Arrow"
className="w-[0.7rem]"
>
<path
fillRule="evenodd"
d="M.366 19.708c.405.39 1.06.39 1.464 0l8.563-8.264a1.95 1.95 0 0 0 0-2.827L1.768.292A1.063 1.063 0 0 0 .314.282a.976.976 0 0 0-.011 1.425l7.894 7.617a.975.975 0 0 1 0 1.414L.366 18.295a.974.974 0 0 0 0 1.413"
// fill=""
className="color000000 svgShape fill-[#fff]"
></path>
</svg>
)}
</button>
</div>
</div>
</div>
:
<div className='w-full'>
<h1 className='text-red-600 text-lg'>This task depends on the task below</h1>
<div className='my-1 w-full'>
<h2 className="w-full flex gap-1 items-center font-semibold text-slate-900 dark:text-white tracking-wide">
{dependOn?.offer_depend_uid && <i className="fa-solid fa-lock p-1 text-red-500 text-[12px]"></i>}
{dependOn?.title}
</h2>
</div>
<div className={`p-2 flex flex-col items-start`}>
<p className="py-1 job-label w-full">Description</p>
<div className={`w-full p-2 text-slate-900 dark:text-white market-pop rounded-2xl bg-slate-50 break-words min-h-[100px] max-h-[100px]`}>
{dependOn?.description}
</div>
</div>
</div>
}
</div>
<div className="py-2 w-full md:col-span-1 h-full flex flex-col rounded-2xl">
<div className="mx-auto bg-[#f1f8ff] dark:bg-[#C2C8D3] px-4 rounded-md w-full h-full md:min-h-[420px] flex flex-col justify-between">
<div className="w-full flex flex-col justify-center pb-4 gap-2">
<p className="job-label w-full">
Interested?
</p>
<hr />
{completedTask.loading ?
<p className='py-3 w-full text-center text-lg'>Loading...</p>
:completedTask?.data?.filter(item => item?.job_uid == details.offer_depend_uid).length > 0 ?
<button
className="btn-gradient text-white px-2 py-2 border-4 border-slate-300 text-lg lg:text-xl font-medium rounded-2xl"
name="market-interest"
onClick={ManageInterest}
>
{" "}
<div className="flex md:flex-col justify-center gap-2">
<span>Notify</span>
<span>Owner</span>
</div>
</button>
:
<h1 className='text-red-600 text-base font-bold'>This task depends on completion of another task</h1>
}
<>
{manageInt.loading ? (
<p className="text-sm italic">please wait...</p>
) : (
<>
{manageInt?.msg !== "" && (
<p
className={`text-sm italic ${
manageInt?.state ? "text-green-500" : "text-red-500"
}`}
>
{manageInt?.msg}
</p>
)}
</>
)}
</>
</div>
<div className="text-slate-900">
<p className="flex items-center tracking-wide">
<span className="job-label">Interest: </span> <b className="ml-1">{details.interest_count}</b>
</p>
<hr />
<p className="my-1 flex flex-col">
<span className="job-label">Expire: </span>
<span> {new Date(details.expire).toLocaleString()} </span>
</p>
</div>
</div>
</div>
</>
}
</>
)
}
+188 -171
View File
@@ -5,8 +5,9 @@ import ModalCom from "../../Helpers/ModalCom";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import { SocketValues } from "../../Contexts/SocketIOContext";
import LockJob from "./LockJob";
const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
const MarketPopUp = ({ details, onClose, situation, marketInt, marketPlaceProduct }) => {
let {sendJobInterestToOwner} = SocketValues() // function to emit job interest request
const emitOfferInterest = () => {
@@ -143,186 +144,202 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
</div>
<div className="md:grid md:grid-cols-4 bg-white dark:bg-dark-white text-slate-900 dark:text-white rounded-lg">
<div className="px-4 py-1 w-full md:col-span-3 md:border-r-1">
<div className="min-h-[300px]">
<h2 className="w-full flex gap-1 items-center font-semibold text-slate-900 dark:text-white tracking-wide">
{details?.offer_depend_uid && <i className="fa-solid fa-lock p-1 text-red-500 text-[12px]"></i>}
{details?.title}
</h2>
{details?.offer_depend_uid ?
<LockJob
marketPlaceProduct={marketPlaceProduct}
details={details}
ManageInterest={ManageInterest}
manageInt={manageInt}
marketMsg={marketMsg}
errMsg={errMsg}
textValue={textValue}
MarketDetail={MarketDetail}
handleInputChange={handleInputChange}
/>
:
<>
<div className="px-4 py-1 w-full md:col-span-3 md:border-r-1">
<div className="min-h-[300px]">
<h2 className="w-full flex gap-1 items-center font-semibold text-slate-900 dark:text-white tracking-wide">
{details?.offer_depend_uid && <i className="fa-solid fa-lock p-1 text-red-500 text-[12px]"></i>}
{details?.title}
</h2>
{/* INPUT SECTION */}
{[
{
name: "Description",
content: details.description,
},
{
name: "",
content: {
text: `Timeline: ${details.timeline_days} day(s) -- `,
bold: `Budget: ${thePrice}`,
{/* INPUT SECTION */}
{[
{
name: "Description",
content: details.description,
},
},
{
name: "Delivery Detail",
content: cleanedText,
danger: true,
},
].map(({ name, content, danger }, idx) => (
<div className={`my-3 md:flex items-start`} key={idx}>
<label className="py-2 job-label w-full md:w-[19%]">
{name}
</label>
<div
className={`w-full p-2 md:w-3/4 text-slate-900 dark:text-white market-pop rounded-2xl ${
name == "Description"
? "min-h-[150px] max-h-[150px] h-full overflow-y-auto break-words bg-slate-50"
: name == "Delivery Detail" ? " overflow-y-auto h-full min-h-[150px] max-h-[150px] bg-slate-50"
: "h-full flex items-center"
}`}
>
{danger ? (
<p
className={`dark:text-white`}
dangerouslySetInnerHTML={{
__html: danger && content,
}}
/>
) : (
<p className={`w-full text-slate-900 dark:text-white`}>
{name !== "Delivery Detail" ? (
<>
{typeof content !== "object" ? content : null}
{typeof content === "object" && (
<>
{/* <hr className="mb-1" /> */}
<span className='flex w-full mb-1 h-[1px] bg-slate-500'></span>
<span className="flex items-center gap-2 dark:text-white">
{content?.text}
<strong>{thePrice}</strong>
</span>
<span className='flex w-full mt-1 h-[1px] bg-slate-500'></span>
{/* <hr className="mt-1" /> */}
</>
)}
</>
) : (
""
)}
</p>
)}
</div>
</div>
))}
</div>
<hr className='my-1' />
<div className='w-full'>
<label className="job-label w-full flex gap-2 items-center">
If you have any questions about this task:
<span className={`text-sm ${marketMsg.state ? 'text-[#57cd89]' : 'text-red-500'}`}>
{marketMsg.state && "Message Sent!"}
{errMsg.market && "Failed to send"}
</span>
</label>
<div className="w-full flex items-center gap-3">
<div className="w-full">
<textarea
className={`p-1 w-full text-sm text-slate-900 dark:text-white ${
marketMsg.loading && "italic text-[#9CA3AF]"
} bg-transparent outline-none border-2 border-slate-300 rounded-md`}
rows="3"
style={{ resize: "none" }}
placeholder="Enter message here ..."
value={marketMsg.loading ? "Sending..." : textValue}
onChange={handleInputChange}
/>
</div>
<div className="relative flex flex-col">
<button
className="rounded-full flex justify-center items-center w-12 h-11 bg-yellow-500 text-white"
name="market-message"
onClick={MarketDetail}
disabled={marketMsg.loading}
>
{marketMsg.loading ? (
<LoadingSpinner size={5} color="white" />
) : (
// "Send Message"
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 11 20"
id="Arrow"
className="w-[0.7rem]"
{
name: "",
content: {
text: `Timeline: ${details.timeline_days} day(s) -- `,
bold: `Budget: ${thePrice}`,
},
},
{
name: "Delivery Detail",
content: cleanedText,
danger: true,
},
].map(({ name, content, danger }, idx) => (
<div className={`my-3 md:flex items-start`} key={idx}>
<label className="py-2 job-label w-full md:w-[19%]">
{name}
</label>
<div
className={`w-full p-2 md:w-3/4 text-slate-900 dark:text-white market-pop rounded-2xl ${
name == "Description"
? "min-h-[150px] max-h-[150px] h-full overflow-y-auto break-words bg-slate-50"
: name == "Delivery Detail" ? " overflow-y-auto h-full min-h-[150px] max-h-[150px] bg-slate-50"
: "h-full flex items-center"
}`}
>
<path
fillRule="evenodd"
d="M.366 19.708c.405.39 1.06.39 1.464 0l8.563-8.264a1.95 1.95 0 0 0 0-2.827L1.768.292A1.063 1.063 0 0 0 .314.282a.976.976 0 0 0-.011 1.425l7.894 7.617a.975.975 0 0 1 0 1.414L.366 18.295a.974.974 0 0 0 0 1.413"
// fill=""
className="color000000 svgShape fill-[#fff]"
></path>
</svg>
)}
</button>
{/* <span className="text-sm text-[#57cd89]">
{marketMsg.state && "Sent!"}
{errMsg.market && "Failed"}
</span> */}
</div>
</div>
</div>
</div>
<div className="py-2 w-full md:col-span-1 h-full flex flex-col rounded-2xl">
<div className="mx-auto bg-[#f1f8ff] dark:bg-[#C2C8D3] px-4 rounded-md w-full h-full md:min-h-[420px] flex flex-col justify-between">
<div className="w-full flex flex-col justify-center pb-4 gap-2">
<p className="job-label w-full">
Interested?
</p>
<hr />
<button
className="btn-gradient text-white px-2 py-2 border-4 border-slate-300 text-lg lg:text-xl font-medium rounded-2xl"
name="market-interest"
onClick={ManageInterest}
>
{" "}
<div className="flex md:flex-col justify-center gap-2">
<span>Notify</span>
<span>Owner</span>
</div>
</button>
<>
{manageInt.loading ? (
<p className="text-sm italic">please wait...</p>
) : (
<>
{manageInt?.msg !== "" && (
{danger ? (
<p
className={`text-sm italic ${
manageInt?.state ? "text-green-500" : "text-red-500"
}`}
>
{manageInt?.msg}
className={`dark:text-white`}
dangerouslySetInnerHTML={{
__html: danger && content,
}}
/>
) : (
<p className={`w-full text-slate-900 dark:text-white`}>
{name !== "Delivery Detail" ? (
<>
{typeof content !== "object" ? content : null}
{typeof content === "object" && (
<>
{/* <hr className="mb-1" /> */}
<span className='flex w-full mb-1 h-[1px] bg-slate-500'></span>
<span className="flex items-center gap-2 dark:text-white">
{content?.text}
<strong>{thePrice}</strong>
</span>
<span className='flex w-full mt-1 h-[1px] bg-slate-500'></span>
{/* <hr className="mt-1" /> */}
</>
)}
</>
) : (
""
)}
</p>
)}
</>
)}
</>
</div>
</div>
))}
</div>
<div className="text-slate-900">
<p className="flex items-center tracking-wide">
<span className="job-label">Interest: </span> <b className="ml-1">{details.interest_count}</b>
</p>
<hr />
<p className="my-1 flex flex-col">
<span className="job-label">Expire: </span>
<span> {new Date(details.expire).toLocaleString()} </span>
</p>
<hr className='my-1' />
<div className='w-full'>
<label className="job-label w-full flex gap-2 items-center">
If you have any questions about this task:
<span className={`text-sm ${marketMsg.state ? 'text-[#57cd89]' : 'text-red-500'}`}>
{marketMsg.state && "Message Sent!"}
{errMsg.market && "Failed to send"}
</span>
</label>
<div className="w-full flex items-center gap-3">
<div className="w-full">
<textarea
className={`p-1 w-full text-sm text-slate-900 dark:text-white ${
marketMsg.loading && "italic text-[#9CA3AF]"
} bg-transparent outline-none border-2 border-slate-300 rounded-md`}
rows="3"
style={{ resize: "none" }}
placeholder="Enter message here ..."
value={marketMsg.loading ? "Sending..." : textValue}
onChange={handleInputChange}
/>
</div>
<div className="relative flex flex-col">
<button
className="rounded-full flex justify-center items-center w-12 h-11 bg-yellow-500 text-white"
name="market-message"
onClick={MarketDetail}
disabled={marketMsg.loading}
>
{marketMsg.loading ? (
<LoadingSpinner size={5} color="white" />
) : (
// "Send Message"
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 11 20"
id="Arrow"
className="w-[0.7rem]"
>
<path
fillRule="evenodd"
d="M.366 19.708c.405.39 1.06.39 1.464 0l8.563-8.264a1.95 1.95 0 0 0 0-2.827L1.768.292A1.063 1.063 0 0 0 .314.282a.976.976 0 0 0-.011 1.425l7.894 7.617a.975.975 0 0 1 0 1.414L.366 18.295a.974.974 0 0 0 0 1.413"
// fill=""
className="color000000 svgShape fill-[#fff]"
></path>
</svg>
)}
</button>
{/* <span className="text-sm text-[#57cd89]">
{marketMsg.state && "Sent!"}
{errMsg.market && "Failed"}
</span> */}
</div>
</div>
</div>
</div>
</div>
{/* END OF ACTION SECTION */}
<div className="py-2 w-full md:col-span-1 h-full flex flex-col rounded-2xl">
<div className="mx-auto bg-[#f1f8ff] dark:bg-[#C2C8D3] px-4 rounded-md w-full h-full md:min-h-[420px] flex flex-col justify-between">
<div className="w-full flex flex-col justify-center pb-4 gap-2">
<p className="job-label w-full">
Interested?
</p>
<hr />
<button
className="btn-gradient text-white px-2 py-2 border-4 border-slate-300 text-lg lg:text-xl font-medium rounded-2xl"
name="market-interest"
onClick={ManageInterest}
>
{" "}
<div className="flex md:flex-col justify-center gap-2">
<span>Notify</span>
<span>Owner</span>
</div>
</button>
<>
{manageInt.loading ? (
<p className="text-sm italic">please wait...</p>
) : (
<>
{manageInt?.msg !== "" && (
<p
className={`text-sm italic ${
manageInt?.state ? "text-green-500" : "text-red-500"
}`}
>
{manageInt?.msg}
</p>
)}
</>
)}
</>
</div>
<div className="text-slate-900">
<p className="flex items-center tracking-wide">
<span className="job-label">Interest: </span> <b className="ml-1">{details.interest_count}</b>
</p>
<hr />
<p className="my-1 flex flex-col">
<span className="job-label">Expire: </span>
<span> {new Date(details.expire).toLocaleString()} </span>
</p>
</div>
</div>
</div>
</>
}
</div>
<div className="modal-footer-wrapper">
<button
className="custom-btn bg-transparent border border-red-500 text-red-500 ml-auto"
+1
View File
@@ -183,6 +183,7 @@ export const apiConst = {
WRENCHBOARD_JOB_EXTEND_EXPIRE: 13041,
WRENCHBOARD_JOB_RESEND_MESSAGE: 13042,
WRENCHBOARD_JOB_CANCEL_OFFER: 13043,
WRENCHBOARD_VERIFY_COMPLETED_TASK: 13033,
WRENCHBOARD_JOB_JOBGROUPS: 13045,
WRENCHBOARD_JOB_JOBGROUPADD: 13046,
+12
View File
@@ -1481,6 +1481,18 @@ class usersService {
return this.postAuxEnd("/jobmanagerfiles", postData);
}
// API FUNCTION FOR GETTING LIST OF VERIFY COMPLETED TASK
getVerifyCompletedTask(reqData) {
var postData = {
member_uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: apiConst.WRENCHBOARD_VERIFY_COMPLETED_TASK,
...reqData
};
return this.postAuxEnd("/verifycompleted", postData);
}
/*
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(username)
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(password)