Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ffc6a23ac5 | |||
| ed7bd861de | |||
| 4f107df131 | |||
| f64cdcb316 | |||
| 7998eaf52d | |||
| 2ac82ee20b | |||
| f5575ecce5 | |||
| b5b95a9040 | |||
| 24f3a40a43 |
@@ -4,6 +4,8 @@ import InputCom from "../Helpers/Inputs/InputCom";
|
|||||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
import usersService from "../../services/UsersService";
|
import usersService from "../../services/UsersService";
|
||||||
|
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
import { Form, Formik } from "formik";
|
import { Form, Formik } from "formik";
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
|
|
||||||
@@ -31,31 +33,43 @@ const validationSchema = Yup.object().shape({
|
|||||||
timeline_days: Yup.number()
|
timeline_days: Yup.number()
|
||||||
.typeError("you must specify a number")
|
.typeError("you must specify a number")
|
||||||
.min(1, "Price must be greater than 0")
|
.min(1, "Price must be greater than 0")
|
||||||
.required("Price is required"),
|
.required("Timeline is required"),
|
||||||
});
|
});
|
||||||
|
|
||||||
let initialValues = {
|
// let initialValues = {
|
||||||
// initial values for formik
|
// // initial values for formik
|
||||||
country: "",
|
// country: "NG",
|
||||||
price: 0,
|
// price: 0,
|
||||||
title: "",
|
// title: "",
|
||||||
description: "",
|
// description: "",
|
||||||
job_detail: "",
|
// job_detail: "",
|
||||||
timeline_days: "",
|
// timeline_days: "",
|
||||||
};
|
// };
|
||||||
|
|
||||||
function AddJob() {
|
function AddJob() {
|
||||||
const ApiCall = new usersService();
|
const ApiCall = new usersService();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
let {userDetails} = useSelector((state)=> state.userDetails)
|
||||||
|
|
||||||
let [pageLoading, setPageLoading] = useState(true); // State used for knowing when the page is mounting
|
let [pageLoading, setPageLoading] = useState(true); // State used for knowing when the page is mounting
|
||||||
|
|
||||||
let [country, setCountry] = useState({
|
let [country, setCountry] = useState({
|
||||||
loading: false,
|
loading: true,
|
||||||
status: false,
|
status: false,
|
||||||
data: [],
|
data: [],
|
||||||
}); // To Hold the array of country getUserCountry returns
|
}); // To Hold the array of country getUserCountry returns
|
||||||
|
|
||||||
|
let initialValues = {
|
||||||
|
// initial values for formik
|
||||||
|
country: userDetails.country,
|
||||||
|
price: "",
|
||||||
|
title: "",
|
||||||
|
description: "",
|
||||||
|
job_detail: "",
|
||||||
|
timeline_days: "",
|
||||||
|
};
|
||||||
|
|
||||||
let [requestStatus, setRequestStatus] = useState({
|
let [requestStatus, setRequestStatus] = useState({
|
||||||
loading: false,
|
loading: false,
|
||||||
status: false,
|
status: false,
|
||||||
@@ -119,8 +133,8 @@ function AddJob() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setPageLoading(false);
|
|
||||||
getUserCountry();
|
getUserCountry();
|
||||||
|
setPageLoading(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return pageLoading.loading ? (
|
return pageLoading.loading ? (
|
||||||
@@ -149,16 +163,17 @@ function AddJob() {
|
|||||||
<div className="xl:flex xl:space-x-7 mb-6">
|
<div className="xl:flex xl:space-x-7 mb-6">
|
||||||
<div className="field w-full mb-6 xl:mb-0">
|
<div className="field w-full mb-6 xl:mb-0">
|
||||||
{/* <InputCom
|
{/* <InputCom
|
||||||
fieldClass="px-6"
|
fieldClass="px-6 cursor-not-allowed"
|
||||||
label="Country"
|
label="Country"
|
||||||
labelClass='tracking-wide'
|
labelClass='tracking-wide'
|
||||||
inputBg = 'bg-slate-100'
|
inputBg = 'bg-slate-100'
|
||||||
type="text"
|
type="text"
|
||||||
name="country"
|
name="country"
|
||||||
// placeholder="Select Country"
|
disable={true}
|
||||||
value={props.values.country}
|
value={country.loading ? 'loading' : country.data ? country.data : 'no country found!'}
|
||||||
inputHandler={props.handleChange}
|
inputHandler={(e)=> setCountry((prev) => ({...prev, data:e.target.value}))}
|
||||||
/> */}
|
|
||||||
|
/> */}
|
||||||
<label
|
<label
|
||||||
htmlFor="country"
|
htmlFor="country"
|
||||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
|
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
|
||||||
@@ -168,6 +183,7 @@ function AddJob() {
|
|||||||
<select
|
<select
|
||||||
id="country"
|
id="country"
|
||||||
name="country"
|
name="country"
|
||||||
|
disabled
|
||||||
value={props.values.country}
|
value={props.values.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`}
|
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}
|
onChange={props.handleChange}
|
||||||
@@ -182,15 +198,19 @@ function AddJob() {
|
|||||||
<option className="text-slate-500 text-lg" value="">
|
<option className="text-slate-500 text-lg" value="">
|
||||||
Select...
|
Select...
|
||||||
</option>
|
</option>
|
||||||
{country.data.map((item, index) => (
|
{country.data.map((item, index) => {
|
||||||
<option
|
if(item[0] == userDetails.country){
|
||||||
key={index}
|
return (
|
||||||
className="text-slate-500 text-lg"
|
<option
|
||||||
value={item[0]}
|
key={index}
|
||||||
>
|
className="text-slate-500 text-lg"
|
||||||
{item[1]}
|
value={item[0]}
|
||||||
</option>
|
>
|
||||||
))}
|
{item[1]}
|
||||||
|
</option>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<option className="text-slate-500 text-lg" value="">
|
<option className="text-slate-500 text-lg" value="">
|
||||||
@@ -214,7 +234,7 @@ function AddJob() {
|
|||||||
inputBg="bg-slate-100"
|
inputBg="bg-slate-100"
|
||||||
type="number"
|
type="number"
|
||||||
name="price"
|
name="price"
|
||||||
// placeholder="Please Enter Amount"
|
placeholder="0"
|
||||||
value={props.values.price}
|
value={props.values.price}
|
||||||
inputHandler={props.handleChange}
|
inputHandler={props.handleChange}
|
||||||
blurHandler={props.handleBlur}
|
blurHandler={props.handleBlur}
|
||||||
@@ -272,17 +292,6 @@ function AddJob() {
|
|||||||
|
|
||||||
{/* Details */}
|
{/* Details */}
|
||||||
<div className="field w-full mb-6">
|
<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
|
<label
|
||||||
htmlFor="Job Delivery Details"
|
htmlFor="Job Delivery Details"
|
||||||
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'
|
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import LoadingSpinner from "../Spinners/LoadingSpinner";
|
|||||||
|
|
||||||
export default function FamilyTable({ className, familyList, loader }) {
|
export default function FamilyTable({ className, familyList, loader }) {
|
||||||
const filterCategories = ["All Categories", "Explore", "Featured"];
|
const filterCategories = ["All Categories", "Explore", "Featured"];
|
||||||
|
|
||||||
const [selectedCategory, setCategory] = useState(filterCategories[0]);
|
const [selectedCategory, setCategory] = useState(filterCategories[0]);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -13,12 +12,12 @@ export default function FamilyTable({ className, familyList, loader }) {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="relative w-full overflow-x-auto sm:rounded-lg">
|
<div className="relative w-full overflow-x-auto sm:rounded-lg">
|
||||||
{loader ? (
|
{loader ? (
|
||||||
<div className="h-full min-h-[500px] w-full overflow-hidden flex justify-center items-center">
|
<div className="h-full min-h-[500px] w-full overflow-hidden flex justify-center items-center">
|
||||||
<LoadingSpinner size='16' color='sky-blue' />
|
<LoadingSpinner size="16" color="sky-blue" />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400 relative">
|
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400 relative">
|
||||||
<>
|
<>
|
||||||
<thead className="sticky top-0">
|
<thead className="sticky top-0">
|
||||||
<tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-bottom ">
|
<tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-bottom ">
|
||||||
@@ -31,55 +30,65 @@ export default function FamilyTable({ className, familyList, loader }) {
|
|||||||
<tbody className="overflow-y-scroll h-auto">
|
<tbody className="overflow-y-scroll h-auto">
|
||||||
<>
|
<>
|
||||||
{familyList?.length > 0 ? (
|
{familyList?.length > 0 ? (
|
||||||
familyList?.map(({ firstname, lastname, age }, idx) => (
|
familyList?.map(
|
||||||
<tr
|
(
|
||||||
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
|
{ firstname, lastname, age, added, last_login },
|
||||||
key={idx}
|
idx
|
||||||
>
|
) => {
|
||||||
<td className=" py-4">
|
let addedDate = added?.split(" ")[0];
|
||||||
<div className="flex space-x-2 items-center">
|
return (
|
||||||
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
|
<tr
|
||||||
<img
|
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
|
||||||
src={dataImage1}
|
key={idx}
|
||||||
alt="data"
|
|
||||||
className="w-full h-full"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col">
|
|
||||||
<h1 className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
|
|
||||||
{`${firstname} ${lastname} (${age})`}
|
|
||||||
</h1>
|
|
||||||
<span className="text-sm text-thin-light-gray">
|
|
||||||
Added{" "}
|
|
||||||
<span className="text-purple">10-10-2029</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td className="text-center py-4 px-2">
|
|
||||||
<div className="flex space-x-1 items-center justify-center">
|
|
||||||
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
|
|
||||||
10-10-2019
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td className="text-center py-4 px-2">
|
|
||||||
<div className="flex space-x-1 items-center justify-center">
|
|
||||||
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
|
|
||||||
100
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td className="text-right py-4 px-2">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
|
||||||
>
|
>
|
||||||
Manage
|
<td className=" py-4">
|
||||||
</button>
|
<div className="flex space-x-2 items-center">
|
||||||
</td>
|
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
|
||||||
</tr>
|
<img
|
||||||
))
|
src={dataImage1}
|
||||||
|
alt="data"
|
||||||
|
className="w-full h-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<h1 className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
|
||||||
|
{`${firstname} ${lastname} (${age})`}
|
||||||
|
</h1>
|
||||||
|
<span className="text-sm text-thin-light-gray">
|
||||||
|
Added:{" "}
|
||||||
|
<span className="text-purple ml-1">
|
||||||
|
{addedDate}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="text-center py-4 px-2">
|
||||||
|
<div className="flex space-x-1 items-center justify-center">
|
||||||
|
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
|
||||||
|
{last_login}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="text-center py-4 px-2">
|
||||||
|
<div className="flex space-x-1 items-center justify-center">
|
||||||
|
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
|
||||||
|
100
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="text-right py-4 px-2 flex items-center justify-center">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||||
|
>
|
||||||
|
Manage
|
||||||
|
</button>
|
||||||
|
</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" colSpan="4">
|
<td className="p-2" colSpan="4">
|
||||||
@@ -90,8 +99,8 @@ export default function FamilyTable({ className, familyList, loader }) {
|
|||||||
</>
|
</>
|
||||||
</tbody>
|
</tbody>
|
||||||
</>
|
</>
|
||||||
</table>
|
</table>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ export default function InputCom({
|
|||||||
name={name}
|
name={name}
|
||||||
minLength={minLengthValidation()}
|
minLength={minLengthValidation()}
|
||||||
maxLength={maxLengthValidation()}
|
maxLength={maxLengthValidation()}
|
||||||
pattern={() => inputPatterns}
|
// pattern={inputPatterns()}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
readOnly={disable}
|
readOnly={disable}
|
||||||
onBlur={blurHandler}
|
onBlur={blurHandler}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,31 +1,59 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import ModalCom from "../Helpers/ModalCom";
|
|
||||||
import Layout from "../Partials/Layout";
|
import Layout from "../Partials/Layout";
|
||||||
import { useLocation, useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import ActiveJobMessage from "./ActiveJobMessage";
|
import ActiveJobMessage from "./ActiveJobMessage";
|
||||||
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
|
|
||||||
|
import usersService from "../../services/UsersService";
|
||||||
|
|
||||||
|
function ActiveJobs(props) {
|
||||||
|
const ApiCall = new usersService()
|
||||||
|
|
||||||
function ActiveJobs() {
|
|
||||||
let { userDetails } = useSelector((state) => state.userDetails);
|
let { userDetails } = useSelector((state) => state.userDetails);
|
||||||
let navigate = useNavigate()
|
let navigate = useNavigate()
|
||||||
let {state} = useLocation()
|
|
||||||
|
|
||||||
let [details, setDetails] = useState({})
|
let [messageToSend, setMessageToSend] = useState('') // State to hold the value of message to be sent
|
||||||
|
|
||||||
// console.log(state, userDetails);
|
let [requestStatus, setRequestStatus] = useState({loading: false, status: false, message: ''})
|
||||||
|
|
||||||
useEffect(()=>{
|
// FUNCTION TO HANDLE MESSAGE CHANGE
|
||||||
if(!state){
|
const handleMessageChange = ({target:{value}}) => {
|
||||||
navigate('/my-active-jobs', {replace: true})
|
setMessageToSend(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION TO SEND TASK MESSAGE
|
||||||
|
const sendTaskMessage = () => {
|
||||||
|
let reqData={message: messageToSend, msg_type: 'TEXT', contract:props.details.contract}
|
||||||
|
if(!reqData.message){
|
||||||
|
setRequestStatus({loading: false, status: false, message: 'Message is empty'})
|
||||||
|
return setTimeout(()=>{
|
||||||
|
setRequestStatus({loading: false, status: false, message: ''})
|
||||||
|
}, 5000)
|
||||||
}
|
}
|
||||||
setDetails(state)
|
setRequestStatus({loading: true, status: false, message: ''})
|
||||||
},[])
|
ApiCall.sendTaskMessage(reqData).then((res)=>{
|
||||||
|
if(res.status != 200 || res.data.internal_return < 0){
|
||||||
|
setRequestStatus({loading: false, status: false, message: 'Message could not be sent, try again later'})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setRequestStatus({loading: false, status: true, message: 'Message Sent Successfully'})
|
||||||
|
props.reloadActiveJobList(prev => !prev) // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
|
||||||
|
setMessageToSend('') // SENDS MESSAGE TO SEND BACK TO EMPTY STRINGS
|
||||||
|
}).catch(error => {
|
||||||
|
setRequestStatus({loading: false, status: false, message: 'Opps! something went wrong'})
|
||||||
|
}).finally(()=>{
|
||||||
|
setTimeout(()=>{
|
||||||
|
setRequestStatus({loading: false, status: false, message: ''})
|
||||||
|
}, 5000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
{/* <div className="logout-modal-wrapper min-w-[850px] h-full lg:h-auto lg:rounded-2xl overflow-y-auto"> */}
|
|
||||||
|
|
||||||
<div className="p-4 lg:flex justify-between items-start space-y-4 lg:space-x-4 lg:space-y-0 rounded-lg shadow-lg bg-slate-100">
|
<div className="p-4 lg:flex justify-between items-start space-y-4 lg:space-x-4 lg:space-y-0 rounded-lg shadow-lg bg-slate-100">
|
||||||
<div className="w-full lg:w-3/4">
|
<div className="w-full lg:w-1/2">
|
||||||
<div className="py-[20px] bg-white px-4 rounded-md shadow-md">
|
<div className="py-[20px] bg-white px-4 rounded-md shadow-md">
|
||||||
{/* back btn and title */}
|
{/* back btn and title */}
|
||||||
<div className="w-full flex justify-start space-x-3 items-center">
|
<div className="w-full flex justify-start space-x-3 items-center">
|
||||||
@@ -45,7 +73,7 @@ function ActiveJobs() {
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<h1 className="text-lg font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="text-lg font-bold text-dark-gray dark:text-white tracking-wide">
|
||||||
{details.title && details.title}
|
{props.details?.title && props.details.title}
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
{/* END of back btn and title */}
|
{/* END of back btn and title */}
|
||||||
@@ -53,11 +81,11 @@ function ActiveJobs() {
|
|||||||
<div className="mt-2 w-full lg:flex lg:justify-between lg:items-center lg:space-x-2">
|
<div className="mt-2 w-full lg:flex lg:justify-between lg:items-center lg:space-x-2">
|
||||||
<div className="my-2 lg:my-0">
|
<div className="my-2 lg:my-0">
|
||||||
<p className="text-base text-slate-700 dark:text-black">
|
<p className="text-base text-slate-700 dark:text-black">
|
||||||
{details.contract && details.contract}
|
{props.details?.contract && props.details.contract}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-base text-slate-700 dark:text-black">
|
<p className="text-base text-slate-700 dark:text-black">
|
||||||
<span className="font-semibold">Description: </span>
|
<span className="font-semibold">Description: </span>
|
||||||
{details.description && details.description}
|
{props.details?.description && props.details.description}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-base text-sky-blue">Delivery Detail</p>
|
<p className="text-base text-sky-blue">Delivery Detail</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -67,15 +95,15 @@ function ActiveJobs() {
|
|||||||
</p>
|
</p>
|
||||||
<p className="text-base text-slate-700 dark:text-black">
|
<p className="text-base text-slate-700 dark:text-black">
|
||||||
<span className="font-semibold">Due: </span>
|
<span className="font-semibold">Due: </span>
|
||||||
{details.delivery_date &&
|
{props.details?.delivery_date &&
|
||||||
details.delivery_date.split(" ")[0]}
|
props.details.delivery_date.split(" ")[0]}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-base text-slate-700 dark:text-black">
|
<p className="text-base text-slate-700 dark:text-black">
|
||||||
{details.delivery_date &&
|
{props.details?.delivery_date &&
|
||||||
details.delivery_date.split(" ")[1]}
|
props.details.delivery_date.split(" ")[1]}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-base text-slate-700 dark:text-black">
|
<p className="text-base text-slate-700 dark:text-black">
|
||||||
{details.timeline_days && details.timeline_days} day(s)
|
{props.details?.timeline_days && props.details.timeline_days} day(s)
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -88,14 +116,39 @@ function ActiveJobs() {
|
|||||||
className="p-4 w-full text-base text-slate-600 border-y border-slate-300 outline-none"
|
className="p-4 w-full text-base text-slate-600 border-y border-slate-300 outline-none"
|
||||||
rows="10"
|
rows="10"
|
||||||
style={{ resize: "none" }}
|
style={{ resize: "none" }}
|
||||||
|
name='message'
|
||||||
|
onChange={handleMessageChange}
|
||||||
|
value={messageToSend}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
|
||||||
|
<div className="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>
|
||||||
|
)
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
{/* End of error or success display */}
|
||||||
|
|
||||||
{/* Buttons Sections */}
|
{/* Buttons Sections */}
|
||||||
<div className="py-2 mb-8 sm:flex sm:justify-center sm:items-center">
|
<div className="py-2 mb-8 sm:flex sm:justify-center sm:items-center">
|
||||||
<div className="w-full sm:w-3/4 mb-5 sm:mb-0">
|
<div className="w-full sm:w-2/4 mb-5 sm:mb-0">
|
||||||
<button
|
<button
|
||||||
onClick={()=> console.log('working')}
|
onClick={()=>{console.log('working')}}
|
||||||
type="button"
|
type="button"
|
||||||
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-md flex justify-center items-center"
|
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-md flex justify-center items-center"
|
||||||
>
|
>
|
||||||
@@ -107,7 +160,7 @@ function ActiveJobs() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-full sm:w-1/4 flex justify-between items-center space-x-2">
|
<div className="w-full sm:w-2/4 flex justify-between items-center space-x-2">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="bg-red-600 text-base text-white tracking-wide px-4 py-2 rounded-md hover:opacity-90"
|
className="bg-red-600 text-base text-white tracking-wide px-4 py-2 rounded-md hover:opacity-90"
|
||||||
@@ -115,10 +168,15 @@ function ActiveJobs() {
|
|||||||
<span className="text-white">Clear</span>
|
<span className="text-white">Clear</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
onClick={sendTaskMessage}
|
||||||
type="button"
|
type="button"
|
||||||
className="btn-gradient text-base text-white tracking-wide px-4 py-2 rounded-md"
|
className="btn-gradient text-base text-white tracking-wide px-4 py-2 rounded-md"
|
||||||
>
|
>
|
||||||
|
{requestStatus.loading ?
|
||||||
|
<LoadingSpinner size='6' color='sky-blue' />
|
||||||
|
:
|
||||||
<span className="text-white">Send</span>
|
<span className="text-white">Send</span>
|
||||||
|
}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -128,7 +186,7 @@ function ActiveJobs() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* ACTION SECTION */}
|
{/* ACTION SECTION */}
|
||||||
<div className="w-full lg:w-1/4 h-full">
|
<div className="w-full lg:w-1/2 h-full">
|
||||||
<div className="py-[20px] bg-white px-4 rounded-md shadow-md">
|
<div className="py-[20px] bg-white px-4 rounded-md shadow-md">
|
||||||
<h1 className="text-lg font-bold text-dark-gray dark:text-white tracking-wide">Actions</h1>
|
<h1 className="text-lg font-bold text-dark-gray dark:text-white tracking-wide">Actions</h1>
|
||||||
|
|
||||||
@@ -140,14 +198,17 @@ function ActiveJobs() {
|
|||||||
<div className="mt-5 bg-white p-4 rounded-md shadow-md">
|
<div className="mt-5 bg-white p-4 rounded-md shadow-md">
|
||||||
<div className="">
|
<div className="">
|
||||||
<p className="text-lg font-bold text-dark-gray dark:text-black tracking-wide">Message</p>
|
<p className="text-lg font-bold text-dark-gray dark:text-black tracking-wide">Message</p>
|
||||||
<ActiveJobMessage />
|
{props.activeJobMesList.loading ?
|
||||||
|
<LoadingSpinner size='16' color='sky-blue' />
|
||||||
|
:
|
||||||
|
<ActiveJobMessage activeJobMesList={props.activeJobMesList} />
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* </div> */}
|
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import dataImage1 from "../../assets/images/data-table-user-1.png";
|
import dataImage1 from "../../assets/images/data-table-user-1.png";
|
||||||
import dataImage2 from "../../assets/images/data-table-user-2.png";
|
import dataImage2 from "../../assets/images/data-table-user-2.png";
|
||||||
import dataImage3 from "../../assets/images/data-table-user-3.png";
|
import dataImage3 from "../../assets/images/data-table-user-3.png";
|
||||||
@@ -10,8 +10,42 @@ import DeleteJobPopout from "../jobPopout/DeleteJobPopout";
|
|||||||
import PaginatedList from "../Pagination/PaginatedList";
|
import PaginatedList from "../Pagination/PaginatedList";
|
||||||
import { handlePagingFunc } from "../Pagination/HandlePagination";
|
import { handlePagingFunc } from "../Pagination/HandlePagination";
|
||||||
import EditJobPopOut from "../jobPopout/EditJobPopout";
|
import EditJobPopOut from "../jobPopout/EditJobPopout";
|
||||||
|
import usersService from "../../services/UsersService";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
export default function MyJobTable({ MyJobList, className }) {
|
export default function MyJobTable({ MyJobList, className }) {
|
||||||
|
const [myCountry, setCountries] = useState("");
|
||||||
|
const {
|
||||||
|
userDetails: { country },
|
||||||
|
} = useSelector((state) => state?.userDetails);
|
||||||
|
|
||||||
|
const userApi = useMemo(() => new usersService(), []);
|
||||||
|
|
||||||
|
// Get Country Api
|
||||||
|
const getCountryList = useCallback(async () => {
|
||||||
|
const res = await userApi.getSignupCountryData();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (res.status === 200) {
|
||||||
|
const {
|
||||||
|
data: { signup_country },
|
||||||
|
} = await res;
|
||||||
|
console.log(signup_country);
|
||||||
|
let checkCountry = signup_country
|
||||||
|
?.filter((item) => item[0] == country)
|
||||||
|
?.map((item, idx) => item[1])
|
||||||
|
.join("");
|
||||||
|
setCountries(checkCountry);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(error);
|
||||||
|
}
|
||||||
|
}, [userApi, country]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getCountryList();
|
||||||
|
}, [getCountryList]);
|
||||||
|
|
||||||
const filterCategories = ["All Categories", "Explore", "Featured"];
|
const filterCategories = ["All Categories", "Explore", "Featured"];
|
||||||
const [selectedCategory, setCategory] = useState(filterCategories[0]);
|
const [selectedCategory, setCategory] = useState(filterCategories[0]);
|
||||||
|
|
||||||
@@ -209,6 +243,7 @@ export default function MyJobTable({ MyJobList, className }) {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
situation={editJob.show}
|
situation={editJob.show}
|
||||||
|
country={myCountry}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { createRoutesFromChildren } from 'react-router-dom';
|
|||||||
|
|
||||||
const PaginatedList = ({ onClick, prev, next, data, start, stop }) => {
|
const PaginatedList = ({ onClick, prev, next, data, start, stop }) => {
|
||||||
|
|
||||||
if(data.length){
|
if(data.length > process.env.REACT_APP_ITEM_PER_PAGE){
|
||||||
return (
|
return (
|
||||||
<div className='p-3 flex justify-center items-center space-x-2 border-t-2'>
|
<div className='p-3 flex justify-center items-center space-x-2 border-t-2'>
|
||||||
{/* Render pagination buttons */}
|
{/* Render pagination buttons */}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import ModalCom from "../Helpers/ModalCom";
|
import ModalCom from "../Helpers/ModalCom";
|
||||||
import { Form, Formik } from "formik";
|
import { Form, Formik } from "formik";
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import InputCom from "../Helpers/Inputs/InputCom";
|
import InputCom from "../Helpers/Inputs/InputCom";
|
||||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
|
import usersService from "../../services/UsersService";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
const EditJobPopOut = ({ details, onClose, situation }) => {
|
const EditJobPopOut = ({ details, onClose, situation, country }) => {
|
||||||
let [requestStatus, setRequestStatus] = useState({
|
let [requestStatus, setRequestStatus] = useState({
|
||||||
loading: false,
|
loading: false,
|
||||||
status: false,
|
status: false,
|
||||||
@@ -41,7 +43,7 @@ const EditJobPopOut = ({ details, onClose, situation }) => {
|
|||||||
|
|
||||||
let initialValues = {
|
let initialValues = {
|
||||||
// initial values for formik
|
// initial values for formik
|
||||||
country: details?.country,
|
country: country,
|
||||||
price: details?.price,
|
price: details?.price,
|
||||||
title: details?.title,
|
title: details?.title,
|
||||||
description: details?.description,
|
description: details?.description,
|
||||||
@@ -49,7 +51,34 @@ const EditJobPopOut = ({ details, onClose, situation }) => {
|
|||||||
timeline_days: details?.timeline_days,
|
timeline_days: details?.timeline_days,
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(details);
|
const jobApi = useMemo(() => new usersService(), []);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const handleEditJob = useCallback(
|
||||||
|
async (values) => {
|
||||||
|
setRequestStatus({ loading: true, message: "" });
|
||||||
|
let reqData = {
|
||||||
|
job_id: details.job_id,
|
||||||
|
job_uid: details.job_uid,
|
||||||
|
...values,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
let res = await jobApi.jobManagerUpdateJob(reqData);
|
||||||
|
let { data } = await res;
|
||||||
|
if (data?.internal_return < 0) return;
|
||||||
|
setRequestStatus({ loading: false, message: null });
|
||||||
|
setTimeout(() => {
|
||||||
|
navigate("/myjobs", { replace: true });
|
||||||
|
onClose();
|
||||||
|
}, 1000);
|
||||||
|
} catch (error) {
|
||||||
|
setRequestStatus({ loading: false, message: error });
|
||||||
|
throw new Error(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[jobApi, navigate, onClose, details]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalCom action={onClose} situation={situation} className="edit-popup">
|
<ModalCom action={onClose} situation={situation} className="edit-popup">
|
||||||
<div className="logout-modal-wrapper lg:w-[600px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
|
<div className="logout-modal-wrapper lg:w-[600px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
|
||||||
@@ -87,6 +116,7 @@ const EditJobPopOut = ({ details, onClose, situation }) => {
|
|||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
validationSchema={validationSchema}
|
validationSchema={validationSchema}
|
||||||
|
onSubmit={handleEditJob}
|
||||||
>
|
>
|
||||||
{(props) => (
|
{(props) => (
|
||||||
<Form className="w-full">
|
<Form className="w-full">
|
||||||
@@ -94,26 +124,19 @@ const EditJobPopOut = ({ details, onClose, situation }) => {
|
|||||||
<div className="fields w-full">
|
<div className="fields w-full">
|
||||||
<div className="xl:flex xl:space-x-7 mb-6">
|
<div className="xl:flex xl:space-x-7 mb-6">
|
||||||
<div className="field w-full mb-6 xl:mb-0">
|
<div className="field w-full mb-6 xl:mb-0">
|
||||||
<label
|
<InputCom
|
||||||
htmlFor="country"
|
fieldClass="px-6 cursor-default"
|
||||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
|
label="Country"
|
||||||
>
|
labelClass="tracking-wide"
|
||||||
Country
|
inputBg="bg-slate-100"
|
||||||
</label>
|
inputClass="input-curve lg border border-light-purple"
|
||||||
<select
|
type="text"
|
||||||
id="country"
|
|
||||||
name="country"
|
name="country"
|
||||||
value={props.values.country}
|
value={props.values.country}
|
||||||
className={`input-field py-2 px-6 mt-3 rounded-[50px] 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`}
|
inputHandler={props.handleChange}
|
||||||
onChange={props.handleChange}
|
blurHandler={props.handleBlur}
|
||||||
onBlur={props.handleBlur}
|
disable={true}
|
||||||
disabled
|
/>
|
||||||
>
|
|
||||||
<option
|
|
||||||
className="text-slate-500 text-lg"
|
|
||||||
value={props.values.country}
|
|
||||||
/>
|
|
||||||
</select>
|
|
||||||
{props.errors.country && props.touched.country && (
|
{props.errors.country && props.touched.country && (
|
||||||
<p className="text-sm text-red-500">
|
<p className="text-sm text-red-500">
|
||||||
{props.errors.country}
|
{props.errors.country}
|
||||||
|
|||||||
@@ -461,6 +461,44 @@ class usersService {
|
|||||||
return this.postAuxEnd("/jobmanagercreatejob", postData);
|
return this.postAuxEnd("/jobmanagercreatejob", postData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jobManagerUpdateJob(reqData) {
|
||||||
|
var postData = {
|
||||||
|
uid: localStorage.getItem("uid"),
|
||||||
|
member_id: localStorage.getItem("member_id"),
|
||||||
|
sessionid: localStorage.getItem("session_token"),
|
||||||
|
job_id: localStorage.getItem("job_id"),
|
||||||
|
action: 13010,
|
||||||
|
...reqData
|
||||||
|
};
|
||||||
|
return this.postAuxEnd("/jobmanagerupdatejob", postData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION TO GET ACTIVE JOB MESSAGE LIST
|
||||||
|
activeJobMesList(reqData) {
|
||||||
|
var postData = {
|
||||||
|
uid: localStorage.getItem("uid"),
|
||||||
|
member_id: localStorage.getItem("member_id"),
|
||||||
|
sessionid: localStorage.getItem("session_token"),
|
||||||
|
limit: 30,
|
||||||
|
action: 14011,
|
||||||
|
offset: 0,
|
||||||
|
...reqData
|
||||||
|
};
|
||||||
|
return this.postAuxEnd("/activejobmsglist", postData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION TO SEND ACTIVE JOB TASK MESSAGE
|
||||||
|
sendTaskMessage(reqData) {
|
||||||
|
var postData = {
|
||||||
|
uid: localStorage.getItem("uid"),
|
||||||
|
member_id: localStorage.getItem("member_id"),
|
||||||
|
sessionid: localStorage.getItem("session_token"),
|
||||||
|
action: 14010,
|
||||||
|
...reqData
|
||||||
|
};
|
||||||
|
return this.postAuxEnd("/sendtaskmessage", postData);
|
||||||
|
}
|
||||||
|
|
||||||
// END POINT TO DELETE A JOB
|
// END POINT TO DELETE A JOB
|
||||||
deleteJob(reqData) {
|
deleteJob(reqData) {
|
||||||
var postData = {
|
var postData = {
|
||||||
|
|||||||
@@ -1,9 +1,45 @@
|
|||||||
import React from 'react'
|
import React, {useState, useEffect} from 'react'
|
||||||
import ActiveJobs from '../components/MyActiveJobs/ActiveJobs'
|
import ActiveJobs from '../components/MyActiveJobs/ActiveJobs'
|
||||||
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
|
import usersService from '../services/UsersService'
|
||||||
|
|
||||||
function ManageActiveJobs() {
|
function ManageActiveJobs() {
|
||||||
|
|
||||||
|
const ApiCall = new usersService()
|
||||||
|
|
||||||
|
let navigate = useNavigate()
|
||||||
|
let {state} = useLocation()
|
||||||
|
|
||||||
|
let [details, setDetails] = useState({}) // to hold state values
|
||||||
|
|
||||||
|
let [activeJobMesList, setActiveJobMesList] = useState({loading: true, error: false, data: []})
|
||||||
|
|
||||||
|
let [activeJobMesListReload, setActiveJobMesListReload] = useState(false)// state to determine when ACTIVE JOB MESSAGE LIST RELOADS/RE-RENDERS
|
||||||
|
|
||||||
|
const getActiveJobMesList = () => { // FUNCTION TO GET ACTIVE JOB MESSAGE LIST
|
||||||
|
setActiveJobMesList({loading: true, error: false, data: []})
|
||||||
|
let contract = {contract: state.contract}
|
||||||
|
ApiCall.activeJobMesList(contract).then((res)=>{
|
||||||
|
if(res.status != 200 || res.data.internal_return < 0){
|
||||||
|
setActiveJobMesList({loading: false, error: false, data: []})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setActiveJobMesList({loading: false, error: false, data: res.data.result_list})
|
||||||
|
}).catch((error)=>{
|
||||||
|
setActiveJobMesList({loading: false, error: true, data: []})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(!state){
|
||||||
|
navigate('/my-active-jobs', {replace: true})
|
||||||
|
}
|
||||||
|
setDetails(state)
|
||||||
|
getActiveJobMesList()
|
||||||
|
},[activeJobMesListReload])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ActiveJobs />
|
<ActiveJobs details={state} activeJobMesList={activeJobMesList} reloadActiveJobList={setActiveJobMesListReload} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user