Add job implemented
This commit was merged in pull request #57.
This commit is contained in:
@@ -0,0 +1,340 @@
|
||||
import React, {useState, useEffect} from 'react'
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import InputCom from '../Helpers/Inputs/InputCom';
|
||||
import LoadingSpinner from '../Spinners/LoadingSpinner';
|
||||
import usersService from '../../services/UsersService';
|
||||
|
||||
import { Form, Formik } from "formik";
|
||||
import * as Yup from "yup";
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
country: Yup.string()
|
||||
.min(1, "Minimum 3 characters")
|
||||
.max(25, "Maximum 25 characters")
|
||||
.required("Country is required"),
|
||||
price: Yup.number()
|
||||
.typeError("you must specify a number")
|
||||
.min(1, "Price must be greater than 0")
|
||||
.required("Price is required"),
|
||||
title: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(100, "Maximum 25 characters")
|
||||
.required("Title is required"),
|
||||
description: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(250, "Maximum 250 characters")
|
||||
.required("Description is required"),
|
||||
job_detail: Yup.string()
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(250, "Maximum 250 characters")
|
||||
.required("Details is required"),
|
||||
timeline_days: Yup.number()
|
||||
.typeError("you must specify a number")
|
||||
.min(1, "Price must be greater than 0")
|
||||
.required("Price is required"),
|
||||
});
|
||||
|
||||
let initialValues = { // initial values for formik
|
||||
country: '',
|
||||
price: '',
|
||||
title: '',
|
||||
description: '',
|
||||
job_detail: '',
|
||||
timeline_days: ''
|
||||
}
|
||||
|
||||
function AddJob() {
|
||||
const ApiCall = new usersService()
|
||||
const navigate = useNavigate()
|
||||
|
||||
let [pageLoading, setPageLoading] = useState(true) // State used for knowing when the page is mounting
|
||||
|
||||
let [country, setCountry] = useState({loading: false, status: false, data:[]}) // To Hold the array of country getUserCountry returns
|
||||
|
||||
let [requestStatus, setRequestStatus] = useState({loading: false, status: false, message:''}) // Holds state when submit button is pressed
|
||||
|
||||
// FUNCTION TO GET COUNTRY
|
||||
const getUserCountry = () =>{
|
||||
setCountry(prev => ({...prev, loading:true}))
|
||||
ApiCall.getSignupCountryData().then(res => {
|
||||
if(res.data.internal_return < 1){
|
||||
setCountry({loading: false, status: true, data:[]})
|
||||
return
|
||||
}
|
||||
setCountry({loading: false, status: true, data:res.data.signup_country})
|
||||
}).catch(err => {
|
||||
setCountry({loading: false, status: false, data:[]})
|
||||
})
|
||||
}
|
||||
|
||||
// FUNCTION TO HANDLE ADD JOB FORM
|
||||
const handleAddJob = (values, helpers) => {
|
||||
console.log(values)
|
||||
setRequestStatus({loading: true, status: false, message:''})
|
||||
ApiCall.jobManagerCreateJob(values).then(res => {
|
||||
if(res.data.internal_return < 1){
|
||||
setRequestStatus({loading: false, status: false, message:'Could not complete your request at the moment'})
|
||||
return
|
||||
}
|
||||
setRequestStatus({loading: false, status: true, message:'Job Added Successfully'})
|
||||
setTimeout(()=>{
|
||||
navigate('/myjobs', {replace: true})
|
||||
},1000)
|
||||
|
||||
}).catch(err => {
|
||||
setRequestStatus({loading: false, status: false, message:'Opps! soemthing went wrong. Try Again'})
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
setPageLoading(false)
|
||||
getUserCountry()
|
||||
},[])
|
||||
|
||||
return pageLoading.loading ? (
|
||||
<div className="personal-info-tab w-full flex flex-col justify-between">
|
||||
<div className="p-3">
|
||||
<LoadingSpinner size="32" color="sky-blue" />
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="add-job p-5 w-full bg-white rounded-md flex flex-col justify-between">
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={handleAddJob}
|
||||
>
|
||||
{(props) => {
|
||||
return (
|
||||
<Form>
|
||||
<h1 className='py-2 my-4 text-lg md:text-xl font-bold tracking-wide'>Create New Job</h1>
|
||||
<div className="flex flex-col-reverse sm:flex-row">
|
||||
<div className="fields w-full">
|
||||
|
||||
{/* inputs starts here */}
|
||||
{/* country */}
|
||||
<div className="xl:flex xl:space-x-7 mb-6">
|
||||
<div className="field w-full mb-6 xl:mb-0">
|
||||
{/* <InputCom
|
||||
fieldClass="px-6"
|
||||
label="Country"
|
||||
labelClass='tracking-wide'
|
||||
inputBg = 'bg-slate-100'
|
||||
type="text"
|
||||
name="country"
|
||||
// placeholder="Select Country"
|
||||
value={props.values.country}
|
||||
inputHandler={props.handleChange}
|
||||
/> */}
|
||||
<label
|
||||
htmlFor='country'
|
||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block">
|
||||
Country
|
||||
</label>
|
||||
<select
|
||||
id='country'
|
||||
name='country'
|
||||
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`}
|
||||
onChange={props.handleChange}
|
||||
>
|
||||
{country.loading ? (
|
||||
<option className="text-slate-500 text-lg" value="">
|
||||
Loading...
|
||||
</option>
|
||||
) : country.data.length ? (
|
||||
<>
|
||||
<option className="text-slate-500 text-lg" value="">
|
||||
Select...
|
||||
</option>
|
||||
{country.data.map((item, index) => (
|
||||
<option
|
||||
key={index}
|
||||
className="text-slate-500 text-lg"
|
||||
value={item[0]}
|
||||
>
|
||||
{item[1]}
|
||||
</option>
|
||||
))}
|
||||
</>
|
||||
) : (
|
||||
<option className="text-slate-500 text-lg" value="">
|
||||
No Options Found! Try Again
|
||||
</option>
|
||||
)}
|
||||
</select>
|
||||
{props.errors.country && props.touched.country && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.country}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Price */}
|
||||
<div className="field w-full">
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
label="Price"
|
||||
labelClass='tracking-wide'
|
||||
inputBg = 'bg-slate-100'
|
||||
type="text"
|
||||
name="price"
|
||||
// placeholder="Please Enter Amount"
|
||||
value={props.values.price}
|
||||
inputHandler={props.handleChange}
|
||||
/>
|
||||
{props.errors.price && props.touched.price && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.price}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Title */}
|
||||
|
||||
<div className="field w-full mb-6">
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
label="Title"
|
||||
labelClass='tracking-wide'
|
||||
inputBg = 'bg-slate-100'
|
||||
type="text"
|
||||
name="title"
|
||||
// placeholder="Enter Job Title"
|
||||
value={props.values.title}
|
||||
inputHandler={props.handleChange}
|
||||
/>
|
||||
{props.errors.title && props.touched.title && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.title}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Description */}
|
||||
<div className="field w-full mb-6">
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
label="Description"
|
||||
labelClass='tracking-wide'
|
||||
inputBg = 'bg-slate-100'
|
||||
type="text"
|
||||
name="description"
|
||||
// placeholder="Enter a description"
|
||||
value={props.values.description}
|
||||
inputHandler={props.handleChange}
|
||||
/>
|
||||
{props.errors.description && props.touched.description && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.description}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Details */}
|
||||
<div className="field w-full mb-6">
|
||||
{/* <InputCom
|
||||
fieldClass="px-6"
|
||||
label="Job Delivery Details"
|
||||
labelClass='tracking-wide'
|
||||
inputBg = 'bg-slate-100'
|
||||
type="text"
|
||||
name="details"
|
||||
// placeholder="Please Enter Detail Description of Job"
|
||||
value={props.values.details}
|
||||
inputHandler={props.handleChange}
|
||||
/> */}
|
||||
<label
|
||||
htmlFor="Job Delivery Details"
|
||||
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'>
|
||||
Job Delivery Details
|
||||
</label>
|
||||
<textarea name="details" id="Job Delivery Details" rows="7"
|
||||
className={`input-field p-6 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-full bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
|
||||
style={{resize:'none'}}
|
||||
name='job_detail'
|
||||
value={props.values.job_detail}
|
||||
onChange={props.handleChange}
|
||||
/>
|
||||
{props.errors.job_detail && props.touched.job_detail && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.job_detail}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="field w-full mb-6">
|
||||
<InputCom
|
||||
fieldClass="px-6"
|
||||
label="Timeline"
|
||||
labelClass='tracking-wide'
|
||||
inputBg = 'bg-slate-100'
|
||||
type="text"
|
||||
name="timeline_days"
|
||||
spanTag = ' - Expected duration of this task'
|
||||
// placeholder="Please Enter Detail Description of Job"
|
||||
value={props.values.timeline_days}
|
||||
inputHandler={props.handleChange}
|
||||
/>
|
||||
{props.errors.timeline_days && props.touched.timeline_days && (
|
||||
<p className="text-sm text-red-500">
|
||||
{props.errors.timeline_days}
|
||||
</p>
|
||||
)}
|
||||
</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 className="w-full h-[120px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
|
||||
<div className="flex items-center space-x-4 mr-9">
|
||||
<Link
|
||||
to="/myjobs"
|
||||
className="text-18 text-light-red tracking-wide "
|
||||
>
|
||||
<span className="border-b dark:border-[#5356fb29] border-light-red">
|
||||
{" "}
|
||||
Cancel
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
{requestStatus.loading ? (
|
||||
<LoadingSpinner size="8" color="sky-blue" />
|
||||
) : (
|
||||
<button
|
||||
type="submit"
|
||||
className="w-[152px] h-[46px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
// className='w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white'
|
||||
>
|
||||
Add Job
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
}}
|
||||
</Formik>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AddJob
|
||||
Reference in New Issue
Block a user