Compare commits

...

4 Commits

4 changed files with 762 additions and 639 deletions
+316 -195
View File
@@ -12,22 +12,28 @@ import { useReactToPrint } from "react-to-print";
import usersService from "../../services/UsersService"; import usersService from "../../services/UsersService";
function ActiveJobs(props) { function ActiveJobs(props) {
const ApiCall = new usersService() const ApiCall = new usersService();
let navigate = useNavigate() let navigate = useNavigate();
let { userDetails } = useSelector((state) => state.userDetails); let { userDetails } = useSelector((state) => state.userDetails);
let [passDue, setPassDue] = useState(new Date() > new Date(props.details?.delivery_date)) // STATE TO KNOW IF TASK IS PASSED DUE TIME let [passDue, setPassDue] = useState(
new Date() > new Date(props.details?.delivery_date)
); // STATE TO KNOW IF TASK IS PASSED DUE TIME
let [messageToSend, setMessageToSend] = useState('') // State to hold the value of message to be sent let [messageToSend, setMessageToSend] = useState(""); // State to hold the value of message to be sent
let [filesToSend, setFilesToSend] = useState([]) // State to hold the value of files to be sent let [filesToSend, setFilesToSend] = useState([]); // State to hold the value of files to be sent
let [tab, setTab] = useState('message') let [tab, setTab] = useState("message");
let [requestStatus, setRequestStatus] = useState({loading: false, status: false, message: ''}) let [requestStatus, setRequestStatus] = useState({
loading: false,
status: false,
message: "",
});
let [popUp, setPopUp] = useState(false) // STATE FOR POPOUT MODAL let [popUp, setPopUp] = useState(false); // STATE FOR POPOUT MODAL
const printRef = useRef(); const printRef = useRef();
// to handle printing // to handle printing
@@ -35,112 +41,164 @@ function ActiveJobs(props) {
content: () => printRef.current, content: () => printRef.current,
}); });
const popUpHandler = () => { // FUNCTION TO HANDLE POPOUT const popUpHandler = () => {
setPopUp(prev => !prev) // FUNCTION TO HANDLE POPOUT
} setPopUp((prev) => !prev);
};
// FUNCTION TO HANDLE MESSAGE CHANGE // FUNCTION TO HANDLE MESSAGE CHANGE
const handleMessageChange = ({target:{value}}) => { const handleMessageChange = ({ target: { value } }) => {
setMessageToSend(value) setMessageToSend(value);
} };
// FUNCTION TO HANDLE FILE UPlOAD CHANGE // FUNCTION TO HANDLE FILE UPlOAD CHANGE
const handleFileChange = ({target:{files}}) => { const handleFileChange = ({ target: { files } }) => {
setRequestStatus({loading: false, status: false, message: ''}) // State to determine error state setRequestStatus({ loading: false, status: false, message: "" }); // State to determine error state
if(!files[0]) { // IF NO FILE SELECTED RETURN if (!files[0]) {
return // IF NO FILE SELECTED RETURN
return;
} }
if(files[0].size > Number(process.env.REACT_APP_MAX_FILE_SIZE)){ if (files[0].size > Number(process.env.REACT_APP_MAX_FILE_SIZE)) {
setRequestStatus({loading: false, status: false, message: 'File must be <= 1mb'}) setRequestStatus({
setTimeout(()=>{ loading: false,
setRequestStatus({loading: false, status: false, message: ''}) status: false,
}, 5000) message: "File must be <= 1mb",
return });
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
return;
} }
if(filesToSend.length >= Number(process.env.REACT_APP_TOTAL_NUM_FILE)){ if (filesToSend.length >= Number(process.env.REACT_APP_TOTAL_NUM_FILE)) {
setRequestStatus({loading: false, status: false, message: `Total number of attachment is ${Number(process.env.REACT_APP_TOTAL_NUM_FILE)}`}) setRequestStatus({
setTimeout(()=>{ loading: false,
setRequestStatus({loading: false, status: false, message: ''}) status: false,
}, 5000) message: `Total number of attachment is ${Number(
return process.env.REACT_APP_TOTAL_NUM_FILE
)}`,
});
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
return;
} }
// INCLUDE FILE IF NO ERROR // INCLUDE FILE IF NO ERROR
setFilesToSend(prev => ([...prev, files[0]])) setFilesToSend((prev) => [...prev, files[0]]);
} };
// FUNCTION TO CLEAR ALL TYPED MESSAGE OR FILES // FUNCTION TO CLEAR ALL TYPED MESSAGE OR FILES
const handleClearAll = ({target:{name}}) => { const handleClearAll = ({ target: { name } }) => {
if(tab == 'message'){ if (tab == "message") {
setMessageToSend('') setMessageToSend("");
}else if(tab=='files'){ } else if (tab == "files") {
setFilesToSend([]) setFilesToSend([]);
}else{ } else {
return return;
}
} }
};
// FUNCTION TO REMOVE AND IMAGE // FUNCTION TO REMOVE AND IMAGE
const handleRemoveImage = (imageToDelete) => { const handleRemoveImage = (imageToDelete) => {
setFilesToSend(prev => prev.filter(item => item.name != imageToDelete.name)) setFilesToSend((prev) =>
} prev.filter((item) => item.name != imageToDelete.name)
);
};
// FUNCTION TO SEND TASK MESSAGE // FUNCTION TO SEND TASK MESSAGE
const sendTaskMessage = () => { const sendTaskMessage = () => {
let reqData={message: messageToSend, msg_type: 'TEXT', contract:props.details.contract} let reqData = {
if(!reqData.message){ message: messageToSend,
setRequestStatus({loading: false, status: false, message: 'Message is empty'}) msg_type: "TEXT",
return setTimeout(()=>{ contract: props.details.contract,
setRequestStatus({loading: false, status: false, message: ''}) };
}, 5000) if (!reqData.message) {
setRequestStatus({
loading: false,
status: false,
message: "Message is empty",
});
return setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
} }
setRequestStatus({loading: true, status: false, message: ''}) setRequestStatus({ loading: true, status: false, message: "" });
ApiCall.sendTaskMessage(reqData).then((res)=>{ ApiCall.sendTaskMessage(reqData)
if(res.status != 200 || res.data.internal_return < 0){ .then((res) => {
setRequestStatus({loading: false, status: false, message: 'Message could not be sent, try again later'}) if (res.status != 200 || res.data.internal_return < 0) {
return setRequestStatus({
loading: false,
status: false,
message: "Message could not be sent, try again later",
});
return;
} }
setRequestStatus({loading: false, status: true, message: 'Message Sent Successfully'}) setRequestStatus({
props.reloadActiveJobList(prev => !prev) // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD loading: false,
setMessageToSend('') // SENDS MESSAGE TO SEND BACK TO EMPTY STRINGS status: true,
}).catch(error => { message: "Message Sent Successfully",
setRequestStatus({loading: false, status: false, message: 'Opps! something went wrong'}) });
}).finally(()=>{ props.reloadActiveJobList((prev) => !prev); // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
setTimeout(()=>{ setMessageToSend(""); // SENDS MESSAGE TO SEND BACK TO EMPTY STRINGS
setRequestStatus({loading: false, status: false, message: ''})
}, 5000)
}) })
} .catch((error) => {
setRequestStatus({
loading: false,
status: false,
message: "Opps! something went wrong",
});
})
.finally(() => {
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
});
};
// FUNCTION TO SEND FILES // FUNCTION TO SEND FILES
const sendFile = async () => { const sendFile = async () => {
setRequestStatus({loading: true, status: false, message: ''}) setRequestStatus({ loading: true, status: false, message: "" });
if(!filesToSend.length){ // checks if file to send is empty if (!filesToSend.length) {
setRequestStatus({loading: false, status: false, message: 'No File(s) selected'}) // checks if file to send is empty
return setTimeout(()=>{ setRequestStatus({
setRequestStatus({loading: false, status: false, message: ''}) loading: false,
}, 5000) status: false,
message: "No File(s) selected",
});
return setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
} }
for(let i=0; i<=filesToSend.length-1; i++){ // Loops through files to send array and trigger upload API call for (let i = 0; i <= filesToSend.length - 1; i++) {
// Loops through files to send array and trigger upload API call
const fileToBase64 = async () =>{ // Converts file data to base64 string const fileToBase64 = async () => {
// Converts file data to base64 string
try { try {
const base64String = await convertFileToBase64(filesToSend[i]); const base64String = await convertFileToBase64(filesToSend[i]);
return base64String; return base64String;
} catch (error) { } catch (error) {
return false; return false;
} }
} };
// if(await !fileToBase64()){ // if(await !fileToBase64()){
// return // return
// } // }
let reqData={file_name: filesToSend[i].name, file_size: filesToSend[i].size, file_type: 'image/png', file_data: await fileToBase64(), msg_type: 'FILE', contract:props.details.contract} let reqData = {
file_name: filesToSend[i].name,
file_size: filesToSend[i].size,
file_type: "image/png",
file_data: await fileToBase64(),
msg_type: "FILE",
contract: props.details.contract,
};
ApiCall.sendFiles(reqData).then((res)=>{ ApiCall.sendFiles(reqData)
.then((res) => {
// if(res.status != 200 || res.data.internal_return < 0){ // if(res.status != 200 || res.data.internal_return < 0){
// setRequestStatus({loading: false, status: false, message: 'Files(s) could not be sent, try again later'}) // setRequestStatus({loading: false, status: false, message: 'Files(s) could not be sent, try again later'})
// return // return
@@ -148,47 +206,50 @@ function ActiveJobs(props) {
// setRequestStatus({loading: false, status: true, message: 'File(s) Uploaded Successfully'}) // setRequestStatus({loading: false, status: true, message: 'File(s) Uploaded Successfully'})
// props.reloadActiveJobList(prev => !prev) // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD // props.reloadActiveJobList(prev => !prev) // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
// setFilesToSend([]) // SETS FILES TO SEND TO SEND BACK TO EMPTY ARRAY // setFilesToSend([]) // SETS FILES TO SEND TO SEND BACK TO EMPTY ARRAY
}).catch(error => {
// setRequestStatus({loading: false, status: false, message: 'Opps! something went wrong'})
}).finally(()=>{
if(i==filesToSend.length-1){
setRequestStatus({loading: false, status: true, message: 'File(s) Uploaded Successfully'})
setFilesToSend([]) // SETS FILES TO SEND TO SEND BACK TO EMPTY ARRAY
props.reloadActiveJobList(prev => !prev) // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
setTimeout(()=>{
setRequestStatus({loading: false, status: false, message: ''})
}, 5000)
}
}) })
.catch((error) => {
// setRequestStatus({loading: false, status: false, message: 'Opps! something went wrong'})
})
.finally(() => {
if (i == filesToSend.length - 1) {
setRequestStatus({
loading: false,
status: true,
message: "File(s) Uploaded Successfully",
});
setFilesToSend([]); // SETS FILES TO SEND TO SEND BACK TO EMPTY ARRAY
props.reloadActiveJobList((prev) => !prev); // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
} }
});
} }
};
// FUNCTION TO CHECK IF TASK PASS DUE IS REACHED // FUNCTION TO CHECK IF TASK PASS DUE IS REACHED
let isPassedDue = () => { let isPassedDue = () => {
// console.log('TESTING',new Date() > new Date(props.details?.delivery_date) ) // console.log('TESTING',new Date() > new Date(props.details?.delivery_date) )
if(new Date() > new Date(props.details?.delivery_date)){ if (new Date() > new Date(props.details?.delivery_date)) {
setPassDue(true) setPassDue(true);
}else{ } else {
setPassDue(false) setPassDue(false);
}
} }
};
useEffect(() => {
useEffect(()=>{ if (!passDue) {
if(!passDue){ let passDueInterval = setInterval(() => {
let passDueInterval = setInterval(()=>{ isPassedDue();
isPassedDue() }, 1000);
},1000) return () => {
return ()=>{ clearInterval(passDueInterval);
clearInterval(passDueInterval) };
} }
} }, [passDue]);
},[passDue])
return ( return (
<Layout> <Layout>
<div className="py-[20px] bg-white px-4 rounded-2xl shadow-md md:flex justify-between items-start gap-16"> <div className="py-[20px] bg-white px-4 rounded-2xl shadow-md md:flex justify-between items-start gap-16">
{/* job title */} {/* job title */}
<div className="w-full md:w-8/12"> <div className="w-full md:w-8/12">
@@ -196,7 +257,9 @@ function ActiveJobs(props) {
<button <button
type="button" type="button"
className="min-w-[45px] h-auto text-[#374557] border border-sky-blue p-1 rounded-full" className="min-w-[45px] h-auto text-[#374557] border border-sky-blue p-1 rounded-full"
onClick={() => navigate(props.details.pathname, {replace: true})} onClick={() =>
navigate(props.details.pathname, { replace: true })
}
> >
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@@ -219,7 +282,9 @@ function ActiveJobs(props) {
</p> </p>
<div className="text-base text-slate-700 dark:text-black tracking-wide"> <div className="text-base text-slate-700 dark:text-black tracking-wide">
<p className="font-semibold text-black">Description: </p> <p className="font-semibold text-black">Description: </p>
<p className="p-2 border border-sky-blue">{props.details?.description && props.details.description}</p> <p className="p-2 border border-sky-blue">
{props.details?.description && props.details.description}
</p>
</div> </div>
</div> </div>
</div> </div>
@@ -228,8 +293,7 @@ function ActiveJobs(props) {
{/* job details */} {/* job details */}
<div className="w-full md:w-4/12"> <div className="w-full md:w-4/12">
<p className="text-base text-sky-blue">Delivery Detail</p> <p className="text-base text-sky-blue">Delivery Detail</p>
{passDue ? {passDue ? (
(
<div className="my-1"> <div className="my-1">
<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>
@@ -241,9 +305,7 @@ function ActiveJobs(props) {
props.details.delivery_date.split(" ")[1]} props.details.delivery_date.split(" ")[1]}
</p> </p>
</div> </div>
) ) : (
:
(
<div className="my-1 flex items-start gap-3"> <div className="my-1 flex items-start gap-3">
<p className="font-semibold">Due: </p> <p className="font-semibold">Due: </p>
<div className="flex flex-col justify-between"> <div className="flex flex-col justify-between">
@@ -257,16 +319,20 @@ function ActiveJobs(props) {
</div> </div>
</div> </div>
</div> </div>
) )}
}
<div className="my-1 text-base text-slate-700 dark:text-black tracking-wide flex items-center gap-3"> <div className="my-1 text-base text-slate-700 dark:text-black tracking-wide flex items-center gap-3">
<span className="font-semibold text-black">Duration: </span> <span className="font-semibold text-black">Duration: </span>
<span className="">{props.details?.timeline_days && props.details.timeline_days} day(s)</span> <span className="">
{props.details?.timeline_days && props.details.timeline_days}{" "}
day(s)
</span>
</div> </div>
<div className="my-1 text-base text-slate-700 dark:text-black tracking-wide flex items-center gap-3"> <div className="my-1 text-base text-slate-700 dark:text-black tracking-wide flex items-center gap-3">
<span className="font-semibold text-black">No: </span> <span className="font-semibold text-black">No: </span>
<span className="">{props.details?.contract && props.details.contract}</span> <span className="">
{props.details?.contract && props.details.contract}
</span>
</div> </div>
</div> </div>
{/* end of job details */} {/* end of job details */}
@@ -275,7 +341,9 @@ function ActiveJobs(props) {
<div className="my-4 py-[20px] bg-white px-4 rounded-2xl shadow-md lg:flex justify-between items-start space-y-4 lg:space-x-4 lg:space-y-0"> <div className="my-4 py-[20px] bg-white px-4 rounded-2xl shadow-md lg:flex justify-between items-start space-y-4 lg:space-x-4 lg:space-y-0">
<div className="w-full lg:w-1/2"> <div className="w-full lg:w-1/2">
<div className=""> <div className="">
<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>
{/* <p className="my-3 py-1 text-base"> {/* <p className="my-3 py-1 text-base">
Waiting for the completion message from the client before you can approve. Waiting for the completion message from the client before you can approve.
</p> */} </p> */}
@@ -288,47 +356,67 @@ function ActiveJobs(props) {
{/* <p className="relative py-2 my-2 text-lg font-bold text-slate-600 dark:text-black border-b-2 border-slate-300 tracking-wide after:absolute after:-bottom-0.5 after:content-[''] after:w-[100px] after:h-[2px] after:bg-sky-blue after:left-0">Message(s)</p> */} {/* <p className="relative py-2 my-2 text-lg font-bold text-slate-600 dark:text-black border-b-2 border-slate-300 tracking-wide after:absolute after:-bottom-0.5 after:content-[''] after:w-[100px] after:h-[2px] after:bg-sky-blue after:left-0">Message(s)</p> */}
<div className="my-2 flex items-center border-b border-slate-300"> <div className="my-2 flex items-center border-b border-slate-300">
<button <button
name='message' name="message"
onClick={(e) => setTab(e.target.name)} onClick={(e) => setTab(e.target.name)}
className={`p-2 text-lg font-bold text-slate-600 dark:text-black border ${tab == 'message'? 'border-sky-blue':'border-slate-300'} tracking-wide transition duration-200`}> className={`p-2 text-lg font-bold text-slate-600 dark:text-black border ${
tab == "message" ? "border-sky-blue" : "border-slate-300"
} tracking-wide transition duration-200`}
>
Send Message Send Message
</button> </button>
<button <button
name='files' name="files"
onClick={(e) => setTab(e.target.name)} onClick={(e) => setTab(e.target.name)}
className={`p-2 text-lg font-bold text-slate-600 dark:text-black border ${tab == 'files'? 'border-sky-blue':'border-slate-300'} tracking-wide transition duration-200`}> className={`p-2 text-lg font-bold text-slate-600 dark:text-black border ${
tab == "files" ? "border-sky-blue" : "border-slate-300"
} tracking-wide transition duration-200`}
>
Send Files Send Files
</button> </button>
</div> </div>
{tab == 'message' ? {tab == "message" ? (
(
<textarea <textarea
className="p-4 w-full h-[300px] text-base text-slate-600 border border-slate-300 outline-none" className="p-4 w-full h-[300px] text-base text-slate-600 border border-slate-300 outline-none"
// rows="10" // rows="10"
style={{ resize: "none" }} style={{ resize: "none" }}
name='message' name="message"
onChange={handleMessageChange} onChange={handleMessageChange}
value={messageToSend} value={messageToSend}
/> />
) ) : (
:
<div className="p-4 w-full h-[300px] text-base text-slate-600 border border-slate-300"> <div className="p-4 w-full h-[300px] text-base text-slate-600 border border-slate-300">
<div className="files"> <div className="files">
<label htmlFor="file" className="h-20 btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer">Select Files to Upload</label> <label
<input type="file" id='file' accept="image/*" style={{display: 'none'}} onChange={handleFileChange}/> htmlFor="file"
className="h-20 btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer"
>
Select Files to Upload
</label>
<input
type="file"
id="file"
accept="image/*"
style={{ display: "none" }}
onChange={handleFileChange}
/>
</div> </div>
<div className="selected_file my-2"> <div className="selected_file my-2">
{filesToSend.length > 0 && {filesToSend.length > 0 &&
filesToSend.map((item, index)=> ( filesToSend.map((item, index) => (
<p key={index} className="flex items-center space-x-2"> <p key={index} className="flex items-center space-x-2">
<span>{item.name}</span> <span>{item.name}</span>
<button name='remove' onClick={()=>handleRemoveImage(item)} className="px-2 flex justify-center items-center rounded-full border border-red-500 text-red-500">x</button> <button
name="remove"
onClick={() => handleRemoveImage(item)}
className="px-2 flex justify-center items-center rounded-full border border-red-500 text-red-500"
>
x
</button>
</p> </p>
)) ))}
}
</div> </div>
</div> </div>
} )}
</div> </div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */} {/* ERROR DISPLAY AND SUBMIT BUTTON */}
@@ -363,44 +451,44 @@ function ActiveJobs(props) {
> >
<span className="text-gradient">Clear</span> <span className="text-gradient">Clear</span>
</button> </button>
{tab == 'files' ? {tab == "files" ? (
(
<button <button
onClick={sendFile} onClick={sendFile}
type="button" type="button"
className="btn-gradient text-base tracking-wide px-4 py-3 rounded-full flex justify-center items-center" className="btn-gradient text-base tracking-wide px-4 py-3 rounded-full flex justify-center items-center"
> >
{requestStatus.loading ? {requestStatus.loading ? (
<LoadingSpinner size='6' color='sky-blue' /> <LoadingSpinner size="6" color="sky-blue" />
: ) : (
<> <>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill='white'> <svg
<path d="M12 2L2 12h3v8h14v-8h3L12 2zm0 16v-6h-2v6H7l5-5 5 5h-3z"/> xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24"
fill="white"
>
<path d="M12 2L2 12h3v8h14v-8h3L12 2zm0 16v-6h-2v6H7l5-5 5 5h-3z" />
</svg> </svg>
<span className="text-white">Upload Files</span> <span className="text-white">Upload Files</span>
</> </>
} )}
</button> </button>
) ) : (
:
(
<button <button
onClick={sendTaskMessage} onClick={sendTaskMessage}
type="button" type="button"
className="btn-gradient text-base text-white tracking-wide px-4 py-3 rounded-full" className="btn-gradient text-base text-white tracking-wide px-4 py-3 rounded-full"
> >
{requestStatus.loading ? {requestStatus.loading ? (
<LoadingSpinner size='6' color='sky-blue' /> <LoadingSpinner size="6" color="sky-blue" />
: ) : (
<span className="text-white">Send</span> <span className="text-white">Send</span>
} )}
</button> </button>
) )}
}
</div> </div>
</div> </div>
{/* end of Buttons Sections */} {/* end of Buttons Sections */}
</div> </div>
@@ -410,43 +498,54 @@ function ActiveJobs(props) {
{/* MESSAGE SECTION */} {/* MESSAGE SECTION */}
<div className="w-full lg:w-1/2"> <div className="w-full lg:w-1/2">
<div className="flex justify-between items-center gap-5"> <div className="flex justify-between items-center gap-5">
<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">
<button type="button" onClick={popUpHandler} className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"> Message
</p>
<button
type="button"
onClick={popUpHandler}
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
view all view all
</button> </button>
</div> </div>
{props.activeJobMesList.loading ? {props.activeJobMesList.loading ? (
<LoadingSpinner size='16' color='sky-blue' /> <LoadingSpinner size="16" color="sky-blue" />
: ) : (
<ActiveJobMessage activeJobMesList={props.activeJobMesList} /> <ActiveJobMessage activeJobMesList={props.activeJobMesList} />
} )}
</div> </div>
{/* END OF MESSAGE */} {/* END OF MESSAGE */}
</div> </div>
{/* POPOUT SECTION */} {/* POPOUT SECTION */}
{popUp && {popUp && (
<PopModal popUpHandler={popUpHandler} popUp={popUp} details={props.details} activeJobMesList={props.activeJobMesList} handlePrint={handlePrint} myRef={printRef} /> <PopModal
} popUpHandler={popUpHandler}
popUp={popUp}
details={props.details}
activeJobMesList={props.activeJobMesList}
handlePrint={handlePrint}
myRef={printRef}
/>
)}
{/* END OF POPOUT SECTION */} {/* END OF POPOUT SECTION */}
</Layout> </Layout>
); );
} }
export default ActiveJobs; export default ActiveJobs;
function convertFileToBase64(file) { function convertFileToBase64(file) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const reader = new FileReader(); const reader = new FileReader();
reader.onload = () => { reader.onload = () => {
const base64String = reader.result.split(',')[1]; const base64String = reader.result.split(",")[1];
resolve(base64String); resolve(base64String);
}; };
reader.onerror = error => { reader.onerror = (error) => {
reject(error); reject(error);
}; };
@@ -455,10 +554,20 @@ function convertFileToBase64(file) {
} }
//POPOUT COMPONENT FUNCTION //POPOUT COMPONENT FUNCTION
const PopModal = ({popUpHandler, popUp, details, activeJobMesList, handlePrint, myRef}) => { const PopModal = ({
popUpHandler,
popUp,
details,
activeJobMesList,
handlePrint,
myRef,
}) => {
return ( return (
<ModalCom action={popUpHandler} situation={popUp} className="edit-popup"> <ModalCom action={popUpHandler} situation={popUp} className="edit-popup">
<div ref={myRef} className="message-modal-wrapper min-w-[500px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl"> <div
ref={myRef}
className="message-modal-wrapper min-w-[500px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl"
>
<div className="message-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple"> <div className="message-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide"> <h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
{details?.contract} {details?.contract}
@@ -491,67 +600,79 @@ const PopModal = ({popUpHandler, popUp, details, activeJobMesList, handlePrint,
</div> </div>
<div className="job-action-modal-body w-full px-10 py-8 gap-4"> <div className="job-action-modal-body w-full px-10 py-8 gap-4">
<div className="w-full flex flex-col items-center"> <div className="w-full flex flex-col items-center">
{activeJobMesList.loading ? {activeJobMesList.loading ? (
<LoadingSpinner size='16' color='sky-blue' /> <LoadingSpinner size="16" color="sky-blue" />
: ) : (
<div className="message-table h-[500px] overflow-y-auto"> <div className="message-table h-[500px] overflow-y-auto">
<table className="wallet-activity w-full table-auto border-collapse text-left"> <table className="wallet-activity w-full table-auto border-collapse text-left">
<thead className='border-b-2'> <thead className="border-b-2">
<tr className='text-slate-600'> <tr className="text-slate-600">
<th className="p-2"></th> <th className="p-2"></th>
</tr> </tr>
</thead> </thead>
{activeJobMesList?.data?.length ? {activeJobMesList?.data?.length ? (
(
<tbody> <tbody>
{activeJobMesList?.data?.map((item, index) => ( {activeJobMesList?.data?.map((item, index) => (
<tr key={index} className='text-slate-500'> <tr key={index} className="text-slate-500">
<td> <td>
<div className="msg_box"> <div className="msg_box">
<div className="msg_header">{item.msg_date} {item.msg_firstname}</div> <div className="msg_header">
<span className="p-2" dangerouslySetInnerHTML={{__html: item.message}}></span> {item.msg_date} {item.msg_firstname}
</div>
<span
className="p-2"
dangerouslySetInnerHTML={{
__html: item.message,
}}
></span>
</div> </div>
</td> </td>
</tr> </tr>
))} ))}
</tbody> </tbody>
) ) : activeJobMesList.error ? (
:
activeJobMesList.error ?
(
<tbody> <tbody>
<tr className='text-slate-500'> <tr className="text-slate-500">
<td className="p-2" colSpan={4}>Opps! an error occurred. Please try again!</td> <td className="p-2" colSpan={4}>
Opps! an error occurred. Please try again!
</td>
</tr> </tr>
</tbody> </tbody>
) ) : (
:
<tbody> <tbody>
<tr className='text-slate-500'> <tr className="text-slate-500">
<td className="p-2" colSpan={4}>No Message Found!</td> <td className="p-2" colSpan={4}>
No Message Found!
</td>
</tr> </tr>
</tbody> </tbody>
} )}
</table> </table>
</div> </div>
} )}
</div> </div>
{/* btn */} {/* btn */}
<div className='flex justify-end items-center'> <div className="flex justify-end items-center">
<div className="py-3 w-full lg:w-1/2 flex justify-between items-center"> <div className="py-3 w-full lg:w-1/2 flex justify-between items-center">
<button onClick={handlePrint} type="button" className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"> <button
<span className='text-white'>Print</span> onClick={handlePrint}
type="button"
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
<span className="text-white">Print</span>
</button> </button>
<button onClick={popUpHandler} type="button" className="w-20 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white"> <button
<span className='text-gradient'>Cancel</span> onClick={popUpHandler}
type="button"
className="w-20 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white"
>
<span className="text-gradient">Cancel</span>
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</ModalCom> </ModalCom>
) );
} };
@@ -1,17 +1,12 @@
import React, { useState } from "react"; import React, { useState } from "react";
import dataImage2 from "../../assets/images/data-table-user-2.png"; import dataImage2 from "../../assets/images/data-table-user-2.png";
import { useNavigate, useLocation } from "react-router-dom"; import { useNavigate, useLocation } from "react-router-dom";
import { handlePagingFunc } from "../Pagination/HandlePagination"; 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();
const filterCategories = ["All Categories", "Explore", "Featured"];
const [selectedCategory, setCategory] = useState(filterCategories[0]);
const [currentPage, setCurrentPage] = useState(0); const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage); const indexOfFirstItem = Number(currentPage);
@@ -45,8 +40,11 @@ export default function MyActiveJobTable({ MyJobList, className }) {
<> <>
{MyJobList && {MyJobList &&
MyJobList?.result_list && MyJobList?.result_list &&
MyJobList.result_list.length > 0 ? MyJobList.result_list.length > 0 ? (
currentActiveJobList.map((value, index) => ( currentActiveJobList.map((value, index) => {
let deliveryDate = value?.delivery_date?.split(" ")[0];
return (
<tr <tr
key={index} key={index}
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50" className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
@@ -71,6 +69,7 @@ export default function MyActiveJobTable({ MyJobList, className }) {
{value.price * 0.01} {value.price * 0.01}
</span> </span>
</span> </span>
<div className="flex gap-4 items-center">
<span className="text-sm text-thin-light-gray"> <span className="text-sm text-thin-light-gray">
Duration:{" "} Duration:{" "}
<span className="text-purple"> <span className="text-purple">
@@ -79,21 +78,24 @@ export default function MyActiveJobTable({ MyJobList, className }) {
</span> </span>
</span> </span>
<span className="text-sm text-thin-light-gray"> <span className="text-sm text-thin-light-gray">
Expire:{" "} Due:{" "}
<span className="text-purple"> <span className="text-purple">
{" "} {" "}
{value.expire} {deliveryDate}
</span> </span>
</span> </span>
<span className="text-sm text-thin-light-gray"> <span className="text-sm text-thin-light-gray">
Send to:{" "} Send to:{" "}
<span className="text-purple"> <span className="text-purple">
{" "} {" "}
{value.job_to} {value.job_to === null
? "public"
: value.job_to}
</span> </span>
</span> </span>
</div> </div>
</div> </div>
</div>
</td> </td>
<td className="text-right py-4 px-2"> <td className="text-right py-4 px-2">
@@ -102,7 +104,7 @@ export default function MyActiveJobTable({ MyJobList, className }) {
type="button" type="button"
onClick={() => { onClick={() => {
navigate("/manage-active-job", { navigate("/manage-active-job", {
state: {...value, pathname}, state: { ...value, pathname },
}); });
}} }}
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"
@@ -112,14 +114,13 @@ export default function MyActiveJobTable({ MyJobList, className }) {
</div> </div>
</td> </td>
</tr> </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"> <td className="p-2">No Active Task!</td>
No Active Task!
</td>
</tr> </tr>
} )}
</> </>
} }
</tbody> </tbody>
+1 -3
View File
@@ -12,9 +12,7 @@ export default function MyActiveJobs(props) {
console.log("AMEYE LOC1", props.MyJobList); console.log("AMEYE LOC1", props.MyJobList);
return ( return (
<Layout> <Layout>
<CommonHead <CommonHead commonHeadData={props.commonHeadData} />
commonHeadData={props.commonHeadData}
/>
<div className="notification-page w-full mb-10"> <div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full"> <div className="notification-wrapper w-full">
{/* heading */} {/* heading */}
+10 -7
View File
@@ -45,17 +45,19 @@ export default function MyJobTable({ className, ActiveJobList }) {
: "none", : "none",
}} }}
> >
{/* Adding this dark overlay in order to see the texts properly */}
{!ActiveJobList?.data.length && ( {!ActiveJobList?.data.length && (
<div class="absolute inset-0 bg-black opacity-30"></div> <div class="absolute inset-0 bg-black opacity-30"></div>
)} )}
{ActiveJobList.loading ? ( {ActiveJobList?.data.length > 0 && ActiveJobList.loading && (
<div className="w-full h-[520px] flex items-center justify-center"> <div className="w-full h-[520px] flex items-center justify-center">
<LoadingSpinner size="16" color="sky-blue" /> <LoadingSpinner size="16" color="sky-blue" />
</div> </div>
) : ( )}
<div className="relative w-full sm:rounded-lg"> <div className="relative w-full sm:rounded-lg">
<div className="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"
@@ -121,8 +123,9 @@ export default function MyJobTable({ className, ActiveJobList }) {
</button> </button>
</div> </div>
</div> </div>
)) ))}
) : ActiveJobList.status ? (
{ActiveJobList?.data?.length <= 0 && (
<div className="flex flex-col items-center justify-center gap-9 my-5"> <div className="flex flex-col items-center justify-center gap-9 my-5">
<div className="p-2 font-bold text-3xl text-white whitespace-nowrap"> <div className="p-2 font-bold text-3xl text-white whitespace-nowrap">
You currently have "0" task You currently have "0" task
@@ -138,7 +141,8 @@ export default function MyJobTable({ className, ActiveJobList }) {
)} )}
</button> </button>
</div> </div>
) : ( )}
{ActiveJobList?.internal_return < 0 && (
<div className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap"> <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> <p className="p-2">Error Occurred! Unable to display Tasks!</p>
</div> </div>
@@ -161,7 +165,6 @@ export default function MyJobTable({ className, ActiveJobList }) {
/> />
{/* END OF PAGINATION BUTTON */} {/* END OF PAGINATION BUTTON */}
</div> </div>
)}
</div> </div>
); );
} }