Compare commits

..

83 Commits

Author SHA1 Message Date
victorAnumudu 575710a807 image bug fixed 2023-11-08 18:26:50 +01:00
ameye 9ddb127bd3 Merge branch 'job-image-icon' of WrenchBoard/Users-Wrench into master 2023-11-08 16:24:00 +00:00
victorAnumudu a85e5fdb91 changed default icons to server icons 2023-11-08 09:41:06 +01:00
victorAnumudu 09ad8a94ca changed default icons to server icons 2023-11-08 09:39:28 +01:00
ameye 6ddffdf2e6 Merge branch 'Server-path-added' of WrenchBoard/Users-Wrench into master 2023-11-08 04:29:31 +00:00
Chief Bube 5043540abb Added conditionals to the paths to avoid breakage and resolved some images in family account 2023-11-07 09:24:28 -08:00
ameye 5f39accdd6 Merge branch 'pend-interest' of WrenchBoard/Users-Wrench into master 2023-11-07 16:20:23 +00:00
victorAnumudu b5aeaf59a4 changed from offer_uid to job_uid 2023-11-07 17:13:50 +01:00
ameye f3e63d2ef6 Merge branch 'default-icon' of WrenchBoard/Users-Wrench into master 2023-11-07 13:52:19 +00:00
victorAnumudu 44a055e76b Merge master into default-icon 2023-11-07 14:22:49 +01:00
victorAnumudu 67c1b2aaa0 placed default job icons 2023-11-07 14:20:19 +01:00
ameye 313cfc1f28 Merge branch 'edit-job-bug-fix' of WrenchBoard/Users-Wrench into master 2023-11-07 12:40:34 +00:00
victorAnumudu 59a7f110be Fixed save job bug 2023-11-07 07:35:40 +01:00
ameye 52e8447f6a Merge branch 'Server-path-added' of WrenchBoard/Users-Wrench into master 2023-11-06 23:33:16 +00:00
Chief Bube c60e28928a changed to job_uid 2023-11-06 15:29:23 -08:00
ameye 58357fd501 Merge branch 'Server-path-added' of WrenchBoard/Users-Wrench into master 2023-11-06 21:15:03 +00:00
Chief Bube 5402980d6c Chnged path from profile to job 2023-11-06 11:15:11 -08:00
ameye 32c7b3d513 Merge branch 'Server-path-added' of WrenchBoard/Users-Wrench into master 2023-11-06 18:56:32 +00:00
Chief Bube a30b22170d Added images server path 2023-11-06 10:53:26 -08:00
ameye e3314b0460 Merge branch 'job-image-upload-fix' of WrenchBoard/Users-Wrench into master 2023-11-06 18:01:42 +00:00
victorAnumudu 86eb1f16bb fixed job image upload 2023-11-06 19:00:28 +01:00
ameye 5660d74e75 Merge branch 'job-image-upload' of WrenchBoard/Users-Wrench into master 2023-11-06 15:48:53 +00:00
victorAnumudu 612016784d added job image upload API 2023-11-06 16:34:41 +01:00
ameye 988aadfb7e Merge branch 'Server-path-added' of WrenchBoard/Users-Wrench into master 2023-11-06 14:28:14 +00:00
ameye 54851b5f77 Merge branch 'family-image-bug' of WrenchBoard/Users-Wrench into master 2023-11-06 14:27:50 +00:00
victorAnumudu 91f3b92138 Merge master into family-image-bug 2023-11-06 15:24:06 +01:00
victorAnumudu f48de9d65f upload bug fixed 2023-11-06 15:22:56 +01:00
Chief Bube c920c35a9c image now works 2023-11-06 06:15:12 -08:00
ameye 7bcaead120 Merge branch 'Server-path-added' of WrenchBoard/Users-Wrench into master 2023-11-06 14:04:08 +00:00
Chief Bube 828f56ed84 Added Image Path for server image 2023-11-06 05:30:30 -08:00
ameye 07118c10a8 Merge branch 'family-profile-image-upload' of WrenchBoard/Users-Wrench into master 2023-11-06 12:13:26 +00:00
victorAnumudu ca5923a7f8 Merge master into family-profile-image-upload 2023-11-06 12:43:20 +01:00
victorAnumudu 4f0d432176 family profile image upload API added 2023-11-06 12:42:10 +01:00
ameye dd3f9d99f3 Merge branch 'Family-Acc-layout-update' of WrenchBoard/Users-Wrench into master 2023-11-06 09:33:43 +00:00
Chief Bube 8807b671ad update market data 2023-11-06 01:25:44 -08:00
victorAnumudu 7020e6d4dc added family profile image upload 2023-11-06 04:10:03 +01:00
ameye d66093a2ad Merge branch 'edit-job-add-image' of WrenchBoard/Users-Wrench into master 2023-11-05 10:53:44 +00:00
victorAnumudu b79eb6b158 Merge master into edit-job-add-image 2023-11-04 17:37:19 +01:00
victorAnumudu a759daaf90 edit job upload image added 2023-11-04 17:35:18 +01:00
ameye 600aec62cf Merge branch 'Family-Acc-layout-update' of WrenchBoard/Users-Wrench into master 2023-11-04 15:54:50 +00:00
Chief Bube 1612bf11ce Added JobOfferCancel 2023-11-04 08:47:42 -07:00
ameye f4e261eb6c Merge branch 'Family-Acc-layout-update' of WrenchBoard/Users-Wrench into master 2023-11-04 08:13:03 +00:00
Chief Bube b622398b6a added assignJobTask function to userServices 2023-11-03 18:47:14 -07:00
ameye e60957e6be Merge branch 'dummy-lnd-page' of WrenchBoard/Users-Wrench into master 2023-11-02 21:35:01 +00:00
victorAnumudu 6a2082d732 added lnd page 2023-11-02 19:01:48 +01:00
ameye 452c6bf8a1 Merge branch 'session-bug' of WrenchBoard/Users-Wrench into master 2023-11-02 01:54:41 +00:00
victorAnumudu 9f89376aa9 Hid text when session expires 2023-11-01 22:11:34 +01:00
ameye 4e91e47978 Merge branch 'session-implement' of WrenchBoard/Users-Wrench into master 2023-11-01 20:09:08 +00:00
ameye fcaa485b17 Merge branch 'history-header-removal' of WrenchBoard/Users-Wrench into master 2023-11-01 20:08:55 +00:00
victorAnumudu e4526652d3 Merge master into session-implement 2023-11-01 20:27:35 +01:00
victorAnumudu 64056bb2a4 changed payment to purchase 2023-11-01 18:45:25 +01:00
victorAnumudu e49c4d66f8 removed table headers if no record is found 2023-11-01 18:39:24 +01:00
ameye 8fdb939b72 Merge branch 'Family-Acc-layout-update' of WrenchBoard/Users-Wrench into master 2023-11-01 17:06:51 +00:00
victorAnumudu 79325450f3 session logout implemented 2023-11-01 18:04:47 +01:00
Chief Bube 7849a027b4 changed fill 2023-11-01 10:04:00 -07:00
ameye 38432a6d50 Merge branch 'Family-Acc-layout-update' of WrenchBoard/Users-Wrench into master 2023-11-01 16:08:13 +00:00
Chief Bube 83a54ff3ef . 2023-11-01 07:37:00 -07:00
Chief Bube 5e0fdffa1e done 2023-11-01 07:34:23 -07:00
ameye 11d2cb3e3a Merge branch 'Added-uid-to-completesignup' of WrenchBoard/Users-Wrench into master 2023-11-01 14:00:31 +00:00
ameye 93ac55b44b Merge branch 'error-page-style' of WrenchBoard/Users-Wrench into master 2023-11-01 14:00:23 +00:00
Chief Bube 237ce13a6c . 2023-11-01 06:40:13 -07:00
Chief Bube 4253174494 . 2023-11-01 06:31:05 -07:00
victorAnumudu da0ed0364b changed the height of the page 2023-11-01 13:43:51 +01:00
ameye 466175c49d Merge branch 'fixing-height-in-intrest-popup' of WrenchBoard/Users-Wrench into master 2023-11-01 10:39:10 +00:00
Chief Bube ed148ce267 Fixed Family Profile Break 2023-10-31 21:42:15 -07:00
ameye 6de795c07b Merge branch 'error-page' of WrenchBoard/Users-Wrench into master 2023-10-31 21:29:49 +00:00
victorAnumudu 436498bef9 added background image to error page 2023-10-31 19:51:36 +01:00
victorAnumudu 086b1202a4 error 404 page adjusted 2023-10-31 16:59:02 +01:00
ameye a81ccdc4d7 Merge branch 'reward-tab-cleanup' of WrenchBoard/Users-Wrench into master 2023-10-31 12:57:55 +00:00
victorAnumudu 33abbbcd2b adjusted reward component contents 2023-10-31 13:53:02 +01:00
ameye 04844af733 Merge branch 'lastname-bug-fix' of WrenchBoard/Users-Wrench into master 2023-10-31 12:42:42 +00:00
victorAnumudu 46d919090d lastname bug fixed 2023-10-31 13:36:53 +01:00
ameye 8e67892f16 Merge branch 'rewards-tab' of WrenchBoard/Users-Wrench into master 2023-10-31 12:21:17 +00:00
victorAnumudu a67d2b7bb4 reward tab clean up 2023-10-31 13:16:33 +01:00
victorAnumudu 99c0c24489 Merge master into rewards-tab 2023-10-31 13:15:22 +01:00
victorAnumudu 1a1d59a8c7 rewards API implemented 2023-10-31 13:13:58 +01:00
ameye 31dcfcfd0b Merge branch 'fixing-height-in-intrest-popup' of WrenchBoard/Users-Wrench into master 2023-10-31 11:45:48 +00:00
Chief Bube e9aa58f2f5 Added tracking text color 2023-10-31 04:42:50 -07:00
victorAnumudu 55fe2bf6d2 Merge master into rewards-tab 2023-10-31 04:23:42 +01:00
victorAnumudu 738eb1589e rewards tab added 2023-10-31 04:22:50 +01:00
ameye 139e0c2827 Merge branch 'send-btn-disable' of WrenchBoard/Users-Wrench into master 2023-10-30 17:43:22 +00:00
victorAnumudu 30642bba14 disabled send btn on successful transfer 2023-10-30 16:29:45 +01:00
ameye f5921612b8 Merge branch 'balance-bug' of WrenchBoard/Users-Wrench into master 2023-10-30 14:43:49 +00:00
44 changed files with 1043 additions and 516 deletions
+2
View File
@@ -49,6 +49,7 @@ import MyWaitingJobsPage from "./views/MyWaitingJobsPage";
import FamilyMarketPage from "./views/FamilyMarketPage";
import FacebookRedirect from "./views/FacebookRedirect";
import AppleRedirectPage from "./views/AppleRedirectPage";
import LndPage from "./views/LndPage";
export default function Routers() {
return (
@@ -76,6 +77,7 @@ export default function Routers() {
<Route path="/vemail" element={<VerifyLinkPages />} />
<Route path="/complereset" element={<VerifyPasswordPages />} />
<Route exact path="/outmessage" element={<VerifyYouPages />} />
<Route exact path="/lnd/*" element={<LndPage />} />
{/* private route */}
<Route element={<AuthRoute />}>
Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

+15
View File
@@ -17,6 +17,10 @@ import { updateUserDetails } from "../../../store/UserDetails";
import ReCAPTCHA from "react-google-recaptcha";
export default function Login() {
const queryParams = new URLSearchParams(location?.search);
const sessionExpired = queryParams.get("sessionExpired")
const dispatch = useDispatch();
const { state } = useLocation();
@@ -241,6 +245,9 @@ 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]">
Sign In to WrenchBoard
@@ -255,6 +262,14 @@ export default function Login() {
</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>
}
{/* switch login component */}
<div className="ml-7 flex justify-start items-center gap-3">
@@ -6,6 +6,7 @@ import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout";
export default function SignUp() {
// eslint-disable-next-line no-restricted-globals
const queryParams = new URLSearchParams(location?.search);
const country = queryParams.get("cnt")?.toUpperCase();
@@ -54,6 +54,8 @@ export default function VerifyLink() {
localStorage.setItem("member_id", `${data?.member_id}`);
localStorage.setItem("session_token", `${data?.session}`);
localStorage.setItem("session", `${data?.session}`);
localStorage.setItem("uid", data?.uid)
navigate("/", { replace: true });
setLinkLoader(false);
+9 -2
View File
@@ -1,5 +1,4 @@
import { useEffect, useState } from "react";
import dataImage2 from "../../assets/images/taskbanners/default.jpg";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import MarketPopUp from "../MarketPlace/PopUp/MarketPopUp";
@@ -8,6 +7,7 @@ export default function AvailableJobsCard({
datas,
hidden = false,
contentDisplay,
image_server,
}) {
//debugger;
const [marketPopUp, setMarketPopUp] = useState({ show: false, data: {} });
@@ -23,6 +23,13 @@ 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" ? (
@@ -131,7 +138,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={dataImage2} alt="data" className="w-full h-full" />
<img src={image} alt="data" className="w-full h-full" />
</div>
<div className="flex flex-col flex-[0.9]">
<h1
+15 -25
View File
@@ -2,13 +2,24 @@ import localImgLoad from "../../lib/localImgLoad";
import CountDown from "../Helpers/CountDown";
import { PriceFormatter } from "../Helpers/PriceFormatter";
export default function OfferCard({ datas, hidden = false, setOfferPopout }) {
export default function OfferCard({
datas,
hidden = false,
setOfferPopout,
image_server,
}) {
let thePrice = PriceFormatter(
datas?.price * 0.01,
datas?.currency_code,
datas?.currency
);
let image = localStorage.getItem("session_token")
? `${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">
@@ -18,9 +29,7 @@ export default function OfferCard({ datas, hidden = false, setOfferPopout }) {
<div
className="thumbnail w-full h-full rounded-xl overflow-hidden px-4 pt-4"
style={{
background: `url(${localImgLoad(
`images/taskbanners/${datas?.banner || "default.jpg"}`
)}) center / contain no-repeat`,
background: `url(${image}) center / contain no-repeat`,
}}
>
{hidden && <div className="flex justify-center"></div>}
@@ -31,26 +40,7 @@ export default function OfferCard({ datas, hidden = false, setOfferPopout }) {
<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">
@@ -96,7 +86,7 @@ export default function OfferCard({ datas, hidden = false, setOfferPopout }) {
<button
type="button"
onClick={() =>
setOfferPopout({ show: true, data: { ...datas, thePrice } })
setOfferPopout({ show: true, data: { ...datas, thePrice, image } })
}
className="btn-shine w-[98px] h-[33px] text-white rounded-full text-sm bg-pink flex justify-center items-center"
>
+53 -15
View File
@@ -33,7 +33,7 @@ export default function FamilyManageTabs({
loading: false,
data: null,
};
// console.log('accountDetails',accountDetails)
// State for family details, tasks, waitlist, and pending
const [details, setDetails] = useState({
familyDetails: { ...initialDetailState },
@@ -66,8 +66,10 @@ export default function FamilyManageTabs({
// State for family task popout
const [familyTaskPopout, setFamilyTaskPopout] = useState(false);
let [uploadStatus, setUploadStatus] = useState({loading: false, status: false, message:''}) // HOLDS STATE FOR UPLOAD PROFILE PICTURE STATUS
// State for profile image
const [profileImg, setProfileImg] = useState(profile);
const [profileImg, setProfileImg] = useState(accountDetails.image ? accountDetails.image : profile);
// Ref for profile image input
const profileImgInput = useRef(null);
@@ -90,24 +92,59 @@ 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;
const profileImgChangeHandler = (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 (file) {
const imgReader = new FileReader();
imgReader.onload = () => {
const imageDataUrl = imgReader.result;
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)
}
// Set the profile image
setProfileImg(imageDataUrl);
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,
msg_type: 'FILE',
action: 11305
}
setUploadStatus({loading: true, status: false, message:'Loading...'})
apiCall.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'})
setProfileImg(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(file);
imgReader.readAsDataURL(e.target.files[0]);
}
};
@@ -298,6 +335,7 @@ export default function FamilyManageTabs({
profileImgChangeHandler={profileImgChangeHandler}
browseProfileImg={browseProfileImg}
accountDetails={accountDetails}
uploadStatus={uploadStatus}
/>
<div className="mt-4 flex flex-col justify-center items-center gap-2 lg:flex-row lg:justify-center lg:items-center xl:flex-col xl:justify-center xl:items-center 2xl:flex-row 2xl:justify-center 2xl:items-center 2xl:gap-[2px]">
<button
+53 -7
View File
@@ -19,6 +19,7 @@ export default function FamilyTable({
familyList,
loader,
popUpHandler,
imageServer
}) {
const navigate = useNavigate();
const [currentPage, setCurrentPage] = useState(0);
@@ -52,21 +53,34 @@ export default function FamilyTable({
task_count,
family_uid,
banner,
enable_traking,
profile_picture,
imageServer
}) => {
// Check for valid dates
const addedDate = added ? added.split(" ")[0] : "N/A";
const loginDate = last_login ? formatDateString(last_login) : "N/A";
const key = `family-${family_uid}`; // Assign a unique key
const image = localStorage.getItem('session_token') ? `${imageServer}${localStorage.getItem('session_token')}/family/${family_uid}` : ''
const trackingStatus =
enable_traking === "0"
? "Stopped"
: enable_traking === "100"
? "Active"
: "";
return (
<tr
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
key={family_uid}
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
key={key}
>
<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 flex-[0.1]">
<img
src={localImgLoad(`images/icons/${banner}`)}
// src={profile_picture}
src={image || profile_picture || localImgLoad(`images/icons/${banner}`)}
alt={`Avatar of ${firstname} ${lastname}`}
className="w-full h-full"
/>
@@ -85,6 +99,23 @@ export default function FamilyTable({
</div>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span
className={`text-base font-medium whitespace-nowrap ${
enable_traking === "0"
? "text-[#FF0000] dark:text-[#FF6666]"
: enable_traking === "100"
? "text-[#00A000] dark:text-[#00FF00]"
: "text-dark-gray dark:text-white"
}`}
>
{trackingStatus}
</span>
</div>
</td>
<td className="text-center py-4 px-2">
<div className="flex space-x-1 items-center justify-center">
<span className="text-base text-dark-gray dark:text-white font-medium whitespace-nowrap">
@@ -92,6 +123,7 @@ export default function FamilyTable({
</span>
</div>
</td>
<td className="text-right py-4 px-2 flex items-center justify-center">
<button
onClick={() =>
@@ -104,12 +136,25 @@ export default function FamilyTable({
task_count,
family_uid,
banner,
image
})
}
type="button"
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
className="w-12 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Manage
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 11 20"
id="Arrow"
className="w-[0.7rem]"
>
<path
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]"
></path>
</svg>
</button>
</td>
</tr>
@@ -134,13 +179,14 @@ export default function FamilyTable({
<thead className="sticky top-0">
<tr className="text-base text-thin-light-gray whitespace-nowrap border-b dark:border-[#5356fb29] default-border-bottom ">
<th className="py-4">Name</th>
<th className="py-4 text-center">Tracking</th>
<th className="py-4 text-center">No of Tasks</th>
<th className="py-4 text-right"></th>
</tr>
</thead>
<tbody className="h-full">
{currentFamilyList?.map((familyMember, index) => {
return <FamilyRow key={index} {...familyMember} />;
return <FamilyRow key={index} {...familyMember} imageServer={imageServer} />;
})}
</tbody>
</table>
@@ -171,7 +217,7 @@ export default function FamilyTable({
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0}
next={currentPage + itemsPerPage >= familyList.length}
next={currentPage + itemsPerPage >= familyList?.length}
data={familyList}
start={indexOfFirstItem}
stop={indexOfLastItem}
@@ -54,7 +54,7 @@ export default function FamilyPending({
value?.currency_code,
value?.currency
);
let image = value.banner ? value.banner : "default.jpg";
let image = `${familyData.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
return (
<tr
key={index}
@@ -64,9 +64,7 @@ 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={localImgLoad(
`images/taskbanners/${image}`
)}
src={image}
alt="data"
className="w-full h-full rounded-full"
/>
@@ -49,12 +49,12 @@ export default function FamilyProfile({ familyData, className }) {
// initial values for formik
let initialValues = {
family_uid: familyData.uid,
firstname: familyData.firstname,
lastname: familyData.lastname,
year: familyData.year,
month: familyData.month,
enable_traking: familyData.enable_traking,
family_uid: familyData?.uid,
firstname: familyData?.firstname,
lastname: familyData?.lastname,
year: familyData?.year,
month: familyData?.month,
enable_traking: familyData?.enable_traking,
action: 22020,
};
@@ -67,9 +67,7 @@ export default function FamilyTasks({
value?.currency_code,
value?.currency
);
let image = value.banner
? value.banner
: "default.jpg";
let image = `${familyData.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
return (
<tr
key={index}
@@ -79,9 +77,7 @@ 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={localImgLoad(
`images/taskbanners/${image}`
)}
src={image}
alt="data"
className="w-full h-full rounded-full"
/>
@@ -67,6 +67,8 @@ 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,6 +7,7 @@ export default function ProfileInfo({
profileImgChangeHandler,
browseProfileImg,
accountDetails,
uploadStatus
}) {
// console.log(accountDetails.banner)
return (
@@ -52,6 +53,11 @@ 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}
@@ -278,7 +278,8 @@ function FamilyAddFundPopout({action, situation, wallet, familyData}) {
:
<button
type="submit"
className="w-[150px] h-[48px] rounded-full text-base text-white bg-sky-500 hover:bg-sky-400"
className={`w-[150px] h-[48px] rounded-full text-base text-white bg-sky-500 hover:bg-sky-400 ${requestStatus.status ? 'opacity-50' : ''}`}
disabled={requestStatus.status}
>
Send
</button>
+7 -6
View File
@@ -5,7 +5,7 @@ import React, {
useMemo,
useState,
} from "react";
import SiteService from "../../services/SiteService";
import usersService from "../../services/UsersService";
import InputCom from "../Helpers/Inputs/InputCom";
import ModalCom from "../Helpers/ModalCom";
import Layout from "../Partials/Layout";
@@ -17,7 +17,7 @@ export default function FamilyAcc() {
// 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);
@@ -27,7 +27,7 @@ export default function FamilyAcc() {
last_name: "",
});
const apiCall = useMemo(() => new SiteService(), []);
const apiCall = useMemo(() => new usersService(), []);
const popUpHandler = () => {
setPopUp((prev) => !prev);
@@ -115,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 } = data;
setFamilyList(result_list);
const { result_list, session_image_server } = data;
setFamilyList({result_list, session_image_server});
setLoader(false);
} else {
return;
@@ -172,9 +172,10 @@ export default function FamilyAcc() {
</div>
<Suspense fallback={<LoadingSpinner color="sky-blue" size="16" />}>
<FamilyTable
familyList={familyList}
familyList={familyList?.result_list}
loader={loader}
popUpHandler={popUpHandler}
imageServer={familyList?.session_image_server}
/>
</Suspense>
</div>
+12 -5
View File
@@ -2,6 +2,8 @@ import React from "react";
// import Lottie from "react-lottie";
import { useNavigate } from "react-router-dom";
import * as animationData from "../../assets/images/Lotties/77618-website-404-error-animation.json";
import { localImgLoad } from "../../lib";
// import BgError from '../../assets/images/wrench-page-notfound.jpg'
export default function FourZeroFour() {
const navigate = useNavigate();
@@ -14,16 +16,21 @@ export default function FourZeroFour() {
},
};
return (
<div className="flex justify-center items-center w-full h-screen bg-[#232247]">
<div>
<div className={`my-custom-bg-class flex justify-center items-center w-full min-h-screen before:content-[''] before:absolute before:inset-0 before:bg-[#cdcdcd]/[.8]`}>
<div className="relative pt-32 max-w-3xl">
{/* <Lottie options={defaultOptions} width={600} height={600} /> */}
<div className="flex justify-center">
<div className="px-16 md:px-24 flex flex-col items-center justify-center gap-4">
<img src={localImgLoad('images/404.png')} className="w-72" alt='404Image' />
<p className="mt-8 text-red-600 font-black text-4xl md:text-5xl tracking-wider text-center">Sorry!</p>
<h1 className="text-black text-4xl md:text-5xl font-black tracking-wide text-center leading-tight">The page cant be found.</h1>
<p className="px-2 md:px-8 text-slate-700 text-base md:text-lg text-center">The page you're looking for isn't available. Use the go back button below</p>
<button
onClick={() => navigate(-1)}
type="button"
className="btn-gradient text-white text-lg w-[150px] h-[50px] rounded-full"
className="px-4 md:px-8 border-2 border-[#2b70fa] rounded-lg text-[#007bff] text-base md:text-lg h-[48px] flex justify-center items-center gap-1"
>
Go Back
<span>Go Back</span>
<span className="pb-1">&rarr;</span>
</button>
</div>
</div>
+103
View File
@@ -0,0 +1,103 @@
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 RewardsTable() {
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 getFamilyRewardHistory = ()=>{
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}))
})
}
useEffect(()=>{
getFamilyRewardHistory()
}, [])
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 Rewards 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 RewardsTable
+25 -4
View File
@@ -10,6 +10,7 @@ import usersService from "../../services/UsersService";
import PurchasesTable from "../MyWallet/WalletComponent/PurchasesTable";
import RecentActivityTable from "../MyWallet/WalletComponent/RecentActivityTable";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import RewardsTable from "./RewardsTable";
export default function History() {
@@ -58,6 +59,9 @@ export default function History() {
useEffect(()=>{
getPaymentHistory()
}, [])
useEffect(()=>{
getPurchaseHistory()
}, [])
@@ -236,15 +240,24 @@ export default function History() {
>
Recent Activity
</button>
<button
name="reward"
onClick={(e) => setTab(e.target.name)}
className={`px-4 py-1 rounded-t-2xl ${
tab == "reward" ? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white" : "bg-white text-[#000] border-t-[2px]"
}`}
>
Rewards
</button>
</div>
{/* END OF switch button */}
<div className="history-tables w-full">
{/* PURCHASE SECTION */}
{tab == 'purchases' &&
<div className="wallet w-full border-t">
<h1 className="p-2 text-xl font-bold text-dark-gray dark:text-white tracking-wide">Purchases</h1>
{/* <h1 className="p-2 text-xl font-bold text-dark-gray dark:text-white tracking-wide">Purchases</h1> */}
{purchaseHistory.loading ?
<LoadingSpinner size='16' color='sky-blue' />
<LoadingSpinner size='16' color='sky-blue' height='h-[500px]' />
:
<PurchasesTable purchase={purchaseHistory} />
}
@@ -255,16 +268,24 @@ export default function History() {
{/* RECENT ACTIVITY SECTION */}
{tab == 'recent' &&
<div className="wallet w-full border-t">
<h1 className="p-2 text-xl font-bold text-dark-gray dark:text-white tracking-wide">Recent Activity</h1>
{/* <h1 className="p-2 text-xl font-bold text-dark-gray dark:text-white tracking-wide">Recent Activity</h1> */}
{/* <p className='text-base text-slate-500 dark:text-white'>Activity Report</p> */}
{paymentHistory.loading ?
<LoadingSpinner size='16' color='sky-blue' />
<LoadingSpinner size='16' color='sky-blue' height='h-[500px]' />
:
<RecentActivityTable payment={paymentHistory} />
}
</div>
}
{/* END OF RECENT ACTIVITY SECTION */}
{/* REWARD SECTION */}
{tab == 'reward' &&
<div className="wallet w-full border-t">
<RewardsTable />
</div>
}
{/* END OF REWARD SECTION */}
</div>
</div>
{/*<HistoryTable />*/}
+7 -3
View File
@@ -4,15 +4,19 @@ import MyOffersFamilyTable from "../MyTasks/MyOffersFamilyTable";
import FamilyActiveLSlde from "./FamilyActiveLSlde";
export default function FamilyDash({ familyOffers, MyActiveJobList }) {
console.log("PROPS IN FAMILY DASH->", familyOffers);
// console.log("PROPS IN FAMILY DASH->", familyOffers?.result_list);
const trending = MyActiveJobList;
return (
<div>
<div className="home-page-wrapper">
{/* <CommonHead commonHeadData={props.commonHeadData} /> */}
{familyOffers && familyOffers.length > 0 && (
<MyOffersFamilyTable familyOffers={familyOffers} className="mb-10" />
{familyOffers?.result_list && familyOffers?.result_list.length > 0 && (
<MyOffersFamilyTable
familyOffers={familyOffers?.result_list}
image_server={familyOffers?.session_image_server}
className="mb-10"
/>
)}
{trending && trending.length > 0 && (
<FamilyActiveLSlde trending={trending} className="mb-10" />
+1 -1
View File
@@ -75,7 +75,7 @@ export default function Home(props) {
<FamilyDash
account={userDetails}
commonHeadData={props.bannerList}
familyOffers={MyOffersList?.data?.result_list}
familyOffers={MyOffersList?.data}
MyActiveJobList={MyActiveJobList?.data}
/>
) : userDetails && userDetails?.account_type == "FULL" ? (
+27
View File
@@ -0,0 +1,27 @@
import React, { useEffect, useState } from 'react'
import Layout from '../Partials/Layout'
import LoadingSpinner from '../Spinners/LoadingSpinner'
function Lnd() {
const [reqStatus, setReqStatus] = useState({loading:true, data: []})
useEffect(()=>{
const timer = setTimeout(()=>{
setReqStatus({loading:false, data: []})
},2000)
return () => clearTimeout(timer)
}, [])
return (
<>
{reqStatus.loading ?
<LoadingSpinner color='sky-blue' size='32' height='min-h-screen' />
:
<div className='min-h-screen flex flex-col justify-center items-center'>Empty Dummy Page</div>
}
</>
)
}
export default Lnd
@@ -8,6 +8,7 @@ import SelectBox from "../Helpers/SelectBox";
export default function MainSection({
className,
marketPlaceProduct,
image_server,
categories,
}) {
// Creating All cart..
@@ -110,6 +111,7 @@ export default function MainSection({
{({ datas }) => (
<AvailableJobsCard
contentDisplay={contentDisplay}
image_server={image_server}
key={datas.id}
datas={datas}
/>
+2
View File
@@ -7,6 +7,7 @@ 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 (
<>
@@ -15,6 +16,7 @@ export default function MarketPlace({ commonHeadData }) {
<MainSection
marketPlaceProduct={marketData}
categories={categories}
image_server={image_server}
className="mb-10"
/>
</Layout>
@@ -6,6 +6,7 @@ import { handlePagingFunc } from "../Pagination/HandlePagination";
import PaginatedList from "../Pagination/PaginatedList";
export default function MyActiveJobTable({ MyJobList, className }) {
const navigate = useNavigate();
let { pathname } = useLocation();
@@ -44,6 +45,7 @@ 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}
@@ -51,11 +53,9 @@ export default function MyActiveJobTable({ MyJobList, className }) {
>
<td className=" py-4">
<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">
<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">
<img
src={localImgLoad(
`images/taskbanners/${value.banner}`
)}
src={image}
alt="data"
className="w-full h-full rounded-full"
/>
+32 -8
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 }) {
@@ -101,12 +101,19 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
}
};
const JobListItem = ({ value, index }) => {
const JobListItem = ({ value, index, image_server }) => {
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}
@@ -116,7 +123,11 @@ 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={localImgLoad(`images/taskbanners/${value.banner ? value.banner : 'default.jpg'}`)} alt="data" className="w-full h-full rounded-full" />
<img
src={image}
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">
@@ -147,7 +158,11 @@ 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
@@ -160,7 +175,11 @@ 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>
@@ -193,7 +212,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)}
@@ -213,7 +232,12 @@ 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} />
<JobListItem
index={index}
key={index}
value={value}
image_server={MyJobList?.data.session_image_server}
/>
))
) : (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
@@ -8,6 +8,7 @@ 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);
@@ -45,6 +46,7 @@ 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}
@@ -54,7 +56,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={localImgLoad(`images/taskbanners/${value.banner || "default.jpg"}`)}
src={image}
alt="data"
className="w-full h-full rounded-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 }) {
export default function MyOffersFamilyTable({ className, familyOffers, image_server }) {
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,6 +117,7 @@ export default function MyOffersFamilyTable({ className, familyOffers }) {
key={item.id}
datas={item}
setOfferPopout={setOfferPopout}
image_server={image_server}
/>
);
})}
@@ -44,7 +44,7 @@ export default function MyWaitingJobTable({ MyJobList, className }) {
value?.currency_code,
value?.currency
);
let image = value.banner ? value.banner : 'default.jpg'
let image = `${MyJobList.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
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="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<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">
<img
src={localImgLoad(`images/taskbanners/${image}`)}
src={image}
alt="data"
className="w-full h-full rounded-full"
/>
@@ -16,45 +16,36 @@ function PurchasesTable({purchase}) {
return (
<div className='flex flex-col justify-between min-h-[500px]'>
<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">Trx.</th>
<th className="p-2">Amount</th>
<th className="p-2">Fee</th>
</tr>
</thead>
{purchase.data.length ?
(
<tbody>
{currentPurchase.map((item, index) => (
<tr key={index} className='text-slate-500'>
<td className="p-2">{item.added_date}<br />
<b>{item.confirmation} </b>
</td>
<td className="p-2">{item.amount}</td>
<td className="p-2">{item.fee}</td>
</tr>
))}
</tbody>
)
<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">Trx.</th>
<th className="p-2">Amount</th>
<th className="p-2">Fee</th>
</tr>
</thead>
<tbody>
{currentPurchase.map((item, index) => (
<tr key={index} className='text-slate-500'>
<td className="p-2">{item.added_date}<br />
<b>{item.confirmation} </b>
</td>
<td className="p-2">{item.amount}</td>
<td className="p-2">{item.fee}</td>
</tr>
))}
</tbody>
</table>
:purchase.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>
:
purchase.error ?
(
<tbody>
<tr className='text-slate-500'>
<td className="p-2" colSpan={4}>Opps! an error occurred. Please try again!</td>
</tr>
</tbody>
)
:
<tbody>
<tr className='text-slate-500'>
<td className="p-2" colSpan={4}>No Purchase History Found!</td>
</tr>
</tbody>
<div className="p-2 text-slate-500 flex flex-col grow justify-center items-center">
<span>No Purchase History Found!</span>
</div>
}
</table>
{/* PAGINATION BUTTON */}
<PaginatedList onClick={handlePagination} prev={currentPage == 0 ? true : false} next={currentPage+Number(process.env.REACT_APP_ITEM_PER_PAGE) >= purchase?.data?.length ? true : false} data={purchase?.data} start={indexOfFirstItem} stop={indexOfLastItem} />
@@ -19,16 +19,16 @@ function RecentActivityTable({ payment }) {
return (
<div className="flex flex-col justify-between min-h-[500px]">
<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">Date</th>
<th className="p-4">Trx.</th>
<th className="p-2">Amnt./Fee</th>
<th className="p-2">Status</th>
</tr>
</thead>
{payment?.data?.length > 0 ? (
{payment?.data?.length > 0 ?
<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">Date</th>
<th className="p-4">Trx.</th>
<th className="p-2">Amnt./Fee</th>
<th className="p-2">Status</th>
</tr>
</thead>
<tbody>
{currentActivity.map((item, index) => (
<tr key={index} className="text-slate-500">
@@ -46,24 +46,16 @@ function RecentActivityTable({ payment }) {
</tr>
))}
</tbody>
) : payment?.error ? (
<tbody>
<tr className="text-slate-500">
<td className="p-2" colSpan={4}>
Opps! an error occurred. Please try again!
</td>
</tr>
</tbody>
) : (
<tbody>
<tr className="text-slate-500">
<td className="p-2" colSpan={4}>
No Payment History Found!
</td>
</tr>
</tbody>
)}
</table>
</table>
:payment.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 Payment History Found!</span>
</div>
}
{/* PAGINATION BUTTON */}
<PaginatedList
+7 -1
View File
@@ -36,6 +36,12 @@ 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.session_image_server}${localStorage.getItem(
"session_token"
)}/profile/${userDetails.uid}`
: "";
const handlerBalance = () => {
setbalanceValue.toggle();
if (notificationDropdown) {
@@ -91,7 +97,7 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
// User Profile
let { firstname, lastname, email, profile_pic_url } = userDetails;
let userEmail = email?.split("@")[0];
const userProfileImage = profile_pic_url || DEFAULT_PROFILE_IMAGE;
const userProfileImage = image || DEFAULT_PROFILE_IMAGE;
return (
<>
+1 -1
View File
@@ -15,7 +15,7 @@ export default function Sidebar({
logoutModalHandler,
myJobList,
}) {
const darkMode = useContext(DarkModeContext);
const darkMode = useContext(DarkModeContext);
let { userDetails } = useSelector((state) => state.userDetails);
//const jobLists = getJobList(); // pass from upper - we need in a lot of places
+195 -64
View File
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React, { useEffect, useRef, useState } from "react";
import { useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import usersService from "../../../services/UsersService";
@@ -6,6 +6,9 @@ import Icons from "../../Helpers/Icons";
import InputCom from "../../Helpers/Inputs/InputCom";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import cover from "../../../assets/images/profile-info-cover.png";
import profileImage from "../../../assets/images/profile.jpg";
import { Form, Formik } from "formik";
import * as Yup from "yup";
@@ -43,18 +46,15 @@ export default function PersonalInfoTab({
frstNmeHndlr,
lstNmeHndlr,
dscrphn,
profileImg,
coverImg,
profileImgInput,
browseProfileImg,
profileImgChangHandler,
coverImgInput,
browseCoverImg,
coverImgChangHandler,
uploadStatus
}) {
let { userDetails } = useSelector((state) => state.userDetails);
const image = localStorage.getItem("session_token")
? `${userDetails.session_image_server}${localStorage.getItem(
"session_token"
)}/profile/${userDetails.uid}`
: "";
const apiCall = new usersService();
let navigate = useNavigate();
@@ -85,6 +85,125 @@ export default function PersonalInfoTab({
status: false,
});
const [profileImg, setProfileImg] = useState(
userDetails?.session_image_server ? image : profileImage
);
let [uploadStatus, setUploadStatus] = useState({
loading: false,
status: false,
message: "",
}); // HOLDS STATE FOR UPLOAD PROFILE PICTURE STATUS
const [coverImg, setCoverImg] = useState(cover);
// profile img
const profileImgInput = useRef(null);
const browseProfileImg = () => {
profileImgInput.current.click();
};
const profileImgChangHandler = (e) => {
setUploadStatus({ loading: false, status: false, message: "" });
const acceptedFormat = ["jpeg", "jpg", "png", "bmp", "gif"]; // ARRAY OF SUPPORTED FORMATS
const uploadedFile = e.target.files[0]; //UPLOADED FILE
const fileFormat = uploadedFile?.type?.split("/")[1]?.toLowerCase();
const MAX_FILE_SIZE = 5 * 1048576; // 5MB
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 > MAX_FILE_SIZE) {
// 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
file_name: uploadedFile?.name,
file_size: uploadedFile?.size,
file_type: uploadedFile?.type?.split("/")[0]?.toLowerCase(),
file_data: base64Img,
msg_type: "FILE",
action: 11300,
};
setUploadStatus({
loading: true,
status: false,
message: "Loading...",
});
apiCall
.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",
});
setProfileImg(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(uploadedFile);
}
};
// cover img
const coverImgInput = useRef(null);
const browseCoverImg = () => {
coverImgInput.current.click();
};
const coverImgChangHandler = (e) => {
if (e.target.value !== "") {
const imgReader = new FileReader();
imgReader.onload = (event) => {
setCoverImg(event.target.result);
};
imgReader.readAsDataURL(e.target.files[0]);
}
};
const handleUpdateUser = (values, helpers) => {
setRequestState({ message: "", loading: true, status: false });
@@ -363,65 +482,77 @@ export default function PersonalInfoTab({
</div>
</div>
{/* {process.env.REACT_APP_SHOW_UPLOAD_PROFILE_PICTURE != 0 && */}
<div className="w-[232px] mb-10">
<div className="update-profile w-full mb-9">
<h1 className="text-xl tracking-wide font-bold text-dark-gray dark:text-white flex items-center mb-2">
Update Profile
<span className="ml-1">
<Icons name="block-question" />
</span>
</h1>
<p className="text-base text-thin-light-gray mb-5">
Profile of at least Size
<span className="ml-1 text-dark-gray dark:text-white">
300x300
</span>
. Gifs work too.
<span className="ml-1 text-dark-gray dark:text-white">
Max 5mb
</span>
.
</p>
<div className="flex justify-center">
<div className="w-full relative">
<img
src={profileImg}
alt="profile"
className="sm:w-[198px] sm:h-[198px] w-[120px] h-[120px] rounded-full overflow-hidden object-contain object-center"
/>
<input
ref={profileImgInput}
onChange={(e) => profileImgChangHandler(e)}
type="file"
className="hidden"
/>
<div
onClick={browseProfileImg}
className="w-[32px] h-[32px] absolute bottom-7 sm:right-10 right-[105px] hover:bg-pink bg-dark-gray rounded-full cursor-pointer"
<div className="w-[232px] mb-10">
<div className="update-profile w-full mb-9">
<h1 className="text-xl tracking-wide font-bold text-dark-gray dark:text-white flex items-center mb-2">
Update Profile
<span className="ml-1">
<Icons name="block-question" />
</span>
</h1>
<p className="text-base text-thin-light-gray mb-5">
Profile of at least Size
<span className="ml-1 text-dark-gray dark:text-white">
200x200
</span>
. Gifs work too.
<span className="ml-1 text-dark-gray dark:text-white">
Max 5mb
</span>
.
</p>
<div className="flex justify-center">
<div className="w-[200px] h-[200px] relative">
<img
src={profileImg}
alt="profile"
className="sm:w-[198px] sm:h-[198px] w-full h-full rounded-full overflow-hidden object-cover object-center"
/>
<input
ref={profileImgInput}
onChange={(e) => profileImgChangHandler(e)}
type="file"
className="hidden"
/>
<div
onClick={browseProfileImg}
className="w-[32px] h-[32px] absolute bottom-4 right-4 hover:bg-pink bg-dark-gray rounded-full cursor-pointer"
>
<svg
width="32"
height="32"
viewBox="0 0 32 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<svg
width="32"
height="32"
viewBox="0 0 32 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M16.5147 11.5C17.7284 12.7137 18.9234 13.9087 20.1296 15.115C19.9798 15.2611 19.8187 15.4109 19.6651 15.5683C17.4699 17.7635 15.271 19.9587 13.0758 22.1539C12.9334 22.2962 12.7948 22.4386 12.6524 22.5735C12.6187 22.6034 12.5663 22.6296 12.5213 22.6296C11.3788 22.6334 10.2362 22.6297 9.09365 22.6334C9.01498 22.6334 9 22.6034 9 22.536C9 21.4009 9 20.2621 9.00375 19.1271C9.00375 19.0746 9.02997 19.0109 9.06368 18.9772C10.4123 17.6249 11.7609 16.2763 13.1095 14.9277C14.2295 13.8076 15.3459 12.6913 16.466 11.5712C16.4884 11.5487 16.4997 11.5187 16.5147 11.5Z"
fill="white"
/>
<path
d="M20.9499 14.2904C19.7436 13.0842 18.5449 11.8854 17.3499 10.6904C17.5634 10.4694 17.7844 10.2446 18.0054 10.0199C18.2639 9.76139 18.5261 9.50291 18.7884 9.24443C19.118 8.91852 19.5713 8.91852 19.8972 9.24443C20.7251 10.0611 21.5492 10.8815 22.3771 11.6981C22.6993 12.0165 22.7105 12.4698 22.3996 12.792C21.9238 13.2865 21.4443 13.7772 20.9686 14.2717C20.9648 14.2792 20.9536 14.2867 20.9499 14.2904Z"
fill="white"
/>
</svg>
</div>
<path
d="M16.5147 11.5C17.7284 12.7137 18.9234 13.9087 20.1296 15.115C19.9798 15.2611 19.8187 15.4109 19.6651 15.5683C17.4699 17.7635 15.271 19.9587 13.0758 22.1539C12.9334 22.2962 12.7948 22.4386 12.6524 22.5735C12.6187 22.6034 12.5663 22.6296 12.5213 22.6296C11.3788 22.6334 10.2362 22.6297 9.09365 22.6334C9.01498 22.6334 9 22.6034 9 22.536C9 21.4009 9 20.2621 9.00375 19.1271C9.00375 19.0746 9.02997 19.0109 9.06368 18.9772C10.4123 17.6249 11.7609 16.2763 13.1095 14.9277C14.2295 13.8076 15.3459 12.6913 16.466 11.5712C16.4884 11.5487 16.4997 11.5187 16.5147 11.5Z"
fill="white"
/>
<path
d="M20.9499 14.2904C19.7436 13.0842 18.5449 11.8854 17.3499 10.6904C17.5634 10.4694 17.7844 10.2446 18.0054 10.0199C18.2639 9.76139 18.5261 9.50291 18.7884 9.24443C19.118 8.91852 19.5713 8.91852 19.8972 9.24443C20.7251 10.0611 21.5492 10.8815 22.3771 11.6981C22.6993 12.0165 22.7105 12.4698 22.3996 12.792C21.9238 13.2865 21.4443 13.7772 20.9686 14.2717C20.9648 14.2792 20.9536 14.2867 20.9499 14.2904Z"
fill="white"
/>
</svg>
</div>
</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>
{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>
{/* } */}
</div>
+115 -194
View File
@@ -6,8 +6,6 @@ import React, {
useState,
} from "react";
import { useSelector } from "react-redux";
import cover from "../../assets/images/profile-info-cover.png";
import profile from "../../assets/images/profile.jpg";
import usersService from "../../services/UsersService";
import Icons from "../Helpers/Icons";
import Layout from "../Partials/Layout";
@@ -26,161 +24,8 @@ import RecipientAccountTab from "./Tabs/RecipientAccountTab";
export default function Settings({ faq }) {
const apiCall = new usersService();
const { userDetails } = useSelector((state) => state?.userDetails);
const [profileImg, setProfileImg] = useState(
userDetails?.profile_pic_url ? userDetails.profile_pic_url : profile
);
let [uploadStatus, setUploadStatus] = useState({loading: false, status: false, message:''}) // HOLDS STATE FOR UPLOAD PROFILE PICTURE STATUS
const [coverImg, setCoverImg] = useState(cover);
const [reloadCardList, setReloadCardList] = useState(false); // STATE TO DETERMINE WHEN CARD LIST RELOADS. EG: WHEN USER DELETES A CARD
// profile img
const profileImgInput = useRef(null);
const browseProfileImg = () => {
profileImgInput.current.click();
};
const profileImgChangHandler = (e) => {
// if (e.target.value !== "") {
// const imgReader = new FileReader();
// imgReader.onload = (event) => {
// setProfileImg(event.target.result);
// };
// imgReader.readAsDataURL(e.target.files[0]);
// }
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
if(!acceptedFormat.includes(uploadedFile?.type?.split("/")[1]?.toLowerCase())){ //CHECKING FOR CORRECT UPLOAD FORMAT
let msg = 'Please select '
for(let i=0; i<=acceptedFormat.length-1; i++){
if(i == acceptedFormat.length-1){
msg+=`or ${acceptedFormat[i]}`
}else{
msg+=`${acceptedFormat[i]}, `
}
}
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 reqData = { // PAYLOAD FOR API CALL
file_name: uploadedFile?.name,
file_size: uploadedFile?.size,
file_type: uploadedFile?.type?.split("/")[0]?.toLowerCase(),
file_data: event?.target?.result,
msg_type: 'FILE',
action: 'WRENCHBOARD_PICTURE_PROFILE',
// action: 11307
}
setUploadStatus({loading: true, status: false, message:'Loading...'})
apiCall.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'})
setProfileImg(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]);
}
};
// cover img
const coverImgInput = useRef(null);
const browseCoverImg = () => {
coverImgInput.current.click();
};
const coverImgChangHandler = (e) => {
if (e.target.value !== "") {
const imgReader = new FileReader();
imgReader.onload = (event) => {
setCoverImg(event.target.result);
};
imgReader.readAsDataURL(e.target.files[0]);
}
};
// Tabs Handling
const tabs = [
{
id: 1,
name: "personal",
title: "Edit Profile",
iconName: "people-hover",
},
{
id: 2,
name: "payment",
title: "Payment Cards",
iconName: "bank-card",
},
{
id: 3,
name: "recipients-account",
title: "Recipients Account",
iconName: "bank-card",
},
{
id: 4,
name: "notification",
title: "Notification Setting",
iconName: "notification-setting",
},
{
id: 5,
name: "login_activity",
title: "Login Activity",
iconName: "login-activity",
},
{
id: 6,
name: "password",
title: "Change Password",
iconName: "password-hover",
},
{
id: 7,
name: "faq",
title: "FAQ",
iconName: "block-question",
},
{
id: 8,
name: "privacy",
title: "Privacy Policy",
iconName: "page-right",
},
{
id: 9,
name: "terms",
title: "Terms and Conditions",
iconName: "page-right",
},
];
const [tab, setTab] = useState(tabs[0].name);
const tabHandler = (value) => {
setTab(value);
};
// Recipient Account
const [recipientAccount, setRecipientAccount] = useState({
state: false,
@@ -223,6 +68,120 @@ export default function Settings({ faq }) {
getRecipientAccount();
}, [reloadCardList]);
// Tabs Handling
const tabs = [
{
id: 1,
name: "personal",
title: "Edit Profile",
iconName: "people-hover",
},
{
id: 2,
name: "payment",
title: "Payment Cards",
iconName: "bank-card",
},
{
id: 3,
name: "recipients_account",
title: "Recipients Account",
iconName: "bank-card",
},
{
id: 4,
name: "notification",
title: "Notification Setting",
iconName: "notification-setting",
},
{
id: 5,
name: "login_activity",
title: "Login Activity",
iconName: "login-activity",
},
{
id: 6,
name: "password",
title: "Change Password",
iconName: "password-hover",
},
{
id: 7,
name: "faq",
title: "FAQ",
iconName: "block-question",
},
{
id: 8,
name: "privacy",
title: "Privacy Policy",
iconName: "page-right",
},
{
id: 9,
name: "terms",
title: "Terms and Conditions",
iconName: "page-right",
},
];
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 = {
personal: (
<div className="tab-item">
<PersonalInfoTab />
</div>
),
payment: (
<div className="tab-item">
<PaymentMathodsTab />
</div>
),
recipients_account: (
<div className="tab-item">
<RecipientAccountTab
recipientAccount={recipientAccount}
setRecipientAccount={setRecipientAccount}
setReloadCardList={setReloadCardList}
/>
</div>
),
notification: (
<div className="tab-item">
<NotificationSettingTab />
</div>
),
login_activity: <LoginActivityTab />,
password: <ChangePasswordTab />,
faq: <FaqTab datas={faq} />,
privacy: <PrivacyPolicyTab />,
terms: <TermsConditionTab />,
};
// Default tab component
const defaultTabComponent = (
<div className="tab-item">
<PersonalInfoTab />
</div>
);
// Selected tab component based on the current 'tab'
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
return (
<>
<Layout>
@@ -263,45 +222,7 @@ export default function Settings({ faq }) {
</div>
<div className="w-[1px] bg-[#E3E4FE] dark:bg-[#a7a9b533] mr-10"></div>
<div className="content-body-items flex-1">
{tab === "personal" && (
<div className="tab-item">
<PersonalInfoTab
profileImg={profileImg}
coverImg={coverImg}
browseProfileImg={browseProfileImg}
profileImgInput={profileImgInput}
profileImgChangHandler={profileImgChangHandler}
coverImgChangHandler={coverImgChangHandler}
browseCoverImg={browseCoverImg}
coverImgInput={coverImgInput}
uploadStatus={uploadStatus}
/>
</div>
)}
{tab === "payment" && (
<div className="tab-item">
<PaymentMathodsTab />
</div>
)}
{tab === "recipients-account" && (
<div className="tab-item">
<RecipientAccountTab
recipientAccount={recipientAccount}
setRecipientAccount={setRecipientAccount}
setReloadCardList={setReloadCardList}
/>
</div>
)}
{tab === "notification" && (
<div className="tab-item">
<NotificationSettingTab />
</div>
)}
{tab === "login_activity" && <LoginActivityTab />}
{tab === "password" && <ChangePasswordTab />}
{tab === "faq" && <FaqTab datas={faq} />}
{tab === "privacy" && <PrivacyPolicyTab />}
{tab === "terms" && <TermsConditionTab />}
{selectedTabComponent}
</div>
</div>
</div>
+135 -36
View File
@@ -1,6 +1,6 @@
import { Field, Form, Formik } from "formik";
import React, { useCallback, useMemo, useState } from "react";
import { useDispatch } from "react-redux";
import { useDispatch, useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import * as Yup from "yup";
import usersService from "../../services/UsersService";
@@ -51,6 +51,13 @@ const EditJobPopOut = ({
categories,
}) => {
const dispatch = useDispatch();
const { userDetails } = useSelector((state) => state.userDetails);
const uploadedImage = `${userDetails.session_image_server}${localStorage.getItem('session_token')}/job/${details?.job_uid}`
const [taskImage, setTaskImage] = useState(uploadedImage)
let [uploadStatus, setUploadStatus] = useState({loading: false, status: false, message:''}) // HOLDS STATE FOR UPLOAD PROFILE PICTURE STATUS
let [requestStatus, setRequestStatus] = useState({
loading: false,
@@ -105,6 +112,66 @@ 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]);
}
};
return (
<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">
@@ -138,7 +205,7 @@ const EditJobPopOut = ({
</svg>
</button>
</div>
<div className="logout-modal-body w-full flex flex-col items-center px-10 py-8">
<div className="logout-modal-body w-full flex flex-col items-center px-10 pb-8 pt-2">
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
@@ -258,7 +325,7 @@ const EditJobPopOut = ({
role="group"
aria-labelledby="checked-group"
>
{Object.entries(categories).map(([key, value]) => (
{categories && Object.entries(categories)?.map(([key, value]) => (
<label
key={key}
className="flex gap-1 w-full items-center"
@@ -279,43 +346,68 @@ const EditJobPopOut = ({
</div>
</div>
</div>
<div className="field w-full mb-6">
<div
className={`flex items-center justify-between mb-2.5`}
>
<label
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
htmlFor="timeline_days"
>
Timeline
<span className="text-green-700 text-sm tracking-wide">
- Expected duration of this task
</span>
<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
id="task_image"
className="hidden"
type="file"
accept="image/*"
onChange={taskImgChangeHandler}
/>
{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/80 hover:bg-white hover:shadow-md transition-all duration-500 cursor-pointer text-slate-800">Remove Image</span>
</div>
:
<label
className="absolute -top-5 h-[150px] w-full flex flex-col justify-center items-center bg-slate-100 dark:bg-[#11131F] cursor-pointer input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold" htmlFor='task_image'>
Select Task Image
</label>
}
</div>
{/* END OF TASK IMAGE */}
<Field
component="select"
name="timeline_days"
className={`input-field p-2 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-10 bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none ${
props.errors.timeline_days &&
props.touched.timeline_days
? "border-[#ff0a0a63] shadow-red-500 border-[0.5px] animate-shake"
: "border border-[#f5f8fa] dark:border-[#5e6278]"
}`}
value={props.values.timeline_days}
>
<option value="">Select Duration</option>
{publicArray.map(({ name, duration }, idx) => (
<option
className="text-slate-500 text-lg"
value={duration}
<div className="field w-1/2">
<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"
>
{name}
</option>
))}
</Field>
Timeline -
<span className="w-full text-center text-green-700 text-sm tracking-wide">
Expected duration of this task
</span>
</label>
</div>
<Field
component="select"
name="timeline_days"
className={`input-field p-2 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-10 bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none ${
props.errors.timeline_days &&
props.touched.timeline_days
? "border-[#ff0a0a63] shadow-red-500 border-[0.5px] animate-shake"
: "border border-[#f5f8fa] dark:border-[#5e6278]"
}`}
value={props.values.timeline_days}
>
<option value="">Select Duration</option>
{publicArray.map(({ name, duration }, idx) => (
<option
key={duration}
className="text-slate-500 text-lg"
value={duration}
>
{name}
</option>
))}
</Field>
</div>
</div>
{/* inputs ends here */}
</div>
@@ -341,6 +433,12 @@ 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 ? (
@@ -350,6 +448,7 @@ 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,6 +101,8 @@ function FamilyOfferJobPopout({ details, onClose, situation }) {
});
};
console.log(details)
return (
<ModalCom action={onClose} situation={situation}>
<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">
@@ -138,7 +140,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={localImgLoad(`images/taskbanners/${details.banner}`)} alt='Banner-Image' />
<img className="w-full h-auto" src={details?.image} alt='banner' />
</div>
<div className="details-wrapper">
<p className="text-lg my-5 font-semibold text-slate-900 tracking-wide">
+2 -2
View File
@@ -1,7 +1,7 @@
import { Field, Form, Formik } from "formik";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import * as Yup from "yup";
import SiteService from "../../services/SiteService";
import usersService from "../../services/UsersService";
import InputCom from "../Helpers/Inputs/InputCom/index";
import ModalCom from "../Helpers/ModalCom";
import LoadingSpinner from "../Spinners/LoadingSpinner";
@@ -36,7 +36,7 @@ const dispatch = useDispatch()
},
});
const apiCall = useMemo(() => new SiteService(), []);
const apiCall = useMemo(() => new usersService(), []);
// member listing
const memberList = useCallback(async () => {
+33 -2
View File
@@ -24,6 +24,7 @@ function PendingJobsPopout({ details, onClose, situation }) {
const [pendingJobLoader, setPendingJobLoader] = useState({
extend: false,
offer: false,
cancel: false,
});
let [requestMessage, setRequestMessage] = useState({
@@ -81,6 +82,29 @@ function PendingJobsPopout({ details, onClose, situation }) {
setRequestMessage({ status: false, message: "" });
}, 3000);
});
} else if (name == "cancel") {
// RUNS THIS IF JOB OFFER IS CANCELLED
reqData = { ...pendingData, reason: "cancel", offer_result: 3333 };
setPendingJobLoader({ cancel: true });
apiCall
.pendingCancelOffer(reqData)
.then((res) => {
setRequestMessage({ status: true, message: res.data.status });
setTimeout(() => {
setPendingJobLoader({ cancel: false });
setRequestMessage({ status: false, message: "" });
onClose();
dispatch(tableReload({ type: "PENDINGTABLE" }));
dispatch(tableReload({ type: "JOBTABLE" }));
}, 4000);
})
.catch((error) => {
setRequestMessage("Try Again");
setTimeout(() => {
setPendingJobLoader({ cancel: false });
setRequestMessage({ status: false, message: "" });
}, 3000);
});
} else return;
// try {
// if (name === "extend") {
@@ -274,9 +298,16 @@ function PendingJobsPopout({ details, onClose, situation }) {
<div className="mt-10 md:mt-32 md:flex md:justify-center">
<button
className="px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
onClick={onClose}
onClick={handlePendingJobsBtn}
name="cancel"
>
Cancel Offer
{pendingJobLoader.cancel ? (
<div className="w-[96px] flex justify-center items-center h-full">
<LoadingSpinner size={5} color="sky-blue" />
</div>
) : (
"Cancel Offer"
)}
</button>
</div>
</div>
+6
View File
@@ -304,6 +304,12 @@ input[type="text"][dir="rtl"] {
transform: rotate(360deg);
}
}
.my-custom-bg-class{
background: url("./assets/images/wrench-page-notfound.jpg") center/cover;
position: relative;
}
/* TODO: =================================default end================================ */
/* TODO: =================================update password================================ */
.content-wrapper.thankyou-section {
+85 -48
View File
@@ -19,6 +19,16 @@ 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 = {
@@ -30,12 +40,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);
}
@@ -368,7 +378,7 @@ class usersService {
page: 0,
offset: 0,
limit: 100,
allstatus: 0
allstatus: 0,
};
return this.postAuxEnd("/activetaskslist", postData);
}
@@ -496,6 +506,19 @@ class usersService {
return this.postAuxEnd("/purchasehx", postData);
}
// API FUNCTION TO GET FAMILY REWARD HISTORY
getFamilyRewardHx() {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
offset: 1,
limit: 20,
action: 22011,
};
return this.postAuxEnd("/familyrewardhx", postData);
}
// API FUNCTION TO GET PAYMENT HISTORY
getPaymentHx() {
var postData = {
@@ -585,7 +608,7 @@ class usersService {
sessionid: localStorage.getItem("session_token"),
page: 0,
limit: 100,
...reqdata
...reqdata,
};
return this.postAuxEnd("/familyupdate", postData);
}
@@ -769,6 +792,17 @@ 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 = {
@@ -804,11 +838,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);
}
@@ -1065,52 +1099,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 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 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 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 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);
}
/*
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(username)
@@ -1224,6 +1257,10 @@ 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) => {
+13
View File
@@ -0,0 +1,13 @@
import React from 'react'
import Lnd from '../components/Lnd/Lnd'
function LndPage() {
return (
<>
<Lnd />
</>
)
}
export default LndPage
+1 -1
View File
@@ -22,7 +22,7 @@ export default function MyPendingJobsPage() {
};
useEffect(() => {
getMyJobList();
getMyJobList();
}, [pendingListTable]);
// debugger;