Files
Users-Wrench/src/components/AddJob/AddJob.jsx
T
2025-06-10 17:17:20 +01:00

438 lines
17 KiB
React

import {
validationSchema as VS,
useDispatch,
useSelector,
usersService,
// initialValues as IV,
initialReqState,
useState,
tableReload,
Formik,
InputCom,
Field,
Form,
LoadingSpinner,
} from "./settings";
const validationSchema = VS;
function AddJob({ popUpHandler, categories }) {
const ApiCall = new usersService();
const { walletDetails } = useSelector((state) => state.walletDetails);
let dispatch = useDispatch();
const [requestStatus, setRequestStatus] = useState(initialReqState); // Holds state when submit button is pressed
const handleAddJob = async (values, helpers) => {
const reqData = {
country: values?.country,
price: Number(values.price) * 100,
title: values?.title,
description: values?.description,
job_detail: values?.job_detail,
timeline_days: values?.timeline_days,
category: values.category?.join("@"),
};
setRequestStatus({ loading: true, status: false, message: "" });
try {
const res = await ApiCall.jobManagerCreateJob(reqData);
if (res?.data?.internal_return < 1) {
setRequestStatus({
loading: false,
status: false,
message: "Could not complete your request at the moment",
});
setTimeout(() => {
popUpHandler();
}, 1500);
} else {
setRequestStatus({
loading: false,
status: true,
message: "Job Added Successfully",
});
setTimeout(() => {
dispatch(tableReload({ type: "JOBTABLE" }));
popUpHandler();
}, 1000);
}
} catch (err) {
setRequestStatus({
loading: false,
status: false,
message: "Oops! Something went wrong. Try Again",
});
} finally {
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
}
};
// For form initial values
const initialValues = {
// initial values for formik
country: walletDetails?.data?.length === 1 ? walletDetails.data[0].country : '',
price: "",
title: "",
description: "",
job_detail: "",
timeline_days: "",
category: [],
};
return (
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleAddJob}
>
{(props) => {
return (
<Form className='contents'>
<div className="add-job p-5 w-full h-full rounded-md flex flex-col justify-between overflow-y-auto">
<div className="flex flex-col-reverse sm:flex-row">
<div className="fields w-full">
{/* inputs starts here */}
<div className="xl:flex xl:space-x-7 mb-[5px]">
<div className="field w-full mb-[5px] xl:mb-0">
<label
htmlFor="country"
className="job-label job-label-flex"
>
<span>Currency</span>
{props.errors.country && props.touched.country && (
<span className="text-[12px] text-red-500">
{props.errors.country}
</span>
)}
</label>
<select
id="country"
name="country"
value={props.values.country}
className={`input-field p-2 mt-3 rounded-full placeholder:text-base text-dark-gray w-full h-[42px] bg-slate-100 focus:ring-0 focus:outline-none border`}
onChange={props.handleChange}
onBlur={props.handleBlur}
disabled={walletDetails?.data?.length === 1}
>
{walletDetails?.loading ? (
<option className="text-slate-500 text-lg" value="">
Loading...
</option>
) : walletDetails?.data?.length > 1 ? (
<>
<option className="text-slate-500 text-lg" value="">
Select a currency
</option>
{walletDetails?.data?.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item?.country}
>
{item?.description}
</option>
))}
</>
) : walletDetails?.data?.length === 1 ?
<>
{walletDetails?.data?.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item?.country}
>
{item?.description}
</option>
))}
</>
:(
<option className="text-slate-500 text-lg" value="">
No Options Found! Try Again
</option>
)}
</select>
</div>
{/* Price */}
<div className="field w-full mb-[5px] xl:mb-0">
<InputCom
fieldClass="px-6 text-right flex"
label="Reward"
labelClass=""
type="number"
name="price"
placeholder="0"
value={props.values.price}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={
props.errors.price &&
props.touched.price &&
props.errors.price
}
/>
</div>
{/* Timeline */}
<div className="field w-full mb-[5px] xl:mb-0">
<label
className="job-label job-label-flex"
htmlFor="timeline_days"
>
Timeline
<span className="text-green-700 text-[12px] tracking-wide">
- Duration
</span>
</label>
<Field
component="select"
name="timeline_days"
className={`input-field p-2 mt-3 rounded-full placeholder:text-base text-dark-gray w-full h-[42px] bg-slate-100 focus:ring-0 focus:outline-none border ${
props.errors.timeline_days &&
props.touched.timeline_days
? "border-[#ff0a0a63] shadow-red-500 animate-shake"
: "dark:border-[#5e6278]"
}`}
value={props.values.timeline_days}
>
<option value="" className='text-slate-500 text-lg'>Select Duration</option>
{publicArray.map(({ name, duration }, idx) => (
<option
key={idx}
className="text-slate-500 text-lg"
value={duration}
>
{name}
</option>
))}
</Field>
</div>
</div>
{/* Title */}
<div className="field w-full mb-[5px]">
<InputCom
fieldClass="px-6"
label="Title"
labelClass=""
type="text"
name="title"
value={props.values.title}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={
props.errors.title &&
props.touched.title &&
props.errors.title
}
/>
</div>
{/* Description */}
<div className="field w-full mb-[5px]">
<InputCom
fieldClass="px-6"
label="Description"
labelClass=""
type="text"
name="description"
value={props.values.description}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={
props.errors.description &&
props.touched.description &&
props.errors.description
}
/>
</div>
{/* Details */}
<div className="field flex flex-col sm:flex-row w-full mb-[5px] gap-2">
<div className="sm:w-[60%] w-full">
<label
htmlFor="Job Delivery Details"
className="job-label job-label-flex"
>
Job Delivery Details
{props.errors.job_detail &&
props.touched.job_detail && (
<span className="text-[12px] text-red-500">
{props.errors.job_detail}
</span>
)}
</label>
<textarea
id="Job Delivery Details"
rows="5"
className={`input-field px-3 py-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[100px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[10px] border`}
style={{ resize: "none" }}
name="job_detail"
value={props.values.job_detail}
onChange={props.handleChange}
onBlur={props.handleBlur}
/>
</div>
<div className="sm:w-[35%] w-full">
<label
htmlFor="Job Categories"
className='job-label'
id="checked-group"
>
Categories
</label>
<div
className="sm:flex-col flex flex-wrap px-3 mt-3"
role="group"
aria-labelledby="checked-group"
>
{categories ? (
<>
{Object?.entries(categories).map(([key, value]) => (
<label
key={key}
className="flex gap-1 w-full items-center"
>
<Field
type="checkbox"
name="category"
value={key}
/>
<span className="text-[13.975px]">{value}</span>
</label>
))}
</>
) : (
<label className="flex gap-1 w-full items-center">
<Field type="checkbox" name="category" />
<span className="text-[13.975px]">null</span>
</label>
)}
<span className="h-5 text-sm italic text-[#cf3917]">
{props.errors.category &&
props.touched.category &&
"please select a category"}
</span>
</div>
</div>
</div>
{/* <div className="field w-full mb-[5px]">
<div className={`flex items-center justify-between mb-2.5`}>
<label
className="job-label"
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 border ${
props.errors.timeline_days &&
props.touched.timeline_days
? "border-[#ff0a0a63] shadow-red-500 border-[0.5px] animate-shake"
: "border border-[#f5f8fa] dark:border-[#5e6278]"
}`}
value={props.values.timeline_days}
>
<option value="">Select Duration</option>
{publicArray.map(({ name, duration }, idx) => (
<option
key={idx}
className="text-slate-500 text-lg"
value={duration}
>
{name}
</option>
))}
</Field>
</div> */}
{/* inputs ends here */}
</div>
</div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
<div className="content-footer 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>
) : (
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>
)
))}
{/* End of error or success display */}
</div>
</div>
<div className="modal-footer-wrapper grid grid-cols-1 xxs:grid-cols-3">
<div className="w-full col-span-1 xxs:col-span-2 xxs:col-start-2 flex justify-between items-center">
<button
type="button"
className="custom-btn border border-light-red text-light-red"
>
<span
className="px-2"
onClick={popUpHandler}
>
{" "}
Cancel
</span>
</button>
{requestStatus?.loading ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<button
type="submit"
className="custom-btn btn-gradient text-white"
>
Add Job
</button>
)}
</div>
</div>
</Form>
);
}}
</Formik>
);
}
export default AddJob;
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" },
];