Compare commits

...

21 Commits

Author SHA1 Message Date
victorAnumudu c4cc27490b wallet balance formatted 2023-06-22 15:14:43 +01:00
ameye 90b609d457 Merge branch 'new-price-formatter' of WrenchBoard/Users-Wrench into master 2023-06-22 13:40:47 +00:00
victorAnumudu a6c6c36fbc price formatter style changed 2023-06-22 14:24:56 +01:00
ameye 03b79f0e0c Merge branch 'Cookies-addition-for-family' of WrenchBoard/Users-Wrench into master 2023-06-22 10:43:50 +00:00
Ebube 0af52df1d2 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into Cookies-addition-for-family 2023-06-22 11:42:20 +01:00
ameye 9e1a68f81a Merge branch 'JobList-Categories' of WrenchBoard/Users-Wrench into master 2023-06-22 10:37:26 +00:00
Ebube 12e4b7824a Added Cookies for family 2023-06-22 10:01:39 +01:00
Ebube 5769332e74 . 2023-06-22 08:42:42 +01:00
ameye bab0296f4f Merge branch 'offer-interest-format' of WrenchBoard/Users-Wrench into master 2023-06-21 15:06:12 +00:00
victorAnumudu d457550d58 offer interest page formatted 2023-06-21 15:58:40 +01:00
ameye f106e17ce6 Merge branch 'market-toggle-position' of WrenchBoard/Users-Wrench into master 2023-06-21 10:52:13 +00:00
victorAnumudu 8f1d2b6584 market category toggle position changed 2023-06-21 10:02:47 +01:00
ameye 3a3503447a Merge branch 'market-list-toggle' of WrenchBoard/Users-Wrench into master 2023-06-20 22:34:26 +00:00
ameye e46d2bea8d Merge branch 'JobList-Categories' of WrenchBoard/Users-Wrench into master 2023-06-20 22:34:15 +00:00
victorAnumudu b05c519571 adjusted market toggle position 2023-06-20 22:48:55 +01:00
victorAnumudu 48ab2d80ad market list toggle added, thumbnail images added in add pay card page 2023-06-20 22:37:18 +01:00
Ebube 47876875cf done 2023-06-20 21:33:18 +01:00
ameye d78ad0b648 Merge branch 'JobList-Categories' of WrenchBoard/Users-Wrench into master 2023-06-20 19:52:15 +00:00
Ebube d63690a43c Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into JobList-Categories 2023-06-20 20:47:36 +01:00
Ebube 3ce97a4b76 . 2023-06-20 20:46:51 +01:00
ameye 6e9af99d46 Merge branch 'paycard-listing' of WrenchBoard/Users-Wrench into master 2023-06-20 19:44:35 +00:00
25 changed files with 469 additions and 221 deletions
+1 -1
View File
@@ -89,7 +89,7 @@ export default function Routers() {
<Route exact path="/notification" element={<Notification />} /> <Route exact path="/notification" element={<Notification />} />
<Route exact path="/mytask" element={<MyTaskPage />} /> <Route exact path="/mytask" element={<MyTaskPage />} />
<Route exact path="/myjobs" element={<MyJobsPage />} /> <Route exact path="/myjobs" element={<MyJobsPage />} />
{/* <Route exact path="/add-job" element={<AddJobPage />} /> */} <Route exact path="/add-job" element={<AddJobPage />} />
<Route exact path="/my-active-jobs" element={<MyActiveJobsPage />} /> <Route exact path="/my-active-jobs" element={<MyActiveJobsPage />} />
<Route exact path="/my-pastdue-jobs" element={<MyPastDueJobsPage />} /> <Route exact path="/my-pastdue-jobs" element={<MyPastDueJobsPage />} />
<Route exact path="/my-pending-jobs" element={<MyPendingJobsPage />} /> <Route exact path="/my-pending-jobs" element={<MyPendingJobsPage />} />
+61 -62
View File
@@ -3,11 +3,8 @@ import { Link } from "react-router-dom";
import InputCom from "../Helpers/Inputs/InputCom"; import InputCom from "../Helpers/Inputs/InputCom";
import LoadingSpinner from "../Spinners/LoadingSpinner"; import LoadingSpinner from "../Spinners/LoadingSpinner";
import usersService from "../../services/UsersService"; import usersService from "../../services/UsersService";
import { useSelector, useDispatch } from "react-redux"; import { useSelector, useDispatch } from "react-redux";
import { tableReload } from "../../store/TableReloads"; import { tableReload } from "../../store/TableReloads";
import { Field, Form, Formik } from "formik"; import { Field, Form, Formik } from "formik";
import * as Yup from "yup"; import * as Yup from "yup";
@@ -36,9 +33,10 @@ const validationSchema = Yup.object().shape({
.typeError("you must specify a number") .typeError("you must specify a number")
.min(1, "Price must be greater than 0") .min(1, "Price must be greater than 0")
.required("Timeline is required"), .required("Timeline is required"),
category: Yup.array().min(1, "Select at least one checkbox"),
}); });
function AddJob({ popUpHandler }) { function AddJob({ popUpHandler, categories }) {
const ApiCall = new usersService(); const ApiCall = new usersService();
let dispatch = useDispatch(); let dispatch = useDispatch();
@@ -58,6 +56,7 @@ function AddJob({ popUpHandler }) {
description: "", description: "",
job_detail: "", job_detail: "",
timeline_days: "", timeline_days: "",
category: [],
}; };
let [requestStatus, setRequestStatus] = useState({ let [requestStatus, setRequestStatus] = useState({
@@ -88,6 +87,7 @@ function AddJob({ popUpHandler }) {
// FUNCTION TO HANDLE ADD JOB FORM // FUNCTION TO HANDLE ADD JOB FORM
const handleAddJob = (values, helpers) => { const handleAddJob = (values, helpers) => {
values.category = values.category?.join("@");
setRequestStatus({ loading: true, status: false, message: "" }); setRequestStatus({ loading: true, status: false, message: "" });
ApiCall.jobManagerCreateJob(values) ApiCall.jobManagerCreateJob(values)
.then((res) => { .then((res) => {
@@ -127,6 +127,7 @@ function AddJob({ popUpHandler }) {
getUserCountry(); getUserCountry();
}, []); }, []);
return ( return (
<div className="add-job p-5 w-full bg-white rounded-md flex flex-col justify-between"> <div className="add-job p-5 w-full bg-white rounded-md flex flex-col justify-between">
<Formik <Formik
@@ -187,13 +188,6 @@ function AddJob({ popUpHandler }) {
</option> </option>
)} )}
</select> </select>
<div className={`${!props.errors && "invisible"} h-5`}>
{props.errors.country && props.touched.country && (
<p className="text-sm text-red-500">
{props.errors.country}
</p>
)}
</div>
</div> </div>
{/* Price */} {/* Price */}
@@ -209,14 +203,8 @@ function AddJob({ popUpHandler }) {
value={props.values.price} value={props.values.price}
inputHandler={props.handleChange} inputHandler={props.handleChange}
blurHandler={props.handleBlur} blurHandler={props.handleBlur}
errorBorder={props.errors.price && props.touched.price}
/> />
<div className={`${!props.errors && "invisible"} h-5`}>
{props.errors.price && props.touched.price && (
<p className="text-sm text-red-500">
{props.errors.price}
</p>
)}
</div>
</div> </div>
</div> </div>
@@ -233,14 +221,8 @@ function AddJob({ popUpHandler }) {
value={props.values.title} value={props.values.title}
inputHandler={props.handleChange} inputHandler={props.handleChange}
blurHandler={props.handleBlur} blurHandler={props.handleBlur}
errorBorder={props.errors.title && props.touched.title}
/> />
<div className={`${!props.errors && "invisible"} h-5`}>
{props.errors.title && props.touched.title && (
<p className="text-sm text-red-500">
{props.errors.title}
</p>
)}
</div>
</div> </div>
{/* Description */} {/* Description */}
@@ -255,42 +237,64 @@ function AddJob({ popUpHandler }) {
value={props.values.description} value={props.values.description}
inputHandler={props.handleChange} inputHandler={props.handleChange}
blurHandler={props.handleBlur} blurHandler={props.handleBlur}
errorBorder={props.errors.description && props.touched.description}
/> />
<div className={`${!props.errors && "invisible"} h-5`}>
{props.errors.description &&
props.touched.description && (
<p className="text-sm text-red-500">
{props.errors.description}
</p>
)}
</div>
</div> </div>
{/* Details */} {/* Details */}
<div className="field w-full mb-[5px]"> <div className="field flex flex-col sm:flex-row w-full mb-[5px] gap-2">
<label <div className="sm:w-[60%] w-full">
htmlFor="Job Delivery Details" <label
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"' htmlFor="Job Delivery Details"
> className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'
Job Delivery Details >
</label> Job Delivery Details
<textarea </label>
id="Job Delivery Details" <textarea
rows="7" id="Job Delivery Details"
className={`input-field p-6 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-full bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`} rows="5"
style={{ resize: "none" }} className={`input-field px-6 py-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[100px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] border border-[#dce4e9] rounded-[10px]`}
name="job_detail" style={{ resize: "none" }}
value={props.values.job_detail} name="job_detail"
onChange={props.handleChange} value={props.values.job_detail}
onBlur={props.handleBlur} onChange={props.handleChange}
/> onBlur={props.handleBlur}
<div className={`${!props.errors && "invisible"} h-5`}> />
</div>
<div className="sm:w-[35%] w-full">
<div
htmlFor="Job Categories"
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'
id="checked-group"
>
Categories
</div>
<div
className="sm:flex-col flex flex-wrap px-3 mt-3"
role="group"
aria-labelledby="checked-group"
>
{Object.entries(categories).map(([key, value]) => (
<label key={key} className="flex gap-1 w-full items-center">
<Field
type="checkbox"
name="category"
value={key}
/>
<span className="text-[13.975px]">{value}</span>
</label>
))}
</div>
</div>
{/* <div className={`${!props.errors && "invisible"} h-5`}>
{props.errors.job_detail && props.touched.job_detail && ( {props.errors.job_detail && props.touched.job_detail && (
<p className="text-sm text-red-500"> <p className="text-sm text-red-500">
{props.errors.job_detail} {props.errors.job_detail}
</p> </p>
)} )}
</div> </div> */}
</div> </div>
<div className="field w-full mb-[5px]"> <div className="field w-full mb-[5px]">
@@ -322,14 +326,6 @@ function AddJob({ popUpHandler }) {
</option> </option>
))} ))}
</Field> </Field>
<div className={`${!props.errors && "invisible"} h-5`}>
{props.errors.timeline_days &&
props.touched.timeline_days && (
<p className="text-sm text-red-500">
{props.errors.timeline_days}
</p>
)}
</div>
</div> </div>
{/* inputs ends here */} {/* inputs ends here */}
</div> </div>
@@ -356,13 +352,16 @@ function AddJob({ popUpHandler }) {
))} ))}
{/* End of error or success display */} {/* End of error or success display */}
<div className="w-full h-[120px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center"> <div className="w-full h-[70px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
<div className="flex items-center space-x-4 mr-9"> <div className="flex items-center space-x-4 mr-9">
<Link <Link
to="/myjobs" to="/myjobs"
className="text-18 text-light-red tracking-wide " className="text-18 text-light-red tracking-wide "
> >
<span className="border-b dark:border-[#5356fb29] border-light-red"> <span
className="border-b dark:border-[#5356fb29] border-light-red"
onClick={popUpHandler}
>
{" "} {" "}
Cancel Cancel
</span> </span>
+21 -3
View File
@@ -18,6 +18,9 @@ export default function Login() {
const dispatch = useDispatch(); const dispatch = useDispatch();
let [loginType, setLoginType] = useState({ full: true, family: false }); let [loginType, setLoginType] = useState({ full: true, family: false });
const [selectedLoginType, setSelectedLoginType] = useState(
document.cookie.includes("loginType=family") ? "loginfamily" : "loginfull"
);
const [checked, setValue] = useState(false); const [checked, setValue] = useState(false);
const [loginLoading, setLoginLoading] = useState(false); const [loginLoading, setLoginLoading] = useState(false);
@@ -77,6 +80,10 @@ export default function Login() {
login_mode: 1100, login_mode: 1100,
action: 11025, action: 11025,
}; };
// Clear the loginType cookie if the user switches to loginfull
document.cookie =
"loginType=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
} else if (name == "loginfamily") { } else if (name == "loginfamily") {
// Post Data Info for family Login // Post Data Info for family Login
postData = { postData = {
@@ -86,6 +93,8 @@ export default function Login() {
login_mode: 1105, login_mode: 1105,
action: 11025, action: 11025,
}; };
// Set the loginType cookie to remember the user's selection
document.cookie = "loginType=family; path=/;";
} else { } else {
setLoginLoading(false); setLoginLoading(false);
setMsgError("Invalid Login Type. Consider refreshing the page"); setMsgError("Invalid Login Type. Consider refreshing the page");
@@ -127,15 +136,24 @@ export default function Login() {
}; };
const googleLogin = useGoogleLogin({ const googleLogin = useGoogleLogin({
flow: 'auth-code', flow: "auth-code",
ux_mode:'redirect', ux_mode: "redirect",
redirect_uri: process.env.REACT_APP_GOOGLE_REDIRECT_URL, redirect_uri: process.env.REACT_APP_GOOGLE_REDIRECT_URL,
onSuccess: async (codeResponse) => { onSuccess: async (codeResponse) => {
console.log("GOOGLE LOGIN GOOD --- ",codeResponse); console.log("GOOGLE LOGIN GOOD --- ", codeResponse);
}, },
onError: (errorResponse) => console.log(errorResponse), onError: (errorResponse) => console.log(errorResponse),
}); });
// In order to update the selected login type whenever the component renders
useEffect(() => {
setSelectedLoginType(
document.cookie.includes("loginType=family") ? "loginfamily" : "loginfull"
);
}, []);
console.log("Looking for the cookies >>", selectedLoginType)
useEffect(() => { useEffect(() => {
setMail(""); setMail("");
setPassword(""); setPassword("");
@@ -3,11 +3,13 @@ import { Link, useNavigate } from "react-router-dom";
import MarketPopUp from "../MarketPlace/PopUp/MarketPopUp"; import MarketPopUp from "../MarketPlace/PopUp/MarketPopUp";
import usersService from "../../services/UsersService"; import usersService from "../../services/UsersService";
import { PriceFormatter } from "../Helpers/PriceFormatter"; import { PriceFormatter } from "../Helpers/PriceFormatter";
import dataImage2 from "../../assets/images/data-table-user-2.png";
export default function AvailableJobsCard({ export default function AvailableJobsCard({
className, className,
datas, datas,
hidden = false, hidden = false,
contentDisplay
}) { }) {
//debugger; //debugger;
const [marketPopUp, setMarketPopUp] = useState({ show: false, data: {} }); const [marketPopUp, setMarketPopUp] = useState({ show: false, data: {} });
@@ -49,6 +51,7 @@ export default function AvailableJobsCard({
}, []); }, []);
return ( return (
<> <>
{contentDisplay == 'grid' ?
<div <div
className={`card-style-two w-full h-[426px] p-[20px] bg-white dark:bg-dark-white rounded-2xl section-shadow ${ className={`card-style-two w-full h-[426px] p-[20px] bg-white dark:bg-dark-white rounded-2xl section-shadow ${
className || "" className || ""
@@ -145,6 +148,78 @@ export default function AvailableJobsCard({
</div> </div>
</div> </div>
</div> </div>
:
<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="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" />
</div>
<div className="flex flex-col flex-[0.9]">
<Link to="/shop-details" className="">
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{datas?.title}
</h1>
</Link>
<div className="my-2">
<p className="text-dark-gray dark:text-white">{datas?.description}</p>
</div>
{/* <div className="card-two-info flex gap-2 items-center">
<div className="owned-by flex space-x-2 items-center">
<div>
<p className="text-thin-light-gray text-sm leading-3">Added</p>
<p className="text-base text-dark-gray dark:text-white">
{datas.offer_added}
</p>
</div>
</div>
<div className="w-[1px] bg-light-purple dark:bg-dark-light-purple h-7"></div>
<div className="created-by flex space-x-2 items-center flex-row-reverse">
<div>
<p className="text-thin-light-gray text-sm leading-3 text-right">
Expires
</p>
<p className="text-base text-dark-gray dark:text-white text-right">
{datas.expire}
</p>
</div>
</div>
</div> */}
<div className="block sm:flex flex-wrap gap-4">
<p className="text-sm text-thin-light-gray flex flext-start gap-1">
Price: <span className="text-purple">{thePrice}</span>
</p>
<p className="text-sm text-thin-light-gray">
Duration:{" "}
<span className="text-purple italic">
{" "}
{datas?.timeline_days} day(s)
</span>
</p>
<p className="text-sm text-thin-light-gray">
Code:{" "}
<span className="text-purple">
{" "}
{datas?.offer_code}
</span>
</p>
</div>
</div>
</div>
<div className="">
<button
type="button"
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
onClick={() => {
setMarketPopUp({ show: true, data: datas });
}}
>
View
</button>
</div>
</div>
}
{marketPopUp.show && ( {marketPopUp.show && (
<MarketPopUp <MarketPopUp
details={datas} details={datas}
@@ -72,7 +72,7 @@ export default function FamilyTasks({ familyData, className, loader }) {
{value.title} {value.title}
</h1> </h1>
<div className="flex gap-4 items-center"> <div className="flex gap-4 items-center">
<span className="text-sm text-thin-light-gray"> <span className="text-sm text-thin-light-gray flex flex-start gap-1">
Price:{" "} Price:{" "}
<span className="text-purple"> <span className="text-purple">
{thePrice} {thePrice}
+10
View File
@@ -1,5 +1,9 @@
import React from "react"; import React from "react";
import ATMCard from '../../assets/images/card.svg'
import VisaCard from '../../assets/images/visa.svg'
import MasterCard from '../../assets/images/master.svg'
export default function Icons({ name }) { export default function Icons({ name }) {
return ( return (
<> <>
@@ -483,6 +487,12 @@ export default function Icons({ name }) {
c0.3,0,0.5-0.1,0.7-0.3l5.7-5.7c0,0,0,0,0,0C15.9,12.3,15.9,11.7,15.5,11.3z" c0.3,0,0.5-0.1,0.7-0.3l5.7-5.7c0,0,0,0,0,0C15.9,12.3,15.9,11.7,15.5,11.3z"
></path> ></path>
</svg> </svg>
) : name === "atm-card" ? (
<img className="w-[20px]" src={ATMCard} alt="card" />
) : name === "visa-card" ? (
<img className="w-[20px]" src={VisaCard} alt="card" />
) : name === "master-card" ? (
<img className="w-[20px]" src={MasterCard} alt="card" />
) : ( ) : (
"" ""
)} )}
@@ -21,7 +21,8 @@ export default function InputCom({
blurHandler, blurHandler,
spanTag, spanTag,
inputBg, inputBg,
direction direction,
errorBorder
}) { }) {
const inputRef = useRef(null); const inputRef = useRef(null);
// Entry Validation // Entry Validation
@@ -73,7 +74,7 @@ export default function InputCom({
)} )}
</div> </div>
<div <div
className={`input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base ${inputClass}`} className={`input-wrapper border ${errorBorder ? "border-red-500 border-[0.5px] animate-shake" : "border border-[#f5f8fa] dark:border-[#5e6278]"} w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base ${inputClass}`}
> >
<input <input
placeholder={placeholder} placeholder={placeholder}
@@ -94,8 +95,12 @@ export default function InputCom({
dir={direction} dir={direction}
/> />
{iconName && ( {iconName && (
<div className="absolute right-6 bottom-[10px] z-10"> <div className="absolute right-6 bottom-[10px] z-10 flex gap-2">
<Icons name={iconName} /> {
iconName.split(' ').map((item, index)=>(
<Icons key={index} name={item} />
))
}
</div> </div>
)} )}
{passIcon && ( {passIcon && (
+45 -13
View File
@@ -1,16 +1,48 @@
export const PriceFormatter = (price, currency, currencyName) => { import React from 'react'
const supportedCurrencies = ["USD", "EUR", "GBP"];
const symbolFormatter = supportedCurrencies.includes(currency)
? currency
: undefined;
const formatter = new Intl.NumberFormat("en", { // export const PriceFormatter = (price, currency, currencyName) => {
style: symbolFormatter, // const supportedCurrencies = ["USD", "EUR", "GBP"];
currencyDisplay: "symbol", // const symbolFormatter = supportedCurrencies.includes(currency)
minimumFractionDigits: 2, // ? currency
}); // : undefined;
const displayCurrencyName = symbolFormatter ? "" : currencyName; // const formatter = new Intl.NumberFormat("en", {
// style: symbolFormatter,
// currencyDisplay: "symbol",
// minimumFractionDigits: 2,
// });
return `${formatter.format(price)} ${displayCurrencyName}`; // const displayCurrencyName = symbolFormatter ? "" : currencyName;
};
// return `${formatter.format(price)} ${displayCurrencyName}`;
// };
export const PriceFormatter = (price='00', currency='', currencyName='') => {
// Convert the number to a string
let numStr = String(price);
// Split the string into integer and decimal parts
let parts = numStr.split('.');
let integerPart = parts[0];
let decimalPart = parts[1] || '';
// Add thousands separators to the integer part
// let formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
let formattedInteger = integerPart;
// Truncate or pad the decimal part to two decimal points
let formattedDecimal = decimalPart.slice(0, 2).padEnd(2, '0');
// Combine the formatted integer and decimal parts
// let formattedNumber = formattedInteger + '.' + formattedDecimal;
// return formattedNumber;
return (
<span className='text-sm flex items-center'>
<sup>{currency || currencyName || ''}</sup>
<span className='px-1 font-bold text-lg'>{formattedInteger}</span>
<sup>{formattedDecimal}</sup>
</span>
)
}
+2 -2
View File
@@ -1,7 +1,7 @@
import React, { useState } from "react"; import React, { useState } from "react";
import useToggle from "../../../hooks/useToggle"; import useToggle from "../../../hooks/useToggle";
function SelectBox({ datas = [], className, action, contentBodyClasses }) { function SelectBox({ datas = [], className, action, contentBodyClasses, position }) {
const [item, setItem] = useState(datas[0]); const [item, setItem] = useState(datas[0]);
// custom hook // custom hook
const [toggle, setToggle] = useToggle(false); const [toggle, setToggle] = useToggle(false);
@@ -49,7 +49,7 @@ function SelectBox({ datas = [], className, action, contentBodyClasses }) {
<div <div
style={{ boxShadow: "0px 4px 87px 0px #0000002B" }} style={{ boxShadow: "0px 4px 87px 0px #0000002B" }}
className={`drop-down-content w-[120px] bg-white dark:bg-dark-white rounded-[4px] p-3 absolute right-0 top-[100%] z-20 ${ className={`drop-down-content w-[120px] bg-white dark:bg-dark-white rounded-[4px] p-3 absolute ${position =='left' ? 'left-0' : 'right-0'} top-[100%] z-20 ${
toggle ? "active" : "" toggle ? "active" : ""
} ${contentBodyClasses || ""}`} } ${contentBodyClasses || ""}`}
> >
+42 -7
View File
@@ -1,6 +1,9 @@
import React, { useEffect, useMemo, useState } from "react"; import React, { useEffect, useMemo, useState } from "react";
import DataIteration from "../Helpers/DataIteration"; import DataIteration from "../Helpers/DataIteration";
import AvailableJobsCard from "../Cards/AvailableJobsCard"; import AvailableJobsCard from "../Cards/AvailableJobsCard";
import ListView from '../../assets/images/list-view.png'
import GridView from '../../assets/images/grid-view.svg'
import SelectBox from "../Helpers/SelectBox";
export default function MainSection({ export default function MainSection({
className, className,
@@ -12,7 +15,9 @@ export default function MainSection({
() => ({ All: "All Categories", ...categories }), () => ({ All: "All Categories", ...categories }),
[categories] [categories]
); );
const [tab, setTab] = useState(marketCategories.All); const [tab, setTab] = useState(Object.keys(marketCategories)[0]);
let [contentDisplay, setContentDisplay] = useState('grid') // STATE TO HOLD LIST VIEW STYLE
// Convert to array in order to map // Convert to array in order to map
const mappedArray = Object.entries(marketCategories).map(([key, value]) => { const mappedArray = Object.entries(marketCategories).map(([key, value]) => {
@@ -23,8 +28,18 @@ export default function MainSection({
const tabHandler = (value) => { const tabHandler = (value) => {
setTab(value); setTab(value);
}; };
// Handles the category selection on mobile view
const handleSetCategory = (value) => {
for (let i in marketCategories) {
if (marketCategories[i] == value) {
setTab(i);
}
}
};
useEffect(() => { useEffect(() => {
if (tab === marketCategories.All) { if (tab === "All") {
setProducts(marketPlaceProduct); setProducts(marketPlaceProduct);
} else { } else {
const filteredProducts = marketPlaceProduct.filter((product) => const filteredProducts = marketPlaceProduct.filter((product) =>
@@ -37,9 +52,9 @@ export default function MainSection({
return ( return (
<div className={`market-place-section w-full ${className || ""}`}> <div className={`market-place-section w-full ${className || ""}`}>
<div className="market-place-wrapper w-full"> <div className="market-place-wrapper w-full">
<div className="filter-navigate-area lg:flex justify-between mb-8 items-center"> <div className="filter-navigate-area flex justify-between items-center mb-8">
<div className="tab-item lg:mb-0 mb-5"> <div className="tab-item w-full flex items-center">
<div className="md:flex md:space-x-8 space-x-2"> <div className="hidden lg:flex md:space-x-8 space-x-2">
{mappedArray.map(({ key, value }) => ( {mappedArray.map(({ key, value }) => (
<span <span
key={key} key={key}
@@ -54,17 +69,37 @@ export default function MainSection({
</span> </span>
))} ))}
</div> </div>
{/* market categories on screen smaller than large screen */}
<div className="w-[80%] lg:hidden">
<SelectBox
action={handleSetCategory}
datas={Object.values(marketCategories)}
className="Update-table-dropdown"
contentBodyClasses="w-auto min-w-max"
position='left'
/>
</div>
</div> </div>
{/* contentDisplay toggler */}
<div className="p-2 w-[35px] h-[35px] bg-white dark:bg-slate-200 rounded-lg">
<img
title={contentDisplay=='grid'? 'list view' : 'grid view'}
onClick={()=>setContentDisplay((prev)=>prev=='grid'? 'list' : 'grid')}
src={contentDisplay=='grid'? ListView : GridView}
className="w-full h-full cursor-pointer" alt="view"
/>
</div>
{/* end of contentDisplay toggler */}
</div> </div>
<div className="filter-navigate-content w-full min-h-screen"> <div className="filter-navigate-content w-full min-h-screen">
<div className="grid lg:grid-cols-3 sm:grid-cols-2 gap-[30px]"> <div className={contentDisplay == 'grid' ? 'grid lg:grid-cols-3 sm:grid-cols-2 gap-[30px]' : 'w-full'}>
<DataIteration <DataIteration
datas={products} datas={products}
startLength={process.env.REACT_APP_ZERO_STATE} startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products?.length} endLength={products?.length}
> >
{({ datas }) => ( {({ datas }) => (
<AvailableJobsCard key={datas.id} datas={datas} /> <AvailableJobsCard contentDisplay={contentDisplay} key={datas.id} datas={datas} />
)} )}
</DataIteration> </DataIteration>
</div> </div>
@@ -4,6 +4,7 @@ import { toast } from "react-toastify";
import { Form, Formik } from "formik"; import { Form, Formik } from "formik";
import usersService from "../../../services/UsersService"; import usersService from "../../../services/UsersService";
import LoadingSpinner from "../../Spinners/LoadingSpinner"; import LoadingSpinner from "../../Spinners/LoadingSpinner";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
const MarketPopUp = ({ details, onClose, situation, marketInt }) => { const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
const [marketMsg, setMarketMsg] = useState({ const [marketMsg, setMarketMsg] = useState({
@@ -96,14 +97,18 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
[apiCall, details, onClose, textValue] [apiCall, details, onClose, textValue]
); );
console.log('Checking my mangeInt',manageInt) let thePrice = PriceFormatter(
details?.price * 0.01,
details?.currency_code,
details?.currency
);
// let addedIntDate = marketInt?.added?.split(" ")[0]; // let addedIntDate = marketInt?.added?.split(" ")[0];
let expireIntDate = marketInt?.expire?.split(" ")[0]; let expireIntDate = marketInt?.expire?.split(" ")[0];
return ( return (
<ModalCom action={onClose} situation={situation} className="edit-popup"> <ModalCom action={onClose} situation={situation} className="edit-popup">
<div className="logout-modal-wrapper md:w-[750px] md:h-[700px] h-full bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto"> <div className="logout-modal-wrapper md:w-[750px] md:h-[660px] h-full bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px]"> <div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px]">
<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.offer_code} {details.offer_code}
@@ -112,8 +117,8 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
</div> </div>
<div className="md:flex bg-white rounded-lg"> <div className="md:flex bg-white rounded-lg">
<div className="p-4 w-full md:w-3/4 md:border-r-1"> <div className="p-4 w-full md:w-[75%] md:border-r-1">
<div className="min-h-[290px]"> <div className="min-h-[263px]">
<h2 className="font-semibold text-slate-900 dark:text-black tracking-wide"> <h2 className="font-semibold text-slate-900 dark:text-black tracking-wide">
{details?.title} {details?.title}
</h2> </h2>
@@ -128,7 +133,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
name: "", name: "",
content: { content: {
text: `Timeline: ${details.timeline_days} day(s) -- `, text: `Timeline: ${details.timeline_days} day(s) -- `,
bold: `Budget: ${details.price} naira`, bold: `Budget: ${thePrice}`,
}, },
}, },
{ {
@@ -138,7 +143,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
}, },
].map(({ name, content, danger }, idx) => ( ].map(({ name, content, danger }, idx) => (
<div className={`my-3 md:flex items-center`} key={idx}> <div className={`my-3 md:flex items-center`} key={idx}>
<label className="w-full md:w-1/4 text-slate-900 tracking-wide font-semibold"> <label className="w-full md:w-[19%] text-slate-900 tracking-wide font-semibold whitespace-pre-wrap">
{name} {name}
</label> </label>
<div <div
@@ -156,15 +161,19 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
}} }}
/> />
) : ( ) : (
<p className={`w-full md:w-3/4 text-slate-900`}> <p className={`w-full text-slate-900`}>
{name !== "Delivery Detail" ? ( {name !== "Delivery Detail" ? (
<> <>
{typeof content !== "object" ? content : null} {typeof content !== "object" ? content : null}
{typeof content === "object" && ( {typeof content === "object" && (
<span className="flex items-center gap-2"> <>
{content?.text} <hr className="mb-1" />
<strong>{content?.bold}</strong> <span className="flex items-center gap-2">
</span> {content?.text}
<strong>{content?.bold}</strong>
</span>
<hr className="mt-1" />
</>
)} )}
</> </>
) : ( ) : (
@@ -207,15 +216,15 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
</div> </div>
</div> </div>
<div className="w-full md:w-1/4 h-full "> <div className="w-full md:w-[23%] h-full ">
<div className="w-[90%] mx-auto bg-[#f1f8ff] p-4 rounded-md md:min-h-[550px] flex flex-col justify-between"> <div className="mx-auto bg-[#f1f8ff] p-4 rounded-md md:min-h-[498px] flex flex-col justify-between">
<div className="w-full flex flex-col justify-center py-4 gap-2"> <div className="w-full flex flex-col justify-center py-4 gap-2">
<p className="w-full text-slate-900 tracking-wide my-1"> <p className="w-full text-slate-900 tracking-wide my-1">
Interested in the task? Interested in the task?
</p> </p>
<hr /> <hr />
<button <button
className="bg-[#57cd89] text-center text-lg font-semibold text-white py-2 px-4 rounded-md inline-flex flex-col items-center justify-center" className="bg-[#57cd89] text-center text-lg font-semibold text-white py-2 px-4 rounded-md inline-flex sm:flex-col flex-row sm:gap-0 gap-1 items-center justify-center"
name="market-interest" name="market-interest"
onClick={marketCalls} onClick={marketCalls}
> >
@@ -251,6 +260,13 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
<p className="my-1">Expire: {expireIntDate}</p> <p className="my-1">Expire: {expireIntDate}</p>
</div> </div>
</div> </div>
<button
className="self-end w-[150px] mt-2 h-[52px] rounded-md text-base bg-transparent border border-red-500 text-red-500 mx-auto"
name="cancel"
onClick={onClose}
>
Cancel
</button>
</div> </div>
{/* END OF ACTION SECTION */} {/* END OF ACTION SECTION */}
</div> </div>
@@ -68,7 +68,7 @@ export default function MyActiveJobTable({ MyJobList, className }) {
{value.title} {value.title}
</h1> </h1>
<div>{value.description}</div> <div>{value.description}</div>
<span className="text-sm text-thin-light-gray"> <span className="text-sm text-thin-light-gray flex flext-start gap-1">
Price:{" "} Price:{" "}
<span className="text-purple"> <span className="text-purple">
{thePrice} {thePrice}
+2 -1
View File
@@ -119,7 +119,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
{value.title} {value.title}
</h1> </h1>
<div>{value.description}</div> <div>{value.description}</div>
<span className="text-sm text-thin-light-gray"> <span className="text-sm text-thin-light-gray flex items-start gap-1">
Price: <span className="text-purple">{thePrice}</span> Price: <span className="text-purple">{thePrice}</span>
</span> </span>
<span className="text-sm text-thin-light-gray"> <span className="text-sm text-thin-light-gray">
@@ -280,6 +280,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
}} }}
situation={editJob.show} situation={editJob.show}
country={myCountry} country={myCountry}
categories={currentJobCart}
/> />
)} )}
</div> </div>
+9 -1
View File
@@ -10,6 +10,8 @@ export default function MyJobs(props) {
setPopUp((prev) => !prev); setPopUp((prev) => !prev);
}; };
const categoryOptions = props.MyJobList?.data?.categories;
return ( return (
<Layout> <Layout>
<CommonHead commonHeadData={props.commonHeadData} /> <CommonHead commonHeadData={props.commonHeadData} />
@@ -35,7 +37,13 @@ export default function MyJobs(props) {
</div> </div>
{/* Add Job List Popout */} {/* Add Job List Popout */}
{popUp && <AddJobPage action={popUpHandler} situation={popUp} />} {popUp && (
<AddJobPage
action={popUpHandler}
situation={popUp}
categories={categoryOptions}
/>
)}
{/* End of Add Job List Popout */} {/* End of Add Job List Popout */}
</Layout> </Layout>
); );
@@ -67,7 +67,7 @@ export default function MyPendingJobTable({ MyJobList, className }) {
{value.title} {value.title}
</h1> </h1>
<div>{value.description}</div> <div>{value.description}</div>
<span className="text-sm text-thin-light-gray"> <span className="text-sm text-thin-light-gray flex items-start gap-1">
Price:{" "} Price:{" "}
<span className="text-purple"> <span className="text-purple">
{thePrice} {thePrice}
+1 -1
View File
@@ -86,7 +86,7 @@ export default function MyJobTable({ className, ActiveJobList }) {
<span className="text-base text-gray-600"> <span className="text-base text-gray-600">
{task?.description} {task?.description}
</span> </span>
<span className="text-sm text-thin-light-gray"> <span className="text-sm text-thin-light-gray flex flext-start gap-1">
Price: Price:
<span className="text-purple ml-1">{thePrice}</span> <span className="text-purple ml-1">{thePrice}</span>
</span> </span>
+2 -2
View File
@@ -230,7 +230,7 @@ function AddFundDollars(props) {
<InputCom <InputCom
fieldClass="px-6" fieldClass="px-6"
spanTag='*' spanTag='*'
iconName='wallet-two' iconName='master-card visa-card atm-card'
label="Card Number" label="Card Number"
type="text" type="text"
name="cardNum" name="cardNum"
@@ -318,7 +318,7 @@ function AddFundDollars(props) {
<InputCom <InputCom
fieldClass="px-6" fieldClass="px-6"
spanTag='*' spanTag='*'
iconName='wallet-two' iconName='atm-card'
label="CVV" label="CVV"
type="text" type="text"
name="cvv" name="cvv"
+3 -2
View File
@@ -4,6 +4,7 @@ import RecentActivityTable from './WalletComponent/RecentActivityTable'
import PurchasesTable from './WalletComponent/PurchasesTable' import PurchasesTable from './WalletComponent/PurchasesTable'
import CouponTable from './WalletComponent/CouponTable' import CouponTable from './WalletComponent/CouponTable'
import LoadingSpinner from '../Spinners/LoadingSpinner' import LoadingSpinner from '../Spinners/LoadingSpinner'
import { PriceFormatter } from '../Helpers/PriceFormatter'
function Balance({wallet, coupon}) { function Balance({wallet, coupon}) {
return ( return (
@@ -42,11 +43,11 @@ function Balance({wallet, coupon}) {
</div> </div>
<div className='balance-info'> <div className='balance-info'>
<p className='py-2'>Balance</p> <p className='py-2'>Balance</p>
<span className='py-1 px-2 bg-green-100 text-green-500 rounded-lg'>{item.symbol}{(item.amount*0.01).toFixed(2)}</span> <span className='py-1 px-2 bg-green-100 text-green-500 rounded-lg flex flex-start gap-1'>{PriceFormatter(item.amount * 0.01, item.code)}</span>
</div> </div>
<div className='balance-info'> <div className='balance-info'>
<p className='py-2'>Escrow</p> <p className='py-2'>Escrow</p>
<span className='py-1 px-2 bg-red-100 text-red-500 rounded-lg'>{item.symbol}{(item.escrow*0.01).toFixed(2)}</span> <span className='py-1 px-2 bg-red-100 text-red-500 rounded-lg flex flex-start gap-1'>{PriceFormatter(item.escrow * 0.01, item.code)}</span>
</div> </div>
</div> </div>
+2 -4
View File
@@ -5,6 +5,7 @@ import bank2 from "../../assets/images/bank-2.png";
import bank3 from "../../assets/images/bank-3.png"; import bank3 from "../../assets/images/bank-3.png";
import bank4 from "../../assets/images/bank-4.png"; import bank4 from "../../assets/images/bank-4.png";
import Accordion from "../Helpers/Accordion"; import Accordion from "../Helpers/Accordion";
import { PriceFormatter } from "../Helpers/PriceFormatter";
export default function WalletHeader(props) { export default function WalletHeader(props) {
// debugger; // debugger;
@@ -58,10 +59,7 @@ export default function WalletHeader(props) {
</div> </div>
<div> <div>
<p className="eth text-xl font-bold text-purple"> <p className="eth text-xl font-bold text-purple">
{(value.amount * 0.01).toFixed(2)} {value.code} {PriceFormatter(value.amount * 0.01, value.code)}
</p>
<p className="usd text-base text-thin-light-gray text-right">
{/*(773.69 USD)*/}
</p> </p>
</div> </div>
</div> </div>
@@ -143,13 +143,15 @@ export default function ManageInterestOffer(props) {
{/* info tab */} {/* info tab */}
{tab == 'info' ? {tab == 'info' ?
<div className="info-details w-full border-t"> <div className="info-details w-full border-t">
<div className="my-3 flex items-center gap-1"> <div className="my-0 md:my-3 block md:flex items-center gap-10">
<span className="w-[200px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">Name</span> <div className="my-3 md:my-0 flex items-center gap-1">
<span className="min-w-[100px] text-sm font-bold text-dark-gray dark:text-white tracking-wide">{props.offerDetails?.client_name}</span> <span className="w-[200px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">Name</span>
</div> <span className="min-w-[100px] text-sm font-bold text-dark-gray dark:text-white tracking-wide">{props.offerDetails?.client_name}</span>
<div className="my-3 flex items-center gap-1"> </div>
<span className="w-[200px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">Member Since</span> <div className="my-3 md:my-0 flex items-center gap-1">
<span className="min-w-[100px] text-sm font-bold text-dark-gray dark:text-white tracking-wide">{props.offerDetails?.client_added}</span> <span className="w-[200px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">Member Since</span>
<span className="min-w-[100px] text-sm font-bold text-dark-gray dark:text-white tracking-wide">{props.offerDetails?.client_added}</span>
</div>
</div> </div>
<div className="my-3 flex items-center gap-1"> <div className="my-3 flex items-center gap-1">
<span className="w-[200px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">Jobs completed</span> <span className="w-[200px] text-lg font-bold text-dark-gray dark:text-white tracking-wide">Jobs completed</span>
@@ -226,7 +228,7 @@ export default function ManageInterestOffer(props) {
{/* BUTTON section */} {/* BUTTON section */}
<div className="p-4 w-full min-h-full bg-sky-100 dark:bg-dark-gray col-span-1"> <div className="p-4 w-full min-h-full bg-sky-100 dark:bg-dark-gray col-span-1">
<div className="w-full h-full"> <div className="w-full h-full">
<div className="mt-0 sm:mt-10 flex sm:flex-col justify-center items-center gap-10"> <div className="h-full flex sm:flex-col justify-center items-center gap-10">
{requestStatus.loading && requestStatus.processType == 'accept' ? {requestStatus.loading && requestStatus.processType == 'accept' ?
<LoadingSpinner color='sky-blue' size='10' /> <LoadingSpinner color='sky-blue' size='10' />
: :
@@ -235,9 +237,10 @@ export default function ManageInterestOffer(props) {
name='accept' name='accept'
disabled={requestStatus.loading} disabled={requestStatus.loading}
onClick={interestOfferProcess} onClick={interestOfferProcess}
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white" // className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
className='max-w-[150px] h-[100px] bg-[#57cd89] text-center text-lg font-semibold text-white py-2 px-4 rounded-md shadow-md'
> >
Accept Accept this Interest
</button> </button>
} }
@@ -249,9 +252,10 @@ export default function ManageInterestOffer(props) {
name='reject' name='reject'
disabled={requestStatus.loading} disabled={requestStatus.loading}
onClick={interestOfferProcess} onClick={interestOfferProcess}
className="px-2 py-1 h-11 flex justify-center items-center border-gradient text-base rounded-full text-black" // className="px-2 py-1 h-11 flex justify-center items-center border-gradient text-base rounded-full text-black"
className='max-w-[150px] h-[100px] bg-red-300 text-center text-lg font-semibold text-white py-2 px-4 rounded-md shadow-md'
> >
Reject Reject this Interest
</button> </button>
} }
</div> </div>
+1 -1
View File
@@ -118,7 +118,7 @@ function DeleteJobPopout({ details, onClose, situation }) {
<p className="text-xl tracking-wide text-dark-gray dark:text-white"> <p className="text-xl tracking-wide text-dark-gray dark:text-white">
{details.title} {details.title}
</p> </p>
<p className="text-lg tracking-wide text-dark-gray dark:text-white"> <p className="text-lg tracking-wide text-dark-gray dark:text-white flex items-start gap-1">
Price: {details.thePrice} Price: {details.thePrice}
</p> </p>
<p className="text-lg tracking-wide text-dark-gray dark:text-white"> <p className="text-lg tracking-wide text-dark-gray dark:text-white">
+104 -82
View File
@@ -9,9 +9,14 @@ import { useNavigate } from "react-router-dom";
import { tableReload } from "../../store/TableReloads"; import { tableReload } from "../../store/TableReloads";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
const EditJobPopOut = ({ details, onClose, situation, country }) => { const EditJobPopOut = ({
details,
const dispatch = useDispatch() onClose,
situation,
country,
categories,
}) => {
const dispatch = useDispatch();
let [requestStatus, setRequestStatus] = useState({ let [requestStatus, setRequestStatus] = useState({
loading: false, loading: false,
@@ -54,27 +59,31 @@ const EditJobPopOut = ({ details, onClose, situation, country }) => {
description: details?.description, description: details?.description,
job_detail: details?.job_detail, job_detail: details?.job_detail,
timeline_days: details?.timeline_days, timeline_days: details?.timeline_days,
category: details?.category
}; };
console.log("This is the init values for edit job",initialValues)
const jobApi = useMemo(() => new usersService(), []); const jobApi = useMemo(() => new usersService(), []);
const navigate = useNavigate(); const navigate = useNavigate();
const handleEditJob = useCallback( const handleEditJob = useCallback(
async (values) => { async (values) => {
values.category = values.category?.join("@");
setRequestStatus({ loading: true, message: "" }); setRequestStatus({ loading: true, message: "" });
let reqData = { let reqData = {
job_id: details.job_id, job_id: details.job_id,
job_uid: details.job_uid, job_uid: details.job_uid,
...values, ...values,
}; };
delete reqData?.country delete reqData?.country;
try { try {
let res = await jobApi.jobManagerUpdateJob(reqData); let res = await jobApi.jobManagerUpdateJob(reqData);
let { data } = await res; let { data } = await res;
if (data?.internal_return < 0) return; if (data?.internal_return < 0) return;
setRequestStatus({ loading: false, message: null }); setRequestStatus({ loading: false, message: null });
setTimeout(() => { setTimeout(() => {
dispatch(tableReload({type:'JOBTABLE'})) dispatch(tableReload({ type: "JOBTABLE" }));
navigate("/myjobs", { replace: true }); navigate("/myjobs", { replace: true });
onClose(); onClose();
}, 1000); }, 1000);
@@ -129,7 +138,7 @@ const EditJobPopOut = ({ details, onClose, situation, country }) => {
<Form className="w-full"> <Form className="w-full">
<div className="flex flex-col-reverse sm:flex-row"> <div className="flex flex-col-reverse sm:flex-row">
<div className="fields w-full"> <div className="fields w-full">
<div className="xl:flex xl:space-x-7 mb-6"> <div className="xl:flex xl:space-x-7 mb-[0.5rem]">
<div className="field w-full mb-6 xl:mb-0"> <div className="field w-full mb-6 xl:mb-0">
<InputCom <InputCom
fieldClass="px-6 cursor-default" fieldClass="px-6 cursor-default"
@@ -144,11 +153,6 @@ const EditJobPopOut = ({ details, onClose, situation, country }) => {
blurHandler={props.handleBlur} blurHandler={props.handleBlur}
disable={true} disable={true}
/> />
{props.errors.country && props.touched.country && (
<p className="text-sm text-red-500">
{props.errors.country}
</p>
)}
</div> </div>
{/* Price */} {/* Price */}
@@ -161,20 +165,17 @@ const EditJobPopOut = ({ details, onClose, situation, country }) => {
inputClass="input-curve lg border border-light-purple" inputClass="input-curve lg border border-light-purple"
type="number" type="number"
name="price" name="price"
// placeholder="Please Enter Amount"
value={props.values.price * 0.01} value={props.values.price * 0.01}
inputHandler={props.handleChange} inputHandler={props.handleChange}
blurHandler={props.handleBlur} blurHandler={props.handleBlur}
errorBorder={
props.errors.price && props.touched.price
}
/> />
{props.errors.price && props.touched.price && (
<p className="text-sm text-red-500">
{props.errors.price}
</p>
)}
</div> </div>
</div> </div>
{/* Title */} {/* Title */}
<div className="field w-full mb-6"> <div className="field w-full mb-[0.5rem]">
<InputCom <InputCom
fieldClass="px-6" fieldClass="px-6"
label="Title" label="Title"
@@ -183,20 +184,15 @@ const EditJobPopOut = ({ details, onClose, situation, country }) => {
inputClass=" input-curve lg border border-light-purple" inputClass=" input-curve lg border border-light-purple"
type="text" type="text"
name="title" name="title"
// placeholder="Enter Job Title"
value={props.values.title} value={props.values.title}
inputHandler={props.handleChange} inputHandler={props.handleChange}
blurHandler={props.handleBlur} blurHandler={props.handleBlur}
errorBorder={props.errors.title && props.touched.title}
/> />
{props.errors.title && props.touched.title && (
<p className="text-sm text-red-500">
{props.errors.title}
</p>
)}
</div> </div>
{/* Description */} {/* Description */}
<div className="field w-full mb-6"> <div className="field w-full mb-[0.5rem]">
<InputCom <InputCom
fieldClass="px-6" fieldClass="px-6"
label="Description" label="Description"
@@ -205,84 +201,110 @@ const EditJobPopOut = ({ details, onClose, situation, country }) => {
inputClass=" input-curve lg border border-light-purple" inputClass=" input-curve lg border border-light-purple"
type="text" type="text"
name="description" name="description"
// placeholder="Enter a description"
value={props.values.description} value={props.values.description}
inputHandler={props.handleChange} inputHandler={props.handleChange}
blurHandler={props.handleBlur} blurHandler={props.handleBlur}
errorBorder={
props.errors.description && props.touched.description
}
/> />
{props.errors.description &&
props.touched.description && (
<p className="text-sm text-red-500">
{props.errors.description}
</p>
)}
</div> </div>
{/* Details */} {/* Details */}
<div className="field w-full mb-6"> <div className="field flex flex-col sm:flex-row w-full mb-[5px] gap-2">
<label <div className="sm:w-[60%] w-full">
htmlFor="Job Delivery Details" <label
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block mb-3' htmlFor="Job Delivery Details"
> className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'
Job Delivery Details >
</label> Job Delivery Details
<textarea </label>
id="Job Delivery Details" <textarea
rows="5" id="Job Delivery Details"
className={`input-field px-6 py-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[100px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] border border-[#dce4e9] rounded-[10px]`} rows="5"
style={{ resize: "none" }} className={`input-field px-6 py-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[100px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] border border-[#dce4e9] rounded-[10px]`}
name="job_detail" style={{ resize: "none" }}
value={props.values.job_detail} name="job_detail"
onChange={props.handleChange} value={props.values.job_detail}
onBlur={props.handleBlur} onChange={props.handleChange}
/> onBlur={props.handleBlur}
/>
</div>
<div className="sm:w-[35%] w-full">
<div
htmlFor="Job Categories"
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'
id="checked-group"
>
Categories
</div>
<div
className="sm:flex-col flex flex-wrap px-3 mt-3"
role="group"
aria-labelledby="checked-group"
>
{Object.entries(categories).map(([key, value]) => (
<label
key={key}
className="flex gap-1 w-full items-center"
>
<Field
type="checkbox"
name="category"
value={key}
/>
<span className="text-[13.975px]">{value}</span>
</label>
))}
</div>
</div>
{/* <div className={`${!props.errors && "invisible"} h-5`}>
{props.errors.job_detail && props.touched.job_detail && ( {props.errors.job_detail && props.touched.job_detail && (
<p className="text-sm text-red-500"> <p className="text-sm text-red-500">
{props.errors.job_detail} {props.errors.job_detail}
</p> </p>
)} )}
</div> */}
</div> </div>
<div className="field w-full mb-6"> <div className="field w-full mb-6">
<div className={`flex items-center justify-between mb-2.5`}> <div
<label className={`flex items-center justify-between mb-2.5`}
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
htmlFor="timeline_days"
> >
Timeline <label
<span className="text-green-700 text-sm tracking-wide"> className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
- Expected duration of this task htmlFor="timeline_days"
</span>
</label>
</div>
<Field
component="select"
name="timeline_days"
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"
value={props.values.timeline_days}
>
<option value="">Select Duration</option>
{publicArray.map(({ name, duration }, idx) => (
<option
className="text-slate-500 text-lg"
value={duration}
> >
{name} Timeline
</option> <span className="text-green-700 text-sm tracking-wide">
))} - Expected duration of this task
</Field> </span>
{props.errors.timeline_days && </label>
props.touched.timeline_days && ( </div>
<p className="text-sm text-red-500">
{props.errors.timeline_days} <Field
</p> component="select"
)} name="timeline_days"
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"
value={props.values.timeline_days}
>
<option value="">Select Duration</option>
{publicArray.map(({ name, duration }, idx) => (
<option
className="text-slate-500 text-lg"
value={duration}
>
{name}
</option>
))}
</Field>
</div> </div>
{/* inputs ends here */} {/* inputs ends here */}
</div> </div>
</div> </div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */} {/* ERROR DISPLAY AND SUBMIT BUTTON */}
<div className="content-footer w-full"> <div className="content-footer w-full">
{/* error or success display */} {/* error or success display */}
{requestStatus.message != "" && {requestStatus.message != "" &&
@@ -4,6 +4,7 @@ import ModalCom from "../Helpers/ModalCom";
import usersService from "../../services/UsersService"; import usersService from "../../services/UsersService";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import LoadingSpinner from "../Spinners/LoadingSpinner"; import LoadingSpinner from "../Spinners/LoadingSpinner";
import { PriceFormatter } from "../Helpers/PriceFormatter";
const showSuccessToast = (message) => { const showSuccessToast = (message) => {
toast.success(message, { toast.success(message, {
@@ -133,7 +134,8 @@ function PendingJobsPopout({ details, onClose, situation }) {
<div className="my-2 md:flex"> <div className="my-2 md:flex">
<Detail <Detail
label="Price" label="Price"
value={`${details.price * 0.01} ${details.currency}`} // value={`${details.price * 0.01} ${details.currency}`}
value={PriceFormatter(details.price * 0.01, details?.currency_code, details.currency)}
/> />
</div> </div>
+23 -1
View File
@@ -900,4 +900,26 @@ TODO: Responsive ===========================
.addJob-popup{ .addJob-popup{
top: 30px; top: 30px;
height: 55rem !important; height: 55rem !important;
} }
@keyframes shake {
0% {
transform: translateX(0);
}
25% {
transform: translateX(-5px);
}
50% {
transform: translateX(5px);
}
75% {
transform: translateX(-5px);
}
100% {
transform: translateX(0);
}
}
.ebu-animate-shake {
animation: shake 0.3s linear 3;
}
+4 -4
View File
@@ -2,10 +2,10 @@ import React from "react";
import AddJob from "../components/AddJob/AddJob"; import AddJob from "../components/AddJob/AddJob";
import ModalCom from "../components/Helpers/ModalCom"; import ModalCom from "../components/Helpers/ModalCom";
function AddJobPage({ action, situation }) { function AddJobPage({ action, situation, categories }) {
return ( return (
<ModalCom action={action} situation={situation} className="addJob-popup"> <ModalCom action={action} situation={situation} className="edit-popup">
<div className="lg:w-[600px] w-full h-full lg:overflow-hidden lg:rounded-2xl bg-white dark:bg-dark-white "> <div className="lg:w-[600px] w-full lg:overflow-hidden lg:rounded-2xl bg-white dark:bg-dark-white ">
<div className="heading flex justify-between items-center py-6 md:px-[30px] px-[23px] border-b dark:border-[#5356fb29] border-light-purple dark:border-[#5356fb29] "> <div className="heading flex justify-between items-center py-6 md:px-[30px] px-[23px] border-b dark:border-[#5356fb29] border-light-purple dark:border-[#5356fb29] ">
<p className="text-26 font-bold text-dark-gray dark:text-white tracking-wide"> <p className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Create New Job Create New Job
@@ -31,7 +31,7 @@ function AddJobPage({ action, situation }) {
</svg> </svg>
</button> </button>
</div> </div>
<AddJob popUpHandler={action} /> <AddJob popUpHandler={action} categories={categories} />
</div> </div>
</ModalCom> </ModalCom>
); );