Merge branch 'Server-path-added' of WrenchBoard/Users-Wrench into master

This commit is contained in:
2023-11-29 14:32:03 +00:00
committed by Gogs
2 changed files with 230 additions and 183 deletions
+74 -70
View File
@@ -1,6 +1,5 @@
import { import {
validationSchema as VS, validationSchema as VS,
getWalletDetail,
useDispatch, useDispatch,
useSelector, useSelector,
usersService, usersService,
@@ -20,21 +19,14 @@ const validationSchema = VS;
function AddJob({ popUpHandler, categories }) { function AddJob({ popUpHandler, categories }) {
const ApiCall = new usersService(); const ApiCall = new usersService();
const { walletDetails } = useSelector((state) => state.walletDetails); const { walletDetails } = useSelector((state) => state.walletDetails);
const { userDetails } = useSelector((state) => state.userDetails);
let dispatch = useDispatch(); let dispatch = useDispatch();
const getWalletDetails = getWalletDetail(
userDetails.country,
walletDetails
);
const walletAmount = getWalletDetails; // GETTING USER BALANCE BASED ON COUNTRY SELECTED
const initialValues = { ...IV, country: walletAmount?.description };
const [requestStatus, setRequestStatus] = useState(initialReqState); // Holds state when submit button is pressed const [requestStatus, setRequestStatus] = useState(initialReqState); // Holds state when submit button is pressed
const handleAddJob = async (values, helpers) => { const handleAddJob = async (values, helpers) => {
const reqData = { const reqData = {
country: walletAmount?.country, country: values?.country,
price: Number(values.price) * 100, price: Number(values.price) * 100,
title: values?.title, title: values?.title,
description: values?.description, description: values?.description,
@@ -80,18 +72,10 @@ function AddJob({ popUpHandler, categories }) {
} }
}; };
// Check if the user is using iOS
const isIOS = /MacIntel|MacPPC/.test(navigator.platform) && !window.MSStream;
// Check if the user is using Windows
const isWindows = /Windows/.test(navigator.userAgent);
// console.log(isIOS, isWindows, navigator);
return ( return (
<div className="add-job p-5 w-full bg-white dark:bg-dark-white dark:text-white rounded-md flex flex-col justify-between"> <div className="add-job p-5 w-full bg-white dark:bg-dark-white dark:text-white rounded-md flex flex-col justify-between">
<Formik <Formik
initialValues={initialValues} initialValues={IV}
validationSchema={validationSchema} validationSchema={validationSchema}
onSubmit={handleAddJob} onSubmit={handleAddJob}
> >
@@ -103,24 +87,50 @@ function AddJob({ popUpHandler, categories }) {
{/* inputs starts here */} {/* inputs starts here */}
<div className="xl:flex xl:space-x-7 mb-[5px]"> <div className="xl:flex xl:space-x-7 mb-[5px]">
<div className="field w-full mb-6 xl:mb-0"> <div className="field w-full mb-6 xl:mb-0">
<InputCom <label
fieldClass="px-6 cursor-default" htmlFor="country"
label="Currency" className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex item-center gap-1"
labelClass="tracking-wide" >
// inputBg="bg-slate-100" Currency
// inputClass="input-curve border border-light-purple" {props.errors.country && props.touched.country && (
type="text" <span className="text-[12px] text-red-500">
{props.errors.country}
</span>
)}
</label>
<select
id="country"
name="country" name="country"
value={props.values.country} value={props.values.country}
inputHandler={props.handleChange} 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`}
blurHandler={props.handleBlur} onChange={props.handleChange}
disable={true} onBlur={props.handleBlur}
error={ >
props.errors.country && {walletDetails?.loading ? (
props.touched.country && <option className="text-slate-500 text-lg" value="">
props.errors.country Loading...
} </option>
/> ) : walletDetails.data.length ? (
<>
<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>
))}
</>
) : (
<option className="text-slate-500 text-lg" value="">
No Options Found! Try Again
</option>
)}
</select>
</div> </div>
{/* Price */} {/* Price */}
@@ -187,7 +197,7 @@ function AddJob({ popUpHandler, categories }) {
<div className="sm:w-[60%] w-full"> <div className="sm:w-[60%] w-full">
<label <label
htmlFor="Job Delivery Details" htmlFor="Job Delivery Details"
className='input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1' className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1"
> >
Job Delivery Details Job Delivery Details
{props.errors.job_detail && {props.errors.job_detail &&
@@ -210,52 +220,46 @@ function AddJob({ popUpHandler, categories }) {
</div> </div>
<div className="sm:w-[35%] w-full"> <div className="sm:w-[35%] w-full">
<label <div
htmlFor="Job Categories" htmlFor="Job Categories"
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex item-center gap-1" className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'
id="checked-group"
> >
Categories ({`multiple categories - ${isIOS ? "⌘" : isWindows ? "Ctrl+" : ""}`}) Categories
{props.errors.category && props.touched.category && ( </div>
<span className="text-[12px] text-red-500"> <div
{props.errors.category} className="sm:flex-col flex flex-wrap px-3 mt-3"
</span> role="group"
)} aria-labelledby="checked-group"
</label>
<select
id="category"
name="category"
value={props.values.category}
className={`input-field p-2 mt-1 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-[4.7rem] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none border`}
onChange={props.handleChange}
onBlur={props.handleBlur}
multiple
> >
{walletDetails?.loading ? ( {categories ? (
<option className="text-slate-500 text-lg" value="">
Loading...
</option>
) : walletDetails.data.length ? (
<> <>
{/* <option className="text-slate-500 text-lg" value="">
Select a Category
</option> */}
{Object?.entries(categories).map(([key, value]) => ( {Object?.entries(categories).map(([key, value]) => (
<option <label
key={key} key={key}
className="text-slate-500 " className="flex gap-1 w-full items-center"
value={key}
> >
{value} <Field
</option> type="checkbox"
name="category"
value={key}
/>
<span className="text-[13.975px]">{value}</span>
</label>
))} ))}
</> </>
) : ( ) : (
<option className="text-slate-500 text-lg" value=""> <label className="flex gap-1 w-full items-center">
No Options Found! Try Again <Field type="checkbox" name="category" />
</option> <span className="text-[13.975px]">null</span>
</label>
)} )}
</select> <span className="h-5 text-sm italic text-[#cf3917]">
{props.errors.category &&
props.touched.category &&
"please select a category"}
</span>
</div>
</div> </div>
</div> </div>
+156 -113
View File
@@ -54,12 +54,17 @@ const EditJobPopOut = ({
const { userDetails } = useSelector((state) => state.userDetails); const { userDetails } = useSelector((state) => state.userDetails);
const { walletDetails } = useSelector((state) => state.walletDetails); const { walletDetails } = useSelector((state) => state.walletDetails);
const uploadedImage = `${
const uploadedImage = `${userDetails.session_image_server}${localStorage.getItem('session_token')}/job/${details?.job_uid}` userDetails.session_image_server
}${localStorage.getItem("session_token")}/job/${details?.job_uid}`;
const [taskImage, setTaskImage] = useState(uploadedImage) const [taskImage, setTaskImage] = useState(uploadedImage);
let [uploadStatus, setUploadStatus] = useState({loading: false, status: false, message:''}) // HOLDS STATE FOR UPLOAD PROFILE PICTURE STATUS let [uploadStatus, setUploadStatus] = useState({
loading: false,
status: false,
message: "",
}); // HOLDS STATE FOR UPLOAD PROFILE PICTURE STATUS
let [requestStatus, setRequestStatus] = useState({ let [requestStatus, setRequestStatus] = useState({
loading: false, loading: false,
@@ -115,70 +120,99 @@ const EditJobPopOut = ({
); );
const taskImgChangeHandler = (e) => { const taskImgChangeHandler = (e) => {
setUploadStatus({loading: false, status: false, message:''}) setUploadStatus({ loading: false, status: false, message: "" });
let acceptedFormat = ["jpeg", "jpg", "png", "bmp", "gif"] // ARRAY OF SUPPORTED FORMATS let acceptedFormat = ["jpeg", "jpg", "png", "bmp", "gif"]; // ARRAY OF SUPPORTED FORMATS
let uploadedFile = e.target.files[0] //UPLOADED FILE let uploadedFile = e.target.files[0]; //UPLOADED FILE
const fileFormat = uploadedFile?.type?.split("/")[1]?.toLowerCase(); const fileFormat = uploadedFile?.type?.split("/")[1]?.toLowerCase();
if(!acceptedFormat.includes(fileFormat)){ //CHECKING FOR CORRECT UPLOAD FORMAT if (!acceptedFormat.includes(fileFormat)) {
const msg = `Please select ${acceptedFormat.slice(0, -1).join(', ')} or ${acceptedFormat.slice(-1)}`; //CHECKING FOR CORRECT UPLOAD FORMAT
setUploadStatus({loading: false, status: false, message:msg}) const msg = `Please select ${acceptedFormat
return setTimeout(()=>{ .slice(0, -1)
.join(", ")} or ${acceptedFormat.slice(-1)}`;
setUploadStatus({ loading: false, status: false, message: msg });
return setTimeout(() => {
// profileImgInput.current.value = '' // clear the input // profileImgInput.current.value = '' // clear the input
setUploadStatus({loading: false, status: false, message:''}) setUploadStatus({ loading: false, status: false, message: "" });
},5000) }, 5000);
} }
if(uploadedFile.size > 5*1048576){ // CHECKING FOR CORRECT FILE SIZE if (uploadedFile.size > 5 * 1048576) {
setUploadStatus({loading: false, status: false, message:'File must not exceed 5MB'}) // CHECKING FOR CORRECT FILE SIZE
return setTimeout(()=>{ setUploadStatus({
loading: false,
status: false,
message: "File must not exceed 5MB",
});
return setTimeout(() => {
// profileImgInput.current.value = '' // clear the input // profileImgInput.current.value = '' // clear the input
setUploadStatus({loading: false, status: false, message:''}) setUploadStatus({ loading: false, status: false, message: "" });
},5000) }, 5000);
} }
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 base64Img = imgReader.result.split(",")[1];
let reqData = { // PAYLOAD FOR API CALL let reqData = {
// PAYLOAD FOR API CALL
job_uid: details?.job_uid, job_uid: details?.job_uid,
file_name: uploadedFile?.name.slice(0,19), file_name: uploadedFile?.name.slice(0, 19),
file_size: uploadedFile?.size, file_size: uploadedFile?.size,
file_type: uploadedFile?.type?.split("/")[0]?.toLowerCase(), file_type: uploadedFile?.type?.split("/")[0]?.toLowerCase(),
file_data: base64Img, file_data: base64Img,
msg_type: 'FILE', msg_type: "FILE",
action: 11303 action: 11303,
} };
setUploadStatus({loading: true, status: false, message:'Loading...'}) setUploadStatus({
jobApi.sendFiles(reqData).then(res=>{ loading: true,
if(res.status != 200 || res.data.internal_return < 0){ status: false,
return setUploadStatus({loading: false, status: false, message: 'Something went wrong, try again'}) message: "Loading...",
} });
setUploadStatus({loading: false, status: true, message: 'Uploaded successfully'}) jobApi
setTaskImage(event.target.result); .sendFiles(reqData)
setTimeout(() => { .then((res) => {
dispatch(tableReload({ type: "JOBTABLE" })); if (res.status != 200 || res.data.internal_return < 0) {
navigate("/myjobs", { replace: true }); return setUploadStatus({
onClose(); loading: false,
}, 1000); status: false,
}).catch(error=>{ message: "Something went wrong, try again",
setUploadStatus({loading: false, status: false, message: 'Network error, try again'}) });
}).finally(()=>{ }
setTimeout(()=>{ setUploadStatus({
setUploadStatus({loading: false, status: false, message: ''}) loading: false,
},5000) 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]); imgReader.readAsDataURL(e.target.files[0]);
} }
}; };
// Check if the user is using iOS // Check if the user is using iOS
const isIOS = /MacIntel|MacPPC/.test(navigator.platform) && !window.MSStream; const isIOS = /MacIntel|MacPPC/.test(navigator.platform) && !window.MSStream;
// Check if the user is using Windows // Check if the user is using Windows
const isWindows = /Windows/.test(navigator.userAgent); const isWindows = /Windows/.test(navigator.userAgent);
return ( return (
<ModalCom action={onClose} situation={situation} className="edit-popup"> <ModalCom action={onClose} situation={situation} className="edit-popup">
@@ -321,82 +355,77 @@ const EditJobPopOut = ({
</div> </div>
<div className="sm:w-[35%] w-full"> <div className="sm:w-[35%] w-full">
<label <div
htmlFor="Job Categories" htmlFor="Job Categories"
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex item-center gap-1" className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'
> id="checked-group"
Categories ({`multiple categories - ${isIOS ? "⌘" : isWindows ? "Ctrl+" : ""}`}) >
{props.errors.category && props.touched.category && ( Categories
<span className="text-[12px] text-red-500"> </div>
{props.errors.category} <div
</span> className="sm:flex-col flex flex-wrap px-3 mt-3"
)} role="group"
aria-labelledby="checked-group"
</label> >
<select {categories &&
id="category" Object.entries(categories)?.map(([key, value]) => (
name="category" <label
value={props.values.category}
className={`input-field p-2 mt-1 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-[4.7rem] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none border`}
onChange={props.handleChange}
onBlur={props.handleBlur}
multiple
>
{walletDetails?.loading ? (
<option className="text-slate-500 text-lg" value="">
Loading...
</option>
) : walletDetails.data.length ? (
<>
{/* <option className="text-slate-500 text-lg" value="">
Select a Category
</option> */}
{Object?.entries(categories).map(([key, value]) => (
<option
key={key} key={key}
className="text-slate-500 " className="flex gap-1 w-full items-center"
value={key}
> >
{value} <Field
</option> type="checkbox"
name="category"
value={key}
/>
<span className="text-[13.975px]">{value}</span>
</label>
))} ))}
</> <span className="h-5 text-sm italic text-[#cf3917]">
) : ( {props.errors.category &&
<option className="text-slate-500 text-lg" value=""> props.touched.category &&
No Options Found! Try Again "please select a category"}
</option> </span>
)} </div>
</select> </div>
</div>
</div> </div>
<div className="w-full flex items-center gap-2 mb-2"> <div className="w-full flex items-center gap-2 mb-2">
{/* FOR TASK IMAGE */} {/* FOR TASK IMAGE */}
<div className="w-1/2 relative max-h-[130px] min-h-[130px]"> <div className="w-1/2 relative max-h-[130px] min-h-[130px]">
<input <input
id="task_image" id="task_image"
className="hidden" className="hidden"
type="file" type="file"
accept="image/*" accept="image/*"
onChange={taskImgChangeHandler} 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="uploaded task" /> <img
<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> src={taskImage}
</div> className="max-h-[150px] min-h-[150px] w-full object-cover"
: alt="uploaded task"
<label />
className="absolute -top-5 h-[150px] w-full flex flex-col justify-center items-center bg-slate-100 dark:bg-[#11131F] cursor-pointer input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold" htmlFor='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/80 hover:bg-white hover:shadow-md transition-all duration-500 cursor-pointer text-slate-800"
>
Remove Image
</span>
</div>
) : (
<label
className="absolute -top-5 h-[150px] w-full flex flex-col justify-center items-center bg-slate-100 dark:bg-[#11131F] cursor-pointer input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold"
htmlFor="task_image"
>
Select Task Image Select Task Image
</label> </label>
} )}
</div> </div>
{/* END OF TASK IMAGE */} {/* END OF TASK IMAGE */}
<div className="field w-1/2"> <div className="field w-1/2">
<div <div className={`flex items-center justify-between`}>
className={`flex items-center justify-between`}
>
<label <label
className="w-full input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex flex-col" className="w-full input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex flex-col"
htmlFor="timeline_days" htmlFor="timeline_days"
@@ -456,11 +485,23 @@ const EditJobPopOut = ({
))} ))}
{/* End of error or success display */} {/* End of error or success display */}
{/* DISPLAYS TASK IMAGE UPLOADING STATUS */} {/* DISPLAYS TASK IMAGE UPLOADING STATUS */}
<div className="w-full"> <div className="w-full">
{uploadStatus.message && !uploadStatus.loading && <p className={`text-center ${uploadStatus.status ? 'text-green-500':'text-red-500'}`}>{uploadStatus.message}</p>} {uploadStatus.message && !uploadStatus.loading && (
{uploadStatus.loading && <p className="text-center">{uploadStatus.message}</p>} <p
</div> 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">
@@ -471,7 +512,9 @@ 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} disabled={
requestStatus.loading || uploadStatus.loading
}
> >
Save Save
</button> </button>