Compare commits

..

1 Commits

Author SHA1 Message Date
Chief Bube 53db8df5c7 Added Picture path 2023-11-06 05:07:45 -08:00
101 changed files with 664 additions and 2998 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

+8 -14
View File
@@ -1,22 +1,16 @@
import Toaster from "./components/Helpers/Toaster";
import Routers from "./Routers";
import Default from "./components/Partials/Default";
import { Navigate, useLocation } from "react-router-dom";
function App() {
const {pathname} = useLocation()
return (
<Default>
<>
{pathname.startsWith('/@') ?
<Navigate to="/app" replace={true} />
:
<Routers />
}
<Toaster />
</>
</Default>
);
return (
<Default>
<>
<Routers />
<Toaster />
</>
</Default>
);
}
export default App;
-8
View File
@@ -50,10 +50,6 @@ import FamilyMarketPage from "./views/FamilyMarketPage";
import FacebookRedirect from "./views/FacebookRedirect";
import AppleRedirectPage from "./views/AppleRedirectPage";
import LndPage from "./views/LndPage";
import FamilySettingsPage from "./views/FamilySettingsPage";
import AppDownloadPage from "./views/AppDownloadPage";
import JobGroupsPage from "./views/JobGroupsPage";
import YourPages from "./views/YourPage_";
export default function Routers() {
return (
@@ -82,7 +78,6 @@ export default function Routers() {
<Route path="/complereset" element={<VerifyPasswordPages />} />
<Route exact path="/outmessage" element={<VerifyYouPages />} />
<Route exact path="/lnd/*" element={<LndPage />} />
<Route exact path="/app" element={<AppDownloadPage />} />
{/* private route */}
<Route element={<AuthRoute />}>
@@ -103,7 +98,6 @@ export default function Routers() {
<Route exact path="/market-place" element={<MarketPlacePage />} />
<Route exact path="/market" element={<MarketPlacePage />} />
<Route exact path="/familymarket" element={<FamilyMarketPage />} />
<Route exact path="/familysettings" element={<FamilySettingsPage />} />
<Route exact path="/notification" element={<Notification />} />
<Route exact path="/mytask" element={<MyTaskPage />} />
<Route exact path="/myjobs" element={<MyJobsPage />} />
@@ -116,7 +110,6 @@ export default function Routers() {
<Route exact path="/acc-family" element={<FamilyAccPage />} />
<Route exact path="/manage-family" element={<FamilyManagePage />} />
<Route exact path="/start-job" element={<StartJob />} />
<Route exact path="/yourpage" element={<YourPages />} />
<Route exact path="/manage-active-job" element={<ManageActiveJobs />} />
<Route exact path="/blog-page" element={<BlogPage />} />
<Route exact path="/offer-interest" element={<OffersInterestPage />} />
@@ -137,7 +130,6 @@ export default function Routers() {
<Route exact path="/user-profile" element={<UserProfilePage />} />
<Route exact path="/settings" element={<SettingsPage />} />
<Route exact path="/referral" element={<ReferralPage />} />
<Route exact path="/job-groups" element={<JobGroupsPage />} />
</Route>
<Route path="*" element={<FourZeroFour />} />
</Routes>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

@@ -1 +0,0 @@
<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>

Before

Width:  |  Height:  |  Size: 799 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 68 50" id="Page"><path fill-rule="evenodd" d="M0 13V2a2 2 0 0 1 2-2h64a2 2 0 0 1 2 2v11H0Zm0 4v31a2 2 0 0 0 2 2h20V17H0Zm26 33h40a2 2 0 0 0 2-2V17H26v33Z" fill="#767fad" class="color000000 svgShape"></path></svg>

Before

Width:  |  Height:  |  Size: 265 B

+84 -22
View File
@@ -1,28 +1,74 @@
import {
validationSchema as VS,
useDispatch,
useSelector,
usersService,
initialValues as IV,
initialReqState,
useState,
tableReload,
Formik,
InputCom,
Field,
Form,
LoadingSpinner,
} from "./settings";
import { Field, Form, Formik } from "formik";
import React, { 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";
const validationSchema = VS;
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 at least one checkbox"),
});
function AddJob({ popUpHandler, categories }) {
const ApiCall = new usersService();
const { walletDetails } = useSelector((state) => state.walletDetails);
let dispatch = useDispatch();
const [requestStatus, setRequestStatus] = useState(initialReqState); // Holds state when submit button is pressed
let initialValues = {
// 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 reqData = {
@@ -35,6 +81,21 @@ function AddJob({ popUpHandler, categories }) {
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: "" });
try {
@@ -75,7 +136,7 @@ function AddJob({ popUpHandler, categories }) {
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">
<Formik
initialValues={IV}
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleAddJob}
>
@@ -106,7 +167,7 @@ function AddJob({ popUpHandler, categories }) {
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{walletDetails?.loading ? (
{walletDetails.loading ? (
<option className="text-slate-500 text-lg" value="">
Loading...
</option>
@@ -197,7 +258,7 @@ function AddJob({ popUpHandler, categories }) {
<div className="sm:w-[60%] w-full">
<label
htmlFor="Job Delivery Details"
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1"
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1'
>
Job Delivery Details
{props.errors.job_detail &&
@@ -339,12 +400,13 @@ function AddJob({ popUpHandler, categories }) {
</span>
</button>
{requestStatus?.loading ? (
{requestStatus.loading ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<button
type="submit"
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
</button>
-100
View File
@@ -1,100 +0,0 @@
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
};
@@ -1,9 +0,0 @@
import React from 'react'
export default function AppDownload() {
return (
<div>
<div className='h-screen flex justify-center items-center'>App Download Content Comes here</div>
</div>
)
}
+40 -65
View File
@@ -17,16 +17,14 @@ import { updateUserDetails } from "../../../store/UserDetails";
import ReCAPTCHA from "react-google-recaptcha";
export default function Login() {
// eslint-disable-next-line no-restricted-globals
const queryParams = new URLSearchParams(location?.search);
// const sessionExpired = queryParams.get("sessionExpired");
const sessionExpired = queryParams.get("sessionExpired")
const dispatch = useDispatch();
const { state } = useLocation();
const [sessionExpired, setSessionExpired] = useState(queryParams.get("sessionExpired"))
const [validCaptcha, setValidCaptcha] = useState({ show: false, valid: "" }); // FOR CAPTCHA
const [validCaptcha, setValidCaptcha] = useState({show: false, valid:''}); // FOR CAPTCHA
let [loginType, setLoginType] = useState("");
@@ -117,8 +115,7 @@ export default function Login() {
}, Number(process.env.REACT_APP_LOGIN_ERROR_TIMEOUT));
return;
}
if (name == "full" && !validCaptcha.valid && validCaptcha.show) {
// RUNS AND DISPLAYS CAPTCHA, IF ERROR OCCURED DURING LOGIN FOR FULL LOGIN ALONE
if(name == "full" && !validCaptcha.valid && validCaptcha.show){ // RUNS AND DISPLAYS CAPTCHA, IF ERROR OCCURED DURING LOGIN FOR FULL LOGIN ALONE
setMsgError("Please Verify Captcha");
setLoginLoading(false);
setTimeout(() => {
@@ -139,15 +136,12 @@ export default function Login() {
// setMsgError("Wrong, email/password");
setLoginError(true);
setLoginLoading(false);
setValidCaptcha((prev) => ({ ...prev, show: true })); // DISPLAYS CAPTCHA IF ERROR
setValidCaptcha(prev => ({...prev, show:true})) // DISPLAYS CAPTCHA IF ERROR
return;
}
localStorage.setItem("member_id", `${res.data.member_id}`);
localStorage.setItem("uid", `${res.data.uid}`);
localStorage.setItem("session_token", `${res.data.session}`);
if (name === "family") {
sessionStorage.setItem("family_uid", res.data?.family_uid);
}
// localStorage.setItem("session", `${res.data.session}`);
dispatch(updateUserDetails({ ...res.data }));
setTimeout(() => {
@@ -158,7 +152,7 @@ export default function Login() {
.catch((error) => {
setMsgError("Unable to login, try again");
setLoginLoading(false);
setValidCaptcha((prev) => ({ ...prev, show: true })); // DISPLAYS CAPTCHA IF ERROR
setValidCaptcha(prev => ({...prev, show:true})) // DISPLAYS CAPTCHA IF ERROR
})
.finally(() => {
setTimeout(() => {
@@ -169,12 +163,11 @@ export default function Login() {
});
};
function captchaChecker(value) {
// FUNCTION TO VALIDATE CAPTCHA
if (value) {
setValidCaptcha({ show: true, valid: value });
} else {
setValidCaptcha({ show: true, valid: "" });
function captchaChecker(value) { // FUNCTION TO VALIDATE CAPTCHA
if(value){
setValidCaptcha({show: true, valid:value})
}else{
setValidCaptcha({show: true, valid:''})
}
}
@@ -237,20 +230,6 @@ export default function Login() {
setPassword("");
}, [loginType]);
// EFFECT TO CLEAR SESSION EXPIRY IF IT EXISTS AFTER SOME SECONDS
useEffect(()=>{
let timer;
if(sessionExpired == "true"){
timer = setTimeout(()=>{
setSessionExpired(false)
},5000)
}
return () => {
clearTimeout(timer)
}
}, [])
return (
<>
<AuthLayout slogan="Welcome to WrenchBoard">
@@ -266,32 +245,31 @@ export default function Login() {
</div>
<div className="content-wrapper login shadow-md w-full lg:max-w-[530px] mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5">
<div className="w-full">
{/* HIDES THIS IF USER SESSION HAS EXPIRED */}
{sessionExpired != "true" && (
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
{/* <h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
{sessionExpired != 'true' &&
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
{/* <h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
Sign In to WrenchBoard
</h1> */}
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
New Here?{" "}
<Link
to="/signup"
className="font-semibold text-[#4687ba] hover:text-[#009ef7] transition"
>
Create an Account
</Link>
</span>
</div>
)}
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
New Here?{" "}
<Link
to="/signup"
className="font-semibold text-[#4687ba] hover:text-[#009ef7] transition"
>
Create an Account
</Link>
</span>
</div>
}
{/* SHOWS THIS IF USER SESSION HAS EXPIRED */}
{sessionExpired == "true" && (
<div className="w-full p-1 mb-7">
<p className="text-red-500 text-base text-center">
Your session expired and will need to login again
</p>
</div>
)}
{sessionExpired == 'true' &&
<div className="w-full p-1 mb-7">
<p className="text-red-500 text-base text-center">Your session expired and will need to login again</p>
</div>
}
{/* switch login component */}
<div className="ml-7 flex justify-start items-center gap-3">
@@ -357,16 +335,14 @@ export default function Login() {
</div>
{/* hCaptha clone for the time being */}
{validCaptcha.show && (
<div className="mb-5 flex justify-center w-full">
<ReCAPTCHA
sitekey={
process.env.REACT_APP_GOOGLE_RECAPTCHA_SITEKEY
}
onChange={captchaChecker}
{validCaptcha.show &&
<div className="mb-5 flex justify-center w-full">
<ReCAPTCHA
sitekey={process.env.REACT_APP_GOOGLE_RECAPTCHA_SITEKEY}
onChange={captchaChecker}
/>
</div>
)}
</div>
}
{loginError && (
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-thin leading-[19.5px] text-[13px]">
@@ -523,8 +499,7 @@ export default function Login() {
{loginType == "full" && (
<div className="pt-5 text-[#181c32] text-center font-semibold text-[13.975px] leading-[20.9625px]">
This site is protected by a Captcha. Our Privacy Policy and
Terms of Service apply.
This site is protected by a Captcha. Our Privacy Policy and Terms of Service apply.
</div>
)}
</div>
+14 -13
View File
@@ -47,20 +47,21 @@ export default function SignUp() {
// Get Country Api
const getCountryList = useCallback(async () => {
const res = await userApi.getSignupCountryData();
try {
const res = await userApi.getSignupCountryData();
if (res.status === 200 && res.data.internal_return >= 0) {
const { result_list } = await res.data;
if (res.status === 200) {
const { signup_country } = await res.data;
// setCountries(signup_country);
if(country){ // IF LINK/PATHNAME HAS CNT QUERY VALUE
let cnt = result_list.filter(item => item.code == country) // test to see country passed in query param exist from list of countries supplied by API
let cnt = signup_country.filter(item => item[0]==country) // test to see country passed in query param exist from list of countries supplied by API
if(!cnt.length){ // IF CNT EMPTY, SET FORMDATA COUNTRY BACK TO EMPTY STRING: RE: THIS IS BCOS WE INITAIL SET COUNTRY VALUE IN FORMDATA, IF COUNTRY PARAM IS PRESENT IN LINK
setFormData(prev => ({...prev, country: ''}))
return setCountries({loading: false, data: result_list});
return setCountries({loading: false, data: signup_country});
}
return setCountries({loading: false, data: cnt});
}
setCountries({loading: false, data:result_list});
setCountries({loading: false, data:signup_country});
} else if (res.data.result !== 100) {
setCountries({loading: false, data:[]});
}
@@ -374,17 +375,17 @@ const SelectOption = ({
{data?.data?.length > 1 ?
<>
<option value={""}>Select your Country</option>
{data?.data?.map((item) => (
<option value={item.code} key={item.uid}>
{item.country}
{data?.data?.map((item, idx) => (
<option value={item[0]} key={idx}>
{item[1]}
</option>
))}
</>
:
data?.data?.length == 1 ?
data?.data?.map((item) => (
<option value={item.code} key={item.uid}>
{item.country}
data?.data?.map((item, idx) => (
<option value={item[0]} key={idx}>
{item[1]}
</option>
))
:
+1 -1
View File
@@ -47,7 +47,7 @@ export default function BlogItem(props) {
</h1>
</div>
<div className="notification-wrapper w-full bg-white p-8 rounded-2xl">
{blogdata?.loading ?
{blogdata.loading ?
<LoadingSpinner size='8' color='sky-blue' height='h-[100px]' />
:
blogdata?.data?.blogdata && blogdata.data?.blogdata.length ?
+2 -9
View File
@@ -1,4 +1,5 @@
import { useEffect, useState } from "react";
import dataImage2 from "../../assets/images/taskbanners/default.jpg";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import MarketPopUp from "../MarketPlace/PopUp/MarketPopUp";
@@ -7,7 +8,6 @@ export default function AvailableJobsCard({
datas,
hidden = false,
contentDisplay,
image_server,
}) {
//debugger;
const [marketPopUp, setMarketPopUp] = useState({ show: false, data: {} });
@@ -23,13 +23,6 @@ export default function AvailableJobsCard({
const imagePath = require(`../../assets/images/${datas.thumbnil}`); // Replace with your directory path for local images
setImageUrl(imagePath);
}, []);
const image = localStorage.getItem("session_token")
? `${image_server}${localStorage.getItem("session_token")}/job/${
datas.job_uid
}`
: "";
return (
<>
{contentDisplay == "grid" ? (
@@ -138,7 +131,7 @@ export default function AvailableJobsCard({
<div className="card-style-two w-full p-8 my-2 flex items-center gap-4 bg-white dark:bg-dark-white rounded-2xl section-shadow">
<div className="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={image} alt="data" className="w-full h-full" />
<img src={dataImage2} alt="data" className="w-full h-full" />
</div>
<div className="flex flex-col flex-[0.9]">
<h1
@@ -5,7 +5,7 @@ import localImgLoad from "../../lib/localImgLoad";
import CountDown from "../Helpers/CountDown";
import Icons from "../Helpers/Icons";
export default function FamilyActiveJobsCard({ datas, hidden = false, image_server }) {
export default function FamilyActiveJobsCard({ datas, hidden = false }) {
let { pathname } = useLocation();
@@ -22,8 +22,7 @@ export default function FamilyActiveJobsCard({ datas, hidden = false, image_serv
}
};
//debugger;
// const bannerName = datas.banner == null ?'default.jpg':datas.banner;
let image = `${image_server}${localStorage.getItem('session_token')}/job/${datas.origin_job_uid}`
const bannerName = datas.banner == null ?'default.jpg':datas.banner;
return (
<div className="card-style-one flex flex-col justify-between w-full h-[387px] bg-white dark:bg-dark-white p-3 pb rounded-2xl">
<div className="content">
@@ -32,13 +31,10 @@ export default function FamilyActiveJobsCard({ datas, hidden = false, image_serv
{/* thumbnail image */}
<div
className="thumbnail w-full h-full rounded-xl overflow-hidden px-4 pt-4"
// style={{
// background: `url(${localImgLoad(
// `images/taskbanners/${bannerName}`
// )}) center / contain no-repeat`,
// }}
style={{
background: `url(${image}) center / contain no-repeat`,
background: `url(${localImgLoad(
`images/taskbanners/${bannerName}`
)}) center / contain no-repeat`,
}}
>
{/* <div className="product-options flex justify-between relative">*/}
+25 -11
View File
@@ -2,20 +2,13 @@ import localImgLoad from "../../lib/localImgLoad";
import CountDown from "../Helpers/CountDown";
import { PriceFormatter } from "../Helpers/PriceFormatter";
export default function OfferCard({
datas,
hidden = false,
setOfferPopout,
image_server,
}) {
export default function OfferCard({ datas, hidden = false, setOfferPopout }) {
let thePrice = PriceFormatter(
datas?.price * 0.01,
datas?.currency_code,
datas?.currency
);
let image = `${image_server}${localStorage.getItem("session_token")}/job/${datas.job_uid}`
return (
<div className="card-style-one flex flex-col justify-between w-full h-[387px] bg-white dark:bg-dark-white p-3 pb rounded-2xl">
<div className="content">
@@ -25,7 +18,9 @@ export default function OfferCard({
<div
className="thumbnail w-full h-full rounded-xl overflow-hidden px-4 pt-4"
style={{
background: `url(${image}) center / contain no-repeat`,
background: `url(${localImgLoad(
`images/taskbanners/${datas?.banner || "default.jpg"}`
)}) center / contain no-repeat`,
}}
>
{hidden && <div className="flex justify-center"></div>}
@@ -36,7 +31,26 @@ export default function OfferCard({
<h1 className="text-xl font-bold text-dark-gray dark:text-white mb-2 capitalize line-clamp-1">
{datas.title}
</h1>
{/* countdown */}
{/* <div className="w-full h-[54px] flex justify-evenly items-center p-2 rounded-lg border border-[#E3E4FE] dark:border-[#a7a9b533] ">
<div className="flex flex-col justify-between">
<p className="text-sm text-thin-light-gray dark:text-white tracking-wide">
Task Code
</p>
<p className="text-base font-bold tracking-wide text-dark-gray dark:text-white">
{datas.contract}
</p>
</div>
<div className="w-[1px] h-full bg-[#E3E4FE] dark:bg-[#a7a9b533] "></div>
<div className="flex flex-col justify-between">
<p className="text-sm text-thin-light-gray dark:text-white tracking-wide">
Remaining Time
</p>
<p className="text-base font-bold tracking-wide text-dark-gray dark:text-white">
<CountDown lastDate={datas.expire} />
</p>
</div>
</div> */}
<div className="w-full p-2 rounded-lg border border-[#E3E4FE] dark:border-[#a7a9b533] ">
<div className="grid grid-cols-2 gap-2">
<div className="flex flex-col justify-between items-center border-r-2">
@@ -82,7 +96,7 @@ export default function OfferCard({
<button
type="button"
onClick={() =>
setOfferPopout({ show: true, data: { ...datas, thePrice, image } })
setOfferPopout({ show: true, data: { ...datas, thePrice } })
}
className="btn-shine w-[98px] h-[33px] text-white rounded-full text-sm bg-pink flex justify-center items-center"
>
+23 -4
View File
@@ -33,7 +33,7 @@ export default function FamilyManageTabs({
loading: false,
data: null,
};
// console.log('accountDetails',accountDetails)
console.log('accountDetails',accountDetails)
// State for family details, tasks, waitlist, and pending
const [details, setDetails] = useState({
familyDetails: { ...initialDetailState },
@@ -92,6 +92,26 @@ export default function FamilyManageTabs({
* Checks if the selected file exceeds the maximum file size limit and displays an alert if it does.
* If the file is within the size limit, it reads the file using the FileReader API and sets the profile image state with the result.
*/
// const profileImgChangeHandler = (e) => {
// const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
// const file = e.target.files[0];
// if (file && file.size > MAX_FILE_SIZE) {
// alert("File size exceeds the limit.");
// return;
// }
// if (file) {
// const imgReader = new FileReader();
// imgReader.onload = () => {
// const imageDataUrl = imgReader.result;
// // Set the profile image
// setProfileImg(imageDataUrl);
// };
// imgReader.readAsDataURL(file);
// }
// };
const profileImgChangeHandler = (e) => {
setUploadStatus({loading: false, status: false, message:''})
@@ -119,15 +139,14 @@ export default function FamilyManageTabs({
if (e.target.value !== "") {
const imgReader = new FileReader();
imgReader.onload = (event) => {
let base64Img = imgReader.result.split(",")[1];
let reqData = { // PAYLOAD FOR API CALL
family_uid: accountDetails?.family_uid,
file_name: uploadedFile?.name,
file_size: uploadedFile?.size,
file_type: uploadedFile?.type?.split("/")[0]?.toLowerCase(),
file_data: base64Img,
file_data: event?.target?.result,
msg_type: 'FILE',
action: 11305
action: 111305
}
setUploadStatus({loading: true, status: false, message:'Loading...'})
apiCall.sendFiles(reqData).then(res=>{
@@ -5,8 +5,6 @@ import { PriceFormatter } from "../../Helpers/PriceFormatter";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import Detail from "../../jobPopout/popoutcomponent/Detail";
import { NewTasks } from "./forms";
import { tableReload } from "../../../store/TableReloads";
import { useDispatch } from "react-redux";
const AssignTaskPopout = React.memo(
({
@@ -21,8 +19,6 @@ const AssignTaskPopout = React.memo(
}) => {
const apiCall = new usersService();
const dispatch = useDispatch()
let [requestStatus, setRequestStatus] = useState({
loading: false,
status: false,
@@ -94,11 +90,11 @@ const AssignTaskPopout = React.memo(
const requiredFields = {
banner,
// category,
currency:country,
country,
description,
'job detail':job_detail,
job_detail,
price,
timeline:timeline_days,
timeline_days,
title,
};
@@ -108,7 +104,7 @@ const AssignTaskPopout = React.memo(
setRequestStatus({
loading: false,
status: false,
message: `${field[0].toUpperCase()+field.slice(1).toLowerCase()} is empty`,
message: `${field} is empty`,
});
return setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
@@ -149,7 +145,6 @@ const AssignTaskPopout = React.memo(
message: "action successful",
});
setUpdatePage(prev => !prev) // Updates family task page by calling the useeffect hook
dispatch(tableReload({ type: "WALLETTABLE" })); // RELOADS USER WALLET
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
action(); // FUNCTION THAT CLOSES THE MODAL BOX
@@ -172,8 +167,9 @@ const AssignTaskPopout = React.memo(
<ModalCom
action={action}
situation={situation}
className="assign-task-popup"
>
<div className="w-11/12 lg:w-[700px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="w-full h-full lg:w-[700px] lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="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">
Assign task to{" "}
@@ -205,7 +201,7 @@ const AssignTaskPopout = React.memo(
</svg>
</button>
</div>
{familyTask?.loading ? (
{familyTask.loading ? (
<div className="h-[100px] w-full flex justify-center items-center">
<LoadingSpinner color="sky-blue" size="16" />
</div>
@@ -69,7 +69,7 @@ export default function NewTasks({ formState, setFormState }) {
onChange={handleInputChange}
// onBlur={props.handleBlur}
>
{currency?.loading ? (
{currency.loading ? (
<option className="text-slate-500 text-[13.975px]" value="">
Loading...
</option>
@@ -1,9 +0,0 @@
import React from 'react'
const AddFamily = () => {
return (
<div>Add Family</div>
)
}
export default AddFamily
@@ -1,153 +0,0 @@
import React, { useMemo, useRef, useState } from "react";
import usersService from "../../../../services/UsersService";
const FamilyBanner = ({ imageServer }) => {
const uploadedImage = `${imageServer}${localStorage.getItem(
"session_token"
)}/familybanner/${localStorage.getItem("uid")}`;
const familyBannerRef = useRef(null);
const jobApi = useMemo(() => new usersService(), []);
const [familyBannerImage, setFamilyBannerImage] = useState(uploadedImage);
const [uploadStatus, setUploadStatus] = useState({
loading: false,
status: false,
message: "",
});
/**
* Handles the change event of the family image input field.
* Checks if the selected file exceeds the maximum file size limit and displays an alert if it does.
* If the file is within the size limit, it reads the file using the FileReader API and sets the profile image state with the result.
*/
const familyBannerHandler = (e) => {
setUploadStatus({ loading: false, status: false, message: "" });
let acceptedFormat = ["jpeg", "jpg", "png", "bmp"]; // ARRAY OF SUPPORTED FORMATS
let uploadedFile = e.target.files[0]; //UPLOADED FILE
const fileFormat = uploadedFile?.type?.split("/")[1]?.toLowerCase();
if (!acceptedFormat.includes(fileFormat)) {
//CHECKING FOR CORRECT UPLOAD FORMAT
const msg = `Please select ${acceptedFormat
.slice(0, -1)
.join(", ")} or ${acceptedFormat.slice(-1)}`;
setUploadStatus({ loading: false, status: false, message: msg });
return setTimeout(() => {
// profileImgInput.current.value = '' // clear the input
setUploadStatus({ loading: false, status: false, message: "" });
}, 5000);
}
if (uploadedFile.size > 5 * 1048576) {
// CHECKING FOR CORRECT FILE SIZE
setUploadStatus({
loading: false,
status: false,
message: "File must not exceed 5MB",
});
return setTimeout(() => {
// profileImgInput.current.value = '' // clear the input
setUploadStatus({ loading: false, status: false, message: "" });
}, 5000);
}
if (e.target.value !== "") {
const imgReader = new FileReader();
imgReader.onload = (event) => {
let base64Img = imgReader.result.split(",")[1];
let reqData = {
// PAYLOAD FOR API CALL
job_uid: localStorage.getItem("uid"),
file_name: uploadedFile?.name.slice(0, 19),
file_size: uploadedFile?.size,
file_type: uploadedFile?.type?.split("/")[0]?.toLowerCase(),
file_data: base64Img,
msg_type: "FILE",
action: 11303,
};
setUploadStatus({
loading: true,
status: false,
message: "Loading...",
});
jobApi
.sendFiles(reqData)
.then((res) => {
if (res.status != 200 || res.data.internal_return < 0) {
return setUploadStatus({
loading: false,
status: false,
message: "Something went wrong, try again",
});
}
setUploadStatus({
loading: false,
status: true,
message: "Uploaded successfully",
});
setFamilyBannerImage(event.target.result);
})
.catch((error) => {
setUploadStatus({
loading: false,
status: false,
message: "Network error, try again",
});
})
.finally(() => {
setTimeout(() => {
setUploadStatus({ loading: false, status: false, message: "" });
}, 5000);
});
};
imgReader.readAsDataURL(e.target.files[0]);
}
};
return (
<div className="flex flex-col gap-4">
<div className="w-full lg:h-[400px] rounded-2xl">
<img
src={familyBannerImage}
alt="familyBanner"
className="w-full h-full object-cover rounded-2xl"
/>
</div>
<div className="flex justify-between w-full">
<div>
{uploadStatus.message && !uploadStatus.loading && (
<p
className={`text-center ${
uploadStatus.status ? "text-green-500" : "text-red-500"
}`}
>
{uploadStatus.message}
</p>
)}
{uploadStatus.loading && (
<p className="text-center">{uploadStatus.message}</p>
)}
</div>
<div>
<input
ref={familyBannerRef}
className="hidden"
type="file"
accept="image/*"
onChange={familyBannerHandler}
/>
<button
className="btn-gradient w-[153px] h-[46px] rounded-full text-white lg:flex hidden justify-center items-center"
onClick={() => familyBannerRef.current.click()}
>
Change Banner
</button>
</div>
</div>
</div>
);
};
export default FamilyBanner;
@@ -1,9 +0,0 @@
import React from 'react'
const Relatives = () => {
return (
<div>Relatives</div>
)
}
export default Relatives
@@ -1,5 +0,0 @@
import AddFamily from "./AddFamily";
import FamilyBanner from "./FamilyBanner";
import Relatives from "./Relatives";
export {AddFamily, FamilyBanner, Relatives}
@@ -1,103 +0,0 @@
import React, { useEffect, useState } from "react";
import { Link, useLocation } from "react-router-dom";
import Icons from "../../Helpers/Icons";
import Layout from "../../Partials/Layout";
import { AddFamily, FamilyBanner, Relatives } from "./Tabs";
const FamilySettings = () => {
let {state} = useLocation()
const tabs = [
{
id: 1,
name: "add_family",
title: "Add Family",
iconName: "new-family",
},
{
id: 2,
name: "relatives",
title: "Relatives",
iconName: "people-hover",
},
{
id: 3,
name: "family_banner",
title: "Family Banner",
iconName: "people-hover",
},
];
const [tab, setTab] = useState(() => {
// Retrieve the active tab from local storage or use the default tab
return localStorage.getItem("activeTab") || tabs[0].name;
});
const tabHandler = (value) => {
setTab(value);
};
// Update local storage when the tab changes
useEffect(() => {
localStorage.setItem("activeTab", tab);
}, [tab]);
const tabComponents = {
add_family: <AddFamily />,
relatives: <Relatives />,
family_banner: <FamilyBanner imageServer={state.imageServer} />,
};
const defaultTabComponent = Array(tabComponents)[0].add_family;
const selectedComponent = tabComponents[tab] || defaultTabComponent;
return (
<Layout>
<div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full">
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
<span className={``}>Family Settings</span>
</h1>
</div>
<Link to="/acc-family">Go Back</Link>
</div>
{/* Something Here */}
{/* <form className="logout-modal-body w-full flex flex-col items-center px-10 py-8 gap-4"></form> */}
<div className="w-full bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow h-full ">
<div className="update-table w-full h-full p-4 bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow min-h-[520px] lg:flex lg:px-10 px-4 justify-between">
<div className="content-tab-items lg:w-[230px] w-full mr-2">
<ul className="overflow-hidden mb-10 lg:mb-0 py-8">
{tabs.map(({ name, id, title, iconName }) => (
<li
onClick={() => tabHandler(name)}
key={id}
className={`flex lg:space-x-4 space-x-2 hover:text-purple transition-all duration-300 ease-in-out items-center cursor-pointer lg:mb-11 mb-2 mr-6 lg:mr-0 float-left lg:float-none overflow-hidden ${
tab === name ? "text-purple" : " text-thin-light-gray"
}`}
>
<div>
<Icons name={iconName} />
</div>
<div>
<p className="text-18 tracking-wide">{title}</p>
</div>
</li>
))}
</ul>
</div>
<div className="w-[1px] bg-[#E3E4FE] dark:bg-[#a7a9b533] mr-10"></div>
<div className="flex-1">
<div className="tab-item">{selectedComponent}</div>
</div>
</div>
</div>
</div>
</div>
</Layout>
);
};
export default FamilySettings;
+3 -3
View File
@@ -77,7 +77,7 @@ export default function FamilyTable({
>
<td className="py-4">
<div className="flex space-x-2 items-center w-full">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<div className="w-[60px] h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1]">
<img
// src={profile_picture}
src={image || profile_picture || localImgLoad(`images/icons/${banner}`)}
@@ -87,7 +87,7 @@ export default function FamilyTable({
</div>
<div className="flex flex-col flex-[0.9]">
<h1 className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
{`${firstname} ${lastname} (${age < 10 ? `0${age}` : age})`}
{`${firstname} ${lastname} (${age})`}
</h1>
<span className="text-sm text-thin-light-gray">
Added: <span className="text-purple ml-1">{addedDate}</span>
@@ -149,7 +149,7 @@ export default function FamilyTable({
className="w-[0.7rem]"
>
<path
fillRule="evenodd"
fill-rule="evenodd"
d="M.366 19.708c.405.39 1.06.39 1.464 0l8.563-8.264a1.95 1.95 0 0 0 0-2.827L1.768.292A1.063 1.063 0 0 0 .314.282a.976.976 0 0 0-.011 1.425l7.894 7.617a.975.975 0 0 1 0 1.414L.366 18.295a.974.974 0 0 0 0 1.413"
// fill=""
className="color000000 svgShape fill-[#fff]"
@@ -54,7 +54,7 @@ export default function FamilyPending({
value?.currency_code,
value?.currency
);
let image = `${familyData.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
let image = value.banner ? value.banner : "default.jpg";
return (
<tr
key={index}
@@ -64,7 +64,9 @@ export default function FamilyPending({
<div className="flex space-x-2 items-center w-full">
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<img
src={image}
src={localImgLoad(
`images/taskbanners/${image}`
)}
alt="data"
className="w-full h-full rounded-full"
/>
@@ -67,7 +67,9 @@ export default function FamilyTasks({
value?.currency_code,
value?.currency
);
let image = `${familyData.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
let image = value.banner
? value.banner
: "default.jpg";
return (
<tr
key={index}
@@ -77,7 +79,9 @@ export default function FamilyTasks({
<div className="flex space-x-2 items-center w-full">
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<img
src={image}
src={localImgLoad(
`images/taskbanners/${image}`
)}
alt="data"
className="w-full h-full rounded-full"
/>
@@ -67,8 +67,6 @@ const FamilyWaitlist = memo(
const selectedImage = require(`../../../assets/images/family/${
value?.banner || "default.jpg"
}`);
console.log('VALUE', value)
// let image = `${familyData.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
return (
<tr
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
@@ -7,7 +7,6 @@ export default function ProfileInfo({
profileImgChangeHandler,
browseProfileImg,
accountDetails,
uploadStatus
}) {
// console.log(accountDetails.banner)
return (
@@ -53,11 +52,6 @@ export default function ProfileInfo({
</div>
</div>
</div>
{/* DISPLAYS PROFILE UPLOADING STATUS */}
<div className="w-full">
{uploadStatus.message && !uploadStatus.loading && <p className={`text-center ${uploadStatus.status ? 'text-green-500':'text-red-500'}`}>{uploadStatus.message}</p>}
{uploadStatus.loading && <p className="text-center">{uploadStatus.message}</p>}
</div>
<div className="flex flex-col justify-center gap-3 items-center">
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{accountDetails?.firstname}
+22 -35
View File
@@ -5,7 +5,6 @@ import React, {
useMemo,
useState,
} from "react";
import { Link } from "react-router-dom";
import usersService from "../../services/UsersService";
import InputCom from "../Helpers/Inputs/InputCom";
import ModalCom from "../Helpers/ModalCom";
@@ -14,10 +13,11 @@ import LoadingSpinner from "../Spinners/LoadingSpinner";
import FamilyTable from "./FamilyTable";
export default function FamilyAcc() {
const [selectTab, setValue] = useState("today");
// State to store the selected year and month
const [selectedYear, setSelectedYear] = useState("");
const [selectedMonth, setSelectedMonth] = useState("");
const [familyList, setFamilyList] = useState({});
const [familyList, setFamilyList] = useState([]);
const [loader, setLoader] = useState(false);
const [popUp, setPopUp] = useState(false);
const [listReload, setListReload] = useState(false);
@@ -33,6 +33,10 @@ export default function FamilyAcc() {
setPopUp((prev) => !prev);
};
const filterHandler = (value) => {
setValue(value);
};
// Handle year selection
const handleYearChange = (e) => {
setSelectedYear(e.target.value);
@@ -111,8 +115,8 @@ export default function FamilyAcc() {
const res = await apiCall.familyListings(reqData);
const { data } = res;
if (data?.internal_return >= 0 && data?.status === "OK") {
const { result_list, session_image_server } = data;
setFamilyList({ result_list, session_image_server });
const { result_list } = data;
setFamilyList(result_list);
setLoader(false);
} else {
return;
@@ -142,9 +146,12 @@ export default function FamilyAcc() {
<div className="sm:flex justify-between items-center mb-6">
<div className="mb-5 sm:mb-0">
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
<span className={``}>Family Accounts</span>
{familyList?.result_list?.length <
process.env.REACT_APP_MAX_FAMILY_MEMBERS &&
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
>
Family Accounts
</span>
{familyList.length < process.env.REACT_APP_MAX_FAMILY_MEMBERS &&
!loader && (
<button
onClick={popUpHandler}
@@ -156,38 +163,18 @@ export default function FamilyAcc() {
)}
</h1>
</div>
<Link
to={`/familysettings`}
state={{ imageServer: familyList?.session_image_server }}
className="slider-btns flex space-x-4 w-12 h-12 rounded-md shadow-sm justify-center items-center cursor-pointer dark:bg-[linear-gradient(134.38deg,#f539f8_0%,#c342f9_43.55%,#5356fb_104.51%)]"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="w-6 h-6 dark:stroke-white"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
/>
</svg>
</Link>
<div className="slider-btns flex space-x-4">
<div
onClick={() => filterHandler("today")}
className="relative"
></div>
</div>
</div>
<Suspense fallback={<LoadingSpinner color="sky-blue" size="16" />}>
<FamilyTable
familyList={familyList?.result_list}
familyList={familyList}
loader={loader}
popUpHandler={popUpHandler}
imageServer={familyList?.session_image_server}
/>
</Suspense>
</div>
@@ -226,7 +213,7 @@ const FamilyForm = ({
popUpHandler,
}) => {
return (
<div className="logout-modal-wrapper w-11/12 lg:w-[460px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="logout-modal-wrapper lg:w-[460px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="logout-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 dark:border-[#5356fb29] ">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Add Members
+11 -48
View File
@@ -462,15 +462,6 @@ export default function Icons({ name }) {
clipRule="evenodd"
/>
</svg>
) : name === "my-page" ? (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 68 50" id="Page">
<path
fillRule="evenodd"
d="M0 13V2a2 2 0 0 1 2-2h64a2 2 0 0 1 2 2v11H0Zm0 4v31a2 2 0 0 0 2 2h20V17H0Zm26 33h40a2 2 0 0 0 2-2V17H26v33Z"
fill="#ffffff"
className="color000000 svgShape"
></path>
</svg>
) : name === "accordion-minus" ? (
<svg
width="20"
@@ -487,13 +478,13 @@ export default function Icons({ name }) {
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke-width="1.5"
stroke="currentColor"
className="w-4 h-4"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
stroke-linecap="round"
stroke-linejoin="round"
d="M8.25 4.5l7.5 7.5-7.5 7.5"
/>
</svg>
@@ -519,48 +510,20 @@ export default function Icons({ name }) {
) : name === "master-card" ? (
<img className="w-[30px]" src={MasterCard} alt="card" />
) : name === "new-dashboard" ? (
<img
className="w-[17px] h-[17px]"
src={localImgLoad("images/icons/dashboard.svg")}
alt="dashboard"
/>
<img className="w-[17px] h-[17px]" src={localImgLoad('images/icons/dashboard.svg')} alt="dashboard" />
) : name === "new-family" ? (
<img
className="w-[17px] h-[17px]"
src={localImgLoad("images/icons/family.svg")}
alt="family"
/>
<img className="w-[17px] h-[17px]" src={localImgLoad('images/icons/family.svg')} alt="family" />
) : name === "new-logout" ? (
<img
className="w-[45px] rounded-full bg-white p-1"
src={localImgLoad("images/icons/logout.svg")}
alt="logout"
/>
<img className="w-[45px] rounded-full bg-white p-1" src={localImgLoad('images/icons/logout.svg')} alt="logout" />
) : name === "new-market" ? (
<img
className="w-[17px] h-[17px]"
src={localImgLoad("images/icons/market.svg")}
alt="market"
/>
<img className="w-[17px] h-[17px]" src={localImgLoad('images/icons/market.svg')} alt="market" />
) : name === "new-mytask" ? (
<img
className="w-[17px] h-[17px]"
src={localImgLoad("images/icons/my-task.svg")}
alt="task"
/>
<img className="w-[17px] h-[17px]" src={localImgLoad('images/icons/my-task.svg')} alt="task" />
) : name === "family-id" ? (
<img
className="w-[20px] h-[20px]"
src={localImgLoad("images/icons/family-id.svg")}
alt="family-id"
/>
<img className="w-[20px] h-[20px]" src={localImgLoad('images/icons/family-id.svg')} alt="family-id" />
) : name === "family-pin" ? (
<img
className="w-[20px] h-[20px]"
src={localImgLoad("images/icons/family-pin.svg")}
alt="family-pin"
/>
) : (
<img className="w-[20px] h-[20px]" src={localImgLoad('images/icons/family-pin.svg')} alt="family-pin" />
): (
""
)}
</>
+1 -1
View File
@@ -16,7 +16,7 @@ export default function ModalCom({ action, children, situation, isOpen, classNam
onClick={action || isOpen}
className="fixed top-0 left-0 w-full lg:h-[100vh] h-full bg-black bg-opacity-40 backdrop-filter backdrop-blur-sm z-50"
></div>
<div className={`fixed lg:h-100vh h-full z-[99999999999999] w-full lg:w-auto inset-0 flex flex-col justify-center items-center ${className}`}>
<div className={`children-element fixed lg:h-100vh h-full z-[99999999999999] w-full lg:w-auto ${className}`}>
{children && children}
</div>
</div>
-106
View File
@@ -1,106 +0,0 @@
import React, {useEffect, useState} from 'react'
import Image from '../../assets/images/taskbanners/default.jpg'
import usersService from '../../services/UsersService';
import { handlePagingFunc } from '../../components/Pagination/HandlePagination';
import PaginatedList from '../../components/Pagination/PaginatedList';
import LoadingSpinner from '../Spinners/LoadingSpinner';
import { AmountTo2DP } from '../Helpers/PriceFormatter';
function JobsCompleted() {
const apiCall = new usersService()
let [familyRewardHistory, setFamilyRewardHistory] = useState({ // FOR PURCHASE HISTORY
loading: true,
data: [],
error: false
})
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem = Number(indexOfFirstItem)+Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentReward = familyRewardHistory?.data?.slice(indexOfFirstItem, indexOfLastItem);
const handlePagination = (e) => {
handlePagingFunc(e,setCurrentPage)
}
//FUNCTION TO GET FAMILY REWARD HISTORY
const getJobCompletedHistory = ()=>{
// apiCall.getFamilyRewardHx().then((res)=>{
// if(res.data.internal_return < 0){ // success but no data
// setFamilyRewardHistory(prev => ({...prev, loading: false}))
// return
// }
// setFamilyRewardHistory(prev => ({...prev, loading: false, data: res.data.result_list}))
// }).catch((error)=>{
// setFamilyRewardHistory(prev => ({...prev, loading: false, error: true}))
// })
setTimeout(()=>{
setFamilyRewardHistory(prev => ({...prev, loading: false, error:true}))
},3000)
}
useEffect(()=>{
getJobCompletedHistory()
}, [])
return (
<div className='flex flex-col justify-between min-h-[500px]'>
{familyRewardHistory.loading ?
<LoadingSpinner size='16' color='sky-blue' height='h-[500px]' />
: familyRewardHistory.data.length ?
<table className="wallet-activity w-full table-auto border-collapse text-left">
<thead className='border-b-2'>
<tr className='text-slate-600'>
<th className="p-2"></th>
<th className="p-2">Amount</th>
<th className="p-2">Date</th>
<th className="p-2">Confirmation</th>
</tr>
</thead>
<tbody>
{currentReward.map((item, index) => {
let date = new Date(item.added).toLocaleDateString()
return (
<tr key={index} className='text-slate-500'>
<td className="p-2">
<div className='flex items-center gap-2'>
<img src={item.icon} className='min-w-[60px] max-w-[60px] min-h-[60px] max-h-[60px] rounded-full bg-slate-500' alt='Reward Logo' />
<div className='flex flex-col'>
<h1 className='text-lg font-bold'>Reward to {item.rec_firstname} {item.rec_lastname}</h1>
<p className='text-sm'>{item.description}</p>
</div>
</div>
</td>
<td className="p-2">{AmountTo2DP(item.amount*0.01)} {item.currency}</td>
<td className="p-2">{date}</td>
<td className="p-2">{item.confirmation}</td>
</tr>
)
}
)}
</tbody>
</table>
:familyRewardHistory.error ?
<div className="p-2 text-slate-500 flex flex-col grow justify-center items-center">
<span>Opps! an error occurred. Please try again!</span>
</div>
:
<div className="p-2 text-slate-500 flex flex-col grow justify-center items-center">
<span>No Completed Job History Found!</span>
</div>
}
{/* PAGINATION BUTTON */}
<PaginatedList onClick={handlePagination} prev={currentPage == 0 ? true : false} next={currentPage+Number(process.env.REACT_APP_ITEM_PER_PAGE) >= familyRewardHistory?.data?.length ? true : false} data={familyRewardHistory?.data} start={indexOfFirstItem} stop={indexOfLastItem} />
{/* END OF PAGINATION BUTTON */}
</div>
)
}
export default JobsCompleted
-18
View File
@@ -11,7 +11,6 @@ import PurchasesTable from "../MyWallet/WalletComponent/PurchasesTable";
import RecentActivityTable from "../MyWallet/WalletComponent/RecentActivityTable";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import RewardsTable from "./RewardsTable";
import JobsCompleted from "./JobsCompleted";
export default function History() {
@@ -250,15 +249,6 @@ export default function History() {
>
Rewards
</button>
<button
name="jobs_completed"
onClick={(e) => setTab(e.target.name)}
className={`px-4 py-1 rounded-t-2xl ${
tab == "jobs_completed" ? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white" : "bg-white text-[#000] border-t-[2px]"
}`}
>
Jobs Completed
</button>
</div>
{/* END OF switch button */}
<div className="history-tables w-full">
@@ -296,14 +286,6 @@ export default function History() {
</div>
}
{/* END OF REWARD SECTION */}
{/* JOBS COMPLETED SECTION */}
{tab == 'jobs_completed' &&
<div className="wallet w-full border-t">
<JobsCompleted />
</div>
}
{/* END OF JOBS COMPLETED SECTION */}
</div>
</div>
{/*<HistoryTable />*/}
+2 -2
View File
@@ -4,7 +4,7 @@ import Icons from "../Helpers/Icons";
import SliderCom from "../Helpers/SliderCom";
import FamilyActiveJobsCard from "../Cards/FamilyActiveJobsCard";
export default function FamilyActiveLSlde({ className, trending, image_server }) {
export default function FamilyActiveLSlde({ className, trending }) {
const settings = {
arrows: false,
slidesToShow: 3,
@@ -98,7 +98,7 @@ export default function FamilyActiveLSlde({ className, trending, image_server })
{trending &&
trending.length > 0 &&
trending.map((item) => (
<FamilyActiveJobsCard key={item.id} datas={item} image_server={image_server} />
<FamilyActiveJobsCard key={item.id} datas={item} />
))}
</SliderCom>
</div>
+4 -8
View File
@@ -4,22 +4,18 @@ import MyOffersFamilyTable from "../MyTasks/MyOffersFamilyTable";
import FamilyActiveLSlde from "./FamilyActiveLSlde";
export default function FamilyDash({ familyOffers, MyActiveJobList }) {
// console.log("PROPS IN FAMILY DASH->", familyOffers?.result_list);
console.log("PROPS IN FAMILY DASH->", familyOffers);
const trending = MyActiveJobList;
return (
<div>
<div className="home-page-wrapper">
{/* <CommonHead commonHeadData={props.commonHeadData} /> */}
{familyOffers?.result_list && familyOffers?.result_list.length > 0 && (
<MyOffersFamilyTable
familyOffers={familyOffers?.result_list}
image_server={familyOffers?.session_image_server}
className="mb-10"
/>
{familyOffers && familyOffers.length > 0 && (
<MyOffersFamilyTable familyOffers={familyOffers} className="mb-10" />
)}
{trending && trending.length > 0 && (
<FamilyActiveLSlde trending={trending} className="mb-10" image_server={familyOffers?.session_image_server} />
<FamilyActiveLSlde trending={trending} className="mb-10" />
)}
{/*<TopSellerTopBuyerSliderSection className="mb-10" />*/}
-1
View File
@@ -34,7 +34,6 @@ export default function FullAccountDash(props) {
<MyJobTable
ActiveJobList={props.MyActiveJobList}
Account={userDetails}
imageServer={props.offersList?.data?.session_image_server}
/>
</>
) : !props.offersList?.loading && !props.MyActiveJobList?.loading ? (
+1 -1
View File
@@ -75,7 +75,7 @@ export default function Home(props) {
<FamilyDash
account={userDetails}
commonHeadData={props.bannerList}
familyOffers={MyOffersList?.data}
familyOffers={MyOffersList?.data?.result_list}
MyActiveJobList={MyActiveJobList?.data}
/>
) : userDetails && userDetails?.account_type == "FULL" ? (
-157
View File
@@ -1,157 +0,0 @@
import React, { useState } from 'react'
import ModalCom from '../Helpers/ModalCom'
import LoadingSpinner from '../Spinners/LoadingSpinner'
import InputCom from '../Helpers/Inputs/InputCom/index'
import usersService from '../../services/UsersService'
export default function AddGroup({action, situation , setUpdateList}) {
const api = new usersService()
const [name, setName] = useState('')
const handleChange = ({target:{name, value}}) =>{
setName(value)
}
let [requestStatus, setRequestStatus] = useState({
loading: false,
status: false,
message: "",
}); // STATE FOR KNOWING WHEN A REQUEST IS MADE TO THE SERVER
const addGroup = () => {
setRequestStatus({loading:true, status:false, message:''})
if(name == ''){
setRequestStatus({loading:false, status:false, message:'Please enter a group name'})
return setTimeout(()=>{
setRequestStatus({loading:false, status:false, message:''})
},3000)
}
if(name.length < 6){
setRequestStatus({loading:false, status:false, message:'Group name must be up to six characters'})
return setTimeout(()=>{
setRequestStatus({loading:false, status:false, message:''})
},3000)
}
api.jobGroupAdd({group_name:name, action:13025}).then(response => {
let {status, data} = response
if(status != 200 || data.internal_return < 0){
setRequestStatus({loading:false, status:false, message:'Unable to add Group'})
return
}
setRequestStatus({loading:false, status:true, message:'Group Added'})
setTimeout(()=>{
setRequestStatus({loading:false, status:false, message:''})
// close modal
action()
// reload group page
setUpdateList(prev => !prev)
},3000)
}).catch(error => {
setRequestStatus({loading:false, status:false, message:'Unable to add Group, try again later'})
}).finally(()=>{
setTimeout(()=>{
setRequestStatus({loading:false, status:false, message:''})
},3000)
})
}
return (
<ModalCom
action={action}
situation={situation}
>
<div className="logout-modal-wrapper lg:w-[500px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b border-light-purple dark:border-[#5356fb29] ">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Add Group
</h1>
<button
type="button"
className="text-[#374557] dark:text-red-500"
onClick={action}
>
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
className="fill-current"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z"
fill=""
fillOpacity="0.6"
/>
<path
d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z"
fill="#"
fillOpacity="0.6"
/>
</svg>
</button>
</div>
<div className="logout-modal-body w-full flex flex-col items-center px-10 py-8">
<div className="mb-6 w-full">
<div className="input-item">
<InputCom
labelClass="tracking-wider"
fieldClass="sm:px-6 px-2"
value={name}
placeholder="Group Name"
label="Group Name"
name="name"
type="text"
inputHandler={handleChange}
// iconName="message"
/>
</div>
</div>
<div className="w-full flex justify-between items-center gap-4">
<button
onClick={action}
type="button"
className="text-base text-light-red tracking-wide "
>
<span className="border-b dark:border-[#5356fb29] border-light-red">Cancel</span>
</button>
{requestStatus.loading ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<button
onClick={() => addGroup()}
type="button"
className="w-[152px] h-[46px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Add Group
</button>
)}
</div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
) : (
requestStatus.status && (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
{/* End of error or success display */}
</div>
</div>
</ModalCom>
)
}
-122
View File
@@ -1,122 +0,0 @@
import React, { useState } from 'react'
import ModalCom from '../Helpers/ModalCom'
import LoadingSpinner from '../Spinners/LoadingSpinner'
export default function DeleteGroup({action, situation, details}) {
let [requestStatus, setRequestStatus] = useState({
laoding: false,
status: false,
message: "",
}); // STATE FOR KNOWING WHEN A REQUEST IS MADE TO THE SERVER
const deleteGroup = () => {
}
return (
<ModalCom
action={action}
situation={situation}
>
<div className="logout-modal-wrapper lg:w-[500px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b border-light-purple dark:border-[#5356fb29] ">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Delete Group
</h1>
<button
type="button"
className="text-[#374557] dark:text-red-500"
onClick={action}
>
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
className="fill-current"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z"
fill=""
fillOpacity="0.6"
/>
<path
d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z"
fill="#"
fillOpacity="0.6"
/>
</svg>
</button>
</div>
<div className="logout-modal-body w-full flex flex-col items-center px-10 py-8">
<div className="what-icon mb-6 cursor-pointer">
<svg
width="136"
height="136"
viewBox="0 0 136 136"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="68" cy="68" r="68" fill="#4687ba" />
<path
d="M69.8844 35.7891C71.1588 36.0357 72.4569 36.1967 73.7044 36.5423C81.5447 38.7098 87.2705 45.5378 87.9574 53.6156C88.5113 60.1147 86.3075 65.6006 81.5043 70.0195C79.8359 71.5545 78.0497 72.9604 76.3408 74.4534C76.127 74.6397 75.9654 75.0037 75.9604 75.2872C75.9284 77.2752 75.9435 79.2649 75.9435 81.2965C70.8895 81.2965 65.8758 81.2965 60.7915 81.2965C60.7915 81.0616 60.7915 80.8385 60.7915 80.6137C60.7915 76.5454 60.7999 72.4772 60.7797 68.4106C60.778 67.9392 60.9312 67.649 61.2831 67.3537C64.5643 64.5957 67.8271 61.8175 71.1033 59.0545C72.2616 58.0781 72.9215 56.8702 72.9081 55.3419C72.8878 52.916 70.8608 50.9146 68.423 50.8911C65.9701 50.8693 63.9145 52.8053 63.832 55.2328C63.8084 55.8988 63.8286 56.5665 63.8286 57.2695C58.7745 57.2695 53.7744 57.2695 48.6917 57.2695C48.6917 56.3149 48.6462 55.3385 48.6984 54.3655C49.222 44.699 56.7442 36.8745 66.4331 35.8914C66.5762 35.8763 66.7142 35.8243 66.854 35.7891C67.8641 35.7891 68.8742 35.7891 69.8844 35.7891Z"
fill="white"
/>
<path
d="M67.485 100.21C66.1617 99.9268 64.9041 99.5091 63.803 98.6787C61.3804 96.8484 60.2877 93.7699 61.0386 90.7888C61.7726 87.8747 64.2138 85.6703 67.2089 85.2157C71.273 84.6 75.2024 87.3681 75.8135 91.277C76.4937 95.6153 73.8202 99.3782 69.544 100.103C69.4429 100.12 69.3487 100.172 69.2527 100.209C68.6635 100.21 68.0742 100.21 67.485 100.21Z"
fill="white"
/>
</svg>
</div>
<div className="mb-6">
<p className="text-xl text-center tracking-wide text-dark-gray dark:text-white">
Are you sure, you want to delete <br /> <span>'{details?.group_name}'</span>
</p>
</div>
<div className="flex space-x-2.5">
<button
onClick={action}
type="button"
className=" border-gradient text-18 tracking-wide px-4 py-3 rounded-full"
>
<span className="text-gradient">Cancel</span>
</button>
{requestStatus.laoding ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<button
onClick={() => deleteGroup()}
type="button"
className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full"
>
Confirm Delete
</button>
)}
</div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
) : (
requestStatus.status && (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
{/* End of error or success display */}
</div>
</div>
</ModalCom>
)
}
-122
View File
@@ -1,122 +0,0 @@
import React, { useState } from 'react'
import ModalCom from '../Helpers/ModalCom'
import LoadingSpinner from '../Spinners/LoadingSpinner'
export default function DeleteMember({action, situation, details}) {
let [requestStatus, setRequestStatus] = useState({
laoding: false,
status: false,
message: "",
}); // STATE FOR KNOWING WHEN A REQUEST IS MADE TO THE SERVER
const deleteMember = () => {
}
return (
<ModalCom
action={action}
situation={situation}
>
<div className="logout-modal-wrapper lg:w-[500px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b border-light-purple dark:border-[#5356fb29] ">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Delete Member
</h1>
<button
type="button"
className="text-[#374557] dark:text-red-500"
onClick={action}
>
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
className="fill-current"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z"
fill=""
fillOpacity="0.6"
/>
<path
d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z"
fill="#"
fillOpacity="0.6"
/>
</svg>
</button>
</div>
<div className="logout-modal-body w-full flex flex-col items-center px-10 py-8">
<div className="what-icon mb-6 cursor-pointer">
<svg
width="136"
height="136"
viewBox="0 0 136 136"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="68" cy="68" r="68" fill="#4687ba" />
<path
d="M69.8844 35.7891C71.1588 36.0357 72.4569 36.1967 73.7044 36.5423C81.5447 38.7098 87.2705 45.5378 87.9574 53.6156C88.5113 60.1147 86.3075 65.6006 81.5043 70.0195C79.8359 71.5545 78.0497 72.9604 76.3408 74.4534C76.127 74.6397 75.9654 75.0037 75.9604 75.2872C75.9284 77.2752 75.9435 79.2649 75.9435 81.2965C70.8895 81.2965 65.8758 81.2965 60.7915 81.2965C60.7915 81.0616 60.7915 80.8385 60.7915 80.6137C60.7915 76.5454 60.7999 72.4772 60.7797 68.4106C60.778 67.9392 60.9312 67.649 61.2831 67.3537C64.5643 64.5957 67.8271 61.8175 71.1033 59.0545C72.2616 58.0781 72.9215 56.8702 72.9081 55.3419C72.8878 52.916 70.8608 50.9146 68.423 50.8911C65.9701 50.8693 63.9145 52.8053 63.832 55.2328C63.8084 55.8988 63.8286 56.5665 63.8286 57.2695C58.7745 57.2695 53.7744 57.2695 48.6917 57.2695C48.6917 56.3149 48.6462 55.3385 48.6984 54.3655C49.222 44.699 56.7442 36.8745 66.4331 35.8914C66.5762 35.8763 66.7142 35.8243 66.854 35.7891C67.8641 35.7891 68.8742 35.7891 69.8844 35.7891Z"
fill="white"
/>
<path
d="M67.485 100.21C66.1617 99.9268 64.9041 99.5091 63.803 98.6787C61.3804 96.8484 60.2877 93.7699 61.0386 90.7888C61.7726 87.8747 64.2138 85.6703 67.2089 85.2157C71.273 84.6 75.2024 87.3681 75.8135 91.277C76.4937 95.6153 73.8202 99.3782 69.544 100.103C69.4429 100.12 69.3487 100.172 69.2527 100.209C68.6635 100.21 68.0742 100.21 67.485 100.21Z"
fill="white"
/>
</svg>
</div>
<div className="mb-6">
<p className="text-xl text-center tracking-wide text-dark-gray dark:text-white">
Are you sure, you want to delete <br /> <span>'{details?.firstname} {details.lastname}'</span>
</p>
</div>
<div className="flex space-x-2.5">
<button
onClick={action}
type="button"
className=" border-gradient text-18 tracking-wide px-4 py-3 rounded-full"
>
<span className="text-gradient">Cancel</span>
</button>
{requestStatus.laoding ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<button
onClick={() => deleteMember()}
type="button"
className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full"
>
Confirm Delete
</button>
)}
</div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
) : (
requestStatus.status && (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
{/* End of error or success display */}
</div>
</div>
</ModalCom>
)
}
-72
View File
@@ -1,72 +0,0 @@
import React, { useState } from 'react'
import InputCom from '../../components/Helpers/Inputs/InputCom/index'
import DeleteGroup from './DeleteGroup'
import AddGroup from './AddGroup'
export default function GroupList({groupList, selectedGroup, changeSelectedGroup, setUpdateList}) {
const [deletePopout, setDeletePopout] = useState({
status: false,
data: {}
})
const [addGroupPopout, setAddGroupPopout] = useState(false)
const handleAddGroup = () => {
setAddGroupPopout(true)
}
const handleDeleteGroup = (item) => {
setDeletePopout({
status: true,
data: {...item}
})
}
return (
<>
<div className='p-5 w-full lg:w-[400px] min-h-[300px] bg-sky-100 dark:bg-dark-gray rounded-2xl'>
{/* <h1 className='mb-5 text-lg lg:text-2xl tracking-wide font-bold text-slate-900 dark:text-slate-100'>Jobs Groups</h1> */}
<div className='flex justify-end items-center'>
<button onClick={handleAddGroup} className='py-2 px-4 flex justify-center items-center bg-sky-blue hover:bg-sky-600 text-base rounded-full text-white font-bold'>Add Group</button>
</div>
{groupList && groupList.length < 1 ?
<h1 className='my-5 text-lg tracking-wide text-slate-900 dark:text-slate-100'>No Group Found!</h1>
:
<div className='my-4 max-h-[400px] overflow-y-auto'>
<div className='flex flex-col'>
{groupList.map(item=> (
<div key={item.group_uid} className='p-2 flex gap-2 items-center justify-between w-full'>
<div className='flex gap-2 items-center'>
<input type='radio' name='grouplist' value={item.group_id} checked={selectedGroup?.id == item?.group_id} onChange={changeSelectedGroup} className='w-[20px] h-[20px] outline-none' />
<p className='text-sm lg:text-base text-slate-900 dark:text-slate-100'>{item.group_name}</p>
</div>
<button onClick={()=>{handleDeleteGroup(item)}} className='rounded-lg text-sm bg-red-500 hover:bg-red-400 text-white font-bold py-1 px-2.5 flex justify-center items-center'>X</button>
</div>
))}
</div>
</div>
}
</div>
{deletePopout.status &&
<DeleteGroup
action={()=>setDeletePopout({status:false, data:{}})}
situation={deletePopout.status}
details={deletePopout.data}
/>
}
{addGroupPopout &&
<AddGroup
action={()=>setAddGroupPopout(false)}
situation={addGroupPopout}
setUpdateList={setUpdateList}
/>
}
</>
)
}
@@ -1,98 +0,0 @@
import React, { useState } from 'react'
import { handlePagingFunc } from '../Pagination/HandlePagination';
import PaginatedList from '../Pagination/PaginatedList';
import DeleteMember from './DeleteMember';
export default function GroupMemberTable({selectedList}) {
// Handle Pagination
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem =Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentSelectedList = selectedList?.slice(indexOfFirstItem, indexOfLastItem);
const handlePagination = (e) => {
handlePagingFunc(e, setCurrentPage);
};
const [deletePopout, setDeletePopout] = useState({
status: false,
data: {}
})
const handleDeleteMember = (item) => {
setDeletePopout({
status: true,
data: {...item}
})
}
return (
<div className={`w-full p-8 bg-white dark:bg-dark-gray overflow-hidden rounded-2xl section-shadow`}>
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between min-h-[400px]">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
<>
{selectedList && selectedList?.length > 0 ? (
currentSelectedList.map((value, index) => (
<tr key={value.uid} className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
{/* <td className="p-1">{value?.firstname}</td>
<td className="p-1">{value?.lastname}</td>
<td className="p-1">{value?.email}</td>
<td className="p-1 text-right">
<button onClick={()=>{handleDeleteMember(value)}} className='rounded-lg text-sm bg-red-500 hover:bg-red-400 text-white font-bold py-1 px-2.5'>X</button>
</td> */}
<td className='py-2'>
<div className="flex flex-col">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
{value.firstname && value.firstname} {value.lastname && value.lastname}
</h1>
<span className="text-sm text-thin-light-gray">
{value.email && value.email}
</span>
</div>
</td>
<td className='py-2 text-right'>
<button onClick={()=>{handleDeleteMember(value)}} className='rounded-lg text-sm bg-red-500 hover:bg-red-400 text-white font-bold py-1 px-2.5'>X</button>
</td>
</tr>
))
) : (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<td className="p-2">No Members Found</td>
</tr>
)}
</>
</tbody>
</table>
{/* PAGINATION BUTTON */}
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
selectedList?.length
? true
: false
}
data={selectedList}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
{/* END OF PAGINATION BUTTON */}
</div>
{/* DELETE MEMBER POPOUT */}
{deletePopout.status &&
<DeleteMember
action={()=>setDeletePopout({status:false, data:{}})}
situation={deletePopout.status}
details={deletePopout.data}
/>
}
{/* END OF DELETE MEMBER POPOUT */}
</div>
);
};
-79
View File
@@ -1,79 +0,0 @@
import React, { useEffect, useState } from 'react'
import Layout from '../Partials/Layout'
import GroupList from './GroupList'
import MemberList from './MemberList'
import LoadingSpinner from '../Spinners/LoadingSpinner'
import usersService from '../../services/UsersService'
export default function JobGroups() {
const userApi = new usersService();
const [updateList, setUpdateList] = useState(false)
const [groupList, setGroupList] = useState({
loading:true,
groups: [],
members: []
})
const [selectedGroup, setSelectedGroup] = useState({id:'', name:'', data: []})
const changeSelectedGroup = (e) => {
let groupID = e.target.value
const activeMembers = groupList?.members?.filter(item => item.group_id == groupID)
const activeGroup = groupList?.groups?.filter(item => item.group_id == groupID)
setSelectedGroup({id: groupID, name:activeGroup[0]?.group_name, data:activeMembers})
}
useEffect(()=>{
setGroupList({loading: true, groups: [], members: []})
userApi.jobGroupList({}).then(res => {
const {status, data} = res
if(status != 200 || data?.internal_return < 0){
setGroupList({loading: false, groups: [], members: []})
return
}
if(data.result_list.length < 0){
setGroupList({loading: false, groups: [], members: []})
return
}
setGroupList({loading: false, groups: data.result_list, members: data.result_list_member})
if(selectedGroup.id == ''){
let activeGroupId = data.result_list[0].group_id
let activeGroup = data.result_list[0].group_name
let activeMembers = data.result_list_member?.filter(item => item.group_id == activeGroupId)
setSelectedGroup({id: activeGroupId, name:activeGroup, data:activeMembers})
}else{
let activeMembers = data.result_list_member?.filter(item => item.group_id == selectedGroup?.id)
setSelectedGroup({id: selectedGroup?.id, name:selectedGroup?.name, data:activeMembers})
}
}).catch(error => {
setGroupList({loading: false, groups: [], members: []})
console.log(error)
})
},[updateList])
return (
<Layout>
<div>
<h1 className='mb-5 text-lg lg:text-2xl tracking-wide font-bold text-slate-900 dark:text-slate-100'>Jobs Groups</h1>
</div>
<div className='p-5 w-full min-h-[400px] flex flex-col lg:flex-row gap-3 lg:gap-6 rounded-lg shadow-md bg-white dark:bg-dark-white'>
{groupList.loading ?
<div className='w-full h-[400px] flex justify-center items-center'>
<LoadingSpinner size='16' />
</div>
:
<>
<GroupList groupList={groupList?.groups} selectedGroup={selectedGroup} changeSelectedGroup={changeSelectedGroup} setUpdateList={setUpdateList} />
<MemberList groupList={groupList?.groups} selectedGroup={selectedGroup} setUpdateList={setUpdateList} />
</>
}
</div>
</Layout>
)
}
-262
View File
@@ -1,262 +0,0 @@
import React, { useState } from 'react'
import InputCom from '../../components/Helpers/Inputs/InputCom/index'
import LoadingSpinner from '../Spinners/LoadingSpinner'
import GroupMemberTable from './GroupMemberTable'
import EmailValidator from '../../lib/EmailValidator'
import usersService from '../../services/UsersService'
export default function MemberList({groupList, selectedGroup, setUpdateList}) {
const api = new usersService()
const [fields, setFields] = useState({
firstname: '',
lastname: '',
email: ''
})
const handleFieldsChange = ({target:{name, value}}) => {
setFields(prev => ({...prev, [name]:value}))
// let error = requestState?.errors?.indexOf(name) //// checks if the input field was in error array and removes it when the input changes
// if(error >= 0){
// let oldErrorArr = requestState.errors
// let newErrorArr = oldErrorArr.splice(error, 1)
// setRequestState(prev => ({...prev, errors:oldErrorArr}))
// }
if(value == ''){
setRequestState({
loading: false,
status: false,
message: '',
data: [],
errors: [name]
})
}else{
let error = requestState?.errors?.indexOf(name) //// checks if the input field was in error array and removes it when the input changes
if(error >= 0){
let oldErrorArr = requestState.errors
let newErrorArr = oldErrorArr.splice(error, 1)
setRequestState(prev => ({...prev, errors:oldErrorArr}))
}
}
if(name == 'email'){
//checks if email is a valid email address
let regEx = /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/;
if (!EmailValidator(value)) {
setRequestState({
loading: false,
status: false,
message: '',
data: [],
errors: ['email']
})
}
}
}
const [requestState, setRequestState] = useState({
loading: false,
status: false,
message: '',
data: [],
errors: ['email', 'firstname', 'lastname']
})
const addMember = () => {
// let errors = Object.keys(fields).filter((item) => { // CHECKS FOR EMPTY STRINGS
// if(typeof item == 'string' && fields[item] === ''){
// return item
// }
// })
// if(errors.length){
// setRequestState({
// loading: false,
// status: false,
// message: '',
// data: [],
// errors: [...errors]
// })
// return
// }
//checks if email is a valid email address
let regEx = /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/;
if (!EmailValidator(fields.email)) {
setRequestState({
loading: false,
status: false,
message: 'Email is invalid',
data: [],
errors: []
})
return setTimeout(()=>{
setRequestState({
loading: false,
status: false,
message: '',
data: [],
errors: []
})
},3000)
}
setRequestState({
loading: true,
status: false,
message: '',
data: [],
errors: []
})
const requestData = {
firstname:fields.firstname,lastname:fields.lastname, email:fields.email, group_id: selectedGroup?.id, action:13015
}
api.groupMemberAdd(requestData).then(response => {
let {status, data} = response
if(status != 200 || data?.internal_return < 0){
setRequestState({
loading: false,
status: false,
message: 'Unable to add member',
data: [],
errors: []
})
return
}
setRequestState({
loading: false,
status: true,
message: 'Member added',
data: [],
errors: []
})
setTimeout(()=>{
// trigger group page reload
setUpdateList(prev => !prev)
setRequestState({
loading: false,
status: false,
message: '',
data: [],
errors: []
})
}, 3000)
}).catch(error=>{
setRequestState({
loading: false,
status: false,
message: 'Something went wrong, try again',
data: [],
errors: []
})
}).finally(()=>{
setTimeout(()=>{
setRequestState({
loading: false,
status: false,
message: '',
data: [],
errors: []
})
setFields({
firstname: '',
lastname: '',
email: ''
})
}, 3000)
})
}
return (
<>
<div className='p-5 w-full min-h-[600px] overflow-y-auto'>
{groupList && groupList.length < 1 ?
<>
<h1 className='my-5 text-lg lg:text-xl tracking-wide text-slate-900 dark:text-slate-100'>You Currently Do not have any Group, Please Add Group</h1>
</>
:
<>
<h1 className='mb-5 text-lg lg:text-2xl tracking-wide font-bold text-slate-900 dark:text-slate-100'>{selectedGroup?.name}</h1>
<div className='w-full flex flex-col-reverse lg:flex-col'>
<div className='py-3 w-full'>
<div className='relative grid grid-cols-1 sm:grid-cols-2 gap-2 place-content-center'>
<div className="input-item">
<InputCom
labelClass="tracking-wider"
fieldClass="sm:px-6 px-2"
value={fields.firstname}
inputHandler={handleFieldsChange}
placeholder="First Name"
// label="Firstname"
name="firstname"
type="text"
// iconName="message"
/>
</div>
<div className="input-item">
<InputCom
labelClass="tracking-wider"
fieldClass="sm:px-6 px-2"
value={fields.lastname}
inputHandler={handleFieldsChange}
placeholder="Last Name"
// label="Lastname"
name="lastname"
type="text"
// iconName="message"
/>
</div>
<div className="input-item w-full sm:w-[150%]">
<InputCom
labelClass="tracking-wider"
fieldClass="sm:px-6 px-2"
value={fields.email}
inputHandler={handleFieldsChange}
placeholder="Email"
// label="Email"
name="email"
type="email"
// iconName="message"
/>
</div>
<div className='flex justify-end items-end'>
{requestState.loading ?
<LoadingSpinner size='8' color='sky-blue' />
:
<button
onClick={addMember}
disabled={requestState.loading || requestState.status || requestState.errors.length}
className={`py-2 px-4 h-[42px] flex justify-center items-center text-base rounded-full text-white font-bold transition-all duration-500 ${requestState.loading || requestState.status || requestState.errors.length ? 'bg-sky-blue/50' : 'bg-sky-blue hover:bg-sky-600'} `}
>
Add Member
</button>
}
</div>
{!requestState.loading && requestState.message &&
<p className={`text-lg absolute -bottom-7 left-0 ${requestState.status ? 'text-green-500' : 'text-red-500'}`}>{requestState.message}</p>
}
</div>
</div>
<div className='my-2 flex flex-col min-h-[300px]'>
{selectedGroup?.data?.length < 1 ?
<h1 className='my-5 text-lg lg:text-xl tracking-wide text-slate-900 dark:text-slate-100'>No Member Found, Please Add</h1>
:
<GroupMemberTable selectedList={selectedGroup?.data} />
}
</div>
</div>
</>
}
</div>
</>
)
}
@@ -8,7 +8,6 @@ import SelectBox from "../Helpers/SelectBox";
export default function MainSection({
className,
marketPlaceProduct,
image_server,
categories,
}) {
// Creating All cart..
@@ -111,7 +110,6 @@ export default function MainSection({
{({ datas }) => (
<AvailableJobsCard
contentDisplay={contentDisplay}
image_server={image_server}
key={datas.id}
datas={datas}
/>
@@ -117,8 +117,8 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
.replace(/&amp;/g, "&");
return (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper w-11/12 md:w-[650px] md:h-[580px] h-full bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<ModalCom action={onClose} situation={situation} className="edit-popup">
<div className="logout-modal-wrapper md:w-[650px] md:h-[580px] 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]">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
{details.offer_code}
-2
View File
@@ -7,7 +7,6 @@ export default function MarketPlace({ commonHeadData }) {
let { jobLists } = useSelector((state) => state.jobLists);
const marketData = jobLists?.result_list;
const categories = jobLists?.categories;
const image_server = jobLists?.session_image_server;
return (
<>
@@ -16,7 +15,6 @@ export default function MarketPlace({ commonHeadData }) {
<MainSection
marketPlaceProduct={marketData}
categories={categories}
image_server={image_server}
className="mb-10"
/>
</Layout>
@@ -30,26 +30,21 @@ export default function ActiveJobMessage({ activeJobMesList }) {
{activeJobMesList?.data?.length ?
(
<tbody>
{activeJobMesList.data.map((item, index) =>
{
let imageLink = `${activeJobMesList?.image}${localStorage.getItem('session_token')}/contracts/${item.msg_uid}`
return (
<tr key={index} className='text-slate-500'>
<td>
<div className={`msg_box ${item.who}`}>
<div className="msg_header">{item.msg_date} {item.msg_firstname}</div>
{item.msg_type == 'FILE' ?
<a href={imageLink} target="_blank" className="p-2" dangerouslySetInnerHTML={{__html: item.message}}></a>
:
<span className="p-2" dangerouslySetInnerHTML={{__html: item.message}}></span>
}
</div>
</td>
</tr>
)
}
)}
{activeJobMesList.data.map((item, index) => (
<tr key={index} className='text-slate-500'>
<td>
<div className={`msg_box ${item.who}`}>
<div className="msg_header">{item.msg_date} {item.msg_firstname}</div>
{item.msg_type == 'FILE' ?
<a href='' className="p-2" dangerouslySetInnerHTML={{__html: item.message}}></a>
:
<span className="p-2" dangerouslySetInnerHTML={{__html: item.message}}></span>
}
</div>
</td>
</tr>
))}
</tbody>
)
:
+2 -2
View File
@@ -600,10 +600,10 @@ const PopModal = ({
myRef,
}) => {
return (
<ModalCom action={popUpHandler} situation={popUp}>
<ModalCom action={popUpHandler} situation={popUp} className="edit-popup">
<div
ref={myRef}
className="message-modal-wrapper w-11/12 min-w-[350px] max-w-[700px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto"
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">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
@@ -34,7 +34,7 @@ function PastDueJobAction({jobDetails}) {
let reqData = { // API PAYLOADS
contract: jobDetails.contract,
contract_uid: jobDetails.contract_uid,
job_action: 'CANCEL_CONTRACT',
job_action: 'REQUEST_CANCEL',
}
if(!checked){ // CHECKS IF CHECKBOX IS SELECTED
@@ -3,12 +3,9 @@ import ModalCom from '../../Helpers/ModalCom'
import LoadingSpinner from '../../Spinners/LoadingSpinner'
import { useNavigate } from 'react-router-dom'
import usersService from '../../../services/UsersService'
import { useDispatch } from 'react-redux'
import { tableReload } from '../../../store/TableReloads'
function ReviewJobAction({jobDetails}) {
const dispatch = useDispatch()
const apiCall = new usersService()
const navigate = useNavigate()
@@ -51,7 +48,6 @@ function ReviewJobAction({jobDetails}) {
return
}
setReqStatus({loading:false, status: true, message: 'job completion accepted successfully'})
dispatch(tableReload({ type: "WALLETTABLE" }));
setTimeout(()=>{ // Sets popout to false and navigates user to /my-review-jobs after 3 seconds
popUpHandler()
navigate('/my-review-jobs', {replace: true})
@@ -6,7 +6,6 @@ import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList";
export default function MyActiveJobTable({ MyJobList, className }) {
const navigate = useNavigate();
let { pathname } = useLocation();
@@ -45,7 +44,6 @@ export default function MyActiveJobTable({ MyJobList, className }) {
value?.currency_code,
value?.currency
);
let image = `${MyJobList.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
return (
<tr
key={index}
@@ -53,9 +51,11 @@ export default function MyActiveJobTable({ MyJobList, className }) {
>
<td className=" py-4">
<div className="flex space-x-2 items-center w-full">
<div className="max-w-[60px] max-h-[60px] min-w-[60px] min-h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<img
src={image}
src={localImgLoad(
`images/taskbanners/${value.banner}`
)}
alt="data"
className="w-full h-full rounded-full"
/>
@@ -21,7 +21,7 @@ export default function MyPastDueJobs(props) {
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
>
Past Due Job(s)
Pass Due Job(s)
</span>
</h1>
</div>
+17 -41
View File
@@ -11,8 +11,8 @@ import PaginatedList from "../Pagination/PaginatedList";
import EditJobPopOut from "../jobPopout/EditJobPopout";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import EditIcon from "../../assets/images/icon-edit.svg";
import DeleteIcon from "../../assets/images/icon-delete.svg";
import EditIcon from '../../assets/images/icon-edit.svg'
import DeleteIcon from '../../assets/images/icon-delete.svg'
import localImgLoad from "../../lib/localImgLoad";
export default function MyJobTable({ MyJobList, reloadJobList, className }) {
@@ -42,16 +42,16 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
// Get Country Api
const getCountryList = useCallback(async () => {
const res = await userApi.getSignupCountryData();
try {
const res = await userApi.getSignupCountryData();
if (res.status === 200 && res.data.internal_return >= 0) {
if (res.status === 200) {
const {
data: { result_list },
data: { signup_country },
} = await res;
let checkCountry = result_list
?.filter((item) => item.code == country)
?.map((item) => item.country)
let checkCountry = signup_country
?.filter((item) => item[0] == country)
?.map((item, idx) => item[1])
.join("");
setCountries(checkCountry);
}
@@ -59,7 +59,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
throw new Error(error);
}
}, [userApi, country]);
console.log('MY COUNTRY', myCountry)
useEffect(() => {
getCountryList();
}, [getCountryList]);
@@ -101,19 +101,12 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
}
};
const JobListItem = ({ value, index, image_server }) => {
const JobListItem = ({ value, index }) => {
let thePrice = PriceFormatter(
value?.price * 0.01,
value?.currency_code,
value?.currency
);
const image = localStorage.getItem("session_token")
? `${image_server}${localStorage.getItem("session_token")}/job/${
value.job_uid
}`
: "";
return (
<tr
key={index}
@@ -123,11 +116,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
<div className="sm:flex sm:space-x-2 sm:justify-between sm:items-center job-items">
<div className="flex space-x-2 items-center job-items w-full">
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<img
src={image}
alt="data"
className="w-full h-full rounded-full"
/>
<img src={localImgLoad(`images/taskbanners/${value.banner ? value.banner : 'default.jpg'}`)} alt="data" className="w-full h-full rounded-full" />
</div>
<div className="flex flex-col flex-[0.9]">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
@@ -158,11 +147,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
});
}}
>
<img
className="w-[21px] h-[21px]"
src={DeleteIcon}
alt="delete-icon"
/>
<img className="w-[21px] h-[21px]" src={DeleteIcon} alt='delete-icon' />
</button>
<div className="mx-[4px] h-full w-[1px] bg-black dark:bg-dark-gray"></div>
<button
@@ -175,11 +160,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
});
}}
>
<img
className="w-[21px] h-[21px]"
src={EditIcon}
alt="edit-icon"
/>
<img className="w-[21px] h-[21px]" src={EditIcon} alt='edit-icon' />
<span className="text-sm text-sky-blue">Edit</span>
</button>
</div>
@@ -212,7 +193,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide">
{filterCategories[selectedCategory]} Jobs
</h1>
</div>
</div>
<SelectBox
action={handleSetCategory}
datas={Object.values(filterCategories)}
@@ -220,7 +201,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
contentBodyClasses="w-auto min-w-max"
/>
</div>
{MyJobList?.loading ? (
{MyJobList.loading ? (
<LoadingSpinner size="16" color="sky-blue" />
) : (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between min-h-[520px]">
@@ -232,12 +213,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
MyJobList.data?.result_list.length > 0 ? (
filteredCurrentJobList?.length ? (
filteredCurrentJobList.map((value, index) => (
<JobListItem
index={index}
key={index}
value={value}
image_server={MyJobList?.data.session_image_server}
/>
<JobListItem index={index} key={index} value={value} />
))
) : (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
@@ -8,7 +8,6 @@ import localImgLoad from "../../lib/localImgLoad";
export default function MyPendingJobTable({ MyJobList, className }) {
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
const [currentPage, setCurrentPage] = useState(0);
@@ -46,7 +45,6 @@ export default function MyPendingJobTable({ MyJobList, className }) {
value?.currency_code,
value?.currency
);
let image = `${MyJobList.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
return (
<tr
key={index}
@@ -56,7 +54,7 @@ export default function MyPendingJobTable({ MyJobList, className }) {
<div className="flex space-x-2 items-center w-full">
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<img
src={image}
src={localImgLoad(`images/taskbanners/${value.banner || "default.jpg"}`)}
alt="data"
className="w-full h-full rounded-full"
/>
+3 -4
View File
@@ -10,7 +10,7 @@ import localImgLoad from "../../lib/localImgLoad";
const noTasksBg = require("../../assets/images/no-task-background.jpg");
const noFamilyTasksBg = require("../../assets/images/family-no-task-background.jpg");
export default function MyJobTable({ className, ActiveJobList, Account, imageServer }) {
export default function MyJobTable({ className, ActiveJobList, Account }) {
let navigate = useNavigate();
let { pathname } = useLocation();
@@ -55,7 +55,7 @@ export default function MyJobTable({ className, ActiveJobList, Account, imageSer
{!ActiveJobList?.data.length && accountType && (
<div className="absolute inset-0 bg-black opacity-30"></div>
)}
{ActiveJobList?.loading ?
{ActiveJobList.loading ?
<div className="w-full h-[520px] flex items-center justify-center">
<LoadingSpinner size="16" color="sky-blue" />
</div>
@@ -71,7 +71,6 @@ export default function MyJobTable({ className, ActiveJobList, Account, imageSer
task?.currency_code,
task?.currency
);
let image = `${imageServer}${localStorage.getItem('session_token')}/job/${task.origin_job_uid}`
return (
<div
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] w-full flex justify-between items-center hover:bg-gray-50"
@@ -81,7 +80,7 @@ export default function MyJobTable({ className, ActiveJobList, Account, imageSer
<div className="flex space-x-2 items-center">
<div className="w-full min-w-[60px] max-w-[60px] flex-[0.1] h-[60px] rounded-full overflow-hidden flex justify-center items-center">
<img
src={image}
src={localImgLoad(`images/taskbanners/${task?.banner}`)}
alt="data"
className="w-full h-full"
/>
@@ -4,7 +4,7 @@ import Icons from "../Helpers/Icons";
import SliderCom from "../Helpers/SliderCom";
import FamilyOfferJobPopout from "../jobPopout/FamilyOfferJobPopout";
export default function MyOffersFamilyTable({ className, familyOffers, image_server }) {
export default function MyOffersFamilyTable({ className, familyOffers }) {
let [offerPopout, setOfferPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
const settings = {
arrows: false,
@@ -117,7 +117,6 @@ export default function MyOffersFamilyTable({ className, familyOffers, image_ser
key={item.id}
datas={item}
setOfferPopout={setOfferPopout}
image_server={image_server}
/>
);
})}
+1 -1
View File
@@ -122,7 +122,7 @@ export default function MyOffersTable({ className, MyActiveOffersList }) {
MyActiveOffersList?.result_list?.length > 0 &&
MyActiveOffersList.result_list.map((item) => {
return (
<OfferCard key={item.id} datas={item} setOfferPopout={setOfferPopout} image_server={MyActiveOffersList.session_image_server} />
<OfferCard key={item.id} datas={item} setOfferPopout={setOfferPopout} />
)
})}
</SliderCom>
+1 -1
View File
@@ -94,7 +94,7 @@ export default function MyTasks({
</button>
}
</div>
<MyJobTable ActiveJobList={ActiveJobList} Account={userDetails} imageServer={MyActiveOffersList.session_image_server} />
<MyJobTable ActiveJobList={ActiveJobList} Account={userDetails} />
</div>
</div>
</Layout>
@@ -44,7 +44,7 @@ export default function MyWaitingJobTable({ MyJobList, className }) {
value?.currency_code,
value?.currency
);
let image = `${MyJobList.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
let image = value.banner ? value.banner : 'default.jpg'
return (
<tr
key={index}
@@ -52,9 +52,9 @@ export default function MyWaitingJobTable({ MyJobList, className }) {
>
<td className=" py-4">
<div className="flex space-x-2 items-center w-full">
<div className="max-w-[60px] max-h-[60px] min-w-[60px] min-h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<img
src={image}
src={localImgLoad(`images/taskbanners/${image}`)}
alt="data"
className="w-full h-full rounded-full"
/>
@@ -64,21 +64,17 @@ const initialValues = {
};
function AddFundDollars(props) {
let MaxNoOfCards = process.env.REACT_APP_MAX_CREDIT_CARDS; // HOLDS THE VALUE OF THE MAX NUMBER OF CARDS USER CAN ADD
let MaxNoOfCards = process.env.REACT_APP_MAX_CREDIT_CARDS // HOLDS THE VALUE OF THE MAX NUMBER OF CARDS USER CAN ADD
const apiCall = new usersService();
let countryWallet = props.walletItem.country;
const [selectedOption, setSelectedOption] = useState("previous");
const [tab, setTab] = useState("previous");
const { userDetails } = useSelector((state) => state?.userDetails);
const [prevCardDetails, setPrevCardDetails] = useState({});
const [payListCards, setPayListCards] = useState({ loading: true, data: [] });
const [cardIcons, setCardIcons] = useState("atm-card");
const [prevCardError, setPrevCardError] = useState("");
const handleOptionChange = (event) => {
setSelectedOption(event.target.value);
};
const { firstname, lastname } = userDetails;
// Handling Card Icons
@@ -148,12 +144,7 @@ function AddFundDollars(props) {
return;
}
let stateData = {
amount: Number(props.input) * 100,
currency: props.walletItem?.code,
};
if (selectedOption === "previous") {
if (tab === "previous") {
// To check if card is empty
if (Object.keys(prevCardDetails).length === 0) {
setPrevCardError("No card selected!");
@@ -167,26 +158,10 @@ function AddFundDollars(props) {
show: { awaitConfirm: { loader: true } },
}));
// Extracting card_uid from the previous card details
const paymentCardValue = prevCardDetails["payment-card"];
if (paymentCardValue) {
try {
const paymentCardObject = JSON.parse(paymentCardValue);
stateData = {
...stateData,
card_uid: paymentCardObject.card_uid,
};
} catch (error) {
console.error("Error parsing JSON:", error);
}
} else {
// For the new card details
stateData = {
...stateData,
card_uid: "",
};
}
let stateData = {
amount: Number(props.input) * 100,
currency: props.walletItem?.code,
};
try {
const res = await apiCall.getStartCredit(stateData);
@@ -196,11 +171,12 @@ function AddFundDollars(props) {
}
const _response = res.data;
stateData.amount = Number(props.input);
stateData.card =
selectedOption === "previous"
tab === "previous"
? prevCardDetails["payment-card"]
: { ...values, cvv: values.cvv };
stateData.cardType = selectedOption === "previous" ? "prev" : "new";
stateData.cardType = tab === "previous" ? "prev" : "new";
stateData = { ...stateData, ..._response };
setTimeout(() => {
@@ -248,45 +224,36 @@ function AddFundDollars(props) {
</h1>
<div className="my-1 flex items-center gap-2">
<label
onClick={() => setTab("previous")}
htmlFor="previous"
className="cursor-pointer flex items-center gap-1"
>
<input
type="radio"
id="previous"
value="previous"
name="card-option"
onChange={handleOptionChange}
checked={selectedOption === "previous"}
checked={tab === "previous"}
className={`p-2 text-lg font-bold text-slate-600 dark:text-white border pointer-events-none w-7 h-7 ${
selectedOption == "previous" ? "" : ""
tab == "previous" ? "" : ""
} tracking-wide transition duration-200`}
/>
Previous Cards
</label>
<label
onClick={() => setTab("new")}
htmlFor="new"
className={`cursor-pointer flex items-center gap-1 ${
payListCards.data.length >= MaxNoOfCards
? "pointer-events-none"
: ""
}`}
className={`cursor-pointer flex items-center gap-1 ${payListCards.data.length >= MaxNoOfCards ? 'pointer-events-none':''}`}
>
<input
id="new"
type="radio"
name="card-option"
value="new"
onChange={handleOptionChange}
checked={selectedOption === "new"}
checked={tab === "new"}
className={`p-2 text-lg font-bold text-slate-600 dark:text-white border pointer-events-none w-7 h-7 ${
selectedOption == "new" ? "" : ""
tab == "new" ? "" : ""
} tracking-wide transition duration-200`}
/>
Add New Card{" "}
{payListCards.data.length >= MaxNoOfCards && (
<span className="text-[14px] text-red-500">Max Reached</span>
)}
Add New Card {payListCards.data.length >= MaxNoOfCards && <span className="text-[14px] text-red-500">Max Reached</span>}
</label>
</div>
</form>
@@ -294,8 +261,8 @@ function AddFundDollars(props) {
<hr />
{/* END OF switch button */}
{/* previous selectedOption */}
{selectedOption === "previous" && (
{/* previous tab */}
{tab === "previous" && (
<div className="p-4 previous-details w-full min-h-[16.5rem] flex flex-col">
{payListCards.loading ? (
<LoadingSpinner size="10" color="sky-blue" />
@@ -311,11 +278,10 @@ function AddFundDollars(props) {
{currentPreviousCards.map((item, index) => (
<option
key={index}
className={index !== 0 ? "border-t-2" : undefined}
className={index !== 0 && "border-t-2"}
value={JSON.stringify(item)}
title={`${item.description} Card\nBank **************${item.digits}`}
>
{/* <div className="my-2 flex items-center gap-5">
<div className="my-2 flex items-center gap-5">
<div className="card-details">
<h1 className="text-lg font-bold text-dark-gray dark:text-white tracking-wide">
{item.description} Card
@@ -324,8 +290,7 @@ function AddFundDollars(props) {
Bank **************{item.digits}
</p>
</div>
</div> */}
{item.description} Card - Bank **************{item.digits}
</div>
</option>
))}
</select>
@@ -335,7 +300,7 @@ function AddFundDollars(props) {
No Previous Card Found!
</p>
<button
onClick={() => setSelectedOption("new")}
onClick={() => setTab("new")}
type="button"
className="my-5 px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
@@ -349,13 +314,13 @@ function AddFundDollars(props) {
</div>
)}
{selectedOption === "new" && (
{tab === "new" && (
<div className="new-details w-full max-h-[22rem]">
{payListCards.loading ? (
{payListCards.loading ?
<div className="pt-10 flex w-full h-full justify-center items-center">
<LoadingSpinner size="10" color="sky-blue" />
<LoadingSpinner size='10' color='sky-blue' />
</div>
) : payListCards.data.length < MaxNoOfCards ? (
:payListCards.data.length < MaxNoOfCards ?
<div className="w-full flex flex-col justify-between">
<Formik
initialValues={initialValues}
@@ -414,8 +379,7 @@ function AddFundDollars(props) {
*
</span>
<span className="text-[12px] text-red-500 ml-1">
{props.errors.expirationMonth &&
"**"}
{props.errors.expirationMonth && "**"}
</span>
</label>
</div>
@@ -467,8 +431,7 @@ function AddFundDollars(props) {
*
</span>
<span className="text-[12px] text-red-500 italic">
{props.errors.expirationYear &&
"**"}
{props.errors.expirationYear && "**"}
</span>
</label>
</div>
@@ -597,12 +560,14 @@ function AddFundDollars(props) {
}}
</Formik>
</div>
) : null}
:
null
}
</div>
)}
</div>
{selectedOption == "previous" && (
{tab == "previous" && (
<div className="md:py-8 add-fund-btn flex justify-end items-center gap-2 py-4">
<button
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center bg-[#f5a430] text-black items-center text-base rounded-full"
@@ -71,7 +71,6 @@ function AddFundPop({
// Prepare state data for API call
let stateData = {
amount: Number(input) * 100,
card_uid: "", //added card_uid as empty string
currency: walletItem?.code,
};
@@ -45,7 +45,7 @@ function ThePaymentText({ value, type }) {
* @returns {JSX.Element} - The rendered component.
*/
function AmountSection({ currency, amount, country }) {
const formattedAmount = (+amount * 0.01)?.toFixed(2);
const formattedAmount = amount?.toFixed(2);
const gapClassName = country === "US" ? "gap-14" : "gap-4";
return (
@@ -87,7 +87,7 @@ function TransactionFeeSection({ currency, fee, country }) {
*/
function TotalSection({ currency, amount, fee, country }) {
const total = Number(amount) + Number(fee);
const formattedTotal = (total * 0.01)?.toFixed(2);
const formattedTotal = total?.toFixed(2);
const gap = country === "US" ? "gap-[8rem]" : "gap-[6.3rem]";
@@ -130,7 +130,7 @@ function ConfirmAddFund({
public_key: __confirmData?.flutterwave_key,
tx_ref: __confirmData?.credit_reference,
currency: "NGN",
amount: Number(__confirmData.amount) * 0.01,
amount: Number(__confirmData.amount),
payment_options: "card,mobilemoney,ussd",
customer: {
email: userDetails.email,
@@ -224,7 +224,7 @@ function ConfirmAddFund({
// Create request data object with required parameters for making the payment
const reqData = {
amount: amount,
amount: amount * 100,
card_uid,
credit_reference,
currency,
@@ -289,7 +289,7 @@ function ConfirmAddFund({
// Prepare request data
const reqData = {
amount: amount,
amount: amount * 100,
cardnumber: cardNum.replace(/\s/g, ""),
credit_reference,
cvc: cvv,
@@ -104,8 +104,8 @@ function ConfirmNairaWithdraw({
};
return (
<ModalCom action={action} situation={situation}>
<div className="logout-modal-wrapper w-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<ModalCom action={action} situation={situation} className="edit-popup">
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="w-full">
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
<h2 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
@@ -170,9 +170,9 @@ function ConfirmNairaWithdraw({
viewBox="0 0 24 24"
fill="none"
stroke="green"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
className="feather feather-check-circle"
>
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
@@ -186,9 +186,9 @@ function ConfirmNairaWithdraw({
width="100"
height="100"
stroke="red"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
className="feather feather-x-circle"
>
<circle cx="12" cy="12" r="10"></circle>
@@ -35,7 +35,7 @@ const CreditPopup = ({ details, onClose, situation, walletItem }) => {
situation={situation}
className="assign-task-popup"
>
<div className="logout-modal-wrapper w-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto 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] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
{confirmCredit?.show?.acceptConfirm?.loader
@@ -25,7 +25,7 @@ function NairaWithdraw({
},
newAccount: {
country: wallet.walletCountry
? wallet.walletCountry[0]?.code
? wallet.walletCountry[0][0]
: wallet.country,
bank: state?.newAccount?.amount || "",
accountNumber: state?.newAccount?.amount || "",
@@ -34,6 +34,7 @@ function NairaWithdraw({
city: state?.newAccount?.amount || "",
},
};
const [errorMsgs, setErrorMsgs] = useState(initialValues);
let [sendMoneyFee, setSendMoneyFee] = useState({
@@ -68,7 +69,7 @@ function NairaWithdraw({
// Handling card change
const handleBankOptions = (event) => {
let bankCountry = wallet.walletCountry
? wallet.walletCountry[0]?.code
? wallet.walletCountry[0][0]
: wallet.country
setBankName((prev) => ({ loading: true, data: [] }));
apiCall
@@ -119,7 +120,7 @@ function NairaWithdraw({
}
setAllCountries((prev) => ({
loading: false,
data: res.data.result_list,
data: res.data.signup_country,
}));
})
.catch((error) => {
@@ -286,11 +287,11 @@ function NairaWithdraw({
getRecipients();
}, []);
console.log("Testing Wallet Country", wallet?.walletCountry[0]?.code);
console.log("Testing Wallet Country", wallet?.walletCountry[0][0]);
return (
<ModalCom action={action} situation={situation}>
<div className="logout-modal-wrapper w-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<ModalCom action={action} situation={situation} className="edit-popup">
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="w-full">
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 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">
@@ -559,7 +560,7 @@ function NairaWithdraw({
</label>
<div className="w-full text-base p-2 text-dark-gray dark:text-white border border-slate-300 outline-0 flex-[0.6] rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding tracking-[1.5px] flex items-center pointer-events-none">
<span className="text-slate-500 text-lg italic">
{wallet.walletCountry[0]?.country}
{wallet.walletCountry[0][1]}
</span>
</div>
{/* <select
+2 -2
View File
@@ -41,13 +41,13 @@ const WalletRoutes = () => {
apiCall
.getSignupCountryData()
.then((res) => {
if (res?.data?.internal_return < 0) {
if (res.data.internal_return < 0) {
setAllCountries((prev) => ({ loading: false, data: [] }));
return;
}
setAllCountries((prev) => ({
loading: false,
data: res.data.result_list,
data: res.data.signup_country,
}));
})
.catch((error) => {
-21
View File
@@ -1,7 +1,5 @@
import { useSelector } from "react-redux";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import WalletItemCard from "./WalletItemCard";
import WalletItemCardFamily from "./WalletItemCardFamily";
/**
* Renders a list of wallet items or a loading spinner depending on the state of the `wallet` object.
@@ -9,27 +7,9 @@ import WalletItemCardFamily from "./WalletItemCardFamily";
export default function WalletBox({ wallet, payment, countries }) {
const { loading, data } = wallet;
const { userDetails } = useSelector((state) => state.userDetails);
const accountType = userDetails?.account_type === "FAMILY";
return (
<div className="my-wallet-wrapper w-full mb-10">
<div className="main-wrapper w-full">
{accountType ?
<div className="balance-inquery w-auto grid sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-[repeat(auto-fill,_minmax(354px,_1fr))] min-[1440px]:grid-cols-[repeat(auto-fill,_minmax(415px,_1fr))] gap-5 mb-11 h-auto">
{loading ? (
<div className="w-full h-full flex items-center justify-center">
<LoadingSpinner size="16" color="sky-blue" />
</div>
) : (
data.length > 0 && data.map((item) => (
<div key={item.wallet_uid} className="lg:w-full h-full mb-10 lg:mb-0">
<WalletItemCardFamily walletItem={item} payment={payment} countries={countries} />
</div>
))
)}
</div>
:
<div className="balance-inquery w-auto grid sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-[repeat(auto-fill,_minmax(354px,_1fr))] min-[1440px]:grid-cols-[repeat(auto-fill,_minmax(415px,_1fr))] gap-5 mb-11 h-auto">
{loading ? (
<div className="w-full h-full flex items-center justify-center">
@@ -43,7 +23,6 @@ export default function WalletBox({ wallet, payment, countries }) {
))
)}
</div>
}
</div>
</div>
);
+11 -8
View File
@@ -11,7 +11,8 @@ import WalletAction from "./WalletAction";
* Renders a card displaying information about a wallet item.
*/
export default function WalletItemCard({ walletItem, payment, countries }) {
const { userDetails } = useSelector((state) => state.userDetails);
const accountType = userDetails?.account_type === "FAMILY";
const dispatch = useDispatch();
const [creditPopup, setCreditPopup] = useState({ show: false, data: {} });
@@ -35,8 +36,8 @@ export default function WalletItemCard({ walletItem, payment, countries }) {
};
const currentWalletCurrency = countries
// .map((country) => country)
.filter((country) => country.code === walletItem.country);
.map((country) => country)
.filter((country) => country[0] === walletItem.country);
const image = walletItem.code
? `${walletItem.code.toLowerCase()}.svg`
@@ -90,11 +91,13 @@ export default function WalletItemCard({ walletItem, payment, countries }) {
<div className="my-2 w-full h-[1px] bg-white"></div>
<WalletAction
walletItem={{ ...walletItem, walletCountry: currentWalletCurrency }}
payment={payment}
openPopUp={openPopUp}
/>
{!accountType && (
<WalletAction
walletItem={{ ...walletItem, walletCountry: currentWalletCurrency }}
payment={payment}
openPopUp={openPopUp}
/>
)}
</div>
{creditPopup.show && (
@@ -1,97 +0,0 @@
import React, { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import background from "../../assets/images/bg-sky-blue.jpg"; //shape/balance-bg.svg";
import localImgLoad from "../../lib/localImgLoad";
import { tableReload } from "../../store/TableReloads";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import CreditPopup from "./Popup/CreditPopup";
import WalletAction from "./WalletAction";
/**
* Renders a card displaying information about a wallet item.
*/
export default function WalletItemCardFamily({ walletItem, payment, countries }) {
const dispatch = useDispatch();
const [creditPopup, setCreditPopup] = useState({ show: false, data: {} });
/**
* Opens the credit popup.
* @param {Object} value - The value object.
*/
const openPopUp = (value) => {
setCreditPopup({
show: true,
data: { ...value },
});
};
/**
* Closes the credit popup and dispatches a table reload action.
*/
const closePopUp = () => {
setCreditPopup({ show: false, data: {} });
dispatch(tableReload({ type: "WALLETTABLE" }));
};
const currentWalletCurrency = countries
// .map((country) => country)
.filter((country) => country.code === walletItem.country);
const image = walletItem.code
? `${walletItem.code.toLowerCase()}.svg`
: "default.png";
return (
<>
<div
className="current-balance-widget w-full h-full rounded-2xl overflow-hidden flex flex-col items-center gap-2 p-8 justify-between"
style={{
background: `url(${background}) 0% 0% / cover no-repeat`,
}}
>
<div className="wallet w-full flex justify-between items-center gap-3">
<div className="min-w-[100px] min-h-[100px] max-w-min md:max-w-[150px] max-h-min md:max-h-[150px] rounded-full bg-[#e3e3e3] flex justify-center items-center">
<img
src={localImgLoad(`images/currency/${image}`)}
className="w-full h-full"
alt="currency-icon"
/>
</div>
<div className="balance w-full mt-2 flex justify-center">
<div className="">
<p className="text-base sm:text-lg text-white opacity-[70%] tracking-wide mb-2 sm:mb-6">
Current Balance
</p>
<p className="text-[44px] lg:text-[62px] font-bold text-white tracking-wide leading-10 xxs:scale-100 lg:scale-100 xl:scale-125">
{PriceFormatter(
walletItem.amount * 0.01,
walletItem.code,
undefined,
"text-[2rem]"
)}
</p>
</div>
</div>
</div>
<div className="my-2 w-full h-[1px] bg-white"></div>
{/* <WalletAction
walletItem={{ ...walletItem, walletCountry: currentWalletCurrency }}
payment={payment}
openPopUp={openPopUp}
/> */}
</div>
{creditPopup.show && (
<CreditPopup
details={creditPopup.data}
walletItem={walletItem}
onClose={closePopUp}
situation={openPopUp}
/>
)}
</>
);
}
@@ -6,11 +6,8 @@ import CommonHead from "../UserHeader/CommonHead";
import usersService from "../../services/UsersService";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import OthersInterestedTable from "./OthersInterestedTable";
import { useDispatch } from "react-redux";
import { tableReload } from "../../store/TableReloads";
export default function ManageInterestOffer(props) {
const dispatch = useDispatch()
const navigate = useNavigate()
const apiCall = new usersService()
@@ -92,7 +89,6 @@ export default function ManageInterestOffer(props) {
setRedirectTime(prev => prev - 1)
}, 1000);
setRequestStatus({loading: false, status: true, message: `Offer ${name}ed`, processType: ''})
dispatch(tableReload({ type: "WALLETTABLE" }));
setTimeout(()=>{
navigate('/offer-interest', {replace: true})
clearInterval(intervalTime)
+4 -52
View File
@@ -1,4 +1,4 @@
import React, { useContext, useMemo, useState } from "react";
import React, { useContext, useEffect, useMemo, useState } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom";
import bank1 from "../../assets/images/bank-1.png";
import bank2 from "../../assets/images/bank-2.png";
@@ -36,17 +36,9 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
const { notifications } = useSelector((state) => state?.notifications); // NOTIFICATION STORE
const { walletDetails } = useSelector((state) => state?.walletDetails); // WALLET STORE
const image = localStorage.getItem("session_token")
? userDetails.account_type === "FAMILY"
? `${userDetails.session_image_server}${localStorage.getItem(
"session_token"
)}/family/${sessionStorage.getItem("family_uid")}`
: `${userDetails.session_image_server}${localStorage.getItem(
"session_token"
)}/profile/${userDetails.uid}`
: "";
// 9308RDR122
const image = `${userDetails.session_image_server}${localStorage.getItem(
"session_token"
)}/profile/${userDetails.uid}`;
const handlerBalance = () => {
setbalanceValue.toggle();
@@ -238,9 +230,6 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
</div>
</button>
{/* balance */}
{/* My Page Button */}
<PageButton />
{/*<div className="lg:hidden block"></div>*/}
<WalletHeader
@@ -415,17 +404,6 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
</div>
</Link>
</li>
{userDetails && userDetails?.account_type !== "FAMILY" && (
<li className="content-item my-2 hover:bg-slate-100 transition duration-500 rounded-lg">
<Link to="/yourpage" className="notifications">
<div className="name">
<p className="text-sm py-2 px-4 text-dark-gray dark:text-white hover:text-sky-blue transition font-medium">
My Page
</p>
</div>
</Link>
</li>
)}
{userDetails && userDetails?.account_type !== "FAMILY" && (
<>
<li className="content-item my-2 hover:bg-slate-100 transition duration-500 rounded-lg">
@@ -670,29 +648,3 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
</>
);
}
const PageButton = () => {
return (
<Link to="/yourpage" className="lg:flex hidden user-balance cursor-pointer lg:w-[152px] w-[150px] h-[48px] items-center rounded-full relative bg-sky-blue pr-1.5 pl-4">
<div
className="flex items-center lg:justify-between justify-center w-full h-full"
>
<span className="lg:block hidden w-[25px]">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 68 50" id="Page">
<path
fillRule="evenodd"
d="M0 13V2a2 2 0 0 1 2-2h64a2 2 0 0 1 2 2v11H0Zm0 4v31a2 2 0 0 0 2 2h20V17H0Zm26 33h40a2 2 0 0 0 2-2V17H26v33Z"
fill="#ffffff"
className="color000000 svgShape"
></path>
</svg>
</span>
<p className="lg:text-xl text-lg font-bold text-white">My Page</p>
<span className="lg:block hidden">
{/* <Icons name="deep-plus" /> */}
</span>
</div>
</Link>
)
}
+2 -3
View File
@@ -23,7 +23,6 @@ export default function Layout({ children }) {
localStorage.removeItem("session_token");
localStorage.removeItem("member_id");
localStorage.removeItem("uid");
sessionStorage.removeItem("family_uid");
// localStorage.clear();
// toast.success("Come Back Soon", {
// icon: `🙂`,
@@ -79,7 +78,7 @@ export default function Layout({ children }) {
{children && children}
</div>
<div className="nft-right-side-content 2xl:w-[270px] w-full h-full 2xl:flex justify-center relative flex-[20%]">
<RightSideBar myJobList={userJobList} />
<RightSideBar />
</div>
</div>
</div>
@@ -87,7 +86,7 @@ export default function Layout({ children }) {
</div>
{logoutModal && (
<ModalCom action={logoutModalHandler} situation={logoutModal}>
<div className="logout-modal-wrapper w-11/12 sm:w-[460px] bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="logout-modal-wrapper lg:w-[460px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="logout-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 dark:border-[#5356fb29] ">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Confirm
+2 -163
View File
@@ -3,7 +3,7 @@ import { useSelector } from "react-redux";
import { NavLink } from "react-router-dom";
//import SideStatistics from "./SideStatistics";
export default function RightSideBar({myJobList}) {
export default function RightSideBar() {
const filterDatas = ["Last 15 days", "Last Month", "Last 6 month"];
const [filterDataSet, setFilterDataSet] = useState([10, 30, 20, 40]);
const dataSetHandler = (value) => {
@@ -154,168 +154,7 @@ export default function RightSideBar({myJobList}) {
</div>
</div>
</div>
{/*JOB LINKS*/}
{myJobList?.data?.result_list?.length > 0 &&
<div className="top-platform mt-6 bg-white dark:bg-dark-white rounded-2xl py-8 2xl:w-[268px] w-full 2xl:mb-10 2xl:border-none border ">
{/* heading */}
<div className="px-8 heading flex justify-between items-center mb-3.5">
<h3 className="text-xl font-bold text-dark-gray dark:text-white">
Job Links
</h3>
<div></div>
</div>
<div className="platform-list">
<div className="px-8 item flex space-x-3 items-center mb-4">
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
id="history"
>
<g data-name="14">
<circle cx="9" cy="14" r="7" fill="#ffd54f"></circle>
<path
fill="#ef6c00"
d="M21 9H17a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2zM21 5H3A1 1 0 0 1 3 3H21a1 1 0 0 1 0 2zM21 13H19a1 1 0 0 1 0-2h2a1 1 0 0 1 0 2zM21 17H19a1 1 0 0 1 0-2h2a1 1 0 0 1 0 2zM21 21H17a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2z"
></path>
<path
fill="#ff8f00"
d="M10,10a1,1,0,0,0-2,0v3.59L6.29,15.29a1,1,0,1,0,1.41,1.41l2-2A1,1,0,0,0,10,14Z"
></path>
</g>
</svg>
</div>
{/* name */}
<div>
<p className="text-thin-light-gray text-base font-medium">
<NavLink to="/my-active-jobs">Active Task</NavLink>
</p>
</div>
{/* action */}
</div>
{/* {userDetails && userDetails?.account_type !== "FAMILY" && (
<>
</>
)} */}
<div className="px-8 item flex space-x-3 items-center mb-4">
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
id="add-user"
>
<path
fill="#9bcb5b"
d="M12 13.4c-2 0-3.7-1.6-3.7-3.6s1.6-3.7 3.6-3.7 3.7 1.6 3.7 3.6-1.6 3.6-3.6 3.7zm0-6.2c-1.4 0-2.6 1.1-2.6 2.6 0 1.4 1.1 2.6 2.6 2.6s2.6-1.1 2.6-2.6c-.1-1.5-1.2-2.6-2.6-2.6z"
></path>
<path
fill="#9bcb5b"
d="M16.6 17.9c-.3 0-.5-.2-.6-.5 0-2.2-1.8-4-4-4s-4 1.8-4 4c0 .3-.3.5-.6.5-.2 0-.4-.2-.5-.5 0-2.8 2.3-5.1 5.1-5.1s5.1 2.3 5.1 5.1c0 .3-.2.5-.5.5z"
></path>
<path
fill="#0376bc"
d="M12 23.7C5.5 23.7.3 18.4.3 12 .3 5.5 5.6.3 12 .3c2.6 0 5.1.9 7.2 2.5.2.2.2.6 0 .8-.2.2-.4.2-.7.1-1.9-1.4-4.1-2.2-6.5-2.2C6.2 1.4 1.4 6.2 1.4 12S6.2 22.6 12 22.6 22.6 17.8 22.6 12c0-2.4-.8-4.6-2.2-6.5-.2-.3-.1-.6.2-.8.2-.1.5-.1.7.1 1.6 2 2.5 4.6 2.4 7.2 0 6.4-5.3 11.7-11.7 11.7z"
></path>
<circle cx="20.2" cy="20.3" r="2.4" fill="#fff"></circle>
<path
fill="#9bcb5b"
d="M18 18.1c.6-.6 1.4-.9 2.2-.9.8 0 1.6.3 2.2.9s1 1.4.9 2.2c0 .8-.3 1.6-.9 2.2s-1.4 1-2.2.9c-.8 0-1.6-.3-2.2-.9s-1-1.4-.9-2.2c-.1-.8.3-1.7.9-2.2zm3.8 2.5V20h-1.3v-1.3h-.6V20h-1.3v.6h1.3v1.3h.6v-1.3h1.3z"
></path>
</svg>
</div>
{/* name */}
<div>
<p className="text-thin-light-gray text-base font-medium">
<NavLink to="/my-review-jobs">Review Pending</NavLink>
</p>
</div>
</div>
<div className="px-8 item flex space-x-3 items-center mb-4">
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 48 48"
id="InternationalUser"
>
<path
fill="#e6e7f9"
d="M38.5 31.1c2.1-1.1 3.9-2.5 5.4-4.4h-3.2c-.6 1.6-1.3 3.1-2.2 4.4zm-5.8 1.4c2-.7 3.7-2.8 4.9-5.8h-4.9v5.8zm8.8-8.6h4.2c.9-1.8 1.5-3.7 1.7-5.8h-5.1c-.1 2-.4 4-.8 5.8zm2.4-17.3c-1.5-1.8-3.3-3.3-5.4-4.4.8 1.2 1.6 2.7 2.2 4.4h3.2zm-5.3 2.9h-5.9v5.8h6.7c-.1-2.1-.4-4.1-.8-5.8zm3.7 5.8h5.1c-.2-2.1-.8-4-1.7-5.8h-4.2c.4 1.8.7 3.7.8 5.8zM32.7.8v5.8h4.9c-1.2-2.9-2.9-5.1-4.9-5.8zm6.7 17.3h-6.7v5.8h5.9c.4-1.8.7-3.8.8-5.8zM25 6.6h4.9V.8c-2 .7-3.7 2.9-4.9 5.8zm-1.8 8.7h6.7V9.5H24c-.4 1.7-.7 3.7-.8 5.8zm6.7 17.2v-5.8H25c1.2 3 2.9 5.1 4.9 5.8zM24.1 2.3c-2.1 1.1-3.9 2.5-5.4 4.4H22c.5-1.7 1.3-3.2 2.1-4.4zM24 23.9h5.9v-5.8h-6.7c.1 2 .4 4 .8 5.8z"
className="colorc1e5ff svgShape"
></path>
<path
fill="#ff6699"
d="M3.7 44.7c0 1.6 1.2 2.8 2.8 2.8 1.3 0 2.4-.9 2.7-2.2.3 1.3 1.4 2.2 2.7 2.2 1.5 0 2.8-1.3 2.8-2.8V30.1h3.1V18.8c0-4.2-3.3-7.5-7.4-7.5H8c-4.1 0-7.4 3.4-7.4 7.5v11.3h3.1v14.6z"
className="colorff99b0 svgShape"
></path>
<path
fill="#998da0"
d="M9.2 10.3c2.4 0 4.4-2.2 4.4-4.9S11.6.5 9.2.5C6.8.5 4.8 2.7 4.8 5.4s2 4.9 4.4 4.9z"
className="colorffd499 svgShape"
></path>
<path
fill="#e6e7f9"
d="M16.9 9.5c-.3.6-.5 1.2-.8 1.8 1.3 1 2.3 2.4 2.9 4h1.3c.1-2 .3-4 .8-5.8h-4.2zm2.9 9.3v5.1h1.4c-.4-1.8-.7-3.8-.8-5.8h-.6c-.1.2 0 .4 0 .7zm2.2 7.9h-2.2v1.2c1.3 1.3 2.7 2.4 4.4 3.2-.9-1.3-1.7-2.8-2.2-4.4z"
className="colorc1e5ff svgShape"
></path>
</svg>
</div>
{/* name */}
<div>
<p className="text-thin-light-gray text-base font-medium">
<NavLink to="/my-pastdue-jobs">Past Due</NavLink>
</p>
</div>
</div>
{/* Line */}
<div className="my-4 mx-auto w-10/12 h-[2px] bg-slate-500 dark:bg-white rounded-full"></div>
<div className="px-8 item flex space-x-3 items-center mb-4">
{/* image */}
<div className="w-8 h-8 rounded-full">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 48 48"
id="InternationalUser"
>
<path
fill="#e6e7f9"
d="M38.5 31.1c2.1-1.1 3.9-2.5 5.4-4.4h-3.2c-.6 1.6-1.3 3.1-2.2 4.4zm-5.8 1.4c2-.7 3.7-2.8 4.9-5.8h-4.9v5.8zm8.8-8.6h4.2c.9-1.8 1.5-3.7 1.7-5.8h-5.1c-.1 2-.4 4-.8 5.8zm2.4-17.3c-1.5-1.8-3.3-3.3-5.4-4.4.8 1.2 1.6 2.7 2.2 4.4h3.2zm-5.3 2.9h-5.9v5.8h6.7c-.1-2.1-.4-4.1-.8-5.8zm3.7 5.8h5.1c-.2-2.1-.8-4-1.7-5.8h-4.2c.4 1.8.7 3.7.8 5.8zM32.7.8v5.8h4.9c-1.2-2.9-2.9-5.1-4.9-5.8zm6.7 17.3h-6.7v5.8h5.9c.4-1.8.7-3.8.8-5.8zM25 6.6h4.9V.8c-2 .7-3.7 2.9-4.9 5.8zm-1.8 8.7h6.7V9.5H24c-.4 1.7-.7 3.7-.8 5.8zm6.7 17.2v-5.8H25c1.2 3 2.9 5.1 4.9 5.8zM24.1 2.3c-2.1 1.1-3.9 2.5-5.4 4.4H22c.5-1.7 1.3-3.2 2.1-4.4zM24 23.9h5.9v-5.8h-6.7c.1 2 .4 4 .8 5.8z"
className="colorc1e5ff svgShape"
></path>
<path
fill="#ff6699"
d="M3.7 44.7c0 1.6 1.2 2.8 2.8 2.8 1.3 0 2.4-.9 2.7-2.2.3 1.3 1.4 2.2 2.7 2.2 1.5 0 2.8-1.3 2.8-2.8V30.1h3.1V18.8c0-4.2-3.3-7.5-7.4-7.5H8c-4.1 0-7.4 3.4-7.4 7.5v11.3h3.1v14.6z"
className="colorff99b0 svgShape"
></path>
<path
fill="#998da0"
d="M9.2 10.3c2.4 0 4.4-2.2 4.4-4.9S11.6.5 9.2.5C6.8.5 4.8 2.7 4.8 5.4s2 4.9 4.4 4.9z"
className="colorffd499 svgShape"
></path>
<path
fill="#e6e7f9"
d="M16.9 9.5c-.3.6-.5 1.2-.8 1.8 1.3 1 2.3 2.4 2.9 4h1.3c.1-2 .3-4 .8-5.8h-4.2zm2.9 9.3v5.1h1.4c-.4-1.8-.7-3.8-.8-5.8h-.6c-.1.2 0 .4 0 .7zm2.2 7.9h-2.2v1.2c1.3 1.3 2.7 2.4 4.4 3.2-.9-1.3-1.7-2.8-2.2-4.4z"
className="colorc1e5ff svgShape"
></path>
</svg>
</div>
{/* name */}
<div>
<p className="text-thin-light-gray text-base font-medium">
<NavLink to="/job-groups">Job Groups</NavLink>
</p>
</div>
</div>
</div>
</div>
}
{/*<SideStatistics />*/}
</div>
</>
);
-1
View File
@@ -63,7 +63,6 @@ export default function Resources(props) {
loading: false,
msg: "success",
data: res?.result_list,
image:res?.session_image_server
}));
} catch (error) {
setUploadedFiles((prev) => ({
@@ -13,6 +13,7 @@ export default function MyUploadedFiles({ uploadedFiles }) {
indexOfFirstItem,
indexOfLastItem
);
const handlePagination = (e) => {
handlePagingFunc(e, setCurrentPage);
};
@@ -44,11 +45,10 @@ export default function MyUploadedFiles({ uploadedFiles }) {
currentFiles.map((value, idx) => {
let addedDate = value?.added?.split(" ")[0];
let formattedSize = formatFileSize(value?.file_size);
let imageLink = `${uploadedFiles?.image}${localStorage.getItem('session_token')}/myfile/${value.file_uid}`
return (
<tr
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">
<div className="flex space-x-2 items-center w-full">
@@ -102,17 +102,17 @@ export default function MyUploadedFiles({ uploadedFiles }) {
</td>
<td className="text-right py-4 px-2">
<div className="flex justify-center items-center">
<a
href={imageLink}
title="download"
// className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
<button
type="button"
// onClick={() => {
// navigate("/manage-active-job", {
// state: { ...value, pathname },
// });
// }}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
<img
src={localImgLoad('images/icons/download-arrow.svg')}
alt='download-link'
className="w-auto h-6 flex justify-center items-center"
/>
</a>
View
</button>
</div>
</td>
</tr>
@@ -49,11 +49,9 @@ export default function PersonalInfoTab({
}) {
let { userDetails } = useSelector((state) => state.userDetails);
const image = localStorage.getItem("session_token")
? `${userDetails.session_image_server}${localStorage.getItem(
"session_token"
)}/profile/${userDetails.uid}`
: "";
const image = `${userDetails.session_image_server}${localStorage.getItem(
"session_token"
)}/profile/${userDetails.uid}`;
const apiCall = new usersService();
@@ -139,17 +137,15 @@ export default function PersonalInfoTab({
if (e.target.value !== "") {
const imgReader = new FileReader();
imgReader.onload = (event) => {
let base64Img = imgReader.result.split(",")[1];
let reqData = {
// PAYLOAD FOR API CALL
file_name: uploadedFile?.name,
file_size: uploadedFile?.size,
file_type: uploadedFile?.type?.split("/")[0]?.toLowerCase(),
file_data: base64Img,
file_data: event?.target?.result,
msg_type: "FILE",
action: 11300,
};
setUploadStatus({
loading: true,
status: false,
@@ -157,7 +157,7 @@ export default function ProductUploadField({
fieldClass="px-6"
type="text"
name="name"
placeholder="Item Name"
placeholder="RaidParty Fighters"
inputHandler={inh}
value={datas.itemName}
/>
@@ -186,7 +186,7 @@ export default function ProductUploadField({
<textarea
value={datas.description}
onChange={(e) => dscrphn(e)}
placeholder="Enter detail description"
placeholder="provide a detailed description of your item."
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"
/>
+6 -12
View File
@@ -144,14 +144,14 @@ export default function UploadProduct({uploadTypes}) {
}
let reqData = { // PAYLOAD FOR API CALL
// file_name: selectedFile.substring(0,21).replace(/ /gi, ""),
file_name: `myfile.${imgDetails?.type?.split('/')[1]}`,
file_name: selectedFile.substring(0,21).replace(/ /gi, ""),//selectedFile.replace(/[ -]/gi, ""),
file_size: imgDetails.size,
file_type: imgDetails.type,
file_data: img.file?.split(",")[1],
file_data: img.file,
title: itemName,
description: description,
msg_type: 'FILE',
// action: 'WRENCHBOARD_RESOURCE_MYFILES',
action: 11307
}
@@ -602,10 +602,7 @@ export default function UploadProduct({uploadTypes}) {
//FUNCTIONS to check if file upload type is valid
const isValidFile = (file, supportedFile=[]) => {
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 fileType = file.type.split("/")[1];
let valid = supportedFile.filter(item => (
item.name.toLowerCase() == fileType.toLowerCase()
))
@@ -618,10 +615,7 @@ const isValidFile = (file, supportedFile=[]) => {
//FUNCTIONS TO CHECK IF FILE SIZE IS VALID
const isValidFileSize = (file, supportedFile=[]) => {
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 fileType = file.type.split("/")[1];
let fileSize = file.size;
let valid = supportedFile.filter(item => (
item.name.toLowerCase() == fileType.toLowerCase()
@@ -633,6 +627,6 @@ const isValidFileSize = (file, supportedFile=[]) => {
return {status: false, message: `File must not exceed ${valid[0].max_size_mb}MB`}
}
}else{
return {status: false, message: `Cannot read file size, try again`}
return false
}
}
-14
View File
@@ -1,14 +0,0 @@
import LoadingSpinner from "../Spinners/LoadingSpinner";
const UpdateButton = ({ onClick, loading }) => (
<button
type="submit"
onClick={onClick}
disabled={loading}
className="text-lg text-white bg-sky-blue px-4 py-2 hover:opacity-90 rounded-full"
>
{loading ? <LoadingSpinner size="6" color="sky-blue" /> : "Update"}
</button>
);
export default UpdateButton;
-42
View File
@@ -1,42 +0,0 @@
import InputCom from "../Helpers/Inputs/InputCom/index";
import UpdateButton from "./UpdateButton";
const YourPageForm = ({ values, onChange, onSubmit, loading }) => (
<div className="ml-16 my-2 flex flex-col gap-3">
<div className="field w-full">
<InputCom
fieldClass="px-4"
parentClass="flex items-center gap-1 justify-between"
labelClass="flex-[0.2] mb-0 font-semibold"
inputClass="flex-[0.8]"
inputBg="bg-slate-100"
label="Introduction: "
type="text"
name="intro"
value={values.intro}
inputHandler={onChange}
/>
</div>
<div className="field w-full mb-6 flex gap-1 justify-between">
<label className="text-[#181c32] dark:text-white text-[13.975px] font-semibold flex flex-[0.2] mt-2.5">
Brief Details:
</label>
<textarea
style={{ resize: "none" }}
className="text-base px-4 py-2 rounded-md min-h-[100px] text-dark-gray dark:text-white w-full bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none flex-[0.8]"
name="description"
cols="30"
rows="2"
value={values.description}
onChange={onChange}
/>
</div>
<div className="w-full flex justify-end mb-2">
<UpdateButton onClick={onSubmit} loading={loading} />
</div>
<hr />
</div>
);
export default YourPageForm;
-73
View File
@@ -1,73 +0,0 @@
import React, { useState } from "react";
import Layout from "../Partials/Layout";
import usersService from "../../services/UsersService";
import YourPageForm from "./YourPageForm";
const YourPage = () => {
const [pageValues, setPageValues] = useState({
intro: "",
description: "",
});
const [response, setResponse] = useState({
loading: false,
data: {},
error: "",
msg: "",
});
const handleChange = (event) => {
let { name, value } = event.target;
setPageValues((prev) => ({ ...prev, [name]: value }));
};
const updateYourPageDetails = async () => {
try {
setResponse({ loading: true, error: "", msg: "" });
let api = new usersService();
const res = await api.MyPageIntro(pageValues);
setTimeout(() => {
setResponse({
loading: false,
data: res.data,
msg: "Page updated successfully",
});
// Clear form after successful update
setPageValues({ intro: "", description: "" });
}, 2000);
} catch (error) {
setResponse({
loading: false,
data: {},
error: "Error updating page",
msg: "",
});
}
};
return (
<Layout>
<div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full">
<div className="update-table w-full h-full p-4 bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow min-h-[520px]">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide mb-2">
My page
</h1>
<hr />
<YourPageForm
values={pageValues}
onChange={handleChange}
onSubmit={updateYourPageDetails}
loading={response.loading}
/>
</div>
</div>
</div>
</Layout>
);
};
export default YourPage;
+1 -1
View File
@@ -63,7 +63,7 @@ function DeleteJobPopout({ details, onClose, situation }) {
return (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper lg:w-[600px] 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">
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b border-light-purple dark:border-[#5356fb29] ">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Delete Job
+44 -173
View File
@@ -1,6 +1,6 @@
import { Field, Form, Formik } from "formik";
import React, { useCallback, useMemo, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
import * as Yup from "yup";
import usersService from "../../services/UsersService";
@@ -51,20 +51,18 @@ const EditJobPopOut = ({
categories,
}) => {
const dispatch = useDispatch();
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 [taskImage, setTaskImage] = useState('')
const [taskImage, setTaskImage] = useState(uploadedImage);
let [uploadStatus, setUploadStatus] = useState({
loading: false,
status: false,
message: "",
}); // HOLDS STATE FOR UPLOAD PROFILE PICTURE STATUS
const changeTaskImage = (e) => {
if (e.target.value !== "") {
const imgReader = new FileReader();
imgReader.onload = (event) => {
setTaskImage(event.target.result);
};
imgReader.readAsDataURL(e.target.files[0]);
}
}
let [requestStatus, setRequestStatus] = useState({
loading: false,
@@ -119,104 +117,9 @@ const EditJobPopOut = ({
[jobApi, navigate, onClose, details]
);
const taskImgChangeHandler = (e) => {
setUploadStatus({ loading: false, status: false, message: "" });
let acceptedFormat = ["jpeg", "jpg", "png", "bmp", "gif"]; // ARRAY OF SUPPORTED FORMATS
let uploadedFile = e.target.files[0]; //UPLOADED FILE
const fileFormat = uploadedFile?.type?.split("/")[1]?.toLowerCase();
if (!acceptedFormat.includes(fileFormat)) {
//CHECKING FOR CORRECT UPLOAD FORMAT
const msg = `Please select ${acceptedFormat
.slice(0, -1)
.join(", ")} or ${acceptedFormat.slice(-1)}`;
setUploadStatus({ loading: false, status: false, message: msg });
return setTimeout(() => {
// profileImgInput.current.value = '' // clear the input
setUploadStatus({ loading: false, status: false, message: "" });
}, 5000);
}
if (uploadedFile.size > 5 * 1048576) {
// CHECKING FOR CORRECT FILE SIZE
setUploadStatus({
loading: false,
status: false,
message: "File must not exceed 5MB",
});
return setTimeout(() => {
// profileImgInput.current.value = '' // clear the input
setUploadStatus({ loading: false, status: false, message: "" });
}, 5000);
}
if (e.target.value !== "") {
const imgReader = new FileReader();
imgReader.onload = (event) => {
let base64Img = imgReader.result.split(",")[1];
let reqData = {
// PAYLOAD FOR API CALL
job_uid: details?.job_uid,
file_name: uploadedFile?.name.slice(0, 19),
file_size: uploadedFile?.size,
file_type: uploadedFile?.type?.split("/")[0]?.toLowerCase(),
file_data: base64Img,
msg_type: "FILE",
action: 11303,
};
setUploadStatus({
loading: true,
status: false,
message: "Loading...",
});
jobApi
.sendFiles(reqData)
.then((res) => {
if (res.status != 200 || res.data.internal_return < 0) {
return setUploadStatus({
loading: false,
status: false,
message: "Something went wrong, try again",
});
}
setUploadStatus({
loading: false,
status: true,
message: "Uploaded successfully",
});
setTaskImage(event.target.result);
setTimeout(() => {
dispatch(tableReload({ type: "JOBTABLE" }));
navigate("/myjobs", { replace: true });
onClose();
}, 1000);
})
.catch((error) => {
setUploadStatus({
loading: false,
status: false,
message: "Network error, try again",
});
})
.finally(() => {
setTimeout(() => {
setUploadStatus({ loading: false, status: false, message: "" });
}, 5000);
});
};
imgReader.readAsDataURL(e.target.files[0]);
}
};
// 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 (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper w-11/12 lg:w-[600px] bg-white dark:bg-dark-white lg:rounded-2xl">
<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-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b border-light-purple dark:border-[#5356fb29] ">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Edit Job
@@ -367,20 +270,19 @@ const EditJobPopOut = ({
role="group"
aria-labelledby="checked-group"
>
{categories &&
Object.entries(categories)?.map(([key, value]) => (
<label
key={key}
className="flex gap-1 w-full items-center dark:text-white"
>
<Field
type="checkbox"
name="category"
value={key}
/>
<span className="text-[13.975px]">{value}</span>
</label>
))}
{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>
))}
<span className="h-5 text-sm italic text-[#cf3917]">
{props.errors.category &&
props.touched.category &&
@@ -392,40 +294,31 @@ const EditJobPopOut = ({
<div className="w-full flex items-center gap-2 mb-2">
{/* FOR TASK IMAGE */}
<div className="w-1/2 relative max-h-[130px] min-h-[130px]">
<input
<input
id="task_image"
className="hidden"
type="file"
accept="image/*"
onChange={taskImgChangeHandler}
className="hidden"
type="file"
accept="image/*"
onChange={changeTaskImage}
/>
{taskImage ? (
<div className="w-full absolute -top-5">
<img
src={taskImage}
className="max-h-[150px] min-h-[150px] w-full object-cover"
alt="uploaded task"
/>
<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"
>
{taskImage ?
<div className="w-full absolute -top-5">
<img src={taskImage} className="max-h-[150px] min-h-[150px] w-full object-cover" alt="uplaoded task image" />
<span onClick={()=>setTaskImage('')} className="p-2 absolute text-sm top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white/20 hover:bg-white/70 hover:shadow-md transition-all duration-500 cursor-pointer text-slate-800">Remove Image</span>
</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
</label>
)}
</label>
}
</div>
{/* END OF TASK IMAGE */}
<div className="field w-1/2">
<div className={`flex items-center justify-between`}>
<div
className={`flex items-center justify-between`}
>
<label
className="w-full input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex flex-col"
htmlFor="timeline_days"
@@ -451,7 +344,6 @@ const EditJobPopOut = ({
<option value="">Select Duration</option>
{publicArray.map(({ name, duration }, idx) => (
<option
key={duration}
className="text-slate-500 text-lg"
value={duration}
>
@@ -485,24 +377,6 @@ const EditJobPopOut = ({
))}
{/* End of error or success display */}
{/* DISPLAYS TASK IMAGE UPLOADING STATUS */}
<div className="w-full">
{uploadStatus.message && !uploadStatus.loading && (
<p
className={`text-center ${
uploadStatus.status
? "text-green-500"
: "text-red-500"
}`}
>
{uploadStatus.message}
</p>
)}
{uploadStatus.loading && (
<p className="text-center">{uploadStatus.message}</p>
)}
</div>
<div className="w-full border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
<div className="flex items-center space-x-4 mr-2 mt-2">
{requestStatus.loading ? (
@@ -512,9 +386,6 @@ const EditJobPopOut = ({
type="submit"
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'
disabled={
requestStatus.loading || uploadStatus.loading
}
>
Save
</button>
@@ -101,11 +101,9 @@ function FamilyOfferJobPopout({ details, onClose, situation }) {
});
};
console.log(details)
return (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper w-[90%] md:w-[768px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto 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] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Start Task
@@ -140,7 +138,7 @@ function FamilyOfferJobPopout({ details, onClose, situation }) {
<div className="p-4 w-full md:w-3/4 md:border-r-2">
<div className="flex gap-2">
<div className="image-wrapper w-32">
<img className="w-full h-auto" src={details?.image} alt='banner' />
<img className="w-full h-auto" src={localImgLoad(`images/taskbanners/${details.banner}`)} alt='Banner-Image' />
</div>
<div className="details-wrapper">
<p className="text-lg my-5 font-semibold text-slate-900 tracking-wide">
+159 -264
View File
@@ -23,14 +23,8 @@ const validationSchema = Yup.object().shape({
});
function JobListPopout({ details, onClose, situation }) {
const [selectedTab, setSelectedTab] = useState('public')
const tabs = ['public', 'individual', 'group']
const dispatch = useDispatch()
const [requestStatus, setRequestStatus] = useState({message:'', status:false})
const [familyList, setFamilyList] = useState([]);
let [loader, setLoader] = useState({
member: false,
@@ -102,7 +96,7 @@ const [requestStatus, setRequestStatus] = useState({message:'', status:false})
else if (name === "individual")
setErrMsg({ jobFields: { individual: "please enter email" } });
else if (name === "group")
setErrMsg({ jobFields: { group: "please select a group" } });
setErrMsg({ jobFields: { group: "please select a family member" } });
} finally {
setTimeout(() => {
setErrMsg({ jobFields: "" });
@@ -156,12 +150,9 @@ const [requestStatus, setRequestStatus] = useState({message:'', status:false})
// for group input
reqData = {
...jobReq,
email: '',
group_id: values?.group,
email: values?.individual,
action: 13025,
assign_mode: 110044,
duration: details?.timeline_days,
// duration: 0,
assign_mode: 110033,
};
setLoader({ jobFields: { group: true } });
} else {
@@ -170,56 +161,21 @@ const [requestStatus, setRequestStatus] = useState({message:'', status:false})
try {
const res = await apiCall.assignJobTask(reqData);
let { status, data } = await res;
if(status != 200 || data.internal_return < 0){
setRequestStatus({message:'Unable to complete', status:false})
return setTimeout(()=>{
setLoader({ jobFields: false });
setRequestStatus({message:'', status:false})
},3000)
}
let { data } = await res;
setLoader({ jobFields: false });
dispatch(tableReload({ type: "JOBTABLE" }));
setRequestStatus({message:'Successful', status:true})
setTimeout(()=>{
setLoader({ jobFields: false });
onClose();
throw new Response(data);
},3000)
onClose();
throw new Response(data);
} catch (error) {
setRequestStatus({message:'Unable to complete', status:false})
setTimeout(()=>{
setRequestStatus({message:'', status:false})
setLoader({ jobFields: false });
throw new Error(error);
},3000)
setLoader({ jobFields: false });
throw new Error(error);
}
};
const [groupList, setGroupList] = useState({loading: true, groups: [], members: []})
// FUNCTION TO POPULATE USER GROUP LIST
useEffect(()=>{
// setGroupList({loading: true, groups: [], members: []})
apiCall.jobGroupList({}).then(res => {
const {status, data} = res
if(status != 200 || data?.internal_return < 0){
setGroupList({loading: false, groups: [], members: []})
return
}
if(data.result_list.length < 0){
setGroupList({loading: false, groups: [], members: []})
return
}
setGroupList({loading: false, groups: data.result_list, members: data.result_list_member})
}).catch(error => {
setGroupList({loading: false, groups: [], members: []})
})
},[])
// console.log("Job List P >> ", details)
return (
<ModalCom action={onClose} situation={situation} className="">
<div className="logout-modal-wrapper w-[90%] md:w-[768px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<ModalCom action={onClose} situation={situation} className="job-popup">
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto 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] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-base md:text-lg font-bold text-dark-gray dark:text-white tracking-wide">
{details.title}
@@ -250,8 +206,8 @@ const [requestStatus, setRequestStatus] = useState({message:'', status:false})
</svg>
</button>
</div>
<div className="md:grid grid-cols-2 bg-white dark:bg-dark-white rounded-lg shadow-lg">
<div className="p-4 pb-3 w-full md:border-r-2">
<div className="md:flex bg-white dark:bg-dark-white rounded-lg shadow-lg">
<div className="p-4 w-full md:w-2/4 md:border-r-2">
{/* <p className='text-lg font-semibold text-slate-900 tracking-wide'>{details.title}</p> */}
{/* INPUT SECTION */}
@@ -277,7 +233,7 @@ const [requestStatus, setRequestStatus] = useState({message:'', status:false})
/>
</div>
<div className="">
<div className="my-3">
<label className="w-full text-slate-900 dark:text-white tracking-wide font-semibold">
Delivery Detail
</label>
@@ -293,165 +249,130 @@ const [requestStatus, setRequestStatus] = useState({message:'', status:false})
</div>
{/* ACTION SECTION */}
<div className="p-4 w-ful flex flex-col justify-between">
<h1 className="text-lg mt-3 font-medium tracking-wide text-black dark:text-white">Send this Task to:</h1>
<div className="flex flex-col grow">
<div className="grid grid-cols-3 mt-4">
{tabs.map(item => (
<button
// className={`px-4 py-1 rounded-t-2xl ${selectedTab == item ? 'btn-gradient border-[2px] text-white' : 'bg-white text-[#000] border-t-[2px]'}`}
className={`px-4 py-1 rounded-t-2xl border-t-[2px] transition-all duration-200 flex flex-col justify-center items-center ${selectedTab == item ? 'bg-red-50 dark:bg-[#D85A5A] text-slate-600 font-extrabold' : 'bg-white text-[#000]'}`}
value={item}
name={item}
onClick={()=>setSelectedTab(item)}
>
<div className={`mb-[1px] h-6 w-6 border-4 rounded-full transition-all duration-200 ${selectedTab == item ? 'border-white bg-emerald-500' : 'border-red-50 dark:border-[#D85A5A] bg-white'}`}></div>
{item[0].toUpperCase() + item.slice(1)}
</button>
))}
</div>
<div className="grow flex flex-col bg-red-50 dark:bg-[#D85A5A] rounded-b-2xl">
{selectedTab == 'family' &&
<Formik
initialValues={initialValues}
validationSchema={validationSchema.fields.family}
onSubmit={jobFieldHandler}
>
{(props) => {
return (
<Form className="hidden">
{/* Assign to Family */}
<JobFieldInput
label="Assign to family"
select={true}
inputName="family"
value={props?.values.family}
data={familyList}
btnText="Assign to family"
optionText="Select Family"
loader={loader?.jobFields?.family}
errorHandler={errorHandler}
parentClass='w-full flex flex-col gap-4'
/>
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
{" "}
{props?.values?.family === "" && (
<span>{errMsg?.jobFields?.family}</span>
)}
</p>{" "}
</Form>
);
}}
</Formik>
}
{selectedTab == 'public' &&
<Formik
initialValues={initialValues}
validationSchema={validationSchema.fields.public}
onSubmit={jobFieldHandler}
>
{(props) => {
return (
<Form className="">
{/* Offer this job to public input */}
<JobFieldInput
label="Offer this job to public"
select={true}
inputName="public"
value={props?.values.public}
data={publicArray}
btnText="Show Task to Public"
optionText="Select Duration"
loader={loader?.jobFields?.public}
errorHandler={errorHandler}
parentClass='w-full flex flex-col gap-4'
/>
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
{" "}
{props?.values.public === "" && (
<span>{errMsg?.jobFields?.public}</span>
)}
</p>{" "}
</Form>
);
}}
</Formik>
}
<div className="p-4 w-full md:w-2/4 h-full">
<Formik
initialValues={initialValues}
validationSchema={validationSchema.fields.family}
onSubmit={jobFieldHandler}
>
{(props) => {
return (
<Form className="mb-4 hidden">
{/* Assign to Family */}
<JobFieldInput
label="Assign to family"
select={true}
inputName="family"
value={props?.values.family}
data={familyList}
btnText="Assign to family"
optionText="Select Family"
loader={loader?.jobFields.family}
errorHandler={errorHandler}
/>
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
{" "}
{props?.values.family === "" && (
<span>{errMsg.jobFields.family}</span>
)}
</p>{" "}
</Form>
);
}}
</Formik>
{selectedTab == 'individual' &&
<Formik
initialValues={initialValues}
validationSchema={validationSchema.fields.individual}
onSubmit={jobFieldHandler}
>
{(props) => {
return (
<Form className="">
{/* Offer this job to individual input */}
<JobFieldInput
label="Offer this job to individual"
input={true}
inputName="individual"
value={props?.values.individual}
placeholder="Enter email of individual"
inputHandler={props?.handleChange}
btnText="Send Offer to Individual"
loader={loader?.jobFields?.individual}
errorHandler={errorHandler}
parentClass='w-full flex flex-col gap-4'
/>
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
{" "}
{props?.values.individual === "" && (
<span>{errMsg?.jobFields?.individual}</span>
)}
</p>{" "}
</Form>
);
}}
</Formik>
}
{/* { process.env.REACT_APP_SHOW_OFFER_GROUP_JOB != 0 && } */}
{selectedTab == 'group' &&
<Formik
initialValues={initialValues}
validationSchema={validationSchema.fields.group}
onSubmit={jobFieldHandler}
>
{(props) => {
return (
<Form className="">
{/* Offer this job to your group input */}
<JobFieldInput
label="Offer this job to your Group"
select={true}
inputName="group"
value={props?.values.group}
btnText="Send Order to Group"
optionText="Select Group"
loader={loader?.jobFields?.group}
errorHandler={errorHandler}
data={groupList}
parentClass='w-full flex flex-col gap-4'
/>
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
{" "}
{props?.values.group === "" && (
<span>{errMsg?.jobFields?.group}</span>
)}
</p>
</Form>
);
}}
</Formik>
}
</div>
</div>
<Formik
initialValues={initialValues}
validationSchema={validationSchema.fields.public}
onSubmit={jobFieldHandler}
>
{(props) => {
return (
<Form className="mb-4">
{/* Offer this job to public input */}
<JobFieldInput
label="Offer this job to public"
select={true}
inputName="public"
value={props?.values.public}
data={publicArray}
btnText="Show Task to Public"
optionText="Select Duration"
loader={loader?.jobFields.public}
errorHandler={errorHandler}
/>
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
{" "}
{props?.values.public === "" && (
<span>{errMsg.jobFields.public}</span>
)}
</p>{" "}
</Form>
);
}}
</Formik>
{requestStatus.message &&
<p className={`mt-4 w-full text-lg ${requestStatus.status ? 'text-emerald-600' : 'text-red-600'}`}>{requestStatus.message}</p>
<Formik
initialValues={initialValues}
validationSchema={validationSchema.fields.individual}
onSubmit={jobFieldHandler}
>
{(props) => {
return (
<Form className="mb-4">
{/* Offer this job to individual input */}
<JobFieldInput
label="Offer this job to individual"
input={true}
inputName="individual"
value={props?.values.individual}
placeholder="Enter email of individual"
inputHandler={props?.handleChange}
btnText="Send Offer to Individual"
loader={loader?.jobFields.individual}
errorHandler={errorHandler}
/>
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
{" "}
{props?.values.individual === "" && (
<span>{errMsg.jobFields.individual}</span>
)}
</p>{" "}
</Form>
);
}}
</Formik>
{ process.env.REACT_APP_SHOW_OFFER_GROUP_JOB != 0 &&
<Formik
initialValues={initialValues}
validationSchema={validationSchema.fields.group}
onSubmit={jobFieldHandler}
>
{(props) => {
return (
<Form className="mb-4">
{/* Offer this job to your group input */}
<JobFieldInput
label="Offer this job to your Group"
select={true}
inputName="group"
value={props?.values.group}
btnText="Send Order to Group"
optionText="Group"
loader={loader?.jobFields.group}
errorHandler={errorHandler}
/>
<p className="h-4 text-[13px] font-light italic text-red-600 tracking-wide">
{" "}
{props?.values.group === "" && (
<span>{errMsg.jobFields.group}</span>
)}
</p>
</Form>
);
}}
</Formik>
}
</div>
{/* END OF ACTION SECTION */}
@@ -481,7 +402,7 @@ const JobFieldInput = ({
data,
}) => {
return (
<div className="field w-full h-full px-3 pt-5 pb-3 flex flex-col justify-between gap-4">
<div className="field w-full p-3 mb-2 bg-red-50 dark:bg-[#D85A5A] rounded-md">
{select && (
<>
<div className={`input-com ${parentClass}`}>
@@ -490,7 +411,7 @@ const JobFieldInput = ({
>
{label && (
<label
className="input-label border-2 w-full border-sky-700 py-4 px-2 text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block tracking-wide"
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block tracking-wide"
htmlFor={inputName}
>
{label}
@@ -506,52 +427,27 @@ const JobFieldInput = ({
className={`input-field placeholder:text-base text-dark-gray w-full h-full bg-white outline-none px-2`}
value={value}
>
{/* <option value="">{optionText}</option> */}
{(inputName == 'family' || inputName == 'public') &&
Array.isArray(data) &&
<>
<option value="">{optionText}</option>
{ data?.map((item, idx) => (
<React.Fragment key={idx}>
{inputName === "family" && item?.last_login !== "" && (
<option value={item?.family_uid} key={idx}>
{`${item?.firstname} ${item?.lastname}`}
</option>
)}
{inputName === "public" && (
<option value={item?.duration} key={idx}>
{item?.name}
</option>
)}
{/* {inputName === "group" && (
<option value={item?.group_id} key={idx}>
{item?.group_name}
</option>
)} */}
</React.Fragment>
))}
</>
}
{(inputName == 'group') &&
<>
{data.loading ?
<option value={''}>
Loading...
</option>
: data?.groups?.length > 0 ?
<>
<option value="">{optionText}</option>
{ data?.groups?.map((item, index)=>(
<option value={item?.group_id} key={index}>
{item?.group_name}
<option value="">{optionText}</option>
{Array.isArray(data) &&
data?.map((item, idx) => (
<React.Fragment key={idx}>
{inputName === "family" && item?.last_login !== "" && (
<option value={item?.family_uid} key={idx}>
{`${item?.firstname} ${item?.lastname}`}
</option>
))}
</>
:
<option value="">No Group Found</option>
}
</>
}
)}
{inputName === "public" && (
<option value={item?.duration} key={idx}>
{item?.name}
</option>
)}
{inputName === "group" && (
<option value={item?.family_uid} key={idx}>
{item?.firstname}
</option>
)}
</React.Fragment>
))}
</Field>
</div>
</div>
@@ -562,14 +458,13 @@ const JobFieldInput = ({
<InputCom
fieldClass="px-6"
label={label}
labelClass="tracking-wide border-2 w-full border-sky-700 py-4 px-2"
labelClass="tracking-wide"
type="email"
name={inputName}
placeholder={placeholder}
value={value}
inputHandler={inputHandler}
inputBg="bg-white"
parentClass={`${parentClass}`}
/>
)}
+3 -3
View File
@@ -102,7 +102,7 @@ function OfferJobPopout({ details, onClose, situation }) {
return (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper w-[90%] md:w-[768px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto 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] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Start Task
@@ -133,9 +133,9 @@ function OfferJobPopout({ details, onClose, situation }) {
</svg>
</button>
</div>
<div className="md:flex bg-white dark:bg-dark-white rounded-lg shadow-lg">
<div className="md:flex bg-white rounded-lg shadow-lg">
<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 dark:text-white tracking-wide">
<p className="text-lg my-5 font-semibold text-slate-900 tracking-wide">
{details.title}
</p>
@@ -133,8 +133,8 @@ function PendingJobsPopout({ details, onClose, situation }) {
};
return (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper w-[90%] md:w-[768px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<ModalCom action={onClose} situation={situation} className="edit-popup">
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto 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] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Manage Pending Item
+5 -10
View File
@@ -21,12 +21,10 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
const [loadProfileDetails, setLoadProfileDetails] = useState([]);
const navigate = useNavigate();
const { jobListTable, walletTable } = useSelector(
(state) => state.tableReload
);
const { jobListTable, walletTable } = useSelector((state) => state.tableReload);
const {
userDetails: { username, uid, session},
userDetails: { username, uid, session },
} = useSelector((state) => state?.userDetails); // CHECKS IF USER Details are avaliable, to determine if user is active
let loggedIn = username && session && uid ? true : false; // variable to determine if user is logged in
@@ -37,7 +35,6 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
localStorage.removeItem("uid");
localStorage.removeItem("member_id");
localStorage.removeItem("session_token");
sessionStorage.removeItem("family_uid");
navigate("/login", { replace: true }); // redirects user to login page after session expires
};
@@ -184,15 +181,13 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
useEffect(() => {
const getMyWalletList = async () => {
dispatch(updateWalletDetails({ loading: true, data: [] }));
dispatch(updateWalletDetails({ loading: true, data:[] }));
try {
const res = await apiCall.getUserWallets();
console.log("wallet - >", res.data);
dispatch(
updateWalletDetails({ loading: false, data: res.data?.result_list })
);
dispatch(updateWalletDetails({ loading: false, data:res.data?.result_list }));
} catch (error) {
dispatch(updateWalletDetails({ loading: false, data: [] }));
dispatch(updateWalletDetails({ loading: false, data:[] }));
console.log("Error getting mode");
}
};
+27 -96
View File
@@ -5,16 +5,6 @@ class usersService {
console.log("WRB Service Entry");
}
MyPageIntro(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
...reqData
};
return this.postAuxEnd("/mypageintro", postData);
}
CreateUser(reqData) {
localStorage.setItem("session_token", ``);
return this.postAuxEnd("/createuser", reqData);
@@ -29,16 +19,6 @@ class usersService {
return this.postAuxEnd("/completesignuplink", reqData);
}
assignJobTask(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
...reqData,
};
return this.postAuxEnd("/assigntask", postData);
}
// FUNCTION TO GET USER CURRENT TASK DUE TIME
getHomeDate() {
var postData = {
@@ -50,12 +30,12 @@ class usersService {
return this.postAuxEnd("/dashdata", postData);
}
getRecentActivities() {
getRecentActivities(){
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 11202,
action: 11202
};
return this.postAuxEnd("/recentactivities", postData);
}
@@ -388,7 +368,7 @@ class usersService {
page: 0,
offset: 0,
limit: 100,
allstatus: 0,
allstatus: 0
};
return this.postAuxEnd("/activetaskslist", postData);
}
@@ -618,7 +598,7 @@ class usersService {
sessionid: localStorage.getItem("session_token"),
page: 0,
limit: 100,
...reqdata,
...reqdata
};
return this.postAuxEnd("/familyupdate", postData);
}
@@ -802,17 +782,6 @@ class usersService {
return this.postAuxEnd("/pendingjobsendtome", postData);
}
pendingCancelOffer(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 13043,
...reqData,
};
return this.postAuxEnd("/pendingjobcancel", postData);
}
// FUNCTION TO GET ACTIVE JOB MESSAGE LIST
activeJobMesList(reqData) {
var postData = {
@@ -848,11 +817,11 @@ class usersService {
action: 14010,
...reqData,
};
const formData = new FormData();
for (let data in postData) {
formData.append(data, postData[data]);
}
// return this.postAuxEnd("/uploads", formData);
return this.postAuxEnd("/uploads", postData);
}
@@ -1109,85 +1078,51 @@ class usersService {
return this.postAuxEnd("/blogdata", postData);
}
// FUNCTION TO CANCEL TASK OR SEND REMINDER BY FAMILY MEMBER
suggestStatus(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 22026,
...reqData,
};
return this.postAuxEnd("/suggeststatus", postData);
}
// FUNCTION TO GET FAMILY WALLET
getFamilyWallet(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 22012,
...reqData,
};
return this.postAuxEnd("/familywallet", postData);
}
// FUNCTION TO START FAMILY TRANSFER
familyTransferStart(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
...reqData,
};
return this.postAuxEnd("/familytransferstart", postData);
}
// FUNCTION TO PERFORM FAMILY TRANSFER
familyTransfer(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
...reqData,
};
return this.postAuxEnd("/familytransfer", postData);
}
// FUNCTION GET JOB GROUP LIST
jobGroupList(reqData) {
// FUNCTION TO CANCEL TASK OR SEND REMINDER BY FAMILY MEMBER
suggestStatus(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 13045,
action: 22026,
...reqData,
};
return this.postAuxEnd("/jobgrouplist", postData);
return this.postAuxEnd("/suggeststatus", postData);
}
// FUNCTION TO ADD JOB GROUP
jobGroupAdd(reqData) {
// FUNCTION TO GET FAMILY WALLET
getFamilyWallet(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 22012,
...reqData,
};
return this.postAuxEnd("/familywallet", postData);
}
// FUNCTION TO START FAMILY TRANSFER
familyTransferStart(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
...reqData,
};
return this.postAuxEnd("/jobgroupadd", postData);
return this.postAuxEnd("/familytransferstart", postData);
}
// FUNCTION TO ADD JOB GROUP MEMBER
groupMemberAdd(reqData) {
// FUNCTION TO PERFORM FAMILY TRANSFER
familyTransfer(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
...reqData,
};
return this.postAuxEnd("/groupmemberadd", postData);
return this.postAuxEnd("/familytransfer", postData);
}
/*
@@ -1302,10 +1237,6 @@ class usersService {
console.log(response);
// res = response;
console.log("~~~~~~~ Toks2 POST ~~~~~~~~");
if (response.data.internal_return == "-9999") {
localStorage.clear();
window.location.href = `/login?sessionExpired=true`;
}
return response;
})
.catch((error) => {
+2 -2
View File
@@ -4,8 +4,8 @@ import ModalCom from "../components/Helpers/ModalCom";
function AddJobPage({ action, situation, categories }) {
return (
<ModalCom action={action} situation={situation}>
<div className="lg:w-[600px] w-11/12 lg:overflow-hidden lg:rounded-2xl bg-white dark:bg-dark-white dark:text-white">
<ModalCom action={action} situation={situation} className="edit-popup">
<div className="lg:w-[600px] w-full lg:overflow-hidden lg:rounded-2xl bg-white dark:bg-dark-white dark:text-white">
<div className="heading flex justify-between items-center py-6 md:px-[30px] px-[23px] border-b border-light-purple dark:border-[#5356fb29] ">
<p className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
Create New Job
-13
View File
@@ -1,13 +0,0 @@
import React from "react";
import AppDownload from "../components/AppDownload/AppDownload";
import { useLocation } from "react-router-dom";
function AppDownloadPage() {
return (
<>
<AppDownload />
</>
);
}
export default AppDownloadPage;
+1 -1
View File
@@ -6,4 +6,4 @@ export default function FamilyManagePage() {
<FamilyManage />
</>
);
}
}
-9
View File
@@ -1,9 +0,0 @@
import FamilySettings from "../components/FamilyAcc/FamilySettings";
export default function FamilySettingsPage() {
return (
<>
<FamilySettings />
</>
);
}
-10
View File
@@ -1,10 +0,0 @@
import React from 'react'
import JobGroups from '../components/JobGroups/JobGroups'
export default function JobGroupsPage() {
return (
<>
<JobGroups />
</>
)
}
-1
View File
@@ -39,7 +39,6 @@ function ManageActiveJobs() {
loading: false,
error: false,
data: res.data.result_list,
image: res.data.session_image_server
});
})
.catch((error) => {

Some files were not shown because too many files have changed in this diff Show More