Compare commits

..

10 Commits

7 changed files with 167 additions and 101 deletions
+43 -15
View File
@@ -6,7 +6,7 @@ import usersService from "../../services/UsersService";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { Form, Formik } from "formik"; import { Field, Form, Formik } from "formik";
import * as Yup from "yup"; import * as Yup from "yup";
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
@@ -50,7 +50,7 @@ function AddJob() {
const ApiCall = new usersService(); const ApiCall = new usersService();
const navigate = useNavigate(); const navigate = useNavigate();
let {userDetails} = useSelector((state)=> state.userDetails) 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
@@ -199,7 +199,7 @@ function AddJob() {
Select... Select...
</option> </option>
{country.data.map((item, index) => { {country.data.map((item, index) => {
if(item[0] == userDetails.country){ if (item[0] == userDetails.country) {
return ( return (
<option <option
key={index} key={index}
@@ -208,7 +208,7 @@ function AddJob() {
> >
{item[1]} {item[1]}
</option> </option>
) );
} }
})} })}
</> </>
@@ -316,19 +316,34 @@ function AddJob() {
</div> </div>
<div className="field w-full mb-6"> <div className="field w-full mb-6">
<InputCom <div className={`flex items-center justify-between mb-2.5`}>
fieldClass="px-6" <label
label="Timeline" className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
labelClass="tracking-wide" htmlFor="timeline_days"
inputBg="bg-slate-100" >
type="text" Timeline
<span className="text-green-700 text-sm tracking-wide">
- Expected duration of this task
</span>
</label>
</div>
<Field
component="select"
name="timeline_days" name="timeline_days"
spanTag=" - Expected duration of this task" 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"
// placeholder="Please Enter Detail Description of Job"
value={props.values.timeline_days} value={props.values.timeline_days}
inputHandler={props.handleChange} >
blurHandler={props.handleBlur} <option value="">Select Duration</option>
/> {publicArray.map(({ name, duration }, idx) => (
<option
className="text-slate-500 text-lg"
value={duration}
>
{name}
</option>
))}
</Field>
{props.errors.timeline_days && {props.errors.timeline_days &&
props.touched.timeline_days && ( props.touched.timeline_days && (
<p className="text-sm text-red-500"> <p className="text-sm text-red-500">
@@ -396,3 +411,16 @@ function AddJob() {
} }
export default AddJob; 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" },
];
+5 -5
View File
@@ -58,15 +58,15 @@ export default function MyJobTable({ className, ActiveJobList }) {
<LoadingSpinner size="16" color="sky-blue" /> <LoadingSpinner size="16" color="sky-blue" />
</div> </div>
) : ( ) : (
<div className="relative w-full overflow-x-auto sm:rounded-lg"> <div className="relative w-full sm:rounded-lg">
<div className="overflow-y-auto h-auto w-full"> <div className="h-auto w-full">
{ActiveJobList?.data?.length > 0 ? ( {ActiveJobList?.data?.length > 0 ? (
currentTask?.map((task, idx) => ( currentTask?.map((task, idx) => (
<div <div
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] w-full flex justify-between items-center hover:bg-gray-50" className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] w-full flex justify-between items-center hover:bg-gray-50"
key={idx} key={idx}
> >
<div className=" py-4"> <div className="py-4 max-w-[80%]">
<div className="flex space-x-2 items-center"> <div className="flex space-x-2 items-center">
<div className="w-full min-w-[60px] max-w-[60px] flex-[0.1] h-[60px] rounded-full overflow-hidden flex justify-center items-center"> <div className="w-full min-w-[60px] max-w-[60px] flex-[0.1] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img <img
@@ -76,7 +76,7 @@ export default function MyJobTable({ className, ActiveJobList }) {
/> />
</div> </div>
<div className="flex flex-col flex-[0.9]"> <div className="flex flex-col flex-[0.9]">
<h1 className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap"> <h1 className="font-bold text-xl text-dark-gray dark:text-white">
{task?.title} {task?.title}
</h1> </h1>
<span className="text-base text-gray-600"> <span className="text-base text-gray-600">
@@ -112,7 +112,7 @@ export default function MyJobTable({ className, ActiveJobList }) {
</div> </div>
</div> </div>
<div className="text-right py-4 px-2"> <div className="flex justify-center items-center py-4 px-2">
<button <button
type="button" type="button"
onClick={() => { onClick={() => {
+39 -17
View File
@@ -7,6 +7,7 @@ import Icons from "../Helpers/Icons";
import SliderCom from "../Helpers/SliderCom"; import SliderCom from "../Helpers/SliderCom";
import OfferJobPopout from '../jobPopout/OfferJobPopout' import OfferJobPopout from '../jobPopout/OfferJobPopout'
import LoadingSpinner from "../Spinners/LoadingSpinner";
export default function MyOffersTable({ className, MyActiveOffersList}) { export default function MyOffersTable({ className, MyActiveOffersList}) {
@@ -49,9 +50,9 @@ export default function MyOffersTable({ className, MyActiveOffersList}) {
// } // }
}; };
if ( !MyActiveOffersList || MyActiveOffersList?.result_list?.length == 0 ){ // if ( !MyActiveOffersList || MyActiveOffersList?.result_list?.length == 0 ){
return(''); // want blank or no appear when no items // return(''); // want blank or no appear when no items
} // }
return ( return (
<> <>
@@ -112,37 +113,40 @@ export default function MyOffersTable({ className, MyActiveOffersList}) {
</div> </div>
<div className="slider-content"> <div className="slider-content">
<SliderCom settings={settings} selector={sellSlider}> <SliderCom settings={settings} selector={sellSlider}>
{ MyActiveOffersList.loading ?
{MyActiveOffersList && <LoadingSpinner size={16} color='sky-blue' />
MyActiveOffersList?.result_list?.length > 0 && :
MyActiveOffersList.result_list.map((value, index) => ( MyActiveOffersList?.data?.length > 0 ?
MyActiveOffersList.data.map((value, index) => (
<div className="item" key={index}> <div className="item" key={index}>
<div className="offer-slide-item" > <div className="offer-slide-item flex flex-col justify-between items-center">
{/* title */} {/* title */}
<div className="flex justify-center"> <div className="flex justify-center">
<p className="text-2xl text-dark-gray dark:text-white font-bold mb-2"> <p className="text-xl text-dark-gray dark:text-white font-bold mb-2">
{value.title} {value.title}
</p> </p>
</div> </div>
{/* username */} {/* username */}
<div className="flex justify-center mb-1"> <div className="flex flex-col justify-center my-1">
<p className="text-xs text-thin-light-gray"> <p className="text-xs text-thin-light-gray">
{value.timeline_days} Days {value.timeline_days} Days
</p> </p>
</div> <div className="my-2 flex space-x-1 items-center text-purple text-xs">
{/* items */}
<div className="flex justify-center">
<div className="flex space-x-1 items-center text-purple text-xs">
<span>{value.price*0.01} {value.currency}</span> <span>{value.price*0.01} {value.currency}</span>
</div> </div>
</div> </div>
{/* items */}
{/* <div className="flex justify-center">
<div className="flex space-x-1 items-center text-purple text-xs">
<span>{value.price*0.01} {value.currency}</span>
</div>
</div> */}
<button <button
type="button" type="button"
onClick={() => { onClick={() => {
setOfferPopout({ show: true, data: value }); setOfferPopout({ show: true, data: value });
}} }}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white" className="w-20 h-11 self-center btn-gradient text-base rounded-full text-white"
> >
Start Task Start Task
</button> </button>
@@ -150,7 +154,25 @@ export default function MyOffersTable({ className, MyActiveOffersList}) {
</div> </div>
</div> </div>
))} ))
:
MyActiveOffersList.status ?
(
<div className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<div className="p-2">
No Tasks!
</div>
</div>
)
:
(
<div className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<p className="p-2">
Error Occurred! Unable to display Tasks!
</p>
</div>
)
}
+40 -36
View File
@@ -46,6 +46,8 @@ export default function RightSideBar() {
</div> </div>
<div className="platform-list"> <div className="platform-list">
{userDetails && userDetails?.account_type !== "FAMILY" && (
<>
<div className="item flex space-x-3 items-center mb-4"> <div className="item flex space-x-3 items-center mb-4">
{/* image */} {/* image */}
<div className="w-8 h-8 rounded-full"> <div className="w-8 h-8 rounded-full">
@@ -77,8 +79,7 @@ export default function RightSideBar() {
</div> </div>
{/* action */} {/* action */}
</div> </div>
{userDetails && userDetails?.account_type !== "FAMILY" && (
<>
<div className="item flex space-x-3 items-center mb-4"> <div className="item flex space-x-3 items-center mb-4">
{/* image */} {/* image */}
<div className="w-8 h-8 rounded-full"> <div className="w-8 h-8 rounded-full">
@@ -122,42 +123,45 @@ export default function RightSideBar() {
</p> </p>
</div> </div>
</div> </div>
<div className="item flex space-x-3 items-center mb-4">
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg
width="40"
height="41"
viewBox="0 0 40 41"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<ellipse
cx="20"
cy="20.2341"
rx="20"
ry="19.9392"
fill="#5165FF"
/>
<path
d="M26.1647 27.2085C22.5316 27.2448 19.3317 24.2111 19.3359 20.2195C19.3402 16.4128 22.3393 13.2525 26.1704 13.2554C30.0813 13.2583 33.012 16.5264 33.0006 20.2501C32.9892 24.1456 29.8505 27.2492 26.1647 27.2085Z"
fill="white"
/>
<path
d="M20.5815 27.1983C20.5217 27.2245 20.4405 27.207 20.3607 27.207C16.0039 27.2085 11.647 27.2085 7.29019 27.2085C7.25742 27.2085 7.22465 27.2099 7.1933 27.2085C7.01094 27.2026 7.00951 27.2026 7.00381 27.0076C7.00239 26.9581 7.00381 26.9086 7.00381 26.8576C7.00381 22.4395 7.00381 18.0214 7.00381 13.6033C7.00381 13.5072 6.99099 13.4082 7.01236 13.334C11.5373 17.9559 16.0566 22.5749 20.5815 27.1983Z"
fill="white"
/>
</svg>
</div>
{/* name */}
<div>
<p className="text-thin-light-gray text-base font-medium">
<NavLink to="/resources">Resources</NavLink>
</p>
</div>
</div>
</> </>
)} )}
<div className="item flex space-x-3 items-center mb-4">
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg
width="40"
height="41"
viewBox="0 0 40 41"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<ellipse
cx="20"
cy="20.2341"
rx="20"
ry="19.9392"
fill="#5165FF"
/>
<path
d="M26.1647 27.2085C22.5316 27.2448 19.3317 24.2111 19.3359 20.2195C19.3402 16.4128 22.3393 13.2525 26.1704 13.2554C30.0813 13.2583 33.012 16.5264 33.0006 20.2501C32.9892 24.1456 29.8505 27.2492 26.1647 27.2085Z"
fill="white"
/>
<path
d="M20.5815 27.1983C20.5217 27.2245 20.4405 27.207 20.3607 27.207C16.0039 27.2085 11.647 27.2085 7.29019 27.2085C7.25742 27.2085 7.22465 27.2099 7.1933 27.2085C7.01094 27.2026 7.00951 27.2026 7.00381 27.0076C7.00239 26.9581 7.00381 26.9086 7.00381 26.8576C7.00381 22.4395 7.00381 18.0214 7.00381 13.6033C7.00381 13.5072 6.99099 13.4082 7.01236 13.334C11.5373 17.9559 16.0566 22.5749 20.5815 27.1983Z"
fill="white"
/>
</svg>
</div>
{/* name */}
<div>
<p className="text-thin-light-gray text-base font-medium">
<NavLink to="/resources">Resources</NavLink>
</p>
</div>
</div>
</div> </div>
</div> </div>
{/*<SideStatistics />*/} {/*<SideStatistics />*/}
+32 -13
View File
@@ -3,12 +3,12 @@ import Detail from "./popoutcomponent/Detail";
import ModalCom from "../Helpers/ModalCom"; import ModalCom from "../Helpers/ModalCom";
import InputCom from "../Helpers/Inputs/InputCom/index"; import InputCom from "../Helpers/Inputs/InputCom/index";
import SiteService from "../../services/SiteService"; import SiteService from "../../services/SiteService";
import { Form, Formik, Field } from "formik"; import { Form, Formik, Field, ErrorMessage } from "formik";
import * as Yup from "yup"; import * as Yup from "yup";
import LoadingSpinner from "../Spinners/LoadingSpinner"; import LoadingSpinner from "../Spinners/LoadingSpinner";
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
family: Yup.string().required("THis is required "), family: Yup.string().required("This is required "),
public: Yup.string(), public: Yup.string(),
individual: Yup.string() individual: Yup.string()
.email("Invalid email format") .email("Invalid email format")
@@ -68,18 +68,29 @@ function JobListPopout({ details, onClose, situation }) {
group: "", group: "",
}; };
let [inputs, setInputs] = useState({}); let [textArea, setTextArea] = useState(details?.job_detail);
const [errMsg, setErrMsg] = useState("")
const handleInputChange = ({ target: { name, value } }) => { const handleInputChange = ({ target: { value } }) => {
setInputs((prev) => ({ ...prev, [name]: value })); setTextArea(value);
}; };
const errorHandler = ({target: {name}}) => {
}
const jobFieldHandler = async (values, helpers) => { const jobFieldHandler = async (values, helpers) => {
let { job_id, job_uid, job_detail } = details; let { job_id, job_uid } = details;
if(!textArea) {
setErrMsg("delivery detail is required!")
return
}
let jobReq = { let jobReq = {
job_id, job_id,
job_uid, job_uid,
job_description: job_detail job_description: textArea
}; };
let reqData; let reqData;
@@ -119,16 +130,19 @@ function JobListPopout({ details, onClose, situation }) {
assign_mode: 110033, assign_mode: 110033,
}; };
setLoader({ jobFields: { group: true } }); setLoader({ jobFields: { group: true } });
} else {
setErrMsg("err herre")
return
} }
try { try {
const res = await apiCall.assignJobTask(reqData); const res = await apiCall.assignJobTask(reqData);
let { data } = await res; let { data } = await res;
setLoader({ member: false, jobFields: false }); setLoader({ jobFields: false });
onClose(); onClose();
throw new Response(data); throw new Response(data);
} catch (error) { } catch (error) {
setLoader({ member: false, jobFields: false }); setLoader({ jobFields: false });
throw new Error(error); throw new Error(error);
} }
}; };
@@ -200,11 +214,11 @@ function JobListPopout({ details, onClose, situation }) {
<textarea <textarea
className={`p-1 w-full text-sm text-slate-900 outline-none border border-slate-300 rounded-md`} className={`p-1 w-full text-sm text-slate-900 outline-none border border-slate-300 rounded-md`}
rows="5" rows="5"
name="details"
style={{ resize: "none" }} style={{ resize: "none" }}
value={details.job_detail} value={textArea}
onChange={handleInputChange} onChange={handleInputChange}
/> />
{/* <p>{errMsg}</p> */}
</div> </div>
</div> </div>
@@ -226,9 +240,10 @@ function JobListPopout({ details, onClose, situation }) {
value={props?.values.family} value={props?.values.family}
data={familyList} data={familyList}
btnText="Assign to family" btnText="Assign to family"
optionText="select family" optionText="Select Family"
loader={loader?.jobFields.family} loader={loader?.jobFields.family}
/> />
{/* <p>{errMsg}</p> */}
</Form> </Form>
); );
}} }}
@@ -250,9 +265,10 @@ function JobListPopout({ details, onClose, situation }) {
value={props?.values.public} value={props?.values.public}
data={publicArray} data={publicArray}
btnText="Show Task to Public" btnText="Show Task to Public"
optionText="select duration" optionText="Select Duration"
loader={loader?.jobFields.public} loader={loader?.jobFields.public}
/> />
{/* <p>{errMsg}</p> */}
</Form> </Form>
); );
}} }}
@@ -277,6 +293,7 @@ function JobListPopout({ details, onClose, situation }) {
btnText="Send Offer to Individual" btnText="Send Offer to Individual"
loader={loader?.jobFields.individual} loader={loader?.jobFields.individual}
/> />
{/* <p>{errMsg}</p> */}
</Form> </Form>
); );
}} }}
@@ -300,10 +317,12 @@ function JobListPopout({ details, onClose, situation }) {
optionText="Group" optionText="Group"
loader={loader?.jobFields.group} loader={loader?.jobFields.group}
/> />
{/* <p>{errMsg}</p> */}
</Form> </Form>
); );
}} }}
</Formik> </Formik>
</div> </div>
{/* END OF ACTION SECTION */} {/* END OF ACTION SECTION */}
</div> </div>
+4 -13
View File
@@ -33,10 +33,6 @@ function OfferJobPopout({details, onClose, situation}) {
setRequestStatus({loading: true, status: false, message: '', trigger: 'reject'}) setRequestStatus({loading: true, status: false, message: '', trigger: 'reject'})
reqData.offer_result = 333 reqData.offer_result = 333
} }
if(name == 'cancel'){
setRequestStatus({loading: true, status: false, message: '', trigger: 'cancel'})
reqData.offer_result = 222
}
// API CALL // API CALL
apiUrl.offersResponse(reqData).then(response => { apiUrl.offersResponse(reqData).then(response => {
@@ -191,19 +187,14 @@ function OfferJobPopout({details, onClose, situation}) {
{/* close button */} {/* close button */}
<div className="p-6 flex justify-end"> <div className="p-6 flex justify-end">
{requestStatus.loading && requestStatus.trigger == 'cancel' ? <button
<LoadingSpinner size={8} color='sky-blue' /> onClick={onClose}
:
<button
onClick={handleOffer}
disabled={requestStatus.loading} disabled={requestStatus.loading}
type="button" type="button"
name='cancel' className=" border-gradient text-18 tracking-wide px-2 py-2 rounded-full"
className="border border-red-500 text-red-500 text-18 tracking-wide px-2 py-2 rounded-full"
> >
Cancel <span className="text-gradient">Close</span>
</button> </button>
}
</div> </div>
{/* end of close button */} {/* end of close button */}
</div> </div>
+4 -2
View File
@@ -9,7 +9,7 @@ export default function MyTaskPage() {
const {jobListTable} = useSelector((state) => state.tableReload) const {jobListTable} = useSelector((state) => state.tableReload)
const [MyActiveJobList, setMyActiveJobList] = useState({loading: true, status:false, data:[]}); const [MyActiveJobList, setMyActiveJobList] = useState({loading: true, status:false, data:[]});
const [MyActiveOffersList, setMyActiveOffersList] = useState([]); const [MyActiveOffersList, setMyActiveOffersList] = useState({loading: true, status:false, data:[]});
const api = new usersService(); const api = new usersService();
const commonHeadData =()=>{ const commonHeadData =()=>{
console.log("COMMON HEAD DATA ----------------=====---------------------"); console.log("COMMON HEAD DATA ----------------=====---------------------");
@@ -26,10 +26,12 @@ export default function MyTaskPage() {
} }
}; };
const getMyActiveOffersList = async () => { const getMyActiveOffersList = async () => {
setMyActiveOffersList({loading: true, status:false, data:[]});
try { try {
const res = await api.getOffersList(); const res = await api.getOffersList();
setMyActiveOffersList(res.data); setMyActiveOffersList({loading: false, status:true, data:res.data.result_list});
} catch (error) { } catch (error) {
setMyActiveOffersList({loading: false, status:false, data:[]});
console.log("Error getting offers"); console.log("Error getting offers");
} }
}; };