Compare commits

...

4 Commits

Author SHA1 Message Date
victorAnumudu bdc67590d1 job lock key add 2024-08-22 15:01:04 +01:00
ameye 89d2682eaf Merge branch 'depends-on-select-tag' of WrenchBoard/Users-Wrench into master 2024-08-22 11:59:06 +00:00
victorAnumudu 41a617a265 depends on select tage added 2024-08-22 11:39:15 +01:00
ameye c72765b38c Merge branch 'auth-layout-adjustment' of WrenchBoard/Users-Wrench into master 2024-08-16 04:40:41 +00:00
4 changed files with 213 additions and 191 deletions
+5 -3
View File
@@ -103,9 +103,10 @@ export default function AvailableJobsCard({
{/* <div className="product-two-options flex justify-between mb-5 relative"></div> */} {/* <div className="product-two-options flex justify-between mb-5 relative"></div> */}
<div className="flex justify-between"> <div className="flex justify-between">
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<div> <div className='w-full'>
<p className="w-full font-bold text-xl tracking-wide text-dark-gray dark:text-white"> <p className="w-full flex gap-1 items-center font-bold text-xl tracking-wide text-dark-gray dark:text-white">
{/* {thePrice} | {datas.timeline_days} day(s) */} {/* {thePrice} | {datas.timeline_days} day(s) */}
{datas?.offer_depend_uid && <i className="fa-solid fa-lock p-1 text-red-500 text-[12px]"></i>}
{thePrice} {thePrice}
</p> </p>
<p className="text-sm text-lighter-gray"> <p className="text-sm text-lighter-gray">
@@ -171,7 +172,8 @@ export default function AvailableJobsCard({
</div> </div>
<div className="block sm:flex flex-wrap gap-4"> <div className="block sm:flex flex-wrap gap-4">
<p className="text-sm text-thin-light-gray flex flext-start gap-1"> <p className="text-sm text-thin-light-gray flex flext-start gap-1 items-center">
{datas?.offer_depend_uid && <i className="fa-solid fa-lock p-1 text-red-500 text-[12px]"></i>}
Price: <span className="text-purple">{thePrice}</span> Price: <span className="text-purple">{thePrice}</span>
</p> </p>
<p className="text-sm text-thin-light-gray"> <p className="text-sm text-thin-light-gray">
@@ -145,7 +145,8 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
<div className="md:grid md:grid-cols-4 bg-white dark:bg-dark-white text-slate-900 dark:text-white rounded-lg"> <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="px-4 py-1 w-full md:col-span-3 md:border-r-1">
<div className="min-h-[300px]"> <div className="min-h-[300px]">
<h2 className="font-semibold text-slate-900 dark:text-white tracking-wide"> <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} {details?.title}
</h2> </h2>
+1
View File
@@ -165,6 +165,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
setWalletItem={setWalletItem} setWalletItem={setWalletItem}
openWallet={openPopUp} openWallet={openPopUp}
situation={jobPopout.show} situation={jobPopout.show}
myJobList={MyJobList}
/> />
)} )}
{/* End of Job List Popout */} {/* End of Job List Popout */}
+205 -187
View File
@@ -10,17 +10,19 @@ import LoadingSpinner from "../Spinners/LoadingSpinner";
import Detail from "./popoutcomponent/Detail"; import Detail from "./popoutcomponent/Detail";
import { SocketValues } from "../Contexts/SocketIOContext"; import { SocketValues } from "../Contexts/SocketIOContext";
// .required("This is required ")
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
family: Yup.string().required("This is required "), family: Yup.string(),
public: Yup.string(), public: Yup.string(),
individual: Yup.string() individual: Yup.string()
.email("Invalid email format") .email("Invalid email format")
.matches( .matches(
/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/, /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/,
"Invalid email format" "Invalid email format"
) ),
.required("Email is required"),
group: Yup.string(), group: Yup.string(),
depend_uid: Yup.string(),
}); });
function JobListPopout({ function JobListPopout({
@@ -29,6 +31,7 @@ function JobListPopout({
situation, situation,
openWallet, openWallet,
setWalletItem, setWalletItem,
myJobList
}) { }) {
let {marketUpdate} = SocketValues() // destructures 'SEND MESSAGE' and 'JOIN ROOM' FUNCTIONS FROM SOCKET let {marketUpdate} = SocketValues() // destructures 'SEND MESSAGE' and 'JOIN ROOM' FUNCTIONS FROM SOCKET
@@ -46,12 +49,7 @@ function JobListPopout({
const [familyList, setFamilyList] = useState([]); const [familyList, setFamilyList] = useState([]);
let [loader, setLoader] = useState({ let [loader, setLoader] = useState({
member: false, member: false,
jobFields: { jobFields: false
family: false,
public: false,
individual: false,
group: false,
},
}); });
const apiCall = useMemo(() => new usersService(), []); const apiCall = useMemo(() => new usersService(), []);
@@ -106,6 +104,7 @@ function JobListPopout({
public: "", public: "",
individual: "", individual: "",
group: "", group: "",
depend_uid: ''
}; };
let [textArea, setTextArea] = useState(details?.job_detail); let [textArea, setTextArea] = useState(details?.job_detail);
@@ -136,11 +135,12 @@ function JobListPopout({
} finally { } finally {
setTimeout(() => { setTimeout(() => {
setErrMsg({ jobFields: "" }); setErrMsg({ jobFields: "" });
}, 3000); }, 5000);
} }
}; };
const jobFieldHandler = async (values, helpers) => { const jobFieldHandler = async (values, helpers) => {
setLoader({ jobFields: true });
let { job_id, job_uid } = details; let { job_id, job_uid } = details;
if (!textArea) { if (!textArea) {
@@ -163,15 +163,14 @@ function JobListPopout({
family_uid: values?.family, family_uid: values?.family,
assign_mode: 110011, assign_mode: 110011,
}; };
setLoader({ jobFields: { family: true } });
} else if (values?.public !== "") { } else if (values?.public !== "") {
// for public input // for public input
reqData = { reqData = {
...jobReq, ...jobReq,
duration: Number(values?.public), duration: Number(values?.public),
assign_mode: 110022, assign_mode: 110022,
depend_uid: values?.depend_uid
}; };
setLoader({ jobFields: { public: true } });
} else if (values?.individual !== "") { } else if (values?.individual !== "") {
// for individual input // for individual input
reqData = { reqData = {
@@ -179,7 +178,6 @@ function JobListPopout({
email: values?.individual, email: values?.individual,
assign_mode: 110033, assign_mode: 110033,
}; };
setLoader({ jobFields: { individual: true } });
} else if (values?.group !== "") { } else if (values?.group !== "") {
// for group input // for group input
reqData = { reqData = {
@@ -190,8 +188,8 @@ function JobListPopout({
duration: details?.timeline_days, duration: details?.timeline_days,
// duration: 0, // duration: 0,
}; };
setLoader({ jobFields: { group: true } });
} else { } else {
setLoader({ jobFields: false });
return; return;
} }
@@ -203,7 +201,7 @@ function JobListPopout({
return setTimeout(() => { return setTimeout(() => {
setLoader({ jobFields: false }); setLoader({ jobFields: false });
setRequestStatus({ message: "", status: false }); setRequestStatus({ message: "", status: false });
}, 3000); }, 5000);
} }
marketUpdate('market', 'full-markets-jobs') // sends an event to the socket to update market lists marketUpdate('market', 'full-markets-jobs') // sends an event to the socket to update market lists
dispatch(tableReload({ type: "JOBTABLE" })); // reloads my job page dispatch(tableReload({ type: "JOBTABLE" })); // reloads my job page
@@ -213,14 +211,14 @@ function JobListPopout({
setLoader({ jobFields: false }); setLoader({ jobFields: false });
onClose(); onClose();
// throw new Response(data); // throw new Response(data);
}, 3000); }, 5000);
} catch (error) { } catch (error) {
setRequestStatus({ message: "Unable to complete", status: false }); setRequestStatus({ message: "Unable to complete", status: false });
setTimeout(() => { setTimeout(() => {
setRequestStatus({ message: "", status: false }); setRequestStatus({ message: "", status: false });
setLoader({ jobFields: false }); setLoader({ jobFields: false });
throw new Error(error); throw new Error(error);
}, 3000); }, 5000);
} }
}; };
@@ -355,142 +353,198 @@ function JobListPopout({
))} ))}
</div> </div>
<div className="grow flex flex-col bg-red-50 dark:bg-[#D85A5A] rounded-b-2xl"> <div className="grow flex flex-col bg-red-50 dark:bg-[#D85A5A] rounded-b-2xl">
{selectedTab == "family" && (
<Formik
initialValues={initialValues}
validationSchema={validationSchema.fields.family}
onSubmit={jobFieldHandler}
>
{(props) => {
return (
<Form className="hidden">
{/* Assign to Family */}
<JobFieldInput
label="Assign to family"
select={true}
inputName="family"
value={props?.values.family}
data={familyList}
btnText="Assign to family"
optionText="Select Family"
loader={loader?.jobFields?.family}
errorHandler={errorHandler}
parentClass="w-full flex flex-col gap-4"
/>
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
{" "}
{props?.values?.family === "" && (
<span>{errMsg?.jobFields?.family}</span>
)}
</p>{" "}
</Form>
);
}}
</Formik>
)}
{selectedTab == "public" && ( <Formik
<Formik initialValues={initialValues}
initialValues={initialValues} validationSchema={validationSchema.fields.public}
validationSchema={validationSchema.fields.public} onSubmit={jobFieldHandler}
onSubmit={jobFieldHandler} >
> {(props) => {
{(props) => { return (
return ( <Form className="p-3">
<Form className=""> <div className='flex items-center justify-start mt-1 mb-2.5'>
{/* Offer this job to public input */} <label
<JobFieldInput className="input-label border-2 w-full border-sky-700 rounded py-4 px-2 text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block tracking-wide"
label="Offer this job to public" // htmlFor={''}
select={true} >
inputName="public" {selectedTab == 'family' ?
value={props?.values.public} 'Assign to family'
data={publicArray} : selectedTab == 'public' ?
btnText="Show Task to Public" 'Offer this job to public'
optionText="Select Duration" : selectedTab == 'individual' ?
loader={loader?.jobFields?.public} 'Offer this job to individual'
errorHandler={errorHandler} : selectedTab == 'group' ?
parentClass="w-full flex flex-col gap-4" 'Offer this job to your Group'
/> :
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide"> null
{" "} }
{props?.values.public === "" && ( </label>
<span>{errMsg?.jobFields?.public}</span> </div>
)} <div className='w-full'>
</p>{" "} {/* ASSIGN TO FAMILY */}
</Form> {selectedTab == "family" && (
); <div className='hidden w-full'>
}} <JobFieldInput
</Formik> select={true}
)} inputName="family"
value={props?.values.family}
data={familyList}
optionText="Select Family"
errorHandler={errorHandler}
parentClass="w-full flex flex-col gap-4"
/>
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
{" "}
{props?.values?.family === "" && (
<span>{errMsg?.jobFields?.family}</span>
)}
</p>{" "}
</div>
)}
{selectedTab == "individual" && ( {/* ASSIGN TO PUBLIC/MARKET */}
<Formik {selectedTab == "public" && (
initialValues={initialValues} <div className='w-full'>
validationSchema={validationSchema.fields.individual} <div className='mb-3 w-full flex flex-col xxs:flex-row items-center gap-1'>
onSubmit={jobFieldHandler} <label className='w-full xxs:max-w-[120px] xxs:text-right'>Depends on</label>
> {/* <JobFieldInput
{(props) => { input={true}
return ( select={true}
<Form className=""> inputName="depend_uid"
{/* Offer this job to individual input */} value={props?.values.depend_uid}
<JobFieldInput data={myJobList}
label="Offer this job to individual" optionText="None"
input={true} parentClass="w-full flex flex-col gap-4"
inputName="individual" /> */}
value={props?.values.individual} <div
placeholder="Enter email of individual" className={`input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-[1rem] h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base`}
inputHandler={props?.handleChange} >
btnText="Send Offer to Individual" <select
loader={loader?.jobFields?.individual} className='px-2 w-full h-full bg-white border-0 outline-0'
errorHandler={errorHandler} name="depend_uid"
parentClass="w-full flex flex-col gap-4" value={props?.values.depend_uid}
/> onChange={props.handleChange}
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide"> >
{" "} <>
{props?.values.individual === "" && ( {myJobList.loading ? (
<span>{errMsg?.jobFields?.individual}</span> <option value={""}>Loading...</option>
)} ) : myJobList?.data?.result_list?.length > 0 ? (
</p>{" "} <>
</Form> <option value="">None</option>
); {myJobList?.data?.result_list?.filter(item => item.job_uid != details.job_uid)?.map((item, index) => (
}} <option value={item?.job_uid} key={item.job_uid}>
</Formik> {item?.title}
)} </option>
))}
</>
) : (
<option value="">No Job Found</option>
)}
</>
</select>
</div>
</div>
<div className='mb-3 w-full flex flex-col xxs:flex-row items-center gap-1'>
<label className='w-full xxs:max-w-[120px] xxs:text-right'>Duration <span className='text-red-600 tracking-wide'>{(props?.values.public === "" && errMsg?.jobFields?.public) && '*'}</span></label>
<div className='w-full'>
<JobFieldInput
select={true}
inputName="public"
value={props?.values.public}
data={publicArray}
optionText="Select Duration"
parentClass="w-full flex flex-col gap-4"
/>
{/* <p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
{" "}
{props?.values.public === "" && (
<span>{errMsg?.jobFields?.public}</span>
)}
</p>{" "} */}
</div>
</div>
</div>
)}
{/* { process.env.REACT_APP_SHOW_OFFER_GROUP_JOB != 0 && } */} {/* ASSIGN TO INDIVIDUAL */}
{selectedTab == "group" && ( {selectedTab == "individual" && (
<Formik <div className='w-full'>
initialValues={initialValues} <JobFieldInput
validationSchema={validationSchema.fields.group} input={true}
onSubmit={jobFieldHandler} inputName="individual"
> value={props?.values.individual}
{(props) => { placeholder="Enter email of individual"
return ( inputHandler={props?.handleChange}
<Form className=""> parentClass="w-full flex flex-col gap-4"
{/* Offer this job to your group input */} />
<JobFieldInput <p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
label="Offer this job to your Group" {" "}
select={true} {props?.values.individual === "" && (
inputName="group" <span>{errMsg?.jobFields?.individual}</span>
value={props?.values.group} )}
btnText="Send Order to Group" </p>{" "}
optionText="Select Group" </div>
loader={loader?.jobFields?.group} )}
errorHandler={errorHandler}
data={groupList} {/* ASSIGN TO GROUP */}
parentClass="w-full flex flex-col gap-4" {selectedTab == "group" && (
/> <div className='w-full'>
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide"> <JobFieldInput
{" "} select={true}
{props?.values.group === "" && ( inputName="group"
<span>{errMsg?.jobFields?.group}</span> value={props?.values.group}
)} optionText="Select Group"
</p> data={groupList}
</Form> parentClass="w-full flex flex-col gap-4"
); />
}} <p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
</Formik> {" "}
)} {props?.values.group === "" && (
<span>{errMsg?.jobFields?.group}</span>
)}
</p>
</div>
)}
</div>
<div className="mt-3 mb-1 flex justify-end items-center">
<button
className={`px-4 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white`}
type="submit"
name={
selectedTab == 'family' ?
'family'
: selectedTab == 'public' ?
'public'
: selectedTab == 'individual' ?
'individual'
: selectedTab == 'group' ?
'group'
:
null
}
onClick={errorHandler}
// disabled={!value}
>
{loader?.jobFields ?
<LoadingSpinner size={5} />
: selectedTab == 'family' ?
'Assign to family'
: selectedTab == 'public' ?
'Show Task to Public'
: selectedTab == 'individual' ?
'Send Offer to Individual'
: selectedTab == 'group' ?
'Send Order to Group'
:
null
}
</button>
</div>
</Form>
);
}}
</Formik>
<p <p
className={`text-center w-full text-lg ${ className={`text-center w-full text-lg ${
requestStatus.status requestStatus.status
@@ -530,30 +584,15 @@ const JobFieldInput = ({
select, select,
label, label,
labelClass, labelClass,
btnText,
parentClass, parentClass,
optionText, optionText,
errorHandler,
loader,
data, data,
}) => { }) => {
return ( return (
<div className="field w-full h-full px-3 pt-5 pb-3 flex flex-col justify-between gap-4"> <div className="field w-full flex flex-col justify-between gap-4">
{select && ( {select && (
<> <>
<div className={`input-com ${parentClass}`}> <div className={`input-com ${parentClass}`}>
<div
className={`flex items-center justify-start mb-2.5 ${labelClass}`}
>
{label && (
<label
className="input-label border-2 w-full border-sky-700 rounded py-4 px-2 text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block tracking-wide"
htmlFor={inputName}
>
{label}
</label>
)}
</div>
<div <div
className={`input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-[1rem] h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base ${inputClass}`} className={`input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-[1rem] h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base ${inputClass}`}
> >
@@ -616,8 +655,6 @@ const JobFieldInput = ({
{input && ( {input && (
<InputCom <InputCom
fieldClass="px-6" fieldClass="px-6"
label={label}
labelClass="tracking-wide border-2 w-full border-sky-700 py-4 px-2"
type="email" type="email"
name={inputName} name={inputName}
placeholder={placeholder} placeholder={placeholder}
@@ -627,25 +664,6 @@ const JobFieldInput = ({
parentClass={`${parentClass}`} parentClass={`${parentClass}`}
/> />
)} )}
{/* btn */}
<div className="my-1 flex justify-end items-center">
<button
type="submit"
name={inputName}
onClick={errorHandler}
// className={`px-2 py-1 text-sm text-white btn-gradient tracking-wide rounded-md ${
// !value && "disabled:grayscale-[65%] transition duration-300"
// }`}
className={`px-4 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white ${
!value && ""
}
`}
// disabled={!value}
>
{loader ? <LoadingSpinner size={5} /> : btnText}
</button>
</div>
</div> </div>
); );
}; };