Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0756747143 | |||
| 99eb1591a2 | |||
| 85b9aab229 | |||
| 67a0a34288 | |||
| 814e4c9693 | |||
| e74eb38caf | |||
| 67db1a72bf | |||
| 41e46d8030 | |||
| 8707411dda | |||
| 327a4a42ae | |||
| 455f4001f7 | |||
| 775bcd5005 | |||
| 492bda021f | |||
| eacfae19f0 | |||
| 376cf44a9c | |||
| 1aab0c2910 | |||
| 1f5fb8c7c3 | |||
| a303b24b53 | |||
| 322927045c | |||
| 3cf1dc7166 | |||
| 8ed331e909 | |||
| 2428923f73 | |||
| 139f87c919 | |||
| 1a817e723e | |||
| c023911cd4 |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" id="DownloadArrow"><g fill="#4687ba" class="color9a7baa svgShape"><path d="M30.179 3.525V1.857c0-1.551-1.784-2.415-3.011-1.449L24 2.907 20.824.402c-1.216-.959-3.002-.093-3.002 1.456v1.668a1 1 0 0 0 1 1h10.357c.552-.001 1-.449 1-1.001zM30.179 25.172v-2.524a1 1 0 0 0-1-1H18.822a1 1 0 0 0-1 1v2.524a1 1 0 0 0 1 1h10.357a1 1 0 0 0 1-1zM30.179 10.74V8.217a1 1 0 0 0-1-1H18.822a1 1 0 0 0-1 1v2.524a1 1 0 0 0 1 1h10.357c.552-.001 1-.448 1-1.001zM30.179 17.956v-2.524a1 1 0 0 0-1-1H18.822a1 1 0 0 0-1 1v2.524a1 1 0 0 0 1 1h10.357a1 1 0 0 0 1-1zM25.748 47.029l9.336-15.018c.852-1.371-.133-3.145-1.748-3.145H14.664c-1.614 0-2.6 1.774-1.748 3.145l9.336 15.018a2.058 2.058 0 0 0 3.496 0z" fill="#000000" class="color000000 svgShape"></path></g></svg>
|
||||||
|
After Width: | Height: | Size: 799 B |
@@ -1,74 +1,28 @@
|
|||||||
import { Field, Form, Formik } from "formik";
|
import {
|
||||||
import React, { useEffect, useState } from "react";
|
validationSchema as VS,
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
useDispatch,
|
||||||
import * as Yup from "yup";
|
useSelector,
|
||||||
import usersService from "../../services/UsersService";
|
usersService,
|
||||||
import { tableReload } from "../../store/TableReloads";
|
initialValues as IV,
|
||||||
import InputCom from "../Helpers/Inputs/InputCom";
|
initialReqState,
|
||||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
useState,
|
||||||
|
tableReload,
|
||||||
|
Formik,
|
||||||
|
InputCom,
|
||||||
|
Field,
|
||||||
|
Form,
|
||||||
|
LoadingSpinner,
|
||||||
|
} from "./settings";
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = VS;
|
||||||
country: Yup.string()
|
|
||||||
.min(1, "Minimum 3 characters")
|
|
||||||
.max(25, "Maximum 25 characters")
|
|
||||||
.required("Currency is required"),
|
|
||||||
price: Yup.string()
|
|
||||||
.typeError("Invalid number")
|
|
||||||
.min(1, "Price must be greater than 0")
|
|
||||||
.test("no-e", "Invalid number", (value) => {
|
|
||||||
if (value && /\d+e/.test(value)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
.required("Price is required"),
|
|
||||||
title: Yup.string()
|
|
||||||
.min(5, "Minimum 5 characters")
|
|
||||||
.max(149, "Maximum 149 characters")
|
|
||||||
.required("Title is required"),
|
|
||||||
description: Yup.string()
|
|
||||||
.min(5, "Minimum 5 characters")
|
|
||||||
.max(299, "Maximum 299 characters")
|
|
||||||
.required("Description is required"),
|
|
||||||
job_detail: Yup.string()
|
|
||||||
.min(3, "Minimum 3 characters")
|
|
||||||
.max(499, "Maximum 499 characters")
|
|
||||||
.required("Details is required"),
|
|
||||||
timeline_days: Yup.number()
|
|
||||||
.typeError("you must specify a number")
|
|
||||||
.min(1, "Price must be greater than 0")
|
|
||||||
.required("Timeline is required"),
|
|
||||||
category: Yup.array().min(1, "Select at least one checkbox"),
|
|
||||||
});
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
let dispatch = useDispatch();
|
let dispatch = useDispatch();
|
||||||
|
|
||||||
let initialValues = {
|
const [requestStatus, setRequestStatus] = useState(initialReqState); // Holds state when submit button is pressed
|
||||||
// initial values for formik
|
|
||||||
country: "",
|
|
||||||
price: "",
|
|
||||||
title: "",
|
|
||||||
description: "",
|
|
||||||
job_detail: "",
|
|
||||||
timeline_days: "",
|
|
||||||
category: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
let [requestStatus, setRequestStatus] = useState({
|
|
||||||
loading: false,
|
|
||||||
status: false,
|
|
||||||
message: "",
|
|
||||||
}); // Holds state when submit button is pressed
|
|
||||||
|
|
||||||
// const getWalletDetail = (country) => { // A FUNCTION TO GET USER BALANCE BASED ON COUNTRY SELECTED
|
|
||||||
// const walletChecker = walletDetails?.data.find(
|
|
||||||
// (item) => item.country === country
|
|
||||||
// );
|
|
||||||
// return walletChecker ? walletChecker.amount : 0;
|
|
||||||
// };
|
|
||||||
|
|
||||||
const handleAddJob = async (values, helpers) => {
|
const handleAddJob = async (values, helpers) => {
|
||||||
const reqData = {
|
const reqData = {
|
||||||
@@ -81,21 +35,6 @@ function AddJob({ popUpHandler, categories }) {
|
|||||||
category: values.category?.join("@"),
|
category: values.category?.join("@"),
|
||||||
};
|
};
|
||||||
|
|
||||||
// const walletAmount = getWalletDetail(reqData.country); // GETTING USER BALANCE BASED ON COUNTRY SELECTED
|
|
||||||
|
|
||||||
// if (reqData.price > walletAmount) {
|
|
||||||
// setRequestStatus({
|
|
||||||
// loading: false,
|
|
||||||
// status: false,
|
|
||||||
// message: "Insufficient Balance",
|
|
||||||
// });
|
|
||||||
|
|
||||||
// setTimeout(() => {
|
|
||||||
// setRequestStatus({ loading: false, status: false, message: "" });
|
|
||||||
// }, 1500);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
setRequestStatus({ loading: true, status: false, message: "" });
|
setRequestStatus({ loading: true, status: false, message: "" });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -136,7 +75,7 @@ function AddJob({ popUpHandler, categories }) {
|
|||||||
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}
|
||||||
>
|
>
|
||||||
@@ -258,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='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 &&
|
||||||
@@ -406,7 +345,6 @@ function AddJob({ popUpHandler, categories }) {
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="w-[152px] h-[46px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
className="w-[152px] h-[46px] 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'
|
|
||||||
>
|
>
|
||||||
Add Job
|
Add Job
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
import { Field, Form, Formik } from "formik";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import * as Yup from "yup";
|
||||||
|
import usersService from "../../services/UsersService";
|
||||||
|
import { tableReload } from "../../store/TableReloads";
|
||||||
|
import InputCom from "../Helpers/Inputs/InputCom";
|
||||||
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
|
|
||||||
|
// Initialize state for request values
|
||||||
|
const initialReqState = {
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
message: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
// For form initial values
|
||||||
|
const initialValues = {
|
||||||
|
// initial values for formik
|
||||||
|
country: "",
|
||||||
|
price: "",
|
||||||
|
title: "",
|
||||||
|
description: "",
|
||||||
|
job_detail: "",
|
||||||
|
timeline_days: "",
|
||||||
|
category: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
// const getWalletDetail = (country) => { // A FUNCTION TO GET USER BALANCE BASED ON COUNTRY SELECTED
|
||||||
|
// const walletChecker = walletDetails?.data.find(
|
||||||
|
// (item) => item.country === country
|
||||||
|
// );
|
||||||
|
// return walletChecker ? walletChecker.amount : 0;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// To get the validation schema
|
||||||
|
const validationSchema = Yup.object().shape({
|
||||||
|
country: Yup.string()
|
||||||
|
.min(1, "Minimum 3 characters")
|
||||||
|
.max(25, "Maximum 25 characters")
|
||||||
|
.required("Currency is required"),
|
||||||
|
price: Yup.string()
|
||||||
|
.typeError("Invalid number")
|
||||||
|
.min(1, "Price must be greater than 0")
|
||||||
|
.test("no-e", "Invalid number", (value) => {
|
||||||
|
if (value && /\d+e/.test(value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.required("Price is required"),
|
||||||
|
title: Yup.string()
|
||||||
|
.min(5, "Minimum 5 characters")
|
||||||
|
.max(149, "Maximum 149 characters")
|
||||||
|
.required("Title is required"),
|
||||||
|
description: Yup.string()
|
||||||
|
.min(5, "Minimum 5 characters")
|
||||||
|
.max(299, "Maximum 299 characters")
|
||||||
|
.required("Description is required"),
|
||||||
|
job_detail: Yup.string()
|
||||||
|
.min(3, "Minimum 3 characters")
|
||||||
|
.max(499, "Maximum 499 characters")
|
||||||
|
.required("Details is required"),
|
||||||
|
timeline_days: Yup.number()
|
||||||
|
.typeError("you must specify a number")
|
||||||
|
.min(1, "Price must be greater than 0")
|
||||||
|
.required("Timeline is required"),
|
||||||
|
category: Yup.array().min(1, "Select category"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const getWalletDetail = (countryParams, walletDetails) => {
|
||||||
|
// A FUNCTION TO GET USER BALANCE BASED ON COUNTRY SELECTED
|
||||||
|
const walletChecker = walletDetails?.data.find(
|
||||||
|
(item) => item.country === countryParams
|
||||||
|
);
|
||||||
|
return walletChecker
|
||||||
|
? {
|
||||||
|
description: walletChecker.description,
|
||||||
|
country: walletChecker.country,
|
||||||
|
}
|
||||||
|
: "";
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
Field,
|
||||||
|
Form,
|
||||||
|
Formik,
|
||||||
|
useState,
|
||||||
|
useEffect,
|
||||||
|
useDispatch,
|
||||||
|
useSelector,
|
||||||
|
usersService,
|
||||||
|
InputCom,
|
||||||
|
LoadingSpinner,
|
||||||
|
initialReqState,
|
||||||
|
initialValues,
|
||||||
|
validationSchema,
|
||||||
|
getWalletDetail,
|
||||||
|
tableReload
|
||||||
|
};
|
||||||
@@ -34,7 +34,7 @@ function PastDueJobAction({jobDetails}) {
|
|||||||
let reqData = { // API PAYLOADS
|
let reqData = { // API PAYLOADS
|
||||||
contract: jobDetails.contract,
|
contract: jobDetails.contract,
|
||||||
contract_uid: jobDetails.contract_uid,
|
contract_uid: jobDetails.contract_uid,
|
||||||
job_action: 'REQUEST_CANCEL',
|
job_action: 'CANCEL_CONTRACT',
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!checked){ // CHECKS IF CHECKBOX IS SELECTED
|
if(!checked){ // CHECKS IF CHECKBOX IS SELECTED
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default function MyPastDueJobs(props) {
|
|||||||
<span
|
<span
|
||||||
className={`${selectTab === "today" ? "block" : "hidden"}`}
|
className={`${selectTab === "today" ? "block" : "hidden"}`}
|
||||||
>
|
>
|
||||||
Pass Due Job(s)
|
Past Due Job(s)
|
||||||
</span>
|
</span>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ function ConfirmAddFund({
|
|||||||
public_key: __confirmData?.flutterwave_key,
|
public_key: __confirmData?.flutterwave_key,
|
||||||
tx_ref: __confirmData?.credit_reference,
|
tx_ref: __confirmData?.credit_reference,
|
||||||
currency: "NGN",
|
currency: "NGN",
|
||||||
amount: Number(__confirmData.amount),
|
amount: Number(__confirmData.amount) * 0.01,
|
||||||
payment_options: "card,mobilemoney,ussd",
|
payment_options: "card,mobilemoney,ussd",
|
||||||
customer: {
|
customer: {
|
||||||
email: userDetails.email,
|
email: userDetails.email,
|
||||||
@@ -224,7 +224,7 @@ function ConfirmAddFund({
|
|||||||
|
|
||||||
// Create request data object with required parameters for making the payment
|
// Create request data object with required parameters for making the payment
|
||||||
const reqData = {
|
const reqData = {
|
||||||
amount: amount * 100,
|
amount: amount,
|
||||||
card_uid,
|
card_uid,
|
||||||
credit_reference,
|
credit_reference,
|
||||||
currency,
|
currency,
|
||||||
@@ -289,7 +289,7 @@ function ConfirmAddFund({
|
|||||||
|
|
||||||
// Prepare request data
|
// Prepare request data
|
||||||
const reqData = {
|
const reqData = {
|
||||||
amount: amount * 100,
|
amount: amount,
|
||||||
cardnumber: cardNum.replace(/\s/g, ""),
|
cardnumber: cardNum.replace(/\s/g, ""),
|
||||||
credit_reference,
|
credit_reference,
|
||||||
cvc: cvv,
|
cvc: cvv,
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ export default function Resources(props) {
|
|||||||
loading: false,
|
loading: false,
|
||||||
msg: "success",
|
msg: "success",
|
||||||
data: res?.result_list,
|
data: res?.result_list,
|
||||||
|
image:res?.session_image_server
|
||||||
}));
|
}));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setUploadedFiles((prev) => ({
|
setUploadedFiles((prev) => ({
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ export default function MyUploadedFiles({ uploadedFiles }) {
|
|||||||
indexOfFirstItem,
|
indexOfFirstItem,
|
||||||
indexOfLastItem
|
indexOfLastItem
|
||||||
);
|
);
|
||||||
|
|
||||||
const handlePagination = (e) => {
|
const handlePagination = (e) => {
|
||||||
handlePagingFunc(e, setCurrentPage);
|
handlePagingFunc(e, setCurrentPage);
|
||||||
};
|
};
|
||||||
@@ -45,10 +44,11 @@ export default function MyUploadedFiles({ uploadedFiles }) {
|
|||||||
currentFiles.map((value, idx) => {
|
currentFiles.map((value, idx) => {
|
||||||
let addedDate = value?.added?.split(" ")[0];
|
let addedDate = value?.added?.split(" ")[0];
|
||||||
let formattedSize = formatFileSize(value?.file_size);
|
let formattedSize = formatFileSize(value?.file_size);
|
||||||
|
let imageLink = `${uploadedFiles?.image}${localStorage.getItem('session_token')}/myfile/${value.file_uid}`
|
||||||
return (
|
return (
|
||||||
<tr
|
<tr
|
||||||
key={value?.file_uid}
|
key={value?.file_uid}
|
||||||
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"
|
||||||
>
|
>
|
||||||
<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">
|
||||||
@@ -102,17 +102,17 @@ export default function MyUploadedFiles({ uploadedFiles }) {
|
|||||||
</td>
|
</td>
|
||||||
<td className="text-right py-4 px-2">
|
<td className="text-right py-4 px-2">
|
||||||
<div className="flex justify-center items-center">
|
<div className="flex justify-center items-center">
|
||||||
<button
|
<a
|
||||||
type="button"
|
href={imageLink}
|
||||||
// onClick={() => {
|
title="download"
|
||||||
// navigate("/manage-active-job", {
|
// className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||||
// state: { ...value, pathname },
|
|
||||||
// });
|
|
||||||
// }}
|
|
||||||
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
|
||||||
>
|
>
|
||||||
View
|
<img
|
||||||
</button>
|
src={localImgLoad('images/icons/download-arrow.svg')}
|
||||||
|
alt='download-link'
|
||||||
|
className="w-auto h-6 flex justify-center items-center"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ export default function ProductUploadField({
|
|||||||
fieldClass="px-6"
|
fieldClass="px-6"
|
||||||
type="text"
|
type="text"
|
||||||
name="name"
|
name="name"
|
||||||
placeholder="RaidParty Fighters"
|
placeholder="Item Name"
|
||||||
inputHandler={inh}
|
inputHandler={inh}
|
||||||
value={datas.itemName}
|
value={datas.itemName}
|
||||||
/>
|
/>
|
||||||
@@ -186,7 +186,7 @@ export default function ProductUploadField({
|
|||||||
<textarea
|
<textarea
|
||||||
value={datas.description}
|
value={datas.description}
|
||||||
onChange={(e) => dscrphn(e)}
|
onChange={(e) => dscrphn(e)}
|
||||||
placeholder="provide a detailed description of your item."
|
placeholder="Enter detail description"
|
||||||
rows="7"
|
rows="7"
|
||||||
className="w-full h-full px-7 py-4 border border-light-purple dark:border-[#5356fb29] rounded-[20px] text-dark-gray dark:text-white bg-[#FAFAFA] dark:bg-[#11131F] focus:ring-0 focus:outline-none"
|
className="w-full h-full px-7 py-4 border border-light-purple dark:border-[#5356fb29] rounded-[20px] text-dark-gray dark:text-white bg-[#FAFAFA] dark:bg-[#11131F] focus:ring-0 focus:outline-none"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -144,14 +144,14 @@ export default function UploadProduct({uploadTypes}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let reqData = { // PAYLOAD FOR API CALL
|
let reqData = { // PAYLOAD FOR API CALL
|
||||||
file_name: selectedFile.substring(0,21).replace(/ /gi, ""),//selectedFile.replace(/[ -]/gi, ""),
|
// file_name: selectedFile.substring(0,21).replace(/ /gi, ""),
|
||||||
|
file_name: `myfile.${imgDetails?.type?.split('/')[1]}`,
|
||||||
file_size: imgDetails.size,
|
file_size: imgDetails.size,
|
||||||
file_type: imgDetails.type,
|
file_type: imgDetails.type,
|
||||||
file_data: img.file,
|
file_data: img.file?.split(",")[1],
|
||||||
title: itemName,
|
title: itemName,
|
||||||
description: description,
|
description: description,
|
||||||
msg_type: 'FILE',
|
msg_type: 'FILE',
|
||||||
// action: 'WRENCHBOARD_RESOURCE_MYFILES',
|
|
||||||
action: 11307
|
action: 11307
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -602,7 +602,10 @@ export default function UploadProduct({uploadTypes}) {
|
|||||||
|
|
||||||
//FUNCTIONS to check if file upload type is valid
|
//FUNCTIONS to check if file upload type is valid
|
||||||
const isValidFile = (file, supportedFile=[]) => {
|
const isValidFile = (file, supportedFile=[]) => {
|
||||||
let fileType = file.type.split("/")[1];
|
let fileType = file.type.split("/")[1].toLowerCase();
|
||||||
|
if(fileType=='jpg' || fileType=='jpeg'){ //forcing both JPG and JPEG TO RETURN JPG AS FILE TYPE
|
||||||
|
fileType = 'jpg'
|
||||||
|
}
|
||||||
let valid = supportedFile.filter(item => (
|
let valid = supportedFile.filter(item => (
|
||||||
item.name.toLowerCase() == fileType.toLowerCase()
|
item.name.toLowerCase() == fileType.toLowerCase()
|
||||||
))
|
))
|
||||||
@@ -615,7 +618,10 @@ const isValidFile = (file, supportedFile=[]) => {
|
|||||||
|
|
||||||
//FUNCTIONS TO CHECK IF FILE SIZE IS VALID
|
//FUNCTIONS TO CHECK IF FILE SIZE IS VALID
|
||||||
const isValidFileSize = (file, supportedFile=[]) => {
|
const isValidFileSize = (file, supportedFile=[]) => {
|
||||||
let fileType = file.type.split("/")[1];
|
let fileType = file.type.split("/")[1].toLowerCase();
|
||||||
|
if(fileType=='jpg' || fileType=='jpeg'){ //forcing both JPG and JPEG TO RETURN JPG AS FILE TYPE
|
||||||
|
fileType = 'jpg'
|
||||||
|
}
|
||||||
let fileSize = file.size;
|
let fileSize = file.size;
|
||||||
let valid = supportedFile.filter(item => (
|
let valid = supportedFile.filter(item => (
|
||||||
item.name.toLowerCase() == fileType.toLowerCase()
|
item.name.toLowerCase() == fileType.toLowerCase()
|
||||||
@@ -627,6 +633,6 @@ const isValidFileSize = (file, supportedFile=[]) => {
|
|||||||
return {status: false, message: `File must not exceed ${valid[0].max_size_mb}MB`}
|
return {status: false, message: `File must not exceed ${valid[0].max_size_mb}MB`}
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
return false
|
return {status: false, message: `Cannot read file size, try again`}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,12 +52,19 @@ const EditJobPopOut = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { userDetails } = useSelector((state) => state.userDetails);
|
const { userDetails } = useSelector((state) => state.userDetails);
|
||||||
|
const { walletDetails } = useSelector((state) => state.walletDetails);
|
||||||
|
|
||||||
const uploadedImage = `${userDetails.session_image_server}${localStorage.getItem('session_token')}/job/${details?.job_uid}`
|
const uploadedImage = `${
|
||||||
|
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,
|
||||||
@@ -113,65 +120,100 @@ 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
|
||||||
|
const isIOS = /MacIntel|MacPPC/.test(navigator.platform) && !window.MSStream;
|
||||||
|
|
||||||
|
// Check if the user is using Windows
|
||||||
|
const isWindows = /Windows/.test(navigator.userAgent);
|
||||||
|
|
||||||
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">
|
||||||
@@ -325,19 +367,20 @@ const EditJobPopOut = ({
|
|||||||
role="group"
|
role="group"
|
||||||
aria-labelledby="checked-group"
|
aria-labelledby="checked-group"
|
||||||
>
|
>
|
||||||
{categories && Object.entries(categories)?.map(([key, value]) => (
|
{categories &&
|
||||||
<label
|
Object.entries(categories)?.map(([key, value]) => (
|
||||||
key={key}
|
<label
|
||||||
className="flex gap-1 w-full items-center"
|
key={key}
|
||||||
>
|
className="flex gap-1 w-full items-center"
|
||||||
<Field
|
>
|
||||||
type="checkbox"
|
<Field
|
||||||
name="category"
|
type="checkbox"
|
||||||
value={key}
|
name="category"
|
||||||
/>
|
value={key}
|
||||||
<span className="text-[13.975px]">{value}</span>
|
/>
|
||||||
</label>
|
<span className="text-[13.975px]">{value}</span>
|
||||||
))}
|
</label>
|
||||||
|
))}
|
||||||
<span className="h-5 text-sm italic text-[#cf3917]">
|
<span className="h-5 text-sm italic text-[#cf3917]">
|
||||||
{props.errors.category &&
|
{props.errors.category &&
|
||||||
props.touched.category &&
|
props.touched.category &&
|
||||||
@@ -356,24 +399,33 @@ const EditJobPopOut = ({
|
|||||||
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"
|
||||||
@@ -433,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">
|
||||||
@@ -448,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>
|
||||||
|
|||||||
@@ -133,9 +133,9 @@ function OfferJobPopout({ details, onClose, situation }) {
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="md:flex bg-white rounded-lg shadow-lg">
|
<div className="md:flex bg-white dark:bg-dark-white rounded-lg shadow-lg">
|
||||||
<div className="p-4 w-full md:w-3/4 md:border-r-2">
|
<div className="p-4 w-full md:w-3/4 md:border-r-2">
|
||||||
<p className="text-lg my-5 font-semibold text-slate-900 tracking-wide">
|
<p className="text-lg my-5 font-semibold text-slate-900 dark:text-white tracking-wide">
|
||||||
{details.title}
|
{details.title}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user