Compare commits

...

32 Commits

Author SHA1 Message Date
Ebube a868713ae3 Added family pending component 2023-07-06 15:02:26 +01:00
ameye e68603d836 Merge branch 'family-offer-hidden' of WrenchBoard/Users-Wrench into master 2023-07-06 11:48:40 +00:00
victorAnumudu 67e227c554 hides family offer list when none 2023-07-06 12:39:39 +01:00
ameye f6fc004a06 Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-07-06 10:21:44 +00:00
ameye 1682a2221f Merge branch 'family-dash-revamp' of WrenchBoard/Users-Wrench into master 2023-07-06 10:21:33 +00:00
victorAnumudu b16b356532 family offer new layout 2023-07-06 11:01:54 +01:00
victorAnumudu 62b97d903c family dashboard active and waiting list revamp 2023-07-06 07:06:53 +01:00
Ebube abef3bec01 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into resources-page 2023-07-06 06:33:54 +01:00
Ebube 626835e1e0 Parent Waiting View Added & Market Link goes to bad page fixed 2023-07-06 06:33:33 +01:00
ameye a6d68bc856 Merge branch 'family-current-task' of WrenchBoard/Users-Wrench into master 2023-07-05 19:55:29 +00:00
victorAnumudu a674688dce family current task added 2023-07-05 20:52:34 +01:00
ameye ef339b163d Merge branch 'cookie-fixing' of WrenchBoard/Users-Wrench into master 2023-07-05 16:54:23 +00:00
victorAnumudu 1ce154cc06 cookie bug fixing 2023-07-05 17:48:40 +01:00
victorAnumudu 67eb142ae2 cookie bug fixing 2023-07-05 17:47:05 +01:00
ameye e784d84699 Merge branch 'cookie-value-reading' of WrenchBoard/Users-Wrench into master 2023-07-05 16:10:01 +00:00
CHIEFSOFT\ameye cd6d540c4b Family Activer Job 2023-07-05 11:12:08 -04:00
victorAnumudu b2beaa7c2b changed how the value of login type is read from the cookie 2023-07-05 15:40:05 +01:00
ameye b0db896f6b Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-07-05 14:15:03 +00:00
CHIEFSOFT\ameye fafea8b1ad Task banners 2023-07-05 10:13:19 -04:00
Ebube bbb099d51f Modified status for family waitlist 2023-07-05 14:51:24 +01:00
Ebube bfc0521e54 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into resources-page 2023-07-05 14:45:51 +01:00
Ebube 6870c145d7 Added banner name to suggested task payload 2023-07-05 14:45:29 +01:00
ameye c18373f9db Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-07-05 13:34:21 +00:00
CHIEFSOFT\ameye 24ac0daf29 status_text 2023-07-05 08:58:08 -04:00
Ebube 4dd58b16d8 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into resources-page 2023-07-05 13:52:39 +01:00
Ebube cc66ebbbde Family waitlist complete 2023-07-05 13:51:10 +01:00
CHIEFSOFT\ameye 3d61b3259d Status label 2023-07-05 08:32:00 -04:00
CHIEFSOFT\ameye 40b614356f active task spread 2023-07-05 08:17:57 -04:00
ameye dbba6c4014 Merge branch 'resources-page' of WrenchBoard/Users-Wrench into master 2023-07-05 11:56:34 +00:00
Ebube ae93de5f25 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into resources-page 2023-07-05 12:53:41 +01:00
Ebube 4904f1d398 Added waiting component and rendered the offerlist 2023-07-05 12:53:19 +01:00
ameye 880b084547 Merge branch 'cookie-bug-fix' of WrenchBoard/Users-Wrench into master 2023-07-05 10:26:39 +00:00
36 changed files with 1279 additions and 694 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

