Compare commits

...

17 Commits

Author SHA1 Message Date
victorAnumudu 44a055e76b Merge master into default-icon 2023-11-07 14:22:49 +01:00
victorAnumudu 67c1b2aaa0 placed default job icons 2023-11-07 14:20:19 +01:00
ameye 313cfc1f28 Merge branch 'edit-job-bug-fix' of WrenchBoard/Users-Wrench into master 2023-11-07 12:40:34 +00:00
victorAnumudu 59a7f110be Fixed save job bug 2023-11-07 07:35:40 +01:00
ameye 52e8447f6a Merge branch 'Server-path-added' of WrenchBoard/Users-Wrench into master 2023-11-06 23:33:16 +00:00
Chief Bube c60e28928a changed to job_uid 2023-11-06 15:29:23 -08:00
ameye 58357fd501 Merge branch 'Server-path-added' of WrenchBoard/Users-Wrench into master 2023-11-06 21:15:03 +00:00
Chief Bube 5402980d6c Chnged path from profile to job 2023-11-06 11:15:11 -08:00
ameye 32c7b3d513 Merge branch 'Server-path-added' of WrenchBoard/Users-Wrench into master 2023-11-06 18:56:32 +00:00
Chief Bube a30b22170d Added images server path 2023-11-06 10:53:26 -08:00
ameye e3314b0460 Merge branch 'job-image-upload-fix' of WrenchBoard/Users-Wrench into master 2023-11-06 18:01:42 +00:00
victorAnumudu 86eb1f16bb fixed job image upload 2023-11-06 19:00:28 +01:00
ameye 5660d74e75 Merge branch 'job-image-upload' of WrenchBoard/Users-Wrench into master 2023-11-06 15:48:53 +00:00
victorAnumudu 612016784d added job image upload API 2023-11-06 16:34:41 +01:00
ameye 988aadfb7e Merge branch 'Server-path-added' of WrenchBoard/Users-Wrench into master 2023-11-06 14:28:14 +00:00
ameye 54851b5f77 Merge branch 'family-image-bug' of WrenchBoard/Users-Wrench into master 2023-11-06 14:27:50 +00:00
Chief Bube c920c35a9c image now works 2023-11-06 06:15:12 -08:00
9 changed files with 131 additions and 33 deletions
+7 -2
View File
@@ -1,5 +1,4 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import dataImage2 from "../../assets/images/taskbanners/default.jpg";
import { PriceFormatter } from "../Helpers/PriceFormatter"; import { PriceFormatter } from "../Helpers/PriceFormatter";
import MarketPopUp from "../MarketPlace/PopUp/MarketPopUp"; import MarketPopUp from "../MarketPlace/PopUp/MarketPopUp";
@@ -8,6 +7,7 @@ export default function AvailableJobsCard({
datas, datas,
hidden = false, hidden = false,
contentDisplay, contentDisplay,
image_server,
}) { }) {
//debugger; //debugger;
const [marketPopUp, setMarketPopUp] = useState({ show: false, data: {} }); const [marketPopUp, setMarketPopUp] = useState({ show: false, data: {} });
@@ -23,6 +23,11 @@ export default function AvailableJobsCard({
const imagePath = require(`../../assets/images/${datas.thumbnil}`); // Replace with your directory path for local images const imagePath = require(`../../assets/images/${datas.thumbnil}`); // Replace with your directory path for local images
setImageUrl(imagePath); setImageUrl(imagePath);
}, []); }, []);
const image = `${image_server}${localStorage.getItem(
"session_token"
)}/job/${datas.job_uid}`;
return ( return (
<> <>
{contentDisplay == "grid" ? ( {contentDisplay == "grid" ? (
@@ -131,7 +136,7 @@ export default function AvailableJobsCard({
<div className="card-style-two w-full p-8 my-2 flex items-center gap-4 bg-white dark:bg-dark-white rounded-2xl section-shadow"> <div className="card-style-two w-full p-8 my-2 flex items-center gap-4 bg-white dark:bg-dark-white rounded-2xl section-shadow">
<div className="flex gap-5 items-center w-full"> <div className="flex gap-5 items-center w-full">
<div className="w-full h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1] min-w-[60px] max-w-[60px]"> <div className="w-full h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1] min-w-[60px] max-w-[60px]">
<img src={dataImage2} alt="data" className="w-full h-full" /> <img src={image} alt="data" className="w-full h-full" />
</div> </div>
<div className="flex flex-col flex-[0.9]"> <div className="flex flex-col flex-[0.9]">
<h1 <h1
@@ -8,6 +8,7 @@ import SelectBox from "../Helpers/SelectBox";
export default function MainSection({ export default function MainSection({
className, className,
marketPlaceProduct, marketPlaceProduct,
image_server,
categories, categories,
}) { }) {
// Creating All cart.. // Creating All cart..
@@ -110,6 +111,7 @@ export default function MainSection({
{({ datas }) => ( {({ datas }) => (
<AvailableJobsCard <AvailableJobsCard
contentDisplay={contentDisplay} contentDisplay={contentDisplay}
image_server={image_server}
key={datas.id} key={datas.id}
datas={datas} datas={datas}
/> />
+2
View File
@@ -7,6 +7,7 @@ export default function MarketPlace({ commonHeadData }) {
let { jobLists } = useSelector((state) => state.jobLists); let { jobLists } = useSelector((state) => state.jobLists);
const marketData = jobLists?.result_list; const marketData = jobLists?.result_list;
const categories = jobLists?.categories; const categories = jobLists?.categories;
const image_server = jobLists?.session_image_server;
return ( return (
<> <>
@@ -15,6 +16,7 @@ export default function MarketPlace({ commonHeadData }) {
<MainSection <MainSection
marketPlaceProduct={marketData} marketPlaceProduct={marketData}
categories={categories} categories={categories}
image_server={image_server}
className="mb-10" className="mb-10"
/> />
</Layout> </Layout>
@@ -6,6 +6,7 @@ import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList"; import PaginatedList from "../Pagination/PaginatedList";
export default function MyActiveJobTable({ MyJobList, className }) { export default function MyActiveJobTable({ MyJobList, className }) {
const navigate = useNavigate(); const navigate = useNavigate();
let { pathname } = useLocation(); let { pathname } = useLocation();
@@ -44,6 +45,7 @@ export default function MyActiveJobTable({ MyJobList, className }) {
value?.currency_code, value?.currency_code,
value?.currency value?.currency
); );
let image = `${MyJobList.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
return ( return (
<tr <tr
key={index} key={index}
@@ -51,11 +53,9 @@ export default function MyActiveJobTable({ MyJobList, className }) {
> >
<td className=" py-4"> <td className=" py-4">
<div className="flex space-x-2 items-center w-full"> <div className="flex space-x-2 items-center w-full">
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center"> <div className="max-w-[60px] max-h-[60px] min-w-[60px] min-h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<img <img
src={localImgLoad( src={image}
`images/taskbanners/${value.banner}`
)}
alt="data" alt="data"
className="w-full h-full rounded-full" className="w-full h-full rounded-full"
/> />
+30 -8
View File
@@ -11,8 +11,8 @@ import PaginatedList from "../Pagination/PaginatedList";
import EditJobPopOut from "../jobPopout/EditJobPopout"; import EditJobPopOut from "../jobPopout/EditJobPopout";
import { PriceFormatter } from "../Helpers/PriceFormatter"; import { PriceFormatter } from "../Helpers/PriceFormatter";
import EditIcon from '../../assets/images/icon-edit.svg' import EditIcon from "../../assets/images/icon-edit.svg";
import DeleteIcon from '../../assets/images/icon-delete.svg' import DeleteIcon from "../../assets/images/icon-delete.svg";
import localImgLoad from "../../lib/localImgLoad"; import localImgLoad from "../../lib/localImgLoad";
export default function MyJobTable({ MyJobList, reloadJobList, className }) { export default function MyJobTable({ MyJobList, reloadJobList, className }) {
@@ -101,12 +101,17 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
} }
}; };
const JobListItem = ({ value, index }) => { const JobListItem = ({ value, index, image_server }) => {
let thePrice = PriceFormatter( let thePrice = PriceFormatter(
value?.price * 0.01, value?.price * 0.01,
value?.currency_code, value?.currency_code,
value?.currency value?.currency
); );
const image = `${image_server}${localStorage.getItem(
"session_token"
)}/job/${value.job_uid}`;
return ( return (
<tr <tr
key={index} key={index}
@@ -116,7 +121,11 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
<div className="sm:flex sm:space-x-2 sm:justify-between sm:items-center job-items"> <div className="sm:flex sm:space-x-2 sm:justify-between sm:items-center job-items">
<div className="flex space-x-2 items-center job-items w-full"> <div className="flex space-x-2 items-center job-items w-full">
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center"> <div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<img src={localImgLoad(`images/taskbanners/${value.banner ? value.banner : 'default.jpg'}`)} alt="data" className="w-full h-full rounded-full" /> <img
src={image}
alt="data"
className="w-full h-full rounded-full"
/>
</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"> <h1 className="font-bold text-xl text-dark-gray dark:text-white">
@@ -147,7 +156,11 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
}); });
}} }}
> >
<img className="w-[21px] h-[21px]" src={DeleteIcon} alt='delete-icon' /> <img
className="w-[21px] h-[21px]"
src={DeleteIcon}
alt="delete-icon"
/>
</button> </button>
<div className="mx-[4px] h-full w-[1px] bg-black dark:bg-dark-gray"></div> <div className="mx-[4px] h-full w-[1px] bg-black dark:bg-dark-gray"></div>
<button <button
@@ -160,7 +173,11 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
}); });
}} }}
> >
<img className="w-[21px] h-[21px]" src={EditIcon} alt='edit-icon' /> <img
className="w-[21px] h-[21px]"
src={EditIcon}
alt="edit-icon"
/>
<span className="text-sm text-sky-blue">Edit</span> <span className="text-sm text-sky-blue">Edit</span>
</button> </button>
</div> </div>
@@ -193,7 +210,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide"> <h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
{filterCategories[selectedCategory]} Jobs {filterCategories[selectedCategory]} Jobs
</h1> </h1>
</div> </div>
<SelectBox <SelectBox
action={handleSetCategory} action={handleSetCategory}
datas={Object.values(filterCategories)} datas={Object.values(filterCategories)}
@@ -213,7 +230,12 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
MyJobList.data?.result_list.length > 0 ? ( MyJobList.data?.result_list.length > 0 ? (
filteredCurrentJobList?.length ? ( filteredCurrentJobList?.length ? (
filteredCurrentJobList.map((value, index) => ( filteredCurrentJobList.map((value, index) => (
<JobListItem index={index} key={index} value={value} /> <JobListItem
index={index}
key={index}
value={value}
image_server={MyJobList?.data.session_image_server}
/>
)) ))
) : ( ) : (
<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">
@@ -8,6 +8,7 @@ import localImgLoad from "../../lib/localImgLoad";
export default function MyPendingJobTable({ MyJobList, className }) { export default function MyPendingJobTable({ MyJobList, className }) {
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
const [currentPage, setCurrentPage] = useState(0); const [currentPage, setCurrentPage] = useState(0);
@@ -45,6 +46,7 @@ export default function MyPendingJobTable({ MyJobList, className }) {
value?.currency_code, value?.currency_code,
value?.currency value?.currency
); );
let image = `${MyJobList.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
return ( return (
<tr <tr
key={index} key={index}
@@ -54,7 +56,7 @@ export default function MyPendingJobTable({ MyJobList, className }) {
<div className="flex space-x-2 items-center w-full"> <div className="flex space-x-2 items-center w-full">
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center"> <div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<img <img
src={localImgLoad(`images/taskbanners/${value.banner || "default.jpg"}`)} src={image}
alt="data" alt="data"
className="w-full h-full rounded-full" className="w-full h-full rounded-full"
/> />
@@ -44,7 +44,7 @@ export default function MyWaitingJobTable({ MyJobList, className }) {
value?.currency_code, value?.currency_code,
value?.currency value?.currency
); );
let image = value.banner ? value.banner : 'default.jpg' let image = `${MyJobList.session_image_server}${localStorage.getItem('session_token')}/job/${value.offer_uid}`
return ( return (
<tr <tr
key={index} key={index}
@@ -52,9 +52,9 @@ export default function MyWaitingJobTable({ MyJobList, className }) {
> >
<td className=" py-4"> <td className=" py-4">
<div className="flex space-x-2 items-center w-full"> <div className="flex space-x-2 items-center w-full">
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center"> <div className="max-w-[60px] max-h-[60px] min-w-[60px] min-h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<img <img
src={localImgLoad(`images/taskbanners/${image}`)} src={image}
alt="data" alt="data"
className="w-full h-full rounded-full" className="w-full h-full rounded-full"
/> />
@@ -137,15 +137,17 @@ export default function PersonalInfoTab({
if (e.target.value !== "") { if (e.target.value !== "") {
const imgReader = new FileReader(); const imgReader = new FileReader();
imgReader.onload = (event) => { imgReader.onload = (event) => {
let base64Img = imgReader.result.split(",")[1];
let reqData = { let reqData = {
// PAYLOAD FOR API CALL // PAYLOAD FOR API CALL
file_name: uploadedFile?.name, file_name: uploadedFile?.name,
file_size: uploadedFile?.size, file_size: uploadedFile?.size,
file_type: uploadedFile?.type?.split("/")[0]?.toLowerCase(), file_type: uploadedFile?.type?.split("/")[0]?.toLowerCase(),
file_data: event?.target?.result, file_data: base64Img,
msg_type: "FILE", msg_type: "FILE",
action: 11300, action: 11300,
}; };
setUploadStatus({ setUploadStatus({
loading: true, loading: true,
status: false, status: false,
+77 -14
View File
@@ -1,6 +1,6 @@
import { Field, Form, Formik } from "formik"; import { Field, Form, Formik } from "formik";
import React, { useCallback, useMemo, useState } from "react"; import React, { useCallback, useMemo, useState } from "react";
import { useDispatch } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import * as Yup from "yup"; import * as Yup from "yup";
import usersService from "../../services/UsersService"; import usersService from "../../services/UsersService";
@@ -51,18 +51,13 @@ const EditJobPopOut = ({
categories, categories,
}) => { }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { userDetails } = useSelector((state) => state.userDetails);
const uploadedImage = `${userDetails.session_image_server}${localStorage.getItem('session_token')}/job/${details?.job_uid}`
const [taskImage, setTaskImage] = useState('') const [taskImage, setTaskImage] = useState(uploadedImage)
const changeTaskImage = (e) => { let [uploadStatus, setUploadStatus] = useState({loading: false, status: false, message:''}) // HOLDS STATE FOR UPLOAD PROFILE PICTURE STATUS
if (e.target.value !== "") {
const imgReader = new FileReader();
imgReader.onload = (event) => {
setTaskImage(event.target.result);
};
imgReader.readAsDataURL(e.target.files[0]);
}
}
let [requestStatus, setRequestStatus] = useState({ let [requestStatus, setRequestStatus] = useState({
loading: false, loading: false,
@@ -117,6 +112,66 @@ const EditJobPopOut = ({
[jobApi, navigate, onClose, details] [jobApi, navigate, onClose, details]
); );
const taskImgChangeHandler = (e) => {
setUploadStatus({loading: false, status: false, message:''})
let acceptedFormat = ["jpeg", "jpg", "png", "bmp", "gif"] // ARRAY OF SUPPORTED FORMATS
let uploadedFile = e.target.files[0] //UPLOADED FILE
const fileFormat = uploadedFile?.type?.split("/")[1]?.toLowerCase();
if(!acceptedFormat.includes(fileFormat)){ //CHECKING FOR CORRECT UPLOAD FORMAT
const msg = `Please select ${acceptedFormat.slice(0, -1).join(', ')} or ${acceptedFormat.slice(-1)}`;
setUploadStatus({loading: false, status: false, message:msg})
return setTimeout(()=>{
// profileImgInput.current.value = '' // clear the input
setUploadStatus({loading: false, status: false, message:''})
},5000)
}
if(uploadedFile.size > 5*1048576){ // CHECKING FOR CORRECT FILE SIZE
setUploadStatus({loading: false, status: false, message:'File must not exceed 5MB'})
return setTimeout(()=>{
// profileImgInput.current.value = '' // clear the input
setUploadStatus({loading: false, status: false, message:''})
},5000)
}
if (e.target.value !== "") {
const imgReader = new FileReader();
imgReader.onload = (event) => {
let base64Img = imgReader.result.split(",")[1];
let reqData = { // PAYLOAD FOR API CALL
job_uid: details?.job_uid,
file_name: uploadedFile?.name.slice(0,19),
file_size: uploadedFile?.size,
file_type: uploadedFile?.type?.split("/")[0]?.toLowerCase(),
file_data: base64Img,
msg_type: 'FILE',
action: 11303
}
setUploadStatus({loading: true, status: false, message:'Loading...'})
jobApi.sendFiles(reqData).then(res=>{
if(res.status != 200 || res.data.internal_return < 0){
return setUploadStatus({loading: false, status: false, message: 'Something went wrong, try again'})
}
setUploadStatus({loading: false, status: true, message: 'Uploaded successfully'})
setTaskImage(event.target.result);
setTimeout(() => {
dispatch(tableReload({ type: "JOBTABLE" }));
navigate("/myjobs", { replace: true });
onClose();
}, 1000);
}).catch(error=>{
setUploadStatus({loading: false, status: false, message: 'Network error, try again'})
}).finally(()=>{
setTimeout(()=>{
setUploadStatus({loading: false, status: false, message: ''})
},5000)
})
};
imgReader.readAsDataURL(e.target.files[0]);
}
};
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">
@@ -270,7 +325,7 @@ const EditJobPopOut = ({
role="group" role="group"
aria-labelledby="checked-group" aria-labelledby="checked-group"
> >
{Object.entries(categories).map(([key, value]) => ( {categories && Object.entries(categories)?.map(([key, value]) => (
<label <label
key={key} key={key}
className="flex gap-1 w-full items-center" className="flex gap-1 w-full items-center"
@@ -299,12 +354,12 @@ const EditJobPopOut = ({
className="hidden" className="hidden"
type="file" type="file"
accept="image/*" accept="image/*"
onChange={changeTaskImage} onChange={taskImgChangeHandler}
/> />
{taskImage ? {taskImage ?
<div className="w-full absolute -top-5"> <div className="w-full absolute -top-5">
<img src={taskImage} className="max-h-[150px] min-h-[150px] w-full object-cover" alt="uplaoded task image" /> <img src={taskImage} className="max-h-[150px] min-h-[150px] w-full object-cover" alt="uplaoded task image" />
<span onClick={()=>setTaskImage('')} className="p-2 absolute text-sm top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white/20 hover:bg-white/70 hover:shadow-md transition-all duration-500 cursor-pointer text-slate-800">Remove Image</span> <span onClick={()=>setTaskImage('')} className="p-2 absolute text-sm top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white/80 hover:bg-white hover:shadow-md transition-all duration-500 cursor-pointer text-slate-800">Remove Image</span>
</div> </div>
: :
<label <label
@@ -344,6 +399,7 @@ const EditJobPopOut = ({
<option value="">Select Duration</option> <option value="">Select Duration</option>
{publicArray.map(({ name, duration }, idx) => ( {publicArray.map(({ name, duration }, idx) => (
<option <option
key={duration}
className="text-slate-500 text-lg" className="text-slate-500 text-lg"
value={duration} value={duration}
> >
@@ -377,6 +433,12 @@ const EditJobPopOut = ({
))} ))}
{/* End of error or success display */} {/* End of error or success display */}
{/* DISPLAYS TASK IMAGE UPLOADING STATUS */}
<div className="w-full">
{uploadStatus.message && !uploadStatus.loading && <p className={`text-center ${uploadStatus.status ? 'text-green-500':'text-red-500'}`}>{uploadStatus.message}</p>}
{uploadStatus.loading && <p className="text-center">{uploadStatus.message}</p>}
</div>
<div className="w-full border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center"> <div className="w-full border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
<div className="flex items-center space-x-4 mr-2 mt-2"> <div className="flex items-center space-x-4 mr-2 mt-2">
{requestStatus.loading ? ( {requestStatus.loading ? (
@@ -386,6 +448,7 @@ const EditJobPopOut = ({
type="submit" type="submit"
className="w-[120px] h-[40px] flex justify-center items-center btn-gradient text-base rounded-full text-white" className="w-[120px] h-[40px] 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' // className='w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white'
disabled={requestStatus.loading || uploadStatus.loading}
> >
Save Save
</button> </button>