Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9032b36b13 | |||
| f291382786 | |||
| 69dcee859d | |||
| fe295dc775 | |||
| 044c8edf7d | |||
| c22cffd167 | |||
| 6d77bfa1b0 | |||
| 60cc6f375e | |||
| e6684c56fd | |||
| 4f675b30ef | |||
| 00c7f65092 | |||
| 9a978b1913 | |||
| 23f8346734 | |||
| 585632c1e1 | |||
| 11ee1195c2 | |||
| c44f456cc1 | |||
| b769e4a4ba | |||
| a6ff06e2b4 | |||
| 0f801b2408 | |||
| c26f2b725a | |||
| ee94cbc92c | |||
| dccbe76c5b | |||
| 735d13b440 | |||
| 7f83cd5cc6 | |||
| 71ee75072d | |||
| 265f2b7655 | |||
| 4d264fa18e | |||
| cd6ab8b504 | |||
| 8c81073443 | |||
| 14566de037 | |||
| 69d711eddc | |||
| 159623eb69 | |||
| da26d5c24a | |||
| 40850b7342 | |||
| 28098169b9 | |||
| 2ff6ed777f | |||
| 723a2a09ab | |||
| 68482c7956 | |||
| 225e3ae34c | |||
| 251d5abf10 | |||
| 22314a61c5 | |||
| a9cf3c9d22 | |||
| 01bf8a4c52 |
@@ -15,6 +15,9 @@ REACT_APP_APPSITE="https://myfitapp.mermsemr.com"
|
||||
REACT_APP_AUX_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
|
||||
REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
|
||||
|
||||
#SOCKETS ENDS
|
||||
REACT_APP_PRIMARY_SOCKET="https://socket-dev.wrenchboard.com"
|
||||
|
||||
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
|
||||
|
||||
REACT_APP_SESSION_EXPIRE_MINUTES=600000
|
||||
|
||||
@@ -15,6 +15,9 @@ REACT_APP_APPSITE="https://myfitapp.mermsemr.com"
|
||||
REACT_APP_AUX_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
|
||||
REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
|
||||
|
||||
#SOCKETS ENDS
|
||||
REACT_APP_PRIMARY_SOCKET="https://socket-dev.wrenchboard.com"
|
||||
|
||||
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
|
||||
|
||||
REACT_APP_SESSION_EXPIRE_MINUTES=600000
|
||||
|
||||
@@ -15,6 +15,9 @@ REACT_APP_APPSITE="https://myfitapp.mermsemr.com"
|
||||
REACT_APP_AUX_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/en/wrench/api/v1"
|
||||
REACT_APP_USERS_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/en/wrench/api/v1"
|
||||
|
||||
#SOCKETS ENDS
|
||||
REACT_APP_PRIMARY_SOCKET="https://socket.wrenchboard.com"
|
||||
|
||||
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
|
||||
|
||||
REACT_APP_SESSION_EXPIRE_MINUTES=600000
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"react-to-print": "^2.14.12",
|
||||
"react-toastify": "^9.0.1",
|
||||
"redux": "^4.2.0",
|
||||
"socket.io-client": "^4.4.1",
|
||||
"slick-carousel": "^1.8.1",
|
||||
"web-vitals": "^1.0.1",
|
||||
"yup": "^1.1.1"
|
||||
|
||||
+11
-8
@@ -2,19 +2,22 @@ import { Navigate, useLocation } from "react-router-dom";
|
||||
import Routers from "./Routers";
|
||||
import Toaster from "./components/Helpers/Toaster";
|
||||
import Default from "./components/Partials/Default";
|
||||
import SocketIOContextProvider from "./components/Contexts/SocketIOContext";
|
||||
|
||||
function App() {
|
||||
const { pathname } = useLocation();
|
||||
return (
|
||||
<Default>
|
||||
<>
|
||||
{pathname.startsWith("/@") ? (
|
||||
<Navigate to="/app" replace={true} />
|
||||
) : (
|
||||
<Routers />
|
||||
)}
|
||||
<Toaster />
|
||||
</>
|
||||
<SocketIOContextProvider>
|
||||
<>
|
||||
{pathname.startsWith("/@") ? (
|
||||
<Navigate to="/app" replace={true} />
|
||||
) : (
|
||||
<Routers />
|
||||
)}
|
||||
<Toaster />
|
||||
</>
|
||||
</SocketIOContextProvider>
|
||||
</Default>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
export default function CustomBreadcrumb({title, breadcrumb}) {
|
||||
export default function CustomBreadcrumb({ title, breadcrumb }) {
|
||||
return (
|
||||
<div className="">
|
||||
<h3 className="text-26 font-bold text-dark-gray dark:text-white">{title}</h3>
|
||||
<nav aria-label="breadcrumb" className='text-base text-dark-gray dark:text-white flex items-center'>
|
||||
{breadcrumb.map((value, index) => (
|
||||
<p key={index}>
|
||||
<Link className={`${value.active ? 'opacity-60' : ''}`} to={value.link}>{value.title}</Link>
|
||||
{index != breadcrumb.length - 1 ?
|
||||
<span className='px-1'>/</span>
|
||||
:
|
||||
null
|
||||
}
|
||||
</p>
|
||||
))}
|
||||
</nav>
|
||||
<h3 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
{title}
|
||||
</h3>
|
||||
<nav
|
||||
aria-label="breadcrumb"
|
||||
className="text-base text-dark-gray dark:text-white flex items-center"
|
||||
>
|
||||
{breadcrumb.map((value, index) => (
|
||||
<React.Fragment key={index}>
|
||||
<Link className={value.active ? "opacity-60" : ""} to={value.link}>
|
||||
{value.title}
|
||||
</Link>
|
||||
{index !== breadcrumb.length - 1 && <span className="px-1">\</span>}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import React, { createContext, useContext, useEffect, useState } from "react";
|
||||
import { tableReload } from "../../store/TableReloads";
|
||||
import { useDispatch } from "react-redux";
|
||||
|
||||
import io from "socket.io-client";
|
||||
|
||||
let SocketIOContext = createContext({})
|
||||
|
||||
export default function SocketIOContextProvider({children}) {
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const socket = io.connect(process.env.REACT_APP_PRIMARY_SOCKET);
|
||||
|
||||
// //Room State
|
||||
// const [room, setRoom] = useState("");
|
||||
|
||||
// // Messages States
|
||||
// const [message, setMessage] = useState("");
|
||||
const [socketMsgReceived, setSocketMsgReceived] = useState("");
|
||||
|
||||
const joinRoom = (room) => {
|
||||
if (room !== "") {
|
||||
socket.emit("join_room", room);
|
||||
}
|
||||
};
|
||||
|
||||
const sendMessage = (message, room) => {
|
||||
if(message && room){
|
||||
socket.emit("send_message", { message, room });
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
socket.on("receive_message", (data) => {
|
||||
// setSocketMsgReceived(data.message);
|
||||
dispatch(tableReload({type:'CHATMESSAGELIST'}))
|
||||
});
|
||||
}, [socket]);
|
||||
|
||||
let values = {
|
||||
socket,
|
||||
sendMessage,
|
||||
joinRoom,
|
||||
setSocketMsgReceived,
|
||||
socketMsgReceived,
|
||||
// room,
|
||||
// setRoom,
|
||||
// message,
|
||||
// setMessage,
|
||||
}
|
||||
|
||||
return (
|
||||
<SocketIOContext.Provider value={values}>
|
||||
{children}
|
||||
</SocketIOContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export const SocketValues = () => {
|
||||
return useContext(SocketIOContext)
|
||||
}
|
||||
@@ -1,16 +1,11 @@
|
||||
import React, { Suspense, useMemo, useState } from "react";
|
||||
import React, { Suspense } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import usersService from "../../services/UsersService";
|
||||
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||
import Layout from "../Partials/Layout";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import FamilyTableNew from "./FamilyTableNew";
|
||||
|
||||
export default function FamilyActivities() {
|
||||
const [familyList, setFamilyList] = useState({});
|
||||
const [loader, setLoader] = useState(false);
|
||||
|
||||
const apiCall = useMemo(() => new usersService(), []);
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
{/*<CommonHead />*/}
|
||||
@@ -19,11 +14,26 @@ export default function FamilyActivities() {
|
||||
{/* heading */}
|
||||
<div className="sm:flex justify-between items-center mb-6">
|
||||
<div className="mb-5 sm:mb-0">
|
||||
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
|
||||
<span className={``}>Tasks & Chores</span>
|
||||
</h1>
|
||||
<CustomBreadcrumb
|
||||
title={"Tasks & Chores"}
|
||||
breadcrumb={[
|
||||
{ link: "/", title: "Home" },
|
||||
{
|
||||
link: "/acc-family",
|
||||
title: "Family Account",
|
||||
},
|
||||
{
|
||||
link: "/acc-family/activities",
|
||||
title: "Tasks & Chores",
|
||||
active: true,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<Link className="flex items-center gap-2" to="/acc-family">
|
||||
<Link
|
||||
className="item-content relative text-[18px] transition-all duration-300 ease-in-out bg-[#76a5df] text-white font-medium dark:text-white h-12 px-2 flex items-center gap-2 rounded-md shadow-sm justify-center cursor-pointer dark:bg-[linear-gradient(134.38deg,#f539f8_0%,#c342f9_43.55%,#5356fb_104.51%)]"
|
||||
to="/acc-family"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
@@ -43,11 +53,7 @@ export default function FamilyActivities() {
|
||||
</Link>
|
||||
</div>
|
||||
<Suspense fallback={<LoadingSpinner color="sky-blue" size="16" />}>
|
||||
<FamilyTableNew
|
||||
familyList={familyList?.result_list}
|
||||
loader={loader}
|
||||
imageServer={familyList?.session_image_server}
|
||||
/>
|
||||
<FamilyTableNew />
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -26,17 +26,6 @@ export default function FamilyPendingOffer() {
|
||||
},[])
|
||||
return (
|
||||
<Layout>
|
||||
<div className="mb-5">
|
||||
<CustomBreadcrumb
|
||||
title = {'Ready to Start'}
|
||||
breadcrumb={
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/pending", title: "Pending", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
{myOffersList.loading ?
|
||||
<div className='w-full flex justify-center items-center rounded-2xl bg-white'>
|
||||
<LoadingSpinner size='10' color='sky-blue' height='h-[20rem]' />
|
||||
@@ -49,9 +38,22 @@ export default function FamilyPendingOffer() {
|
||||
className="mb-10"
|
||||
/>
|
||||
:
|
||||
<div className='w-full h-[30rem] bg-white dark:bg-dark-white flex justify-center items-center rounded-2xl'>
|
||||
<p className='text-black dark:text-white'>No Record Found!</p>
|
||||
</div>
|
||||
<>
|
||||
<div className="mb-6">
|
||||
<CustomBreadcrumb
|
||||
title = {'Ready to Start'}
|
||||
breadcrumb={
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/pending", title: "Pending", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className='w-full h-[30rem] bg-white dark:bg-dark-white flex justify-center items-center rounded-2xl'>
|
||||
<p className='text-black dark:text-white'>No Record Found!</p>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
</Layout>
|
||||
)
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import React, { useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import usersService from "../../../services/UsersService";
|
||||
import { tableReload } from "../../../store/TableReloads";
|
||||
import ModalCom from "../../Helpers/ModalCom";
|
||||
import { PriceFormatter } from "../../Helpers/PriceFormatter";
|
||||
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||
import Detail from "../../jobPopout/popoutcomponent/Detail";
|
||||
import { NewTasks } from "./forms";
|
||||
import { tableReload } from "../../../store/TableReloads";
|
||||
import { useDispatch } from "react-redux";
|
||||
|
||||
const AssignTaskPopout = React.memo(
|
||||
({
|
||||
@@ -17,11 +18,27 @@ const AssignTaskPopout = React.memo(
|
||||
familyTask,
|
||||
activeTask,
|
||||
setActiveTask,
|
||||
setUpdatePage
|
||||
setUpdatePage,
|
||||
assignTaskChecker,
|
||||
}) => {
|
||||
const apiCall = new usersService();
|
||||
let { pathname, state } = useLocation();
|
||||
|
||||
const dispatch = useDispatch()
|
||||
const [selectedFamilyUid, setSelectedFamilyUid] = useState(null);
|
||||
|
||||
const handleFamChange = (event) => {
|
||||
setSelectedFamilyUid(event.target.value);
|
||||
};
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const getFamilySession = JSON.parse(sessionStorage.getItem("family_list"));
|
||||
|
||||
const familyList = getFamilySession?.map((member) => (
|
||||
<option key={member?.family_uid} value={member?.family_uid}>
|
||||
{member?.firstname} {member?.lastname}
|
||||
</option>
|
||||
));
|
||||
|
||||
let [requestStatus, setRequestStatus] = useState({
|
||||
loading: false,
|
||||
@@ -73,7 +90,9 @@ const AssignTaskPopout = React.memo(
|
||||
// API PAYLOADS
|
||||
job_id: activeTask.data?.job_id,
|
||||
job_uid: activeTask.data?.job_uid,
|
||||
family_uid: familyDetailsData?.uid || details?.family_uid,
|
||||
family_uid: selectedFamilyUid
|
||||
? selectedFamilyUid
|
||||
: familyDetailsData?.uid || details?.family_uid,
|
||||
job_description: activeTask.data?.description,
|
||||
assign_mode: 110011,
|
||||
};
|
||||
@@ -94,11 +113,11 @@ const AssignTaskPopout = React.memo(
|
||||
const requiredFields = {
|
||||
banner,
|
||||
// category,
|
||||
currency:country,
|
||||
currency: country,
|
||||
description,
|
||||
'job detail':job_detail,
|
||||
"job detail": job_detail,
|
||||
price,
|
||||
timeline:timeline_days,
|
||||
timeline: timeline_days,
|
||||
title,
|
||||
};
|
||||
|
||||
@@ -108,7 +127,9 @@ const AssignTaskPopout = React.memo(
|
||||
setRequestStatus({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: `${field[0].toUpperCase()+field.slice(1).toLowerCase()} is empty`,
|
||||
message: `${
|
||||
field[0].toUpperCase() + field.slice(1).toLowerCase()
|
||||
} is empty`,
|
||||
});
|
||||
return setTimeout(() => {
|
||||
setRequestStatus({ loading: false, status: false, message: "" });
|
||||
@@ -148,7 +169,7 @@ const AssignTaskPopout = React.memo(
|
||||
status: true,
|
||||
message: "action successful",
|
||||
});
|
||||
setUpdatePage(prev => !prev) // Updates family task page by calling the useeffect hook
|
||||
setUpdatePage((prev) => !prev); // Updates family task page by calling the useeffect hook
|
||||
dispatch(tableReload({ type: "WALLETTABLE" })); // RELOADS USER WALLET
|
||||
setTimeout(() => {
|
||||
setRequestStatus({ loading: false, status: false, message: "" });
|
||||
@@ -167,17 +188,35 @@ const AssignTaskPopout = React.memo(
|
||||
});
|
||||
};
|
||||
|
||||
console.log(details);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ModalCom
|
||||
action={action}
|
||||
situation={situation}
|
||||
>
|
||||
<ModalCom action={action} situation={situation}>
|
||||
<div className="w-11/12 lg:w-[700px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
||||
<div className="w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
||||
Assign task to{" "}
|
||||
{familyDetailsData?.firstname || details?.firstName}
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide flex items-center">
|
||||
<>
|
||||
Assign task to{" "}
|
||||
{pathname === "/acc-family/activities" ? (
|
||||
<div className="w-[270px] h-[40px] ml-2">
|
||||
<select
|
||||
name=""
|
||||
id=""
|
||||
className="text-black/70 bg-transparent px-2 transition-all cursor-pointer focus:outline-none border border-gray-200 rounded-lg w-full h-full py-1"
|
||||
onChange={handleFamChange}
|
||||
value={selectedFamilyUid}
|
||||
>
|
||||
<option value="" disabled selected>
|
||||
Select a member
|
||||
</option>
|
||||
{familyList}
|
||||
</select>
|
||||
</div>
|
||||
) : (
|
||||
<>{familyDetailsData?.firstname || details?.firstName}</>
|
||||
)}
|
||||
</>
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Link, useLocation } from "react-router-dom";
|
||||
import CustomBreadcrumb from "../../Breadcrumb/CustomBreadcrumb";
|
||||
import Icons from "../../Helpers/Icons";
|
||||
import Layout from "../../Partials/Layout";
|
||||
import { AddFamily, FamilyBanner, Relatives } from "./Tabs";
|
||||
|
||||
const FamilySettings = () => {
|
||||
let {state} = useLocation()
|
||||
let { state } = useLocation();
|
||||
const tabs = [
|
||||
{
|
||||
id: 1,
|
||||
@@ -58,15 +59,42 @@ const FamilySettings = () => {
|
||||
{/* heading */}
|
||||
<div className="sm:flex justify-between items-center mb-6">
|
||||
<div className="mb-5 sm:mb-0">
|
||||
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
|
||||
<span className={``}>Family Settings</span>
|
||||
</h1>
|
||||
<CustomBreadcrumb
|
||||
title={"Family Settings"}
|
||||
breadcrumb={[
|
||||
{ link: "/", title: "Home" },
|
||||
{
|
||||
link: "/acc-family",
|
||||
title: "Family Account",
|
||||
},
|
||||
{
|
||||
link: "/familysettings",
|
||||
title: "Family Settings",
|
||||
active: true,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<Link to="/acc-family" className="flex gap-2 items-center text-dark-gray dark:text-white">
|
||||
<svg className="w-5 h-5 rtl:rotate-180" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M6.75 15.75L3 12m0 0l3.75-3.75M3 12h18" />
|
||||
<Link
|
||||
className="item-content relative text-[18px] transition-all duration-300 ease-in-out bg-[#76a5df] text-white font-medium dark:text-white h-12 px-2 flex items-center gap-2 rounded-md shadow-sm justify-center cursor-pointer dark:bg-[linear-gradient(134.38deg,#f539f8_0%,#c342f9_43.55%,#5356fb_104.51%)]"
|
||||
to="/acc-family"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={1.5}
|
||||
stroke="currentColor"
|
||||
className="w-4 h-4"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18"
|
||||
/>
|
||||
</svg>
|
||||
Family
|
||||
|
||||
<span>Family</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,314 +1,286 @@
|
||||
import React, {
|
||||
Suspense,
|
||||
lazy,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { useReactToPrint } from "react-to-print";
|
||||
import localImgLoad from "../../lib/localImgLoad";
|
||||
import usersService from "../../services/UsersService";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import AssignTaskPopout from "./FamilyPopout/AssignTaskPopout";
|
||||
import FamilyWallet from "./Tabs/FamilyWallet";
|
||||
import { apiConst } from "../../lib/apiConst";
|
||||
|
||||
// Lazy Imports for components
|
||||
const FamilyWaitlist = lazy(() => import("./Tabs/FamilyWaitlist"));
|
||||
const FamilyAccount = lazy(() => import("./Tabs/FamilyAccount"));
|
||||
const FamilyProfile = lazy(() => import("./Tabs/FamilyProfile"));
|
||||
const FamilyTasks = lazy(() => import("./Tabs/FamilyTasks"));
|
||||
const FamilyPending = lazy(() => import("./Tabs/FamilyPending"));
|
||||
|
||||
export default function FamilyTableNew({
|
||||
className,
|
||||
accountDetails,
|
||||
listReload,
|
||||
loader,
|
||||
}) {
|
||||
// Initial state for family details
|
||||
const initialDetailState = {
|
||||
loading: false,
|
||||
data: null,
|
||||
};
|
||||
import React, { Suspense, lazy, useEffect, useMemo, useState } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { apiConst } from "../../lib/apiConst";
|
||||
import usersService from "../../services/UsersService";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import AssignTaskPopout from "./FamilyPopout/AssignTaskPopout";
|
||||
|
||||
// Lazy Imports for components
|
||||
const FamilyWaitlist = lazy(() => import("./Tabs/FamilyNewWaitlist"));
|
||||
const FamilyTasks = lazy(() => import("./Tabs/FamilyNewTasks"));
|
||||
const FamilyPending = lazy(() => import("./Tabs/FamilyNewPending"));
|
||||
|
||||
export default function FamilyTableNew() {
|
||||
let { pathname } = useLocation();
|
||||
|
||||
// Initial state for family details
|
||||
const initialDetailState = {
|
||||
loading: false,
|
||||
data: null,
|
||||
link: "",
|
||||
};
|
||||
|
||||
const [assignTaskChecker, setAssignTaskChecker] = useState(false);
|
||||
|
||||
// console.log('accountDetails',accountDetails)
|
||||
// State for family details, tasks, waitlist, and pending
|
||||
const [details, setDetails] = useState({
|
||||
// State for family details, tasks, waitlist, and pending
|
||||
const [details, setDetails] = useState({
|
||||
familyDetails: { ...initialDetailState },
|
||||
familyTasks: { ...initialDetailState },
|
||||
familyWaitList: { ...initialDetailState },
|
||||
familyPending: { ...initialDetailState },
|
||||
});
|
||||
|
||||
// Function to reset family details, tasks, waitlist, and pending
|
||||
const resetDetails = () => {
|
||||
setDetails({
|
||||
familyDetails: { ...initialDetailState },
|
||||
familyTasks: { ...initialDetailState },
|
||||
familyWaitList: { ...initialDetailState },
|
||||
familyPending: { ...initialDetailState },
|
||||
});
|
||||
|
||||
// Function to reset family details, tasks, waitlist, and pending
|
||||
const resetDetails = () => {
|
||||
setDetails({
|
||||
familyDetails: { ...initialDetailState },
|
||||
familyTasks: { ...initialDetailState },
|
||||
familyWaitList: { ...initialDetailState },
|
||||
familyPending: { ...initialDetailState },
|
||||
});
|
||||
};
|
||||
|
||||
const [updatePage, setUpdatePage] = useState(false) // State to determine when to update the page
|
||||
|
||||
// State for family task data
|
||||
const [familyTask, setFamilyTask] = useState({ loading: false, data: [] });
|
||||
|
||||
// State for active task
|
||||
const [activeTask, setActiveTask] = useState({ id: 0, data: {} });
|
||||
|
||||
// State for error messages
|
||||
const [errMsg, setErrMsg] = useState("");
|
||||
|
||||
// State for family task popout
|
||||
const [familyTaskPopout, setFamilyTaskPopout] = useState(false);
|
||||
|
||||
// Create an instance of the usersService class
|
||||
const apiCall = useMemo(() => new usersService(), []);
|
||||
|
||||
// Function to handle toggling the family task popout
|
||||
const familyPopUpHandler = () => {
|
||||
setFamilyTaskPopout((prev) => !prev);
|
||||
};
|
||||
|
||||
|
||||
// Ref for the account section
|
||||
const accountRef = useRef();
|
||||
|
||||
// React-to-Print hook for handling printing
|
||||
const useHandlePrint = useReactToPrint({
|
||||
content: () => accountRef.current,
|
||||
});
|
||||
|
||||
// Array of tab names
|
||||
const tabs = [
|
||||
{ id: 1, name: "Tasks" },
|
||||
{ id: 2, name: "Waiting" },
|
||||
{ id: 3, name: "Pending" },
|
||||
];
|
||||
|
||||
// State for the currently selected tab
|
||||
const [tab, setTab] = useState(tabs[0].name);
|
||||
|
||||
// Function to handle tab changes
|
||||
const tabHandler = (value) => {
|
||||
setTab(value);
|
||||
};
|
||||
|
||||
// Object that maps tab names to their corresponding components
|
||||
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.familyPending.loading}
|
||||
/>
|
||||
),
|
||||
Account: (
|
||||
<FamilyAccount
|
||||
familyData={details.familyDetails.data}
|
||||
myRef={accountRef}
|
||||
loader={details.familyDetails.loading}
|
||||
handlePrint={useHandlePrint}
|
||||
/>
|
||||
),
|
||||
Profile: <FamilyProfile familyData={details.familyDetails.data} />,
|
||||
wallet: <FamilyWallet familyData={details.familyDetails.data} />,
|
||||
};
|
||||
|
||||
// Default tab component
|
||||
const defaultTabComponent = (
|
||||
};
|
||||
|
||||
const [updatePage, setUpdatePage] = useState(false); // State to determine when to update the page
|
||||
|
||||
// State for family task data
|
||||
const [familyTask, setFamilyTask] = useState({ loading: false, data: [] });
|
||||
|
||||
// State for active task
|
||||
const [activeTask, setActiveTask] = useState({ id: 0, data: {} });
|
||||
|
||||
// State for error messages
|
||||
const [errMsg, setErrMsg] = useState("");
|
||||
|
||||
// State for family task popout
|
||||
const [familyTaskPopout, setFamilyTaskPopout] = useState(false);
|
||||
|
||||
// Create an instance of the usersService class
|
||||
const apiCall = useMemo(() => new usersService(), []);
|
||||
|
||||
// Function to handle toggling the family task popout
|
||||
const familyPopUpHandler = () => {
|
||||
setFamilyTaskPopout((prev) => !prev);
|
||||
};
|
||||
|
||||
// Array of tab names
|
||||
const tabs = [
|
||||
{ id: 1, name: "Tasks" },
|
||||
{ id: 2, name: "Waiting" },
|
||||
{ id: 3, name: "Pending" },
|
||||
];
|
||||
|
||||
// State for the currently selected tab
|
||||
const [tab, setTab] = useState(tabs[0].name);
|
||||
|
||||
// Function to handle tab changes
|
||||
const tabHandler = (value) => {
|
||||
setTab(value);
|
||||
};
|
||||
|
||||
// Object that maps tab names to their corresponding components
|
||||
const tabComponents = {
|
||||
Tasks: (
|
||||
<FamilyTasks
|
||||
className={className}
|
||||
image_link={details.familyTasks.link}
|
||||
loader={details.familyTasks.loading}
|
||||
familyData={details.familyTasks.data}
|
||||
accountDetails={accountDetails}
|
||||
action={familyPopUpHandler}
|
||||
setAssignTaskChecker={setAssignTaskChecker}
|
||||
/>
|
||||
);
|
||||
|
||||
// Selected tab component based on the current 'tab'
|
||||
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
|
||||
|
||||
// Effect to manage family details and related data
|
||||
useEffect(() => {
|
||||
const manageFamily = async () => {
|
||||
try {
|
||||
resetDetails();
|
||||
|
||||
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;
|
||||
|
||||
// Function to check for errors in data
|
||||
const checkDataError = (data) => data?.internal_return < 0;
|
||||
|
||||
if (
|
||||
checkDataError(familyData) ||
|
||||
checkDataError(tasksData) ||
|
||||
checkDataError(familyWaitData) ||
|
||||
checkDataError(familyPendingData)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
setDetails({
|
||||
familyDetails: { loading: false, data: familyData },
|
||||
familyTasks: { loading: false, data: tasksData },
|
||||
familyWaitList: { loading: false, data: familyWaitData },
|
||||
familyPending: { loading: false, data: familyPendingData },
|
||||
});
|
||||
} catch (error) {
|
||||
resetDetails();
|
||||
setErrMsg("An error occurred");
|
||||
throw new Error(error);
|
||||
),
|
||||
Waiting: (
|
||||
<FamilyWaitlist
|
||||
image_link={details.familyWaitList.link}
|
||||
familyData={details.familyWaitList.data}
|
||||
loader={details.familyWaitList.loading}
|
||||
/>
|
||||
),
|
||||
Pending: (
|
||||
<FamilyPending
|
||||
image_link={details.familyPending.link}
|
||||
familyData={details.familyPending.data}
|
||||
loader={details.familyPending.loading}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
const defaultTabComponent = tabComponents.Tasks;
|
||||
|
||||
// Selected tab component based on the current 'tab'
|
||||
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
|
||||
|
||||
// Effect to manage family details and related data
|
||||
useEffect(() => {
|
||||
const manageFamily = async () => {
|
||||
try {
|
||||
resetDetails();
|
||||
|
||||
setDetails({
|
||||
familyTasks: { loading: true },
|
||||
familyWaitList: { loading: true },
|
||||
familyPending: { loading: true },
|
||||
});
|
||||
|
||||
// const { family_uid } = accountDetails;
|
||||
// const reqData = { family_uid };
|
||||
|
||||
const [familyTasksData, familyWaitingRes, familyPendingRes] =
|
||||
await Promise.all([
|
||||
apiCall.getMyActiveJobList(),
|
||||
apiCall.ManageFamilyNewWaitlist(),
|
||||
apiCall.ManageFamilyPending(),
|
||||
]);
|
||||
|
||||
let tasksData = familyTasksData?.data?.result_list;
|
||||
let _familyWaitData = familyWaitingRes?.data?.result_list;
|
||||
let familyPendingData = familyPendingRes?.data?.result_list;
|
||||
|
||||
// Getting the image server link
|
||||
let imageServerLink = familyWaitingRes.data?.session_image_server;
|
||||
|
||||
// Function to check for errors in data
|
||||
const checkDataError = (data) => data?.internal_return < 0;
|
||||
|
||||
if (
|
||||
checkDataError(tasksData) ||
|
||||
checkDataError(_familyWaitData) ||
|
||||
checkDataError(familyPendingData)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Invoke the manageFamily function when the component mounts
|
||||
manageFamily();
|
||||
}, [updatePage]);
|
||||
|
||||
// Effect to manage family tasks
|
||||
useEffect(() => {
|
||||
let checkFamilyTask = true;
|
||||
const reqData = {
|
||||
limit: 30,
|
||||
offset: 0,
|
||||
job_type: "FAMILY",
|
||||
action: apiConst.WRENCHBOARD_PICTURE_FAMMEMBER,
|
||||
};
|
||||
|
||||
if (checkFamilyTask) {
|
||||
setFamilyTask({ loading: true });
|
||||
apiCall
|
||||
.getMyJobList(reqData)
|
||||
.then((res) => {
|
||||
setFamilyTask({ loading: false, data: res?.data?.result_list });
|
||||
if (res?.data?.result_list?.length) {
|
||||
setActiveTask((prev) => ({
|
||||
...prev,
|
||||
data: res?.data?.result_list[0],
|
||||
}));
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
setFamilyTask({ loading: false, data: [] });
|
||||
console.log("Error", err);
|
||||
});
|
||||
|
||||
setDetails({
|
||||
familyTasks: {
|
||||
loading: false,
|
||||
data: tasksData,
|
||||
link: imageServerLink,
|
||||
},
|
||||
familyWaitList: {
|
||||
loading: false,
|
||||
data: _familyWaitData,
|
||||
link: imageServerLink,
|
||||
},
|
||||
familyPending: {
|
||||
loading: false,
|
||||
data: familyPendingData,
|
||||
link: imageServerLink,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
resetDetails();
|
||||
setErrMsg("An error occurred");
|
||||
throw new Error(error);
|
||||
}
|
||||
|
||||
// Cleanup function to prevent memory leaks
|
||||
return () => {
|
||||
checkFamilyTask = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`w-full bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow h-full ${
|
||||
className || ""
|
||||
}`}
|
||||
>
|
||||
<div className="relative w-full sm:rounded-lg overflow-x-auto">
|
||||
<Suspense
|
||||
fallback={
|
||||
<div className="h-full min-h-[609px] 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-3 min-h-[575px]">
|
||||
<div className="col-span-3 h-full w-full">
|
||||
<div className="flex flex-col w-full">
|
||||
<div className="w-full pr-8 flex items-center gap-1 border-b border-b-[#FAFAF]">
|
||||
<ul className="flex gap-2 items-center 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-[2px] ${
|
||||
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] h-full">
|
||||
<div className="h-full relative overflow-y-auto">
|
||||
<Suspense
|
||||
fallback={<LoadingSpinner size="16" color="sky-blue" />}
|
||||
};
|
||||
|
||||
// Invoke the manageFamily function when the component mounts
|
||||
manageFamily();
|
||||
}, [updatePage]);
|
||||
|
||||
// Effect to manage family tasks
|
||||
useEffect(() => {
|
||||
let checkFamilyTask = true;
|
||||
const reqData = {
|
||||
limit: 30,
|
||||
offset: 0,
|
||||
job_type: "FAMILY",
|
||||
action: apiConst.WRENCHBOARD_PICTURE_FAMMEMBER,
|
||||
};
|
||||
|
||||
if (checkFamilyTask) {
|
||||
setFamilyTask({ loading: true });
|
||||
apiCall
|
||||
.getMyJobList(reqData)
|
||||
.then((res) => {
|
||||
setFamilyTask({ loading: false, data: res?.data?.result_list });
|
||||
if (res?.data?.result_list?.length) {
|
||||
setActiveTask((prev) => ({
|
||||
...prev,
|
||||
data: res?.data?.result_list[0],
|
||||
}));
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
setFamilyTask({ loading: false, data: [] });
|
||||
console.log("Error", err);
|
||||
});
|
||||
}
|
||||
|
||||
// Cleanup function to prevent memory leaks
|
||||
return () => {
|
||||
checkFamilyTask = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`w-full bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow h-full`}
|
||||
>
|
||||
<div className="relative w-full sm:rounded-lg overflow-x-auto">
|
||||
<Suspense
|
||||
fallback={
|
||||
<div className="h-full min-h-[609px] 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-3 min-h-[575px]">
|
||||
<div className="col-span-3 h-full w-full">
|
||||
<div className="flex flex-col w-full">
|
||||
<div className="w-full pr-8 flex items-center gap-1 border-b border-b-[#FAFAF]">
|
||||
<ul className="flex gap-2 items-center 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-[2px] ${
|
||||
tab === name
|
||||
? "text-purple border-r"
|
||||
: "text-thin-light-gray"
|
||||
}`}
|
||||
key={id}
|
||||
>
|
||||
{selectedTabComponent}
|
||||
</Suspense>
|
||||
</div>
|
||||
<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] h-full">
|
||||
<div className="h-full relative overflow-y-auto">
|
||||
<Suspense
|
||||
fallback={<LoadingSpinner size="16" color="sky-blue" />}
|
||||
>
|
||||
{selectedTabComponent}
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Suspense>
|
||||
</div>
|
||||
|
||||
{familyTaskPopout && (
|
||||
<AssignTaskPopout
|
||||
action={familyPopUpHandler}
|
||||
situation={familyTaskPopout}
|
||||
familyTask={familyTask}
|
||||
setFamilyTask={setFamilyTask}
|
||||
setActiveTask={setActiveTask}
|
||||
activeTask={activeTask}
|
||||
familyDetailsData={details.familyDetails.data}
|
||||
setUpdatePage={setUpdatePage}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Suspense>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
{familyTaskPopout && (
|
||||
<AssignTaskPopout
|
||||
action={familyPopUpHandler}
|
||||
situation={familyTaskPopout}
|
||||
familyTask={familyTask}
|
||||
setFamilyTask={setFamilyTask}
|
||||
setActiveTask={setActiveTask}
|
||||
activeTask={activeTask}
|
||||
setUpdatePage={setUpdatePage}
|
||||
pathname={pathname}
|
||||
assignTaskChecker={assignTaskChecker}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
import { useMemo, useState } from "react";
|
||||
import { PriceFormatter } from "../../Helpers/PriceFormatter";
|
||||
import { PaginatedList, handlePagingFunc } from "../../Pagination";
|
||||
import PendingJobsPopout from "../../jobPopout/PendingJobsPopout";
|
||||
|
||||
export default function FamilyPending({ familyData, image_link, loader }) {
|
||||
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
|
||||
|
||||
let filteredFamilyData = useMemo(
|
||||
() => familyData?.filter((data) => data.family_uid !== ""),
|
||||
[familyData]
|
||||
);
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
console.log(image_link);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`update-table w-full p-3 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow lg:min-h-[538px]`}
|
||||
>
|
||||
{familyData && (
|
||||
<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
|
||||
);
|
||||
let image = `${image_link}${localStorage.getItem(
|
||||
"session_token"
|
||||
)}/job/${value.job_uid}`;
|
||||
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-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
|
||||
<img
|
||||
src={image}
|
||||
alt="data"
|
||||
className="w-full h-full rounded-full"
|
||||
/>
|
||||
</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 flex justify-end items-center">
|
||||
<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>
|
||||
<td className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap text-center py-4 px-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,171 @@
|
||||
import React, { useMemo, useState } from "react";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import Icons from "../../Helpers/Icons";
|
||||
import { PriceFormatter } from "../../Helpers/PriceFormatter";
|
||||
import { handlePagingFunc } from "../../Pagination/HandlePagination";
|
||||
import PaginatedList from "../../Pagination/PaginatedList";
|
||||
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||
|
||||
export default function FamilyNewTasks({
|
||||
familyData,
|
||||
className,
|
||||
loader,
|
||||
action,
|
||||
image_link,
|
||||
}) {
|
||||
let navigate = useNavigate();
|
||||
let { pathname } = useLocation();
|
||||
|
||||
// ...
|
||||
let filteredFamilyData = useMemo(
|
||||
() => familyData?.filter((data) => data.family_uid !== ""),
|
||||
[familyData]
|
||||
);
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const indexOfFirstItem = Number(currentPage);
|
||||
const indexOfLastItem =
|
||||
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
||||
const currentTasks = 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-[538px] overflow-hidden rounded-2xl section-shadow p-3 ${
|
||||
familyData?.length <= 0 && "flex items-center justify-center"
|
||||
}`}
|
||||
>
|
||||
{loader ? (
|
||||
<div className="w-full h-full flex justify-center items-center lg:min-h-[470px]">
|
||||
<LoadingSpinner size={16} color="sky-blue" />
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{familyData && (
|
||||
<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>
|
||||
{
|
||||
<>
|
||||
{familyData?.length <= 0 ? (
|
||||
<tr>
|
||||
<td
|
||||
colSpan="2"
|
||||
className="text-center py-4 font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap flex items-center justify-center gap-1"
|
||||
>
|
||||
You currently have no active tasks{" "}
|
||||
<span
|
||||
className="text-blue-400 cursor-pointer hover:underline transition duration-150"
|
||||
onClick={action}
|
||||
>
|
||||
add new
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
currentTasks.map((value, index) => {
|
||||
// find due date
|
||||
const dueDate = value?.delivery_date.split(" ")[0];
|
||||
// the price
|
||||
let thePrice = PriceFormatter(
|
||||
value?.price * 0.01,
|
||||
value?.currency_code,
|
||||
value?.currency
|
||||
);
|
||||
let image = `${image_link}${localStorage.getItem(
|
||||
"session_token"
|
||||
)}/job/${value.job_uid}`;
|
||||
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-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
|
||||
<img
|
||||
src={image}
|
||||
alt="data"
|
||||
className="w-full h-full rounded-full"
|
||||
/>
|
||||
</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 className="flex flex-col sm:flex-row items-start gap-1 md:gap-4 md:items-center">
|
||||
<span className="text-sm text-thin-light-gray flex flex-start gap-1">
|
||||
Price:{" "}
|
||||
<span className="text-purple">
|
||||
{thePrice}
|
||||
</span>
|
||||
</span>
|
||||
<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">
|
||||
Due Date:{" "}
|
||||
<span className="text-purple">
|
||||
{" "}
|
||||
{dueDate}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td className="text-right py-4 px-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
navigate("/manage-active-job", {
|
||||
state: {
|
||||
...value,
|
||||
pathname,
|
||||
},
|
||||
});
|
||||
}}
|
||||
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
<Icons name="right-arrow" />
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})
|
||||
)}
|
||||
</>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
{/* PAGINATION BUTTON */}
|
||||
<PaginatedList
|
||||
onClick={handlePagination}
|
||||
prev={currentPage == 0 ? true : false}
|
||||
next={
|
||||
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
|
||||
filteredFamilyData?.length
|
||||
? true
|
||||
: false
|
||||
}
|
||||
data={filteredFamilyData}
|
||||
start={indexOfFirstItem}
|
||||
stop={indexOfLastItem}
|
||||
/>
|
||||
{/* END OF PAGINATION BUTTON */}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
import { useState } from "react";
|
||||
import SuggestTask from "../../FamilyPopup/SuggestTask";
|
||||
import { PaginatedList, handlePagingFunc } from "../../Pagination";
|
||||
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||
import AssignTaskPopout from "../FamilyPopout/AssignTaskPopout";
|
||||
import Icons from "../../Helpers/Icons";
|
||||
|
||||
const FamilyNewWaitlist = ({
|
||||
familyData,
|
||||
className,
|
||||
accountDetails,
|
||||
loader,
|
||||
}) => {
|
||||
const [popUp, setPopUp] = useState({ show: false, data: {} });
|
||||
const [continueTaskPopup, setContinueTaskPopup] = useState({
|
||||
show: false,
|
||||
data: {},
|
||||
});
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const itemsPerPage = Number(process.env.REACT_APP_ITEM_PER_PAGE);
|
||||
const indexOfFirstItem = currentPage;
|
||||
const indexOfLastItem = currentPage + itemsPerPage;
|
||||
const currentTask = familyData?.slice(
|
||||
indexOfFirstItem,
|
||||
indexOfLastItem
|
||||
);
|
||||
|
||||
const handlePagination = (e) => handlePagingFunc(e, setCurrentPage);
|
||||
|
||||
const openPopUp = (value) => {
|
||||
setPopUp({ show: true, data: { ...value } });
|
||||
};
|
||||
|
||||
const closePopUp = () => {
|
||||
setPopUp({ show: false, data: {} });
|
||||
};
|
||||
|
||||
const openContinueTaskPopup = (value) => {
|
||||
setContinueTaskPopup({ show: true, data: { ...value } });
|
||||
};
|
||||
|
||||
const closeContinueTaskPopup = () => {
|
||||
setContinueTaskPopup({ show: false, data: {} });
|
||||
};
|
||||
|
||||
console.log("Check this >>",continueTaskPopup)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`update-table w-full bg-white dark:bg-dark-white h-full lg:min-h-[538px] p-3 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>
|
||||
) : (
|
||||
<>
|
||||
{familyData && (
|
||||
<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 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"
|
||||
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={selectedImage}
|
||||
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 flex flex-col items-center justify-center">
|
||||
<p className="text-sm font-bold text-dark-gray dark:text-white">
|
||||
{addedDate}
|
||||
</p>
|
||||
<p className="text-xs py-1.5 w-[70px] cursor-default tracking-wide rounded-full bg-gold text-white flex justify-center items-center">
|
||||
{value.firstname}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td className="text-right py-4 px-2 flex justify-end">
|
||||
<button
|
||||
onClick={() => openPopUp(value)}
|
||||
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
|
||||
>
|
||||
{/* View */}
|
||||
<Icons name="right-arrow" />
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
<PaginatedList
|
||||
onClick={handlePagination}
|
||||
prev={currentPage === 0}
|
||||
next={currentPage + itemsPerPage >= familyData?.length}
|
||||
data={familyData}
|
||||
start={indexOfFirstItem}
|
||||
stop={indexOfLastItem}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{popUp.show && (
|
||||
<SuggestTask
|
||||
details={popUp.data}
|
||||
onClose={closePopUp}
|
||||
continuePopupData={openContinueTaskPopup}
|
||||
situation={popUp.show}
|
||||
/>
|
||||
)}
|
||||
|
||||
{continueTaskPopup.show && (
|
||||
<AssignTaskPopout
|
||||
details={continueTaskPopup.data}
|
||||
action={closeContinueTaskPopup}
|
||||
situation={continueTaskPopup.show}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default FamilyNewWaitlist;
|
||||
@@ -13,6 +13,7 @@ import ModalCom from "../Helpers/ModalCom";
|
||||
import Layout from "../Partials/Layout";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import FamilyTable from "./FamilyTable";
|
||||
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||
|
||||
export default function FamilyAcc() {
|
||||
// State to store the selected year and month
|
||||
@@ -108,6 +109,7 @@ export default function FamilyAcc() {
|
||||
if (data?.internal_return >= 0 && data?.status === "OK") {
|
||||
const { result_list, session_image_server } = data;
|
||||
setFamilyList({ result_list, session_image_server });
|
||||
sessionStorage.setItem("family_list", JSON.stringify(result_list))
|
||||
setLoader(false);
|
||||
} else {
|
||||
return;
|
||||
@@ -137,7 +139,18 @@ export default function FamilyAcc() {
|
||||
<div className="sm:flex justify-between items-center mb-6">
|
||||
<div className="mb-5 sm:mb-0">
|
||||
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
|
||||
<span className={``}>Family Accounts</span>
|
||||
{/* <span className={``}>Family Accounts</span> */}
|
||||
<div className="mb-5">
|
||||
<CustomBreadcrumb
|
||||
title = {'Family Account'}
|
||||
breadcrumb={
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/acc-family", title: "Family Account", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
{familyList?.result_list?.length <
|
||||
process.env.REACT_APP_MAX_FAMILY_MEMBERS &&
|
||||
!loader && (
|
||||
@@ -152,13 +165,13 @@ export default function FamilyAcc() {
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 items-center">
|
||||
<Link to="/acc-family/activities" className={`nav-item flex items-center `}>
|
||||
<div className="flex gap-4 items-center">
|
||||
<Link state={familyList} to="/acc-family/activities" className={`nav-item flex items-center rounded-md shadow-sm justify-center cursor-pointer dark:bg-[linear-gradient(134.38deg,#f539f8_0%,#c342f9_43.55%,#5356fb_104.51%)] bg-[#76a5df] text-white px-2 gap-2`}>
|
||||
<span className="item-icon group-hover:bg-purple group-hover:text-white w-8 h-8 flex justify-center items-center transition-all duration-300 ease-in-out bg-light-purple dark:bg-dark-light-purple rounded-full text-dark-gray dark:text-white dark:text-lighter-gray">
|
||||
<Icons name="pending-job" />
|
||||
</span>
|
||||
<span
|
||||
className={`item-content relative group-hover:text-purple text-[18px] transition-all duration-300 ease-in-out text-lighter-gray font-medium`}
|
||||
className={`item-content relative text-[18px] transition-all duration-300 ease-in-out font-medium dark:text-white h-12 flex items-center`}
|
||||
>
|
||||
Activities
|
||||
</span>
|
||||
@@ -166,7 +179,7 @@ export default function FamilyAcc() {
|
||||
<Link
|
||||
to={`/familysettings`}
|
||||
state={{ imageServer: familyList?.session_image_server }}
|
||||
className="slider-btns flex space-x-4 w-12 h-12 rounded-md shadow-sm justify-center items-center cursor-pointer dark:bg-[linear-gradient(134.38deg,#f539f8_0%,#c342f9_43.55%,#5356fb_104.51%)]"
|
||||
className="slider-btns flex space-x-4 w-12 h-12 rounded-md shadow-sm justify-center items-center cursor-pointer dark:bg-[linear-gradient(134.38deg,#f539f8_0%,#c342f9_43.55%,#5356fb_104.51%)] bg-[#76a5df] text-white"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { Form, Formik } from "formik";
|
||||
import { useState } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import ModalCom from "../Helpers/ModalCom";
|
||||
import { Form, Formik } from "formik";
|
||||
import InputCom from "../Helpers/Inputs/InputCom";
|
||||
import usersService from "../../services/UsersService";
|
||||
import Icons from "../Helpers/Icons";
|
||||
import InputCom from "../Helpers/Inputs/InputCom";
|
||||
import ModalCom from "../Helpers/ModalCom";
|
||||
|
||||
const DEFAULT_IMAGE = require("../../assets/images/family/default.jpg");
|
||||
const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
@@ -51,21 +50,47 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
};
|
||||
|
||||
const handleParentSuggestion = (values) => {
|
||||
if (suggestedNextStep == "Send Task") {
|
||||
let firstName = state?.firstname;
|
||||
let family_uid = state?.family_uid;
|
||||
continuePopupData({ ...details, firstName, family_uid });
|
||||
if (suggestedNextStep === "Send Task") {
|
||||
let firstname = state?.firstname || details?.firstname;
|
||||
let family_uid = state?.family_uid || details?.family_uid;
|
||||
continuePopupData({
|
||||
...details,
|
||||
firstname,
|
||||
family_uid,
|
||||
});
|
||||
}
|
||||
onClose();
|
||||
};
|
||||
|
||||
const isActivitiesPage = pathname === "/acc-family/activities";
|
||||
const isManageFamilyPage = pathname === "/manage-family";
|
||||
|
||||
const getButtonText = () => {
|
||||
if (isActivitiesPage) {
|
||||
return suggestedNextStep === "Send Task" ? "Continue" : "Complete";
|
||||
} else {
|
||||
if (!isManageFamilyPage) {
|
||||
if (submitTask.loading) return "Submitting Task";
|
||||
if (submitTask.state === "success") return "Task Submitted";
|
||||
if (submitTask.state === "bad") return "An Error Occurred";
|
||||
return "Send to Parents";
|
||||
} else {
|
||||
return suggestedNextStep === "Send Task" ? "Continue" : "Complete";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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">
|
||||
<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">
|
||||
{pathname === "/manage-family"
|
||||
{isManageFamilyPage
|
||||
? `${state?.firstname}'s Suggested Task`
|
||||
: isActivitiesPage
|
||||
? `${details?.firstname}'s Suggested Task`
|
||||
: "Suggest to Parent"}
|
||||
</h1>
|
||||
<button
|
||||
@@ -97,9 +122,11 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
onSubmit={
|
||||
pathname !== "/manage-family"
|
||||
? handleSuggestedTask
|
||||
: handleParentSuggestion
|
||||
isActivitiesPage
|
||||
? handleParentSuggestion
|
||||
: isManageFamilyPage
|
||||
? handleParentSuggestion
|
||||
: handleSuggestedTask
|
||||
}
|
||||
>
|
||||
{(props) => {
|
||||
@@ -122,12 +149,16 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
<div className="field w-full mb-[15px]">
|
||||
<InputCom
|
||||
fieldClass={
|
||||
pathname === "/manage-family" ? "px-2" : "px-6"
|
||||
pathname === "/manage-family" ||
|
||||
pathname === "/acc-family/activities"
|
||||
? "px-2"
|
||||
: "px-6"
|
||||
}
|
||||
label="Title"
|
||||
labelClass="tracking-wide"
|
||||
inputBg={
|
||||
pathname === "/manage-family"
|
||||
pathname === "/manage-family" ||
|
||||
pathname === "/acc-family/activities"
|
||||
? "bg-white"
|
||||
: "bg-slate-100"
|
||||
}
|
||||
@@ -164,7 +195,8 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
id="description"
|
||||
rows="5"
|
||||
className={`input-field pt-2 placeholder:text-base text-dark-gray dark:text-white w-full ${
|
||||
pathname === "/manage-family"
|
||||
pathname === "/manage-family" ||
|
||||
pathname === "/acc-family/activities"
|
||||
? "px-2 h-[110px]"
|
||||
: "bg-slate-100 px-3 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[10px] h-[130px]"
|
||||
}`}
|
||||
@@ -177,7 +209,8 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
</div>
|
||||
|
||||
{/* Radio buttons for family */}
|
||||
{pathname === "/manage-family" ? (
|
||||
{pathname === "/manage-family" ||
|
||||
pathname === "/acc-family/activities" ? (
|
||||
<div className="h-[20px] w-full border-t dark:border-[#5356fb29] border-light-purple relative">
|
||||
<div id="my-radio-group" className="sr-only">
|
||||
Parent suggested next step
|
||||
@@ -212,9 +245,9 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
id={`parent-suggested-${idx}`}
|
||||
name="parent-suggested"
|
||||
className={`ml-1 ${
|
||||
title == "Not Now"
|
||||
title === "Not Now"
|
||||
? "text-red-500"
|
||||
: title == "Duplicate"
|
||||
: title === "Duplicate"
|
||||
? "text-purple"
|
||||
: "text-black"
|
||||
} font-semibold`}
|
||||
@@ -243,19 +276,9 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
disabled={props.isSubmitting}
|
||||
className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full transition duration-150 ease-in-out flex items-center"
|
||||
>
|
||||
{pathname !== "/manage-family" ? (
|
||||
{/* {pathname === "/acc-family/activities" ? (
|
||||
<>
|
||||
{submitTask.loading
|
||||
? "Submitting Task"
|
||||
: submitTask.state == "success"
|
||||
? "Task Submitted"
|
||||
: submitTask.state == "bad"
|
||||
? "An Error Occurred"
|
||||
: "Send to Parents"}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{suggestedNextStep == "Send Task" ? (
|
||||
{suggestedNextStep === "Send Task" ? (
|
||||
<>
|
||||
Continue <Icons name="chevron-right" />
|
||||
</>
|
||||
@@ -263,7 +286,32 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||
"Complete"
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
) : (
|
||||
<>
|
||||
{pathname !== "/manage-family" ? (
|
||||
<>
|
||||
{submitTask.loading
|
||||
? "Submitting Task"
|
||||
: submitTask.state === "success"
|
||||
? "Task Submitted"
|
||||
: submitTask.state === "bad"
|
||||
? "An Error Occurred"
|
||||
: "Send to Parents"}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{suggestedNextStep === "Send Task" ? (
|
||||
<>
|
||||
Continue <Icons name="chevron-right" />
|
||||
</>
|
||||
) : (
|
||||
"Complete"
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)} */}
|
||||
{getButtonText()}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,7 @@ export default function MainSection({
|
||||
);
|
||||
const [tab, setTab] = useState(Object.keys(marketCategories)[0]);
|
||||
|
||||
let [contentDisplay, setContentDisplay] = useState("grid"); // STATE TO HOLD LIST VIEW STYLE
|
||||
let [contentDisplay, setContentDisplay] = useState("list"); // STATE TO HOLD LIST VIEW STYLE
|
||||
|
||||
// Convert to array in order to map
|
||||
const mappedArray = Object.entries(marketCategories).map(([key, value]) => {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useSelector } from "react-redux";
|
||||
import Layout from "../Partials/Layout";
|
||||
import CommonHead from "../UserHeader/CommonHead";
|
||||
import MainSection from "./MainSection";
|
||||
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||
|
||||
export default function MarketPlace({ commonHeadData }) {
|
||||
let { jobLists } = useSelector((state) => state.jobLists);
|
||||
@@ -13,6 +14,17 @@ export default function MarketPlace({ commonHeadData }) {
|
||||
<>
|
||||
<Layout>
|
||||
<CommonHead commonHeadData={commonHeadData} />
|
||||
<div className="mb-5">
|
||||
<CustomBreadcrumb
|
||||
title = {'Market'}
|
||||
breadcrumb={
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/market", title: "Market", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<MainSection
|
||||
marketPlaceProduct={marketData}
|
||||
categories={categories}
|
||||
|
||||
@@ -11,8 +11,11 @@ import IndexJobActions from "./JobActions/IndexJobActions";
|
||||
|
||||
import usersService from "../../services/UsersService";
|
||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||
import { SocketValues } from "../Contexts/SocketIOContext";
|
||||
|
||||
function ActiveJobs(props) {
|
||||
let {sendMessage, joinRoom} = SocketValues() // destructures 'SEND MESSAGE' and 'JOIN ROOM' FUNCTIONS FROM SOCKET
|
||||
|
||||
const ApiCall = new usersService();
|
||||
const navigate = useNavigate();
|
||||
|
||||
@@ -139,6 +142,9 @@ function ActiveJobs(props) {
|
||||
status: true,
|
||||
message: "Message Sent Successfully",
|
||||
});
|
||||
// function to trigger socket to emit 'send_message'
|
||||
sendMessage(messageToSend, `${props.details.contract}-${props.details.contract_uid}`)
|
||||
|
||||
props.reloadActiveJobList((prev) => !prev); // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
|
||||
setMessageToSend(""); // SENDS MESSAGE TO SEND BACK TO EMPTY STRINGS
|
||||
})
|
||||
@@ -255,6 +261,12 @@ function ActiveJobs(props) {
|
||||
props.details?.currency
|
||||
);
|
||||
|
||||
|
||||
useEffect(()=>{
|
||||
// calls function to add user to a room
|
||||
joinRoom(`${props.details.contract}-${props.details.contract_uid}`)
|
||||
},[props.details.contract, props.details.contract_uid])
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<div className="py-[20px] bg-white dark:bg-black dark:text-white px-4 rounded-2xl shadow-md md:flex justify-between items-start gap-16">
|
||||
|
||||
@@ -3,6 +3,7 @@ import OfferCard from "../Cards/OfferCard";
|
||||
import Icons from "../Helpers/Icons";
|
||||
import SliderCom from "../Helpers/SliderCom";
|
||||
import FamilyOfferJobPopout from "../jobPopout/FamilyOfferJobPopout";
|
||||
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||
|
||||
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
|
||||
@@ -60,10 +61,21 @@ export default function MyOffersFamilyTable({ className, familyOffers, image_ser
|
||||
>
|
||||
{/* heading */}
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<div>
|
||||
{/* <div>
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
Ready to Start?
|
||||
</h1>
|
||||
</div> */}
|
||||
<div className="">
|
||||
<CustomBreadcrumb
|
||||
title = {'Ready to Start'}
|
||||
breadcrumb={
|
||||
[
|
||||
{ link: "/", title: "Home" },
|
||||
{ link: "/pending", title: "Pending", active: true},
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="slider-btns flex space-x-3">
|
||||
<button onClick={nextHandler} type="button">
|
||||
|
||||
@@ -75,7 +75,7 @@ export default function MyTasks({
|
||||
/>
|
||||
)}
|
||||
<div className="w-full mb-5 flex justify-between items-center gap-1">
|
||||
{userDetails.account_type == 'FULL'?
|
||||
{/* {userDetails.account_type == 'FULL'?
|
||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||
<span
|
||||
className={`${selectTab === "today" ? "block" : "hidden"}`}
|
||||
@@ -83,7 +83,7 @@ export default function MyTasks({
|
||||
My Tasks
|
||||
</span>
|
||||
</h1>
|
||||
:
|
||||
: */}
|
||||
<CustomBreadcrumb
|
||||
title = 'My Tasks'
|
||||
breadcrumb={
|
||||
@@ -93,7 +93,7 @@ export default function MyTasks({
|
||||
]
|
||||
}
|
||||
/>
|
||||
}
|
||||
{/* } */}
|
||||
|
||||
{ActiveJobList?.data?.length > 0 && userDetails.account_type == 'FAMILY' &&
|
||||
<button
|
||||
|
||||
@@ -16,12 +16,6 @@ const FamilyWallet = () => {
|
||||
data: [],
|
||||
});
|
||||
|
||||
const [allCountries, setAllCountries] = useState({
|
||||
// STATE TO HOLD LIST OF COUNTRIES
|
||||
loading: true,
|
||||
data: [],
|
||||
});
|
||||
|
||||
const getPaymentHistory = () => {
|
||||
apiCall
|
||||
.getPaymentHx()
|
||||
@@ -37,37 +31,10 @@ const FamilyWallet = () => {
|
||||
});
|
||||
};
|
||||
|
||||
// FUNCTION TO GET COUNTRIES
|
||||
const getCountry = () => {
|
||||
apiCall
|
||||
.getSignupCountryData()
|
||||
.then((res) => {
|
||||
if (res?.data?.internal_return < 0) {
|
||||
setAllCountries((prev) => ({ loading: false, data: [] }));
|
||||
return;
|
||||
}
|
||||
setAllCountries((prev) => ({
|
||||
loading: false,
|
||||
data: res?.data?.result_list,
|
||||
}));
|
||||
})
|
||||
.catch((error) => {
|
||||
setAllCountries((prev) => ({ loading: false, data: [] }));
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getCountry();
|
||||
getPaymentHistory();
|
||||
}, [walletTable]);
|
||||
|
||||
console.log(
|
||||
"Testing all country: ",
|
||||
allCountries,
|
||||
"Testing wallet: ",
|
||||
walletDetails
|
||||
);
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<div className='mb-4'>
|
||||
@@ -85,7 +52,6 @@ const FamilyWallet = () => {
|
||||
<FamilyWalletBox
|
||||
wallet={walletDetails}
|
||||
payment={paymentHistory}
|
||||
countries={allCountries.data}
|
||||
/>
|
||||
</Suspense>
|
||||
</Layout>
|
||||
|
||||
@@ -2,33 +2,102 @@ import { useSelector } from "react-redux";
|
||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||
import WalletItemCard from "./WalletItemCard";
|
||||
import WalletItemCardFamily from "./WalletItemCardFamily";
|
||||
import { useState } from "react";
|
||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||
import SearchCom from "../Helpers/SearchCom";
|
||||
import { localImgLoad } from "../../lib";
|
||||
import background from "../../assets/images/bg-sky-blue.jpg";
|
||||
import FamilyWalletRedeemOptions from "./FamilyWalletRedeemOptions";
|
||||
|
||||
/**
|
||||
* Renders a list of wallet items or a loading spinner depending on the state of the `wallet` object.
|
||||
*/
|
||||
export default function FamilyWalletBox({ wallet, payment, countries }) {
|
||||
export default function FamilyWalletBox({ wallet, payment }) {
|
||||
const { loading, data } = wallet;
|
||||
|
||||
|
||||
const { userDetails } = useSelector((state) => state.userDetails);
|
||||
const accountType = userDetails?.account_type === "FAMILY";
|
||||
|
||||
const [selectedWallet, setSelectedWallet] = useState(data[0])
|
||||
|
||||
const [activeWalletBtn, setActiveWalletBtn] = useState(data[0].code)
|
||||
|
||||
const handleChangeWallet = ({target:{name}}) => { // FUNCTION TO SWITCH WALLET IF USER HAS MORE THAN TWO WALLETS
|
||||
const currentWalletSelected = data?.filter((item) => item.code == name);
|
||||
setSelectedWallet(currentWalletSelected[0])
|
||||
setActiveWalletBtn(name)
|
||||
// console.log(name, currentWalletSelected)
|
||||
}
|
||||
|
||||
const image = selectedWallet?.code
|
||||
? `${selectedWallet?.code.toLowerCase()}.svg`
|
||||
: "default.png";
|
||||
|
||||
|
||||
return (
|
||||
<div className="my-wallet-wrapper w-full mb-10">
|
||||
<div className="main-wrapper w-full">
|
||||
<div className="balance-inquery w-auto grid sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-[repeat(auto-fill,_minmax(354px,_1fr))] min-[1440px]:grid-cols-[repeat(auto-fill,_minmax(415px,_1fr))] gap-5 mb-11 h-auto">
|
||||
{loading ? (
|
||||
<div className="w-full h-full flex items-center justify-center bg-white">
|
||||
<LoadingSpinner size="16" color="sky-blue" height='h-[30rem]' />
|
||||
</div>
|
||||
) : (
|
||||
data.length > 0 && data.map((item) => (
|
||||
<div key={item.wallet_uid} className="lg:w-full h-full mb-10 lg:mb-0">
|
||||
<WalletItemCardFamily walletItem={item} payment={payment} countries={countries} />
|
||||
<div className="w-full">
|
||||
<div className="my-wallet-wrapper w-full mb-10">
|
||||
<div className="main-wrapper w-full">
|
||||
{loading ?
|
||||
<div className="w-full h-full flex items-center justify-center bg-white">
|
||||
<LoadingSpinner size="16" color="sky-blue" height='h-[30rem]' />
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
|
||||
: data.length > 0 ?
|
||||
<div className="w-full mb-10 sm:grid grid-cols-2 gap-4">
|
||||
<div className="w-full mb-4 sm:mb-0">
|
||||
<div className="wal-selection text-black dark:text-white flex items-center gap-2">
|
||||
{data.length > 1 && data.map(item =>(
|
||||
<button
|
||||
className={`py-0.5 px-1 mb-1 rounded-lg border border-orange-500 ${activeWalletBtn == item?.code && 'bg-orange-500'}`}
|
||||
key={item?.wallet_uid}
|
||||
name={item?.code}
|
||||
onClick={handleChangeWallet}
|
||||
>
|
||||
{item?.description}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="p-5 rounded-2xl bg-white-opacity min-h-[240px]"
|
||||
style={{
|
||||
background: `url(${background}) 0% 0% / cover no-repeat`,
|
||||
}}
|
||||
>
|
||||
{/* image */}
|
||||
<div className="min-w-[100px] min-h-[100px] max-w-min md:max-w-[120px] max-h-min md:max-h-[120px] rounded-full bg-[#e3e3e3] flex justify-center items-center">
|
||||
<img
|
||||
src={localImgLoad(`images/currency/${image}`)}
|
||||
className="w-full h-full"
|
||||
alt="currency-icon"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-base sm:text-lg text-white opacity-[70%] tracking-wide my-3">Current Balance</p>
|
||||
<p className="text-[44px] lg:text-[62px] font-bold text-white tracking-wide leading-10">
|
||||
{PriceFormatter(selectedWallet?.amount/100, selectedWallet?.code, undefined, "text-[2rem]")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-5 w-full rounded-2xl bg-white dark:bg-dark-white text-black dark:text-white h-full min-h-[240px] max-h-96">
|
||||
<h1 className="text-xl font-bold text-black dark:text-white">Recent Activities</h1>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<div className="w-full h-32 flex justify-center items-center rounded-2xl bg-white">
|
||||
<p>No Wallet Record Found</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full">
|
||||
<FamilyWalletRedeemOptions />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// data.length>0 && data.map((item) => (
|
||||
// <div key={item.wallet_uid} className="w-full h-full mb-10 ">
|
||||
// {/* <WalletItemCardFamily walletItem={item} payment={payment} countries={countries} /> */}
|
||||
// </div>
|
||||
// ))
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import SearchCom from '../Helpers/SearchCom'
|
||||
import LoadingSpinner from '../Spinners/LoadingSpinner';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
export default function FamilyWalletRedeemOptions() {
|
||||
|
||||
const { familyWalletRedeemOptList } = useSelector((state) => state.familyWalletRedeemOptList); // FAMILY WALLET REDDEM OPTIONS LIST
|
||||
|
||||
const [filteredRedeemData, setFilteredRedeemData] = useState({value: '', data:{}}) // State to hold filtered redeem banner option
|
||||
|
||||
const handleFilterRedeemData = ({target}) => {
|
||||
// thiskey01
|
||||
let filterWord = target.value
|
||||
let filteredData = {}
|
||||
if(!filterWord){
|
||||
filteredData = {...familyWalletRedeemOptList?.data}
|
||||
}else{
|
||||
let matchedData = Object.keys(familyWalletRedeemOptList?.data)?.filter(item => (item.toLowerCase().startsWith(filterWord.toLowerCase())))
|
||||
filteredData = matchedData.map(item => familyWalletRedeemOptList.data[item])
|
||||
}
|
||||
setFilteredRedeemData({value:target.value, data: {...filteredData}})
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
setFilteredRedeemData(prev => ({...prev, data:{...familyWalletRedeemOptList?.data}}))
|
||||
}, [familyWalletRedeemOptList.image])
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="w-full sm:flex items-center gap-4">
|
||||
<h1 className="text-2xl font-bold text-black dark:text-white">Redeem Options</h1>
|
||||
<div className="sm:w-1/2 w-full sm:pr-20 pr-0 mb-5 sm:mb-0">
|
||||
<SearchCom
|
||||
placeholder='Search...'
|
||||
value={filteredRedeemData.value}
|
||||
handleSearch={handleFilterRedeemData}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* redeem options */}
|
||||
{familyWalletRedeemOptList.loading ?
|
||||
<div className='mt-5 w-full h-[20rem] rounded-2xl bg-white dark:bg-dark-white text-black dark:text-white flex justify-center items-center'>
|
||||
<LoadingSpinner size='10' color='sky-blue' height='h-[30rem]' />
|
||||
</div>
|
||||
: Object.keys(familyWalletRedeemOptList?.data)?.length > 0 ?
|
||||
Object.keys(filteredRedeemData?.data)?.length ?
|
||||
<div className="mt-5 grid sm:grid-cols-2 lg:grid-cols-3 xxl:grid-cols-4 gap-4">
|
||||
{ Object.keys(filteredRedeemData?.data)?.map((item)=>{
|
||||
// text, image, description, action
|
||||
let newData = filteredRedeemData?.data[item].banner
|
||||
let bgImage = `url(${newData?.image})`
|
||||
return (
|
||||
<Link to={''} key={item}>
|
||||
<div className={`group relative h-60 text-black dark:text-white rounded-2xl shadow-lg hover:shadow-md transition-all duration-300 overflow-hidden`}
|
||||
style={{
|
||||
// background: `#ffffff ${bgImage} no-repeat center center / cover`
|
||||
}}
|
||||
>
|
||||
<img src={newData?.image} alt='Redeem Image' className='w-full h-full bg-cover rounded-2xl group-hover:scale-110 transition-all duration-300' />
|
||||
<div className='absolute bottom-0 mb-1 left-1/2 -translate-x-1/2 p-2 bg-white/80 rounded-2xl w-[90%] flex flex-col justify-center items-center gap-2'>
|
||||
<h1 className='text-lg font-bold text-[#083e21]'>{newData.text}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
:
|
||||
<div className='mt-5 w-full h-[20rem] rounded-2xl bg-white dark:bg-dark-white text-black dark:text-white flex justify-center items-center'>
|
||||
<p>Search Item not Found!</p>
|
||||
</div>
|
||||
:
|
||||
<div className='mt-5 w-full h-[20rem] rounded-2xl bg-white dark:bg-dark-white text-black dark:text-white flex justify-center items-center'>
|
||||
<p>No Redeem Options Found!</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import background from "../../assets/images/bg-sky-blue.jpg"; //shape/balance-bg
|
||||
import localImgLoad from "../../lib/localImgLoad";
|
||||
import { tableReload } from "../../store/TableReloads";
|
||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||
import CreditPopup from "./Popup/CreditPopup";
|
||||
import WalletAction from "./WalletAction";
|
||||
|
||||
/**
|
||||
@@ -13,26 +12,15 @@ import WalletAction from "./WalletAction";
|
||||
export default function WalletItemCardFamily({ walletItem, payment, countries }) {
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const [creditPopup, setCreditPopup] = useState({ show: false, data: {} });
|
||||
|
||||
/**
|
||||
* Opens the credit popup.
|
||||
* @param {Object} value - The value object.
|
||||
*/
|
||||
const openPopUp = (value) => {
|
||||
setCreditPopup({
|
||||
show: true,
|
||||
data: { ...value },
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Closes the credit popup and dispatches a table reload action.
|
||||
*/
|
||||
const closePopUp = () => {
|
||||
setCreditPopup({ show: false, data: {} });
|
||||
dispatch(tableReload({ type: "WALLETTABLE" }));
|
||||
};
|
||||
|
||||
const currentWalletCurrency = countries?.filter((country) => country.code === walletItem.country);
|
||||
|
||||
@@ -43,10 +31,10 @@ export default function WalletItemCardFamily({ walletItem, payment, countries })
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="current-balance-widget w-full h-full rounded-2xl overflow-hidden flex flex-col items-center gap-2 p-8 justify-between"
|
||||
style={{
|
||||
background: `url(${background}) 0% 0% / cover no-repeat`,
|
||||
}}
|
||||
className="current-balance-widget w-full h-full rounded-2xl overflow-hidden flex flex-col items-center gap-2 p-8 justify-between bg-family-header-bg"
|
||||
// style={{
|
||||
// background: `url(${background}) 0% 0% / cover no-repeat`,
|
||||
// }}
|
||||
>
|
||||
<div className="wallet w-full flex justify-between items-center gap-3">
|
||||
<div className="min-w-[100px] min-h-[100px] max-w-min md:max-w-[150px] max-h-min md:max-h-[150px] rounded-full bg-[#e3e3e3] flex justify-center items-center">
|
||||
@@ -72,24 +60,7 @@ export default function WalletItemCardFamily({ walletItem, payment, countries })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="my-2 w-full h-[1px] bg-white"></div>
|
||||
|
||||
{/* <WalletAction
|
||||
walletItem={{ ...walletItem, walletCountry: currentWalletCurrency }}
|
||||
payment={payment}
|
||||
openPopUp={openPopUp}
|
||||
/> */}
|
||||
</div>
|
||||
|
||||
{creditPopup.show && (
|
||||
<CreditPopup
|
||||
details={creditPopup.data}
|
||||
walletItem={walletItem}
|
||||
onClose={closePopUp}
|
||||
situation={openPopUp}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { updateUserJobList } from "../store/userJobList";
|
||||
import { updateWalletDetails } from "../store/walletDetails";
|
||||
import { familyBannersList } from "../store/FamilyBannerList";
|
||||
import { familyResources } from "../store/FamilyResources";
|
||||
import {familyWalletRedeemOptList} from '../store/FamilyWalletRedeemOpt'
|
||||
|
||||
const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||
const apiCall = useMemo(() => new usersService(), []);
|
||||
@@ -228,7 +229,7 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||
apiCall
|
||||
.getHeroJBanners()
|
||||
.then((res) => {
|
||||
if (res.data.internal_return < 0) {
|
||||
if (res.data?.internal_return < 0) {
|
||||
return;
|
||||
}
|
||||
dispatch(commonHeadBanner(res.data));
|
||||
@@ -291,6 +292,24 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||
}, [isLogin.status]);
|
||||
|
||||
|
||||
//FUNCTION TO GET FAMILY WALLET REDEEM OPTIONS
|
||||
useEffect(() => {
|
||||
if((!loggedIn && !isLogin.status) || account_type == 'FULL'){ // DO NOT CALL THIS, IF USER ACCOUNT TYPE IS FULL
|
||||
return
|
||||
}
|
||||
const familyWalletRedeemOptions = async () => { // FUNCTION TO GET FAMILY WALLET REDDEM OPTIONS
|
||||
dispatch(familyWalletRedeemOptList({loading: true, image: '', data:{}}))
|
||||
apiCall.getFamilyWalletRedeemOptions().then((res)=>{
|
||||
dispatch(familyWalletRedeemOptList({loading: false, image: res?.data?.session_image_server, data:res?.data?.result_list}))
|
||||
}).catch((err)=>{
|
||||
console.log(err)
|
||||
dispatch(familyWalletRedeemOptList({loading: false, image: '', data:{}}))
|
||||
})
|
||||
};
|
||||
familyWalletRedeemOptions()
|
||||
}, [isLogin.status]);
|
||||
|
||||
|
||||
// RENDER PAGE
|
||||
return isLogin.loading && !loggedIn ? (
|
||||
<LoadingSpinner size="32" color="sky-blue" height="h-screen" />
|
||||
|
||||
@@ -388,13 +388,26 @@ class usersService {
|
||||
uid: localStorage.getItem("uid"),
|
||||
member_id: localStorage.getItem("member_id"),
|
||||
sessionid: localStorage.getItem("session_token"),
|
||||
action: apiConst.WRENCHBOARD_JOB_CREATEJOB,
|
||||
action: apiConst.WRENCHBOARD_JOB_CREATEJOB || apiConst.WRENCHBOARD_FAMILY_LIST,
|
||||
limit: 30,
|
||||
offset: 0,
|
||||
};
|
||||
return this.postAuxEnd("/familywaitingtasks", postData);
|
||||
}
|
||||
|
||||
ManageFamilyNewWaitlist() {
|
||||
var postData = {
|
||||
uid: localStorage.getItem("uid"),
|
||||
member_id: localStorage.getItem("member_id"),
|
||||
sessionid: localStorage.getItem("session_token"),
|
||||
action: apiConst.WRENCHBOARD_FAMILY_LIST,
|
||||
limit: 20,
|
||||
page: 1,
|
||||
offset: 0,
|
||||
};
|
||||
return this.postAuxEnd("/familywaitingtasks", postData);
|
||||
}
|
||||
|
||||
ManageFamilyPending() {
|
||||
var postData = {
|
||||
uuid: localStorage.getItem("uid"),
|
||||
@@ -1292,6 +1305,19 @@ class usersService {
|
||||
};
|
||||
return this.postAuxEnd("/blogdata", postData);
|
||||
}
|
||||
|
||||
// API FUNCTION FOR FAMILY WALLET REDEEM OPTIONS
|
||||
getFamilyWalletRedeemOptions() {
|
||||
var postData = {
|
||||
uuid: localStorage.getItem("uid"),
|
||||
member_id: localStorage.getItem("member_id"),
|
||||
sessionid: localStorage.getItem("session_token"),
|
||||
action: apiConst.WRENCHBOARD_JOB_ACTIVE,
|
||||
offset: 0,
|
||||
limit: 30,
|
||||
};
|
||||
return this.postAuxEnd("/familywallet/redeem/options", postData);
|
||||
}
|
||||
|
||||
/*
|
||||
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(username)
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { createSlice } from "@reduxjs/toolkit";
|
||||
|
||||
const initialState = {
|
||||
familyWalletRedeemOptList: {loading: true, image: '', data: {}}
|
||||
};
|
||||
|
||||
export const familyWalletRedeemOptListSlice = createSlice({
|
||||
name: "familyWalletRedeemOptList",
|
||||
initialState,
|
||||
reducers: {
|
||||
familyWalletRedeemOptList: (state,action) => {
|
||||
state.familyWalletRedeemOptList = {...action.payload}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Action creators are generated for each case reducer function
|
||||
export const { familyWalletRedeemOptList } = familyWalletRedeemOptListSlice.actions;
|
||||
|
||||
export default familyWalletRedeemOptListSlice.reducer;
|
||||
@@ -9,6 +9,7 @@ const initialState = {
|
||||
walletTable: false,
|
||||
uploadsTable: false,
|
||||
familyBannersListTable: false,
|
||||
chatMessageList: false,
|
||||
};
|
||||
|
||||
export const tableReloadSlice = createSlice({
|
||||
@@ -41,6 +42,9 @@ export const tableReloadSlice = createSlice({
|
||||
case "FAMILYBANNERSLIST":
|
||||
state.familyBannersListTable = !state.familyBannersListTable;
|
||||
return;
|
||||
case "CHATMESSAGELIST":
|
||||
state.chatMessageList = !state.chatMessageList;
|
||||
return;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
+3
-1
@@ -10,6 +10,7 @@ import userJobListReducer from "./userJobList";
|
||||
import walletDetails from "./walletDetails";
|
||||
import familyBannerListReducer from "./FamilyBannerList"
|
||||
import familyResourcesReducer from './FamilyResources'
|
||||
import familyWalletRedeemOptListReducer from './FamilyWalletRedeemOpt'
|
||||
|
||||
export default configureStore({
|
||||
reducer: {
|
||||
@@ -22,6 +23,7 @@ export default configureStore({
|
||||
notifications: notificationsReducer,
|
||||
walletDetails: walletDetails,
|
||||
familyBannersList: familyBannerListReducer,
|
||||
familyResources: familyResourcesReducer
|
||||
familyResources: familyResourcesReducer,
|
||||
familyWalletRedeemOptList: familyWalletRedeemOptListReducer
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,12 +2,17 @@ import React, { useEffect, useState } from "react";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import ActiveJobs from "../components/MyActiveJobs/ActiveJobs";
|
||||
import usersService from "../services/UsersService";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
/**
|
||||
* This code defines a React functional component called `ManageActiveJobs`.
|
||||
* It fetches a list of active job messages and renders the `ActiveJobs` component with the necessary props.
|
||||
*/
|
||||
function ManageActiveJobs() {
|
||||
const { chatMessageList } = useSelector(
|
||||
(state) => state.tableReload
|
||||
);
|
||||
|
||||
const ApiCall = new usersService();
|
||||
|
||||
const navigate = useNavigate();
|
||||
@@ -54,7 +59,7 @@ function ManageActiveJobs() {
|
||||
}
|
||||
setDetails(state);
|
||||
getActiveJobMesList();
|
||||
}, [activeJobMesListReload]);
|
||||
}, [activeJobMesListReload, chatMessageList]);
|
||||
|
||||
return (
|
||||
<ActiveJobs
|
||||
|
||||
Reference in New Issue
Block a user