+25 -12
View File
@@ -139,25 +139,38 @@ export default function Login() {
// In order to update the selected login type whenever the component renders // In order to update the selected login type whenever the component renders
// useEffect(() => { // useEffect(() => {
// document.cookie.includes("loginType=family") ? "loginfamily" : "loginfull" // Clear the loginType cookie if the user switches to loginfull
// Set the loginType cookie to remember the user's selection
// document.cookie = "loginType=family; expires=Session; path=/;";
// Clear the loginType cookie if the user switches to loginfull
// document.cookie ="loginType=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; // document.cookie ="loginType=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
// }, []); // }, []);
useLayoutEffect(()=>{ // checks the cookie in order to set the login type before components mounts useLayoutEffect(()=>{ // checks the cookie in order to set the login type before components mounts
if(document.cookie.includes("loginType=family")){ // if(document.cookie.includes("loginType=family")){
setLoginType('family') // setLoginType('family')
}else if(document.cookie.includes("loginType=full")){ // }else if(document.cookie.includes("loginType=full")){
setLoginType('full') // setLoginType('full')
}else{ // }else{
setLoginType('full') // setLoginType('full')
// }
function readCookie(cname) { // checks the cookie in order to set the login type before components mounts
let name = cname + "=";
let decoded_cookie = decodeURIComponent(document.cookie);
let carr = decoded_cookie.split(';');
for(let i=0; i<carr.length;i++){
let c = carr[i];
while(c.charAt(0)==' '){
c=c.substring(1);
}
if(c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return 'full'
} }
let loginValue = readCookie('loginType')
setLoginType(loginValue)
},[]) },[])
useEffect(() => { useEffect(() => {
setMail(""); setMail("");
setPassword(""); setPassword("");
+142 -130
View File
@@ -9,7 +9,7 @@ export default function AvailableJobsCard({
className, className,
datas, datas,
hidden = false, hidden = false,
contentDisplay contentDisplay,
}) { }) {
//debugger; //debugger;
const [marketPopUp, setMarketPopUp] = useState({ show: false, data: {} }); const [marketPopUp, setMarketPopUp] = useState({ show: false, data: {} });
@@ -27,121 +27,136 @@ export default function AvailableJobsCard({
}, []); }, []);
return ( return (
<> <>
{contentDisplay == 'grid' ? {contentDisplay == "grid" ? (
<div <div
className={`card-style-two w-full h-[426px] p-[20px] bg-white dark:bg-dark-white rounded-2xl section-shadow ${ className={`card-style-two w-full h-[426px] p-[20px] bg-white dark:bg-dark-white rounded-2xl section-shadow ${
className || "" className || ""
}`} }`}
> >
<div className="flex flex-col justify-between w-full h-full"> <div
<Link to="/shop-details" className="mb-2.5"> onClick={() => {
setMarketPopUp({ show: true, data: datas });
}}
className="flex flex-col justify-between w-full h-full"
>
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize"> <h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{datas.title} {datas.title}
</h1> </h1>
</Link>
<div className="card-two-info flex justify-between items-center"> <div className="card-two-info flex justify-between items-center">
<div className="owned-by flex space-x-2 items-center"> <div className="owned-by flex space-x-2 items-center">
<div>
<p className="text-thin-light-gray text-sm leading-3">Added</p>
<p className="text-base text-dark-gray dark:text-white">
{datas.offer_added}
</p>
</div>
</div>
<div className="w-[1px] bg-light-purple dark:bg-dark-light-purple h-7"></div>
<div className="created-by flex space-x-2 items-center flex-row-reverse">
<div>
<p className="text-thin-light-gray text-sm leading-3 text-right">
Expires
</p>
<p className="text-base text-dark-gray dark:text-white text-right">
{datas.expire}
</p>
</div>
</div>
</div>
<div className="thumbnail-area w-full">
<div
className="w-full h-[236px] p-6 rounded-xl overflow-hidden bg-center bg-cover bg-no-repeat"
style={{
backgroundImage: `url('${imageUrl}')`,
}}
>
<div className="flex justify-center">{datas.description}</div>
</div>
</div>
<div className="details-area">
<div className="product-two-options flex justify-between mb-5 relative">
{/* <div className="status">*/}
{/* {datas.isActive && (*/}
{/* <span className="text-xs px-3 py-1.5 tracking-wide rounded-full bg-gold text-white">*/}
{/* Active*/}
{/*</span>*/}
{/* )}*/}
{/* </div>*/}
{/*<div className=" review flex space-x-2">*/}
{/* <button*/}
{/* onClick={favoriteHandler}*/}
{/* type="button"*/}
{/* className={`w-7 h-7 bg-white rounded-full flex justify-center items-center ${*/}
{/* addFavorite ? "text-red-500" : "text-thin-light-gray"*/}
{/* }`}*/}
{/* >*/}
{/* <Icons name="star" />*/}
{/* </button>*/}
{/*</div>*/}
</div>
<div className="flex justify-between">
<div className="flex items-center space-x-2">
<div> <div>
<p className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white"> <p className="text-thin-light-gray text-sm leading-3">
{/* {thePrice} | {datas.timeline_days} day(s) */} Added
{thePrice}
</p> </p>
<p className="text-sm text-lighter-gray"> <p className="text-base text-dark-gray dark:text-white">
( {datas.offer_code}) | {datas.offer_added}
<span className="italic ml-1">
{datas.timeline_days} day(s)
</span>
</p> </p>
</div> </div>
</div> </div>
<div> <div className="w-[1px] bg-light-purple dark:bg-dark-light-purple h-7"></div>
<button <div className="created-by flex space-x-2 items-center flex-row-reverse">
type="button" <div>
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide" <p className="text-thin-light-gray text-sm leading-3 text-right">
onClick={() => { Expires
setMarketPopUp({ show: true, data: datas }); </p>
}} <p className="text-base text-dark-gray dark:text-white text-right">
> {datas.expire}
View </p>
</button> </div>
</div>
</div>
<div className="thumbnail-area w-full">
<div
className="w-full h-[236px] p-6 rounded-xl overflow-hidden bg-center bg-cover bg-no-repeat"
style={{
backgroundImage: `url('${imageUrl}')`,
}}
>
<div className="flex justify-center">{datas.description}</div>
</div>
</div>
<div className="details-area">
<div className="product-two-options flex justify-between mb-5 relative">
{/* <div className="status">*/}
{/* {datas.isActive && (*/}
{/* <span className="text-xs px-3 py-1.5 tracking-wide rounded-full bg-gold text-white">*/}
{/* Active*/}
{/*</span>*/}
{/* )}*/}
{/* </div>*/}
{/*<div className=" review flex space-x-2">*/}
{/* <button*/}
{/* onClick={favoriteHandler}*/}
{/* type="button"*/}
{/* className={`w-7 h-7 bg-white rounded-full flex justify-center items-center ${*/}
{/* addFavorite ? "text-red-500" : "text-thin-light-gray"*/}
{/* }`}*/}
{/* >*/}
{/* <Icons name="star" />*/}
{/* </button>*/}
{/*</div>*/}
</div>
<div className="flex justify-between">
<div className="flex items-center space-x-2">
<div>
<p className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white">
{/* {thePrice} | {datas.timeline_days} day(s) */}
{thePrice}
</p>
<p className="text-sm text-lighter-gray">
( {datas.offer_code}) |
<span className="italic ml-1">
{datas.timeline_days} day(s)
</span>
</p>
</div>
</div>
<div>
<button
type="button"
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
onClick={() => {
setMarketPopUp({ show: true, data: datas });
}}
>
View
</button>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> ) : (
: <div className="card-style-two w-full p-8 my-2 flex items-center gap-4 bg-white dark:bg-dark-white rounded-2xl section-shadow">
<div className="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="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]">
<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={dataImage2} alt="data" className="w-full h-full" /> </div>
</div> <div className="flex flex-col flex-[0.9]">
<div className="flex flex-col flex-[0.9]"> <h1
<Link to="/shop-details" className=""> onClick={() => {
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize"> setMarketPopUp({ show: true, data: datas });
}}
className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize"
>
{datas?.title} {datas?.title}
</h1> </h1>
</Link>
<div className="my-2"> <div
<p className="text-dark-gray dark:text-white">{datas?.description}</p> onClick={() => {
</div> setMarketPopUp({ show: true, data: datas });
}}
className="my-2"
>
<p className="text-dark-gray dark:text-white">
{datas?.description}
</p>
</div>
{/* <div className="card-two-info flex gap-2 items-center"> {/* <div className="card-two-info flex gap-2 items-center">
<div className="owned-by flex space-x-2 items-center"> <div className="owned-by flex space-x-2 items-center">
<div> <div>
<p className="text-thin-light-gray text-sm leading-3">Added</p> <p className="text-thin-light-gray text-sm leading-3">Added</p>
@@ -162,40 +177,37 @@ export default function AvailableJobsCard({
</div> </div>
</div> </div>
</div> */} </div> */}
<div className="block sm:flex flex-wrap gap-4"> <div className="block sm:flex flex-wrap gap-4">
<p className="text-sm text-thin-light-gray flex flext-start gap-1"> <p className="text-sm text-thin-light-gray flex flext-start gap-1">
Price: <span className="text-purple">{thePrice}</span> Price: <span className="text-purple">{thePrice}</span>
</p> </p>
<p className="text-sm text-thin-light-gray"> <p className="text-sm text-thin-light-gray">
Duration:{" "} Duration:{" "}
<span className="text-purple italic"> <span className="text-purple italic">
{" "} {" "}
{datas?.timeline_days} day(s) {datas?.timeline_days} day(s)
</span> </span>
</p> </p>
<p className="text-sm text-thin-light-gray"> <p className="text-sm text-thin-light-gray">
Code:{" "} Code:{" "}
<span className="text-purple"> <span className="text-purple"> {datas?.offer_code}</span>
{" "} </p>
{datas?.offer_code} </div>
</span>
</p>
</div> </div>
</div> </div>
<div className="">
<button
type="button"
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
onClick={() => {
setMarketPopUp({ show: true, data: datas });
}}
>
View
</button>
</div>
</div> </div>
<div className=""> )}
<button
type="button"
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
onClick={() => {
setMarketPopUp({ show: true, data: datas });
}}
>
View
</button>
</div>
</div>
}
{marketPopUp.show && ( {marketPopUp.show && (
<MarketPopUp <MarketPopUp
details={datas} details={datas}
@@ -0,0 +1,120 @@
import { useState } from "react";
import { Link, useLocation } from "react-router-dom";
import { toast } from "react-toastify";
import localImgLoad from "../../lib/localImgLoad";
import CountDown from "../Helpers/CountDown";
import Icons from "../Helpers/Icons";
export default function FamilyActiveJobsCard({ datas, hidden = false }) {
let { pathname } = useLocation();
console.log('TESTING11111',datas)
const [imageUrl, setImageUrl] = useState("");
const [addFavorite, setValue] = useState(false);
const [options, setOption] = useState(false);
const favoriteHandler = () => {
if (!addFavorite) {
setValue(true);
toast.success("Added to Favorite List");
} else {
setValue(false);
toast.warn("Remove to Favorite List");
}
};
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">
{/* thumbnail */}
<div className="w-full h-40">
{/* thumbnail image */}
<div
className="thumbnail w-full h-full rounded-xl overflow-hidden px-4 pt-4"
style={{
background: `url(${localImgLoad(
`images/taskbanners/${datas.banner}`
)}) center / contain no-repeat`,
}}
>
{/* <div className="product-options flex justify-between relative">*/}
{/*<span*/}
{/* onClick={favoriteHandler}*/}
{/* className={`w-7 h-7 bg-white rounded-full flex justify-center items-center cursor-pointer ${*/}
{/* addFavorite ? "text-pink" : " text-dark-gray"*/}
{/* }`}*/}
{/*>*/}
{/* <Icons name="love" />*/}
{/*</span>*/}
{/* <span*/}
{/* onClick={() => setOption(!options)}*/}
{/* className="w-7 h-7 flex justify-center items-center bg-white rounded-full cursor-pointer"*/}
{/* >*/}
{/* <Icons name="dots" />*/}
{/*</span>*/}
{/* {options && (*/}
{/* <div*/}
{/* onClick={() => setOption(!options)}*/}
{/* className="w-full h-screen fixed top-0 left-0 z-10"*/}
{/* ></div>*/}
{/* )}*/}
{/* <div*/}
{/* style={{ boxShadow: "0px 4px 87px 0px #0000002B" }}*/}
{/* className={`drop-down-content w-[80px] bg-white dark:bg-dark-white rounded-[4px] p-2.5 absolute right-0 top-[100%] z-20 ${*/}
{/* options ? "active" : ""*/}
{/* }`}*/}
{/* >*/}
{/* </div>*/}
{/* </div>*/}
{hidden && (
<div className="flex justify-center">
</div>
)}
</div>
</div>
{/* details */}
<div className="details">
{/* product title */}
<Link
to="/manage-active-job"
state={{ ...datas, pathname }}
className="text-xl font-bold text-dark-gray dark:text-white mb-2 capitalize line-clamp-1"
>
{datas.title}
</Link>
{/* 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.delivery_date} />
</p>
</div>
</div>
</div>
</div>
<div className="card-buttons flex justify-end items-center space-x-2">
<Link
to="/manage-active-job"
state={{ ...datas, pathname }}
className="btn-shine w-[98px] h-[33px] text-white rounded-full text-sm bg-pink flex justify-center items-center"
>
View
</Link>
</div>
</div>
);
}
+71
View File
@@ -0,0 +1,71 @@
import { useState } from "react";
import { toast } from "react-toastify";
import localImgLoad from "../../lib/localImgLoad";
import CountDown from "../Helpers/CountDown";
import Icons from "../Helpers/Icons";
import {PriceFormatter} from '../Helpers/PriceFormatter'
export default function FamilyOfferCard({ datas, hidden = false, setOfferPopout }) {
let thePrice = PriceFormatter(datas?.price * 0.01,datas?.currency_code,datas?.currency);
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">
{/* thumbnail */}
<div className="w-full h-40">
{/* thumbnail image */}
<div
className="thumbnail w-full h-full rounded-xl overflow-hidden px-4 pt-4"
style={{
background: `url(${localImgLoad(
`images/taskbanners/${datas.banner}`
)}) center / contain no-repeat`,
}}
>
{hidden && (
<div className="flex justify-center">
</div>
)}
</div>
</div>
{/* details */}
<div className="details">
<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>
</div>
<div className="card-buttons flex justify-end items-center space-x-2">
<button
type='button'
onClick={()=>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"
>
Start Task
</button>
</div>
</div>
);
}
+3 -3
View File
@@ -1,8 +1,8 @@
import React, { useState, useEffect } from "react"; import React, { useEffect, useState } from "react";
import Layout from "../Partials/Layout";
import FamilyManageTabs from "./Tabs/FamilyManageTabs";
import { useLocation, useNavigate } from "react-router-dom"; import { useLocation, useNavigate } from "react-router-dom";
import Layout from "../Partials/Layout";
import LoadingSpinner from "../Spinners/LoadingSpinner"; import LoadingSpinner from "../Spinners/LoadingSpinner";
import FamilyManageTabs from "./FamilyManageTabs";
export default function FamilyManage() { export default function FamilyManage() {
const [selectTab, setValue] = useState("today"); const [selectTab, setValue] = useState("today");
@@ -0,0 +1,251 @@
import React, {
Suspense,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import { useReactToPrint } from "react-to-print";
import profile from "../../assets/images/profile-info-profile.png";
import usersService from "../../services/UsersService";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import AssignTaskPopout from "./FamilyPopout/AssignTaskPopout";
import {
FamilyWaitlist,
FamilyAccount,
FamilyProfile,
FamilyTasks,
ProfileInfo,
FamilyPending,
} from "./Tabs";
export default function FamilyManageTabs({
className,
accountDetails,
listReload,
loader,
}) {
const [details, setDetails] = useState({
familyDetails: { loading: false, data: null },
familyTasks: { loading: false, data: null },
familyWaitList: { loading: false, data: null },
familyPending: { loading: false, data: null },
});
const [errMsg, setErrMsg] = useState("");
const [familyTaskPopout, setFamilyTaskPopout] = useState(false);
const familyPopUpHandler = () => {
setFamilyTaskPopout((prev) => !prev);
};
const [profileImg, setProfileImg] = useState(profile);
const profileImgInput = useRef(null);
const browseProfileImg = () => {
profileImgInput.current.click();
};
const profileImgChangeHandler = (e) => {
if (e.target.value !== "") {
const imgReader = new FileReader();
imgReader.onload = (event) => {
setProfileImg(event.target.result);
};
imgReader.readAsDataURL(e.target.files[0]);
}
};
const apiCall = useMemo(() => new usersService(), []);
const manageFamily = useCallback(async () => {
try {
setDetails({
familyDetails: { loading: true },
familyTasks: { loading: true },
familyWaitList: { loading: true },
familyPending: { loading: true },
});
const { family_uid } = accountDetails;
const reqData = { family_uid };
const [familyRes, tasksRes, familyWaitRes, familyPending] =
await Promise.all([
apiCall.ManageFamily(reqData),
apiCall.ManageTasks(reqData),
apiCall.ManageFamilyWaitlist(),
apiCall.ManageFamilyPending(),
]);
const familyData = familyRes.data;
const tasksData = tasksRes.data;
const familyWaitData = familyWaitRes.data;
const familyPendingData = familyPending.data;
if (
familyData?.internal_return < 0 ||
tasksData?.internal_return < 0 ||
familyWaitData?.internal_return < 0 ||
familyPendingData?.internal_return < 0
)
return;
setDetails({
familyDetails: { loading: false, data: familyData },
familyTasks: { loading: false, data: tasksData },
familyWaitList: { loading: false, data: familyWaitData },
familyPending: { loading: false, data: familyPendingData },
});
} catch (error) {
setDetails({
familyDetails: { loading: false },
familyTasks: { loading: false },
familyWaitList: { loading: false },
familyPending: { loading: false },
});
setErrMsg("An error occurred");
throw new Error(error);
}
}, [apiCall, accountDetails]);
const accountRef = useRef();
const useHandlePrint = useReactToPrint({
content: () => accountRef.current,
});
const tabs = [
{ id: 1, name: "Tasks" },
{ id: 2, name: "Waiting" },
{ id: 3, name: "Pending" },
{ id: 4, name: "Account" },
{ id: 5, name: "Profile" },
];
const [tab, setTab] = useState(tabs[0].name);
const tabHandler = (value) => {
setTab(value);
};
const tabComponents = {
Tasks: (
<FamilyTasks
className={className}
loader={details.familyTasks.loading}
familyData={details.familyTasks.data}
accountDetails={accountDetails}
/>
),
Waiting: (
<FamilyWaitlist
familyData={details.familyWaitList.data}
accountDetails={accountDetails}
loader={details.familyWaitList.loading}
/>
),
Pending: (
<FamilyPending
familyData={details.familyPending.data}
accountDetails={accountDetails}
loader={details.familyWaitList.loading}
/>
),
Account: (
<FamilyAccount
familyData={details.familyDetails.data}
myRef={accountRef}
loader={details.familyDetails.loading}
handlePrint={useHandlePrint}
/>
),
Profile: <FamilyProfile />,
};
const defaultTabComponent = (
<FamilyTasks
className={className}
loader={details.familyTasks.loading}
familyData={details.familyTasks.data}
accountDetails={accountDetails}
/>
);
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
useEffect(() => {
manageFamily();
}, [tab, manageFamily]);
return (
<div
className={`w-full bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow min-h-[520px] max-h-[600px] ${
className || ""
}`}
>
<div className="relative w-full overflow-x-auto sm:rounded-lg">
<Suspense
fallback={
<div className="h-full min-h-[500px] w-full overflow-hidden flex justify-center items-center">
<LoadingSpinner size="16" color="sky-blue" />
</div>
}
>
<div className="w-full h-full text-sm text-left text-gray-500 dark:text-gray-400 relative grid grid-cols-4 min-h-[520px]">
<div className="border-r border-[#E3E4FE] dark:border-[#a7a9b533] p-6 h-full">
<ProfileInfo
profileImg={profileImg}
profileImgInput={profileImgInput}
profileImgChangeHandler={profileImgChangeHandler}
browseProfileImg={browseProfileImg}
accountDetails={accountDetails}
/>
</div>
<div className="col-span-3 justify-self-end h-full w-full">
<div className="flex flex-col w-full">
<div className="w-full pr-8 flex items-center gap-1">
<ul className="flex gap-2 items-center border-b border-b-[#FAFAF] w-full">
{tabs.map(({ name, id }) => (
<li
onClick={() => tabHandler(name)}
className={`p-4 flex hover:text-purple transition-all ease-in-out items-center cursor-pointer overflow-hidden text-xl relative top-1 ${
tab === name
? "text-purple border-r"
: "text-thin-light-gray"
}`}
key={id}
>
<h1>{name}</h1>
</li>
))}
</ul>
<button
type="button"
onClick={familyPopUpHandler}
className="p-1 my-1 w-[100px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Add task
</button>
</div>
<div className="flex-[0.9] lg:min-h-[450px] h-full">
<div className="h-full p-4 border border-[#dbd9d9] relative overflow-y-auto">
{selectedTabComponent}
</div>
</div>
</div>
</div>
</div>
</Suspense>
</div>
{familyTaskPopout && (
<AssignTaskPopout
action={familyPopUpHandler}
situation={familyTaskPopout}
familyDetails={details.familyDetails.data}
/>
)}
</div>
);
}
@@ -1,6 +1,5 @@
import React, { useCallback, useEffect, useMemo, useState } from "react"; import React, { useCallback, useEffect, useMemo, useState } from "react";
import Layout from "../Partials/Layout"; import Layout from "../Partials/Layout";
import DataIteration from "../Helpers/DataIteration";
import SearchCom from "../Helpers/SearchCom"; import SearchCom from "../Helpers/SearchCom";
import FamilyMarketCard from "../Cards/FamilyMarketCard"; import FamilyMarketCard from "../Cards/FamilyMarketCard";
import usersService from "../../services/UsersService"; import usersService from "../../services/UsersService";
@@ -0,0 +1,56 @@
import { forwardRef } from 'react'
import QRCode from 'react-qr-code';
const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint }, ref) => {
return (
<div
className="w-full lg:min-h-[500px] h-full flex flex-col items-center justify-center"
ref={myRef}
>
<div className="update-table w-full lg:min-h-[450px] h-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow ">
<div className="flex items-center justify-around h-[380px]">
<div className="flex flex-col">
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Username:{" "}
<span className="ml-2 normal-case">
{familyData?.username ? familyData?.username : "please wait..."}
</span>
</h2>
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Pin:{" "}
<span className="ml-2 normal-case">
{familyData?.pin ? familyData?.pin : "please wait..."}
</span>
</h2>
</div>
<span className="text-5xl text-gray-400 opacity-20 font-bold">
or
</span>
<div className="max-w-[200px]">
<p className="text-xl tracking-wide mb-[15px] text-center font-bold text-dark-gray dark:text-white">
Scan the code from mobile app
</p>
<QRCode
size={256}
style={{ height: "auto", maxWidth: "100%", width: "100%" }}
value={`https://www.google.com`}
viewBox={`0 0 256 256`}
/>
</div>
</div>
<div className="h-[50px] w-full flex justify-center items-center">
<button
className="btn-shine w-[116px] h-[46px] text-white rounded-full text-base bg-pink flex justify-center items-center"
onClick={handlePrint}
>
Print
</button>
</div>
</div>
</div>
);
});
export default FamilyAccount
@@ -1,342 +0,0 @@
import React, {
Suspense,
forwardRef,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import QRCode from "react-qr-code";
import { useReactToPrint } from "react-to-print";
import usersService from "../../../services/UsersService";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import profile from "../../../assets/images/profile-info-profile.png";
import FamilyTasks from "./FamilyTasks";
import AssignTaskPopout from '../FamilyPopout/AssignTaskPopout'
export default function FamilyManageTabs({
className,
accountDetails,
listReload,
loader,
}) {
const [details, setDetails] = useState({
familyDetails: {
loading: false,
data: null,
},
familyTasks: {
loading: false,
data: null,
},
});
const [errMsg, setErrMsg] = useState("");
// List of tabs
const tabs = [
{
id: 1,
name: "Tasks",
},
{
id: 2,
name: "Account",
},
{
id: 3,
name: "Profile",
},
];
const [tab, setTab] = useState(tabs[0].name);
const tabHandler = (value) => {
setTab(value);
};
let [familyTaskPopout, setFamilyTaskPopout] = useState(false) // DETERMINES WHEN FAMILY ADD TASK POPOUT DISPLAYS
const familyPopUpHandler = () => { // FUNCTION TO CHANGE THE FAMILY ADD TASK POPOIUT STATE
setFamilyTaskPopout(prev => !prev)
}
// For profile uploads
const [profileImg, setProfileImg] = useState(profile);
// 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]);
}
};
// Api call
const apiCall = useMemo(() => new usersService(), []);
// function for manage family
const manageFamily = useCallback(async () => {
try {
setDetails({
familyDetails: { loading: true },
familyTasks: { loading: true },
});
let { family_uid } = accountDetails;
let reqData = { family_uid };
// the family response
const familyRes = await apiCall.ManageFamily(reqData);
const familyData = familyRes.data;
// the tasks response
const tasksRes = await apiCall.ManageTasks(reqData);
const tasksData = tasksRes.data;
// checking the internal return
if (familyData?.internal_return < 0 || tasksData?.internal_return < 0)
return;
setDetails({
familyDetails: { loading: false, data: familyData },
familyTasks: { loading: false, data: tasksData },
});
} catch (error) {
setDetails({
familyDetails: { loading: false },
familyTasks: { loading: false },
});
setErrMsg("An error occurred");
throw new Error(error);
}
}, [apiCall, accountDetails]);
useEffect(() => {
manageFamily();
}, [tab, manageFamily]);
const accountRef = useRef();
// to handle printing
const useHandlePrint = useReactToPrint({
content: () => accountRef.current,
});
return (
<div
className={`w-full bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow min-h-[520px] max-h-[600px] ${
className || ""
}`}
>
<div className="relative w-full overflow-x-auto sm:rounded-lg">
<Suspense
fallback={
<div className="h-full min-h-[500px] w-full overflow-hidden flex justify-center items-center">
<LoadingSpinner size="16" color="sky-blue" />
</div>
}
>
<div className="w-full h-full text-sm text-left text-gray-500 dark:text-gray-400 relative grid grid-cols-4 min-h-[520px]">
<div className="border-r border-[#E3E4FE] dark:border-[#a7a9b533] p-6 h-full">
<ProfileInfo
profileImg={profileImg}
profileImgInput={profileImgInput}
profileImgChangHandler={profileImgChangHandler}
browseProfileImg={browseProfileImg}
accountDetails={accountDetails}
/>
</div>
<div className="col-span-3 justify-self-end h-full w-full">
<div className="flex flex-col w-full">
<div className="w-full pr-8 flex items-center gap-1">
<ul className="flex gap-2 items-center border-b border-b-[#FAFAF] w-full">
{tabs.map(({ name, id }) => (
<li
onClick={() => tabHandler(name)}
className={`p-4 flex hover:text-purple transition-all ease-in-out items-center cursor-pointer overflow-hidden text-xl ${
tab === name
? "text-purple border-r"
: " text-thin-light-gray"
}`}
key={id}
>
<h1>{name}</h1>
</li>
))}
</ul>
<button
type="button"
onClick={familyPopUpHandler}
className="p-1 my-1 w-[100px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Add task
{/* {accountDetails?.firstname} */}
</button>
</div>
<div className="flex-[0.9] lg:min-h-[450px] h-full">
{/* Your content here */}
{tabs.map(({ name, id }) => {
return (
<div
className={`${
tab === name ? "block" : "hidden"
} h-full p-4 border border-[#dbd9d9] relative overflow-y-auto`}
key={id}
>
{name === "Tasks" && (
<FamilyTasks
className={className}
loader={details.familyTasks.loading}
familyData={details.familyTasks.data}
accountDetails={accountDetails}
/>
)}
{name === "Account" && (
<Account
familyData={details.familyDetails.data}
myRef={accountRef}
loader={details.familyDetails.loading}
handlePrint={useHandlePrint}
/>
)}
{name === "Profile" && <Profile />}
</div>
);
})}
</div>
</div>
</div>
</div>
</Suspense>
</div>
{/* FAMILY ADD TASK POPOUT */}
{familyTaskPopout &&
<AssignTaskPopout
action={familyPopUpHandler}
situation={familyTaskPopout}
familyDetails={details.familyDetails.data}
/>
}
</div>
);
}
function ProfileInfo({
profileImg,
profileImgInput,
profileImgChangHandler,
browseProfileImg,
accountDetails,
}) {
return (
<div className="flex flex-col items-center gap-6">
<div className="flex justify-center">
<div className="w-full relative">
<img
src={profileImg}
alt=""
className="sm:w-[198px] sm:h-[198px] w-[120px] h-[120px] rounded-full overflow-hidden object-cover"
/>
<input
ref={profileImgInput}
onChange={(e) => profileImgChangHandler(e)}
type="file"
className="hidden"
/>
<div
onClick={browseProfileImg}
className="w-[32px] h-[32px] absolute bottom-7 sm:right-2 right-[105px] 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"
>
<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>
</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}
</h1>
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{accountDetails?.lastname}
</h1>
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{accountDetails?.age}
</h1>
</div>
</div>
);
}
const Account = forwardRef(({ familyData, myRef, handlePrint }, ref) => {
return (
<div
className="w-full lg:min-h-[500px] h-full flex flex-col items-center justify-center"
ref={myRef}
>
<div className="update-table w-full lg:min-h-[450px] h-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow ">
<div className="flex items-center justify-around h-[380px]">
<div className="flex flex-col">
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Username:{" "}
<span className="ml-2 normal-case">
{familyData?.username ? familyData?.username : "please wait..."}
</span>
</h2>
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Pin:{" "}
<span className="ml-2 normal-case">
{familyData?.pin ? familyData?.pin : "please wait..."}
</span>
</h2>
</div>
<span className="text-5xl text-gray-400 opacity-20 font-bold">
or
</span>
<div className="max-w-[200px]">
<p className="text-xl tracking-wide mb-[15px] text-center font-bold text-dark-gray dark:text-white">
Scan the code from mobile app
</p>
<QRCode
size={256}
style={{ height: "auto", maxWidth: "100%", width: "100%" }}
value={`https://www.google.com`}
viewBox={`0 0 256 256`}
/>
</div>
</div>
<div className="h-[50px] w-full flex justify-center items-center">
<button
className="btn-shine w-[116px] h-[46px] text-white rounded-full text-base bg-pink flex justify-center items-center"
onClick={handlePrint}
>
Print
</button>
</div>
</div>
</div>
);
});
function Profile() {
return <>Profile</>;
}
@@ -0,0 +1,154 @@
import { useState } from "react";
import { PaginatedList, handlePagingFunc } from "../../Pagination";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import dataImage2 from "../../../assets/images/data-table-user-2.png";
import PendingJobsPopout from "../../jobPopout/PendingJobsPopout";
export default function FamilyPending({
familyData,
className,
accountDetails,
loader,
}) {
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
let filteredFamilyData = familyData?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
);
const [currentPage, setCurrentPage] = useState(0);
const itemsPerPage = Number(process.env.REACT_APP_ITEM_PER_PAGE);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem =
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentPendingTasks = filteredFamilyData?.slice(
indexOfFirstItem,
indexOfLastItem
);
const handlePagination = (e) => {
handlePagingFunc(e, setCurrentPage);
};
return (
<div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px] ${
className || ""
}`}
>
{filteredFamilyData && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{
<>
{currentPendingTasks.length > 0 ? (
currentPendingTasks.map((value, index) => {
let deliveryDate = value?.expire?.split(" ")[0];
let thePrice = PriceFormatter(
value?.price * 0.01,
value?.currency_code,
value?.currency
);
return (
<tr
key={index}
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">
<div className="w-full h-[60px] rounded-full overflow-hidden flex justify-center items-center flex-[0.1] max-w-[60px]">
<img
src={dataImage2}
alt="data"
className="w-full h-full"
/>
</div>
<div className="flex flex-col flex-[0.9]">
<h1 className="font-bold text-xl text-dark-gray dark:text-white">
{value.title}
</h1>
<div>{value.description}</div>
<span className="text-sm text-thin-light-gray flex items-start gap-1">
Price:{" "}
<span className="text-purple">
{thePrice}
</span>
</span>
<div className="flex items-center gap-4">
<span className="text-sm text-thin-light-gray">
Duration:{" "}
<span className="text-purple">
{" "}
{value.timeline_days} day(s)
</span>
</span>
<span className="text-sm text-thin-light-gray">
Expire:{" "}
<span className="text-purple">
{" "}
{deliveryDate}
</span>
</span>
<span className="text-sm text-thin-light-gray">
Sent to:{" "}
<span className="text-purple">
{" "}
{value.job_to}
</span>
</span>
</div>
</div>
</div>
</td>
<td className="text-right py-4 px-2">
<button
type="button"
onClick={() => {
setJobPopout({ show: true, data: value });
}}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
</button>
</td>
</tr>
);
})
) : (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
<td className="p-2">No Pending Task!</td>
</tr>
)}
</>
}
</tbody>
</table>
{/* PAGINATION BUTTON */}
<PaginatedList
onClick={handlePagination}
prev={currentPage == 0}
next={currentPage + itemsPerPage >= filteredFamilyData.length}
data={filteredFamilyData}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
{/* END OF PAGINATION BUTTON */}
</div>
)}
{/* Active Job Popout */}
{jobPopout.show && (
<PendingJobsPopout
details={jobPopout.data}
onClose={() => {
setJobPopout({ show: false, data: {} });
}}
situation={jobPopout.show}
/>
)}
{/* End of Active Job Popout */}
</div>
);
}
@@ -0,0 +1,3 @@
export default function FamilyProfile() {
return <>Profile</>;
}
@@ -0,0 +1,119 @@
import { useState } from "react";
import { handlePagingFunc, PaginatedList } from "../../Pagination";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
import SuggestTask from "../../FamilyPopup/SuggestTask";
const FamilyWaitlist = ({ familyData, className, accountDetails, loader }) => {
const [popUp, setPopUp] = useState({ show: false, data: {} });
let filteredFamilyData = familyData?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
);
const [currentPage, setCurrentPage] = useState(0);
const itemsPerPage = Number(process.env.REACT_APP_ITEM_PER_PAGE);
const indexOfFirstItem = currentPage;
const indexOfLastItem = currentPage + itemsPerPage;
const currentTask = filteredFamilyData?.slice(
indexOfFirstItem,
indexOfLastItem
);
const handlePagination = (e) => handlePagingFunc(e, setCurrentPage);
return (
<div
className={`update-table w-full bg-white dark:bg-dark-white h-full lg:min-h-[450px] overflow-hidden rounded-2xl section-shadow ${
className || ""
}`}
>
{loader ? (
<div className="w-full h-full flex justify-center items-center lg:min-h-[470px]">
<LoadingSpinner size={16} color="sky-blue" />
</div>
) : (
<>
{filteredFamilyData && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{currentTask.map((value) => {
const addedDate = value?.added.split(" ")[0];
const taskImg = require(`../../../assets/images/family/${
value?.banner || "default.jpg"
}`);
return (
<tr
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
key={value.uid}
>
<td className="py-4">
<div className="w-full flex justify-between items-center">
<div className="account-name flex space-x-4 items-center">
<div className="icon w-14 h-14 flex justify-center items-center">
<img
src={taskImg}
alt="task_img"
className="w-full object-cover"
/>
</div>
<div className="">
<p className="text-xl font-bold text-dark-gray dark:text-white mb-2 capitalize line-clamp-1">
{value.title}
</p>
<p className="text-sm text-thin-light-gray font-medium">
{value.description}
</p>
</div>
</div>
<div className="px-2">
<p className="text-sm font-bold text-dark-gray dark:text-white">
{addedDate}
</p>
<p className="text-sm text-dark-gray dark:text-white">
Status: {value.status_text}
</p>
</div>
</div>
</td>
<td className="text-right py-4 px-2">
<button
onClick={() =>
setPopUp({ show: true, data: value })
}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
View
</button>
</td>
</tr>
);
})}
</tbody>
</table>
<PaginatedList
onClick={handlePagination}
prev={currentPage === 0}
next={currentPage + itemsPerPage >= filteredFamilyData?.length}
data={filteredFamilyData}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
</div>
)}
</>
)}
{popUp.show && (
<SuggestTask
details={popUp.data}
onClose={() => {
setPopUp({ show: false, data: {} });
}}
situation={popUp.show}
/>
)}
</div>
);
};
export default FamilyWaitlist;
@@ -0,0 +1,61 @@
import React from "react";
export default function ProfileInfo({
profileImg,
profileImgInput,
profileImgChangHandler,
browseProfileImg,
accountDetails,
}) {
return (
<div className="flex flex-col items-center gap-6">
<div className="flex justify-center">
<div className="w-full relative">
<img
src={profileImg}
alt=""
className="sm:w-[198px] sm:h-[198px] w-[120px] h-[120px] rounded-full overflow-hidden object-cover"
/>
<input
ref={profileImgInput}
onChange={(e) => profileImgChangHandler(e)}
type="file"
className="hidden"
/>
<div
onClick={browseProfileImg}
className="w-[32px] h-[32px] absolute bottom-7 sm:right-2 right-[105px] 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"
>
<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>
</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}
</h1>
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{accountDetails?.lastname}
</h1>
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{accountDetails?.age}
</h1>
</div>
</div>
);
}
+15
View File
@@ -0,0 +1,15 @@
import FamilyAccount from "./FamilyAccount";
import FamilyProfile from "./FamilyProfile";
import FamilyTasks from "./FamilyTasks";
import FamilyWaitlist from "./FamilyWaitlist";
import FamilyPending from "./FamilyPending";
import ProfileInfo from "./ProfileInfo";
export {
FamilyAccount,
FamilyProfile,
FamilyTasks,
FamilyWaitlist,
FamilyPending,
ProfileInfo,
};
+39 -21
View File
@@ -1,4 +1,5 @@
import React, { useMemo, useState } from "react"; import { useState } from "react";
import { useLocation } from "react-router-dom";
import ModalCom from "../Helpers/ModalCom"; import ModalCom from "../Helpers/ModalCom";
import { Form, Formik } from "formik"; import { Form, Formik } from "formik";
import InputCom from "../Helpers/Inputs/InputCom"; import InputCom from "../Helpers/Inputs/InputCom";
@@ -6,6 +7,7 @@ import usersService from "../../services/UsersService";
const DEFAULT_IMAGE = require("../../assets/images/family/default.jpg"); const DEFAULT_IMAGE = require("../../assets/images/family/default.jpg");
const SuggestTask = ({ details, onClose, situation }) => { const SuggestTask = ({ details, onClose, situation }) => {
const { pathname, state } = useLocation();
const [submitTask, setSubmitTask] = useState({ const [submitTask, setSubmitTask] = useState({
loading: false, loading: false,
msg: "", msg: "",
@@ -16,12 +18,13 @@ const SuggestTask = ({ details, onClose, situation }) => {
const initialValues = { const initialValues = {
title: details?.title || "", title: details?.title || "",
description: details?.description || "", description: details?.description || "",
banner: details?.banner,
}; };
const apiCall = new usersService(); const apiCall = new usersService();
const handleSubmit = async (values) => { const handleSubmit = async (values) => {
if(!values.title && !values.description) return; if (!values.title && !values.description) return;
try { try {
setSubmitTask({ loading: true }); setSubmitTask({ loading: true });
const reqData = { ...values }; const reqData = { ...values };
@@ -39,12 +42,16 @@ const SuggestTask = ({ details, onClose, situation }) => {
throw new Error("Error Occurred", error); throw new Error("Error Occurred", error);
} }
}; };
// console.log("state >-->>", state);
return ( return (
<ModalCom action={onClose} situation={situation}> <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"> <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"> <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"> <h1 className="text-base md:text-lg font-bold text-dark-gray dark:text-white tracking-wide">
Suggest to Parent {pathname === "/manage-family"
? `${state?.firstname}'s Suggested Task`
: "Suggest to Parent"}
</h1> </h1>
<button <button
type="button" type="button"
@@ -92,10 +99,17 @@ const SuggestTask = ({ details, onClose, situation }) => {
{/* Title */} {/* Title */}
<div className="field w-full mb-[15px]"> <div className="field w-full mb-[15px]">
<InputCom <InputCom
fieldClass="px-6" fieldClass={
pathname === "/manage-family" ? "px-2" : "px-6"
}
label="Title" label="Title"
labelClass="tracking-wide" labelClass="tracking-wide"
inputBg="bg-slate-100" inputBg={
pathname === "/manage-family"
? "bg-white"
: "bg-slate-100"
}
inputClass="disabled:cursor-default"
type="text" type="text"
name="title" name="title"
disable={details?.title} disable={details?.title}
@@ -127,7 +141,11 @@ const SuggestTask = ({ details, onClose, situation }) => {
<textarea <textarea
id="description" id="description"
rows="5" rows="5"
className={`input-field px-3 pt-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[130px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[10px]`} className={`input-field pt-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[130px] ${
pathname === "/manage-family"
? "px-2"
: "bg-slate-100 px-3 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[10px]"
}`}
style={{ resize: "none" }} style={{ resize: "none" }}
name="description" name="description"
value={props.values.description} value={props.values.description}
@@ -146,21 +164,21 @@ const SuggestTask = ({ details, onClose, situation }) => {
> >
<span className="text-gradient"> Cancel</span> <span className="text-gradient"> Cancel</span>
</button> </button>
{pathname !== "/manage-family" && (
<button <button
type="submit" type="submit"
disabled={props.isSubmitting} disabled={props.isSubmitting}
className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full" className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full"
> >
{submitTask.loading {submitTask.loading
? "Submitting Task" ? "Submitting Task"
: submitTask.state == "success" : submitTask.state == "success"
? "Task Submitted" ? "Task Submitted"
: submitTask.state == "bad" : submitTask.state == "bad"
? "An Error Occurred" ? "An Error Occurred"
: "Send to Parents"} : "Send to Parents"}
</button> </button>
{/* )} */} )}
</div> </div>
</div> </div>
</Form> </Form>
@@ -76,7 +76,7 @@ export default function InputCom({
)} )}
</div> </div>
<div <div
className={`input-wrapper border w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base ${inputClass}`} className={`input-wrapper w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-base ${inputClass ? inputClass : "text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] border"}`}
> >
<input <input
placeholder={placeholder} placeholder={placeholder}
+10 -6
View File
@@ -1,20 +1,22 @@
import React, { useRef } from "react"; import React, { useRef } from "react";
import ProductCardStyleOne from "../Cards/ProductCardStyleOne"; //import ProductCardStyleOne from "../Cards/ProductCardStyleOne";
import Icons from "../Helpers/Icons"; import Icons from "../Helpers/Icons";
import SliderCom from "../Helpers/SliderCom"; import SliderCom from "../Helpers/SliderCom";
import FamilyActiveJobsCard from "../Cards/FamilyActiveJobsCard";
export default function FamilyActiveLSlde({ className, trending }) { export default function FamilyActiveLSlde({ className, trending }) {
const settings = { const settings = {
arrows: false, arrows: false,
slidesToShow: 4, slidesToShow: 3,
slidesToScroll: 4, slidesToScroll: 3,
infinite: true, infinite: trending?.length > 3,
responsive: [ responsive: [
{ {
breakpoint: 1025, breakpoint: 1025,
settings: { settings: {
slidesToShow: 3, slidesToShow: 3,
slidesToScroll: 3, slidesToScroll: 3,
infinite: trending?.length > 3,
}, },
}, },
{ {
@@ -22,6 +24,7 @@ export default function FamilyActiveLSlde({ className, trending }) {
settings: { settings: {
slidesToShow: 2, slidesToShow: 2,
slidesToScroll: 2, slidesToScroll: 2,
infinite: trending?.length > 2,
}, },
}, },
{ {
@@ -29,6 +32,7 @@ export default function FamilyActiveLSlde({ className, trending }) {
settings: { settings: {
slidesToShow: 1, slidesToShow: 1,
slidesToScroll: 1, slidesToScroll: 1,
infinite: trending?.length > 1,
}, },
}, },
], ],
@@ -89,12 +93,12 @@ export default function FamilyActiveLSlde({ className, trending }) {
</div> </div>
</div> </div>
{/* trending products */} {/* trending products */}
<div className="trending-products relative w-full"> <div className="trending-products slider-left relative w-full rounded-2xl p-[10px] bg-alice-blue">
<SliderCom selector={trendingSlider} settings={settings}> <SliderCom selector={trendingSlider} settings={settings}>
{trending && {trending &&
trending.length > 0 && trending.length > 0 &&
trending.map((item) => ( trending.map((item) => (
<ProductCardStyleOne key={item.id} datas={item} /> <FamilyActiveJobsCard key={item.id} datas={item} />
))} ))}
</SliderCom> </SliderCom>
</div> </div>
+9 -4
View File
@@ -6,16 +6,21 @@ import FamilyActiveLSlde from "./FamilyActiveLSlde";
import ParentWaiting from "../MyPendingJobs/ParentWaiting"; import ParentWaiting from "../MyPendingJobs/ParentWaiting";
import MyOffersFamilyTable from "../MyTasks/MyOffersFamilyTable"; import MyOffersFamilyTable from "../MyTasks/MyOffersFamilyTable";
export default function FamilyDash(props) { export default function FamilyDash({familyOffers, MyActiveJobList}) {
console.log("PROPS IN FAMILY DASH->", props); console.log("PROPS IN FAMILY DASH->", familyOffers);
const trending = datas.datas; const trending = MyActiveJobList;
return ( return (
<div> <div>
<div className="home-page-wrapper"> <div className="home-page-wrapper">
{/* <CommonHead commonHeadData={props.commonHeadData} /> */} {/* <CommonHead commonHeadData={props.commonHeadData} /> */}
<MyOffersFamilyTable MyActiveOffersList={trending} className="mb-10" /> {familyOffers && familyOffers.length > 0 &&
<MyOffersFamilyTable familyOffers={familyOffers} className="mb-10" />
}
{trending && trending.length > 0 &&
<FamilyActiveLSlde trending={trending} className="mb-10" /> <FamilyActiveLSlde trending={trending} className="mb-10" />
}
{/*<TopSellerTopBuyerSliderSection className="mb-10" />*/} {/*<TopSellerTopBuyerSliderSection className="mb-10" />*/}
<ParentWaiting className="mb-10" /> <ParentWaiting className="mb-10" />
</div> </div>
+19 -3
View File
@@ -8,15 +8,26 @@ import FullAccountDash from "./FullAccountDash";
export default function Home(props) { export default function Home(props) {
console.log("PROPS IN HOME->", props); console.log("PROPS IN HOME->", props);
const userApi = new usersService();
const { commonHeadBanner } = useSelector((state) => state.commonHeadBanner);
let [nextDueTask, setNextDueTask] = useState({}); let [nextDueTask, setNextDueTask] = useState({});
const [MyOffersList, setMyOffersList] = useState([]); const [MyOffersList, setMyOffersList] = useState([]);
const userApi = new usersService();
const { userDetails } = useSelector((state) => state?.userDetails); const { userDetails } = useSelector((state) => state?.userDetails);
const { commonHeadBanner } = useSelector((state) => state.commonHeadBanner); const [MyActiveJobList, setMyActiveJobList] = useState([]); // STATE TO HOLD ACTIVE/CURRENT TASKS
const getMyActiveJobList = async () => { // FUNCTION TO POPULATE ACTIVE/CURRENT TASK LIST
try {
const res = await userApi.getMyActiveTaskList();
setMyActiveJobList(res?.data?.result_list);
} catch (error) {
setMyActiveJobList([]);
console.log("Error getting tasks");
}
};
// FUNCTION TO GET DASH DATA TO DETERMINE CURRENT TASK DUE TIME // FUNCTION TO GET DASH DATA TO DETERMINE CURRENT TASK DUE TIME
const getHomeDate = () => { const getHomeDate = () => {
@@ -50,6 +61,10 @@ export default function Home(props) {
fetchData(); fetchData();
}, []); }, []);
useEffect(() => {
getMyActiveJobList();
}, []);
return ( return (
<Layout> <Layout>
<div className="home-page-wrapper"> <div className="home-page-wrapper">
@@ -58,6 +73,7 @@ export default function Home(props) {
account={userDetails} account={userDetails}
commonHeadData={props.bannerList} commonHeadData={props.bannerList}
familyOffers={MyOffersList} familyOffers={MyOffersList}
MyActiveJobList={MyActiveJobList}
/> />
) : userDetails && userDetails?.account_type == "FULL" ? ( ) : userDetails && userDetails?.account_type == "FULL" ? (
<FullAccountDash <FullAccountDash
+28 -15
View File
@@ -1,8 +1,8 @@
import React, { useEffect, useMemo, useState } from "react"; import React, { useEffect, useMemo, useState } from "react";
import DataIteration from "../Helpers/DataIteration"; import DataIteration from "../Helpers/DataIteration";
import AvailableJobsCard from "../Cards/AvailableJobsCard"; import AvailableJobsCard from "../Cards/AvailableJobsCard";
import ListView from '../../assets/images/list-view.png' import ListView from "../../assets/images/list-view.png";
import GridView from '../../assets/images/grid-view.svg' import GridView from "../../assets/images/grid-view.svg";
import SelectBox from "../Helpers/SelectBox"; import SelectBox from "../Helpers/SelectBox";
export default function MainSection({ export default function MainSection({
@@ -17,7 +17,7 @@ export default function MainSection({
); );
const [tab, setTab] = useState(Object.keys(marketCategories)[0]); const [tab, setTab] = useState(Object.keys(marketCategories)[0]);
let [contentDisplay, setContentDisplay] = useState('grid') // STATE TO HOLD LIST VIEW STYLE let [contentDisplay, setContentDisplay] = useState("grid"); // STATE TO HOLD LIST VIEW STYLE
// Convert to array in order to map // Convert to array in order to map
const mappedArray = Object.entries(marketCategories).map(([key, value]) => { const mappedArray = Object.entries(marketCategories).map(([key, value]) => {
@@ -29,8 +29,8 @@ export default function MainSection({
setTab(value); setTab(value);
}; };
// Handles the category selection on mobile view // Handles the category selection on mobile view
const handleSetCategory = (value) => { const handleSetCategory = (value) => {
for (let i in marketCategories) { for (let i in marketCategories) {
if (marketCategories[i] == value) { if (marketCategories[i] == value) {
setTab(i); setTab(i);
@@ -57,7 +57,7 @@ export default function MainSection({
<div className="hidden lg:flex md:space-x-8 space-x-2"> <div className="hidden lg:flex md:space-x-8 space-x-2">
{mappedArray.map(({ key, value }) => ( {mappedArray.map(({ key, value }) => (
<span <span
key={key} key={key}
onClick={() => tabHandler(key)} onClick={() => tabHandler(key)}
className={`md:text-[18px] text-md text-dark-gray dark:text-white hover:text-pink border-b hover:border-pink font-medium cursor-pointer ${ className={`md:text-[18px] text-md text-dark-gray dark:text-white hover:text-pink border-b hover:border-pink font-medium cursor-pointer ${
tab === key tab === key
@@ -76,30 +76,43 @@ export default function MainSection({
datas={Object.values(marketCategories)} datas={Object.values(marketCategories)}
className="Update-table-dropdown" className="Update-table-dropdown"
contentBodyClasses="w-auto min-w-max" contentBodyClasses="w-auto min-w-max"
position='left' position="left"
/> />
</div> </div>
</div> </div>
{/* contentDisplay toggler */} {/* contentDisplay toggler */}
<div className="p-2 w-[35px] h-[35px] bg-white dark:bg-slate-200 rounded-lg"> <div className="p-2 w-[35px] h-[35px] bg-white dark:bg-slate-200 rounded-lg">
<img <img
title={contentDisplay=='grid'? 'list view' : 'grid view'} title={contentDisplay == "grid" ? "list view" : "grid view"}
onClick={()=>setContentDisplay((prev)=>prev=='grid'? 'list' : 'grid')} onClick={() =>
src={contentDisplay=='grid'? ListView : GridView} setContentDisplay((prev) => (prev == "grid" ? "list" : "grid"))
className="w-full h-full cursor-pointer" alt="view" }
/> src={contentDisplay == "grid" ? ListView : GridView}
className="w-full h-full cursor-pointer"
alt="view"
/>
</div> </div>
{/* end of contentDisplay toggler */} {/* end of contentDisplay toggler */}
</div> </div>
<div className="filter-navigate-content w-full min-h-screen"> <div className="filter-navigate-content w-full min-h-screen">
<div className={contentDisplay == 'grid' ? 'grid lg:grid-cols-3 sm:grid-cols-2 gap-[30px]' : 'w-full'}> <div
className={
contentDisplay == "grid"
? "grid lg:grid-cols-3 sm:grid-cols-2 gap-[30px]"
: "w-full"
}
>
<DataIteration <DataIteration
datas={products} datas={products}
startLength={process.env.REACT_APP_ZERO_STATE} startLength={process.env.REACT_APP_ZERO_STATE}
endLength={products?.length} endLength={products?.length}
> >
{({ datas }) => ( {({ datas }) => (
<AvailableJobsCard contentDisplay={contentDisplay} key={datas.id} datas={datas} /> <AvailableJobsCard
contentDisplay={contentDisplay}
key={datas.id}
datas={datas}
/>
)} )}
</DataIteration> </DataIteration>
</div> </div>
@@ -95,7 +95,7 @@ export default function ParentWaitingTable() {
<div className="w-full flex justify-between items-center"> <div className="w-full flex justify-between items-center">
<div className="account-name flex space-x-4 items-center"> <div className="account-name flex space-x-4 items-center">
<div className="icon w-14 h-14 flex justify-center items-center"> <div className="icon w-14 h-14 flex justify-center items-center">
<img src={Image} alt="" className="" /> <img src={Image} alt="" className="w-full h-full" />
</div> </div>
<div className=""> <div className="">
<p className="text-xl font-bold text-dark-gray dark:text-white mb-2 capitalize line-clamp-1"> <p className="text-xl font-bold text-dark-gray dark:text-white mb-2 capitalize line-clamp-1">
@@ -107,12 +107,12 @@ export default function ParentWaitingTable() {
</p> </p>
</div> </div>
</div> </div>
<div className="px-2"> <div className="px-2 self-end">
<p className="text-sm font-bold text-dark-gray dark:text-white"> <p className="text-sm font-bold text-dark-gray dark:text-white">
{new Date(item.added).toLocaleString().split(',')[0]} {new Date(item.added).toLocaleString().split(',')[0]}
</p> </p>
<p className="text-sm text-dark-gray dark:text-white">Status: {item.status}</p> <p className="text-xs py-1.5 w-[50px] tracking-wide rounded-full bg-gold text-white flex justify-center items-center">{item.status_text}</p>
</div> </div>
</div> </div>
</li> </li>
+2 -1
View File
@@ -5,6 +5,7 @@ import { handlePagingFunc } from "../Pagination/HandlePagination";
import LoadingSpinner from "../Spinners/LoadingSpinner"; import LoadingSpinner from "../Spinners/LoadingSpinner";
import { useNavigate, useLocation } from "react-router-dom"; import { useNavigate, useLocation } from "react-router-dom";
import { PriceFormatter } from "../Helpers/PriceFormatter"; import { PriceFormatter } from "../Helpers/PriceFormatter";
import localImgLoad from "../../lib/localImgLoad";
const noTasksBg = require("../../assets/images/no-task-background.jpg"); const noTasksBg = require("../../assets/images/no-task-background.jpg");
const noFamilyTasksBg = require("../../assets/images/family-no-task-background.jpg"); const noFamilyTasksBg = require("../../assets/images/family-no-task-background.jpg");
@@ -80,7 +81,7 @@ export default function MyJobTable({ className, ActiveJobList, Account }) {
<div className="flex space-x-2 items-center"> <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"> <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 <img
src={dataImage1} src={localImgLoad(`images/taskbanners/${task?.banner}`)}
alt="data" alt="data"
className="w-full h-full" className="w-full h-full"
/> />
+94 -135
View File
@@ -1,161 +1,120 @@
import { useRef, useState } from "react"; import { useRef, useState } from "react";
import Icons from "../Helpers/Icons"; import Icons from "../Helpers/Icons";
import SliderCom from "../Helpers/SliderCom"; import SliderCom from "../Helpers/SliderCom";
import OfferJobPopout from "../jobPopout/OfferJobPopout"; import OfferJobPopout from "../jobPopout/OfferJobPopout";
import LoadingSpinner from "../Spinners/LoadingSpinner"; import FamilyOfferCard from "../Cards/FamilyOfferCard";
import { PriceFormatter } from "../Helpers/PriceFormatter";
export default function MyOffersFamilyTable({ className, MyActiveOffersList }) { 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 let [offerPopout, setOfferPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
const settings = { const settings = {
arrows: false, arrows: false,
dots: false, slidesToShow: 3,
infinite: MyActiveOffersList?.result_list?.length > 4, slidesToScroll: 3,
autoplay: true, infinite: familyOffers?.length > 3,
slidesToShow: 4,
slidesToScroll: 1,
responsive: [ responsive: [
{ {
breakpoint: 426, breakpoint: 1025,
settings: { settings: {
slidesToShow: 2, slidesToShow: 3,
slidesToScroll: 1, slidesToScroll: 3,
infinite: MyActiveOffersList?.result_list?.length > 2, infinite: familyOffers?.length > 3,
},
},
{
breakpoint: 769,
settings: {
slidesToShow: 2,
slidesToScroll: 2,
infinite: familyOffers?.length > 2,
},
},
{
breakpoint: 619,
settings: {
slidesToShow: 1,
slidesToScroll: 1,
infinite: familyOffers?.length > 1,
},
}, },
},
], ],
};
console.log("YES WE SEE OFFERS", familyOffers);
const trendingSlider = useRef(null);
const prevHandler = () => {
trendingSlider.current.slickPrev();
};
const nextHandler = () => {
trendingSlider.current.slickNext();
}; };
console.log("YES WE SEE OFFERS", MyActiveOffersList); if (!familyOffers || familyOffers?.result_list?.length == 0) {
const sellSlider = useRef(null);
//const buySlider = useRef(null);
const prevHandler = (value) => {
if (value === "sell") {
sellSlider.current.slickPrev();
}
// if (value === "buy") {
// buySlider.current.slickPrev();
// }
};
const nextHandler = (value) => {
if (value === "sell") {
sellSlider.current.slickNext();
}
// if (value === "buy") {
// buySlider.current.slickNext();
// }
};
if (!MyActiveOffersList || MyActiveOffersList?.result_list?.length == 0) {
return ""; // want blank or no appear when no items return ""; // want blank or no appear when no items
} }
return ( return (
<> <>
<div className={`top-seller-top-buyer-wrapper ${className || ""}`}> <div className={`top-seller-top-buyer-wrapper ${className || ""}`}>
<div className="top-seller-top-buyer-wrapper-container"> <div className={`trending-section w-full px-2 sm:px-0 ${className || ""}`}>
<div className="main-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4"> {/* heading */}
<div className="lg:w-2/2 w-full mb-10 lg:mb-0 sm:p-8 p-4 bg-white dark:bg-dark-white rounded-2xl section-shadow"> <div className="flex justify-between items-center mb-6">
<div className="heading flex justify-between items-center mb-4"> <div>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-wide"> <h1 className="text-26 font-bold text-dark-gray dark:text-white">Ready to Start?</h1>
You Have Task(s) Waiting For You
</h1>
<div className="slider-btns flex space-x-4">
<button
onClick={() => nextHandler("sell")}
type="button"
className="transform rotate-180 text-dark-gray dark:text-white dark:opacity-25"
>
<Icons name="arrows" />
</button>
<button
onClick={() => prevHandler("sell")}
type="button"
className="transform rotate-180"
>
<div className=" text-dark-gray dark:text-white">
<svg
width="11"
height="19"
viewBox="0 0 11 19"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9.09766 1.1499L1.13307 9.11449L9.09766 17.0791"
stroke="url(#paint0_linear_220_23410)"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<defs>
<linearGradient
id="paint0_linear_220_23410"
x1="9.09766"
y1="1.1499"
x2="-4.2474"
y2="7.96749"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F539F8" />
<stop offset="0.416763" stopColor="#C342F9" />
<stop offset="1" stopColor="#5356FB" />
</linearGradient>
</defs>
</svg>
</div>
</button>
</div> </div>
</div> <div className="slider-btns flex space-x-3">
<div className="slider-content"> <button onClick={nextHandler} type="button">
<SliderCom settings={settings} selector={sellSlider}> <div className="trending-slider-left-btn relative text-white w-10 h-10 flex justify-center items-center rounded-full overflow-hidden">
{MyActiveOffersList && <svg
MyActiveOffersList?.result_list?.length > 0 && width="11"
MyActiveOffersList?.result_list?.map((value, index) => { height="19"
let thePrice = PriceFormatter( viewBox="0 0 11 19"
value?.price * 0.01, fill="none"
value?.currency_code, xmlns="http://www.w3.org/2000/svg"
value?.currency
);
return (
<div className="item" key={index}>
<div className="offer-slide-item flex flex-col justify-between items-center">
{/* title */}
<div className="flex justify-center">
<p className="text-xl text-dark-gray dark:text-white font-bold mb-2">
{value.title}
</p>
</div>
{/* username */}
<div className="flex flex-col justify-center my-1">
<p className="text-xs text-thin-light-gray">
{value.timeline_days} Days
</p>
<div className="my-2 flex space-x-1 items-center text-purple text-xs">
<span>{thePrice}</span>
</div>
</div>
<button
type="button"
onClick={() => {
setOfferPopout({
show: true,
data: {...value, thePrice },
});
}}
className="w-20 h-11 self-center btn-gradient text-base rounded-full text-white"
> >
Start Task <path
</button> d="M9.09766 1.1499L1.13307 9.11449L9.09766 17.0791"
</div> stroke="url(#paint0_linear_220_23410)"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<defs>
<linearGradient
id="paint0_linear_220_23410"
x1="9.09766"
y1="1.1499"
x2="-4.2474"
y2="7.96749"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F539F8" />
<stop offset="0.416763" stopColor="#C342F9" />
<stop offset="1" stopColor="#5356FB" />
</linearGradient>
</defs>
</svg>
</div> </div>
); </button>
})} <button onClick={prevHandler} type="button">
</SliderCom> <div className="trending-slider-right-btn primary-gradient text-white w-10 h-10 relative flex justify-center items-center rounded-full ">
</div> <Icons name="arrows" />
</div>
</button>
</div>
</div>
{/* trending products */}
<div className="trending-products slider-left relative w-full rounded-2xl p-[10px] bg-alice-blue">
<SliderCom selector={trendingSlider} settings={settings}>
{familyOffers &&
familyOffers.length > 0 &&
familyOffers.map((item) => {
return (
<FamilyOfferCard key={item.id} datas={item} setOfferPopout={setOfferPopout} />
)
})}
</SliderCom>
</div> </div>
</div>
</div> </div>
{/* Offer Job Popout */} {/* Offer Job Popout */}
+4
View File
@@ -0,0 +1,4 @@
import { handlePagingFunc } from "./HandlePagination";
import PaginatedList from "./PaginatedList";
export { handlePagingFunc, PaginatedList };
+7 -7
View File
@@ -6,8 +6,8 @@
"profile_img": "profile.png", "profile_img": "profile.png",
"price": "75,320 ETH", "price": "75,320 ETH",
"thumbnil": "tranding-1.jpg", "thumbnil": "tranding-1.jpg",
"remaing": "2023-03-04 4:00:00", "remaing": "2023-08-04 4:00:00",
"title": "laborum cupidatat sit" "title": "Wash Dishes"
}, },
{ {
"id": 1, "id": 1,
@@ -15,8 +15,8 @@
"profile_img": "profile.png", "profile_img": "profile.png",
"price": "75,320 ETH", "price": "75,320 ETH",
"thumbnil": "tranding-2.jpg", "thumbnil": "tranding-2.jpg",
"remaing": "2023-03-04 4:00:00", "remaing": "2023-07-24 4:00:00",
"title": "velit occaecat voluptate" "title": "Wash Planes"
}, },
{ {
"id": 2, "id": 2,
@@ -24,7 +24,7 @@
"profile_img": "profile.png", "profile_img": "profile.png",
"price": "75,320 ETH", "price": "75,320 ETH",
"thumbnil": "tranding-3.jpg", "thumbnil": "tranding-3.jpg",
"remaing": "2023-03-04 4:00:00", "remaing": "2023-07-17 4:00:00",
"title": "est reprehenderit amet" "title": "est reprehenderit amet"
}, },
{ {
@@ -33,7 +33,7 @@
"profile_img": "profile.png", "profile_img": "profile.png",
"price": "75,320 ETH", "price": "75,320 ETH",
"thumbnil": "tranding-4.jpg", "thumbnil": "tranding-4.jpg",
"remaing": "2023-03-04 4:00:00", "remaing": "2023-08-04 4:00:00",
"title": "velit tempor nostrud" "title": "velit tempor nostrud"
}, },
{ {
@@ -42,7 +42,7 @@
"profile_img": "profile.png", "profile_img": "profile.png",
"price": "75,320 ETH", "price": "75,320 ETH",
"thumbnil": "tranding-4.jpg", "thumbnil": "tranding-4.jpg",
"remaing": "2023-03-04 4:00:00", "remaing": "2023-09-04 4:00:00",
"title": "adipisicing sit nostrud" "title": "adipisicing sit nostrud"
}, },
{ {
+5
View File
@@ -927,3 +927,8 @@ TODO: Responsive ===========================
.ebu-animate-shake { .ebu-animate-shake {
animation: shake 0.3s linear 3; animation: shake 0.3s linear 3;
} }
/* TO REMOVE SLIDER COMPONENT FROM CENTRALIZED */
.slider-left .slick-slider .slick-track{
margin: 0;
}
+34 -7
View File
@@ -251,6 +251,31 @@ class usersService {
return this.postAuxEnd("/jobmanageractive", postData); return this.postAuxEnd("/jobmanageractive", postData);
} }
// Family Waitlist
ManageFamilyWaitlist() {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 13010,
limit: 30,
offset: 0,
};
return this.postAuxEnd("/familywaitingtasks", postData);
}
ManageFamilyPending() {
var postData = {
uuid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
page: 0,
offset: 0,
limit: 100,
};
return this.postAuxEnd("/jobmanageroffers", postData);
}
// Task for the person doing the job // Task for the person doing the job
getMyActiveTaskList() { getMyActiveTaskList() {
var postData = { var postData = {
@@ -312,8 +337,9 @@ class usersService {
}; };
return this.postAuxEnd("/jobmanageroffers", postData); return this.postAuxEnd("/jobmanageroffers", postData);
} }
// //
getResourceList() { // jobs you have shown inteterest in getResourceList() {
// jobs you have shown inteterest in
var postData = { var postData = {
uuid: localStorage.getItem("uid"), uuid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"), member_id: localStorage.getItem("member_id"),
@@ -324,7 +350,8 @@ class usersService {
}; };
return this.postAuxEnd("/resources", postData); return this.postAuxEnd("/resources", postData);
} }
getMyWiatingJobList() { // jobs you have shown inteterest in getMyWiatingJobList() {
// jobs you have shown inteterest in
var postData = { var postData = {
uuid: localStorage.getItem("uid"), uuid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"), member_id: localStorage.getItem("member_id"),
@@ -335,7 +362,7 @@ class usersService {
}; };
return this.postAuxEnd("/waitinginterest", postData); return this.postAuxEnd("/waitinginterest", postData);
} }
getMyJobList(reqData={}) { getMyJobList(reqData = {}) {
var postData = { var postData = {
uuid: localStorage.getItem("uid"), uuid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"), member_id: localStorage.getItem("member_id"),
@@ -343,7 +370,7 @@ class usersService {
page: 0, page: 0,
offset: 0, offset: 0,
limit: 100, limit: 100,
...reqData ...reqData,
}; };
return this.postAuxEnd("/jobmanagerlist", postData); return this.postAuxEnd("/jobmanagerlist", postData);
} }
@@ -818,7 +845,7 @@ class usersService {
member_id: localStorage.getItem("member_id"), member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"), sessionid: localStorage.getItem("session_token"),
action: 13025, action: 13025,
...reqData ...reqData,
}; };
return this.postAuxEnd("/assigntask", postData); return this.postAuxEnd("/assigntask", postData);
} }
@@ -831,7 +858,7 @@ class usersService {
sessionid: localStorage.getItem("session_token"), sessionid: localStorage.getItem("session_token"),
limit: 30, limit: 30,
offset: 0, offset: 0,
action: 13010 action: 13010,
}; };
return this.postAuxEnd("/familysuggestlist", postData); return this.postAuxEnd("/familysuggestlist", postData);
} }
+2 -1
View File
@@ -17,7 +17,8 @@ module.exports = {
"white-opacity": "#7B7EFC", "white-opacity": "#7B7EFC",
"dark-white":"#1D1F2F", "dark-white":"#1D1F2F",
"dark-light-purple":"#5356fb29", "dark-light-purple":"#5356fb29",
'sky-blue': '#3a8fc3' 'sky-blue': '#3a8fc3',
'alice-blue': '#f0f8ff'
}, },
}, },
}, },