Compare commits
116 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3cd8b6e574 | |||
| 9850cdd392 | |||
| 6d98141c39 | |||
| 5fe5ccbd4d | |||
| 76c0994eb0 | |||
| a1bc6db381 | |||
| 6f5d72e033 | |||
| 762de4c23e | |||
| 2a8b7ba6ec | |||
| 50e44dab43 | |||
| 7649a90c47 | |||
| 3c2c46e293 | |||
| 8dc634d900 | |||
| 3a9cb4667e | |||
| 5f4b032f68 | |||
| 8ab3e9ae50 | |||
| 01b5fba75b | |||
| 66b8c96592 | |||
| 616352e1ac | |||
| acc4417835 | |||
| 7da693f298 | |||
| b0423c665c | |||
| 7089b8f14b | |||
| 2c2e2b0ca5 | |||
| ba3dd91d81 | |||
| 3f04c9f9f8 | |||
| 781f5cc5a6 | |||
| 58097d8b57 | |||
| 630ccefa51 | |||
| ed9f2dec0e | |||
| d2ed29c6a6 | |||
| 4e81156d72 | |||
| e402c02c1f | |||
| 5907b5d872 | |||
| 042cc4110c | |||
| 944fd134f6 | |||
| 5e6b208513 | |||
| 762601a5c3 | |||
| 1e28a0e15b | |||
| a910ab177f | |||
| 4e741f587c | |||
| f779529cc6 | |||
| 44cedf2f65 | |||
| fbcba191b0 | |||
| c64d372193 | |||
| abff42e0a8 | |||
| d5c342a57a | |||
| 60d6629526 | |||
| b1fbf89f10 | |||
| ae346d5ac5 | |||
| 75b5102766 | |||
| 9b12ffe0cd | |||
| 408165e718 | |||
| f7a0594447 | |||
| c733b006fb | |||
| 5a6b60578e | |||
| cdd998235e | |||
| 6e9efd7f43 | |||
| 07e9520774 | |||
| c1600a2a13 | |||
| 58e1745ac5 | |||
| 35db4fe536 | |||
| dfdbf404a5 | |||
| 985afa3c7b | |||
| 70d82d89b3 | |||
| 7f5eccb3b7 | |||
| 6729b780bd | |||
| 06224f121a | |||
| dc91649114 | |||
| 22f6eb436d | |||
| f2ab0cd6c9 | |||
| a2819786ae | |||
| 6cd92f6372 | |||
| 7173901c9b | |||
| 380d014964 | |||
| 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 |
@@ -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_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"
|
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"
|
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
|
||||||
|
|
||||||
REACT_APP_SESSION_EXPIRE_MINUTES=600000
|
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_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"
|
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"
|
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
|
||||||
|
|
||||||
REACT_APP_SESSION_EXPIRE_MINUTES=600000
|
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_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"
|
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"
|
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
|
||||||
|
|
||||||
REACT_APP_SESSION_EXPIRE_MINUTES=600000
|
REACT_APP_SESSION_EXPIRE_MINUTES=600000
|
||||||
|
|||||||
Vendored
+10
-1
@@ -21,5 +21,14 @@
|
|||||||
"emmet.triggerExpansionOnTab": true,
|
"emmet.triggerExpansionOnTab": true,
|
||||||
"emmet.includeLanguages": {
|
"emmet.includeLanguages": {
|
||||||
"javascript": "javascriptreact"
|
"javascript": "javascriptreact"
|
||||||
}
|
},
|
||||||
|
"cSpell.words": [
|
||||||
|
"completesignuplink",
|
||||||
|
"MOBILEUSER",
|
||||||
|
"MYFILES",
|
||||||
|
"mynotifications",
|
||||||
|
"PASSWORDRESET",
|
||||||
|
"TRANSFERSTART",
|
||||||
|
"WRENCHBOARD"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -21,9 +21,10 @@ services:
|
|||||||
- backend.wrenchboard.api.live:10.10.33.15
|
- backend.wrenchboard.api.live:10.10.33.15
|
||||||
- backend.wrenchboard.api.test:10.10.33.15
|
- backend.wrenchboard.api.test:10.10.33.15
|
||||||
- apigate.lotus.g1.wrenchboard.com:10.10.33.15
|
- apigate.lotus.g1.wrenchboard.com:10.10.33.15
|
||||||
|
- apigate.nebula.g1.wrenchboard.com:10.10.33.15
|
||||||
- apigate.orion.g1.wrenchboard.com:10.10.33.15
|
- apigate.orion.g1.wrenchboard.com:10.10.33.15
|
||||||
# #- backend.wrenchboard.api.live:172.31.4.27
|
- socket-dev.wrenchboard.com:10.10.33.15
|
||||||
# #- backend.wrenchboard.api.test:10.20.30.27
|
- socket.wrenchboard.com:10.10.33.15
|
||||||
- apigateway.wrenchboard.app.dev.fluxtra.net:10.20.30.19
|
- apigateway.wrenchboard.app.dev.fluxtra.net:10.20.30.19
|
||||||
- apigateway.wrenchboard.app.lotus.fluxtra.net:172.31.4.19
|
- apigateway.wrenchboard.app.lotus.fluxtra.net:172.31.4.19
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
"react-to-print": "^2.14.12",
|
"react-to-print": "^2.14.12",
|
||||||
"react-toastify": "^9.0.1",
|
"react-toastify": "^9.0.1",
|
||||||
"redux": "^4.2.0",
|
"redux": "^4.2.0",
|
||||||
|
"socket.io-client": "^4.4.1",
|
||||||
"slick-carousel": "^1.8.1",
|
"slick-carousel": "^1.8.1",
|
||||||
"web-vitals": "^1.0.1",
|
"web-vitals": "^1.0.1",
|
||||||
"yup": "^1.1.1"
|
"yup": "^1.1.1"
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ import { Navigate, useLocation } from "react-router-dom";
|
|||||||
import Routers from "./Routers";
|
import Routers from "./Routers";
|
||||||
import Toaster from "./components/Helpers/Toaster";
|
import Toaster from "./components/Helpers/Toaster";
|
||||||
import Default from "./components/Partials/Default";
|
import Default from "./components/Partials/Default";
|
||||||
|
import SocketIOContextProvider from "./components/Contexts/SocketIOContext";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
return (
|
return (
|
||||||
<Default>
|
<Default>
|
||||||
|
<SocketIOContextProvider>
|
||||||
<>
|
<>
|
||||||
{pathname.startsWith("/@") ? (
|
{pathname.startsWith("/@") ? (
|
||||||
<Navigate to="/app" replace={true} />
|
<Navigate to="/app" replace={true} />
|
||||||
@@ -15,6 +17,7 @@ function App() {
|
|||||||
)}
|
)}
|
||||||
<Toaster />
|
<Toaster />
|
||||||
</>
|
</>
|
||||||
|
</SocketIOContextProvider>
|
||||||
</Default>
|
</Default>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,9 +89,9 @@ function AddJob({ popUpHandler, categories }) {
|
|||||||
<div className="field w-full mb-6 xl:mb-0">
|
<div className="field w-full mb-6 xl:mb-0">
|
||||||
<label
|
<label
|
||||||
htmlFor="country"
|
htmlFor="country"
|
||||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex item-center gap-1"
|
className="job-label job-label-flex"
|
||||||
>
|
>
|
||||||
Currency
|
<span>Currency</span>
|
||||||
{props.errors.country && props.touched.country && (
|
{props.errors.country && props.touched.country && (
|
||||||
<span className="text-[12px] text-red-500">
|
<span className="text-[12px] text-red-500">
|
||||||
{props.errors.country}
|
{props.errors.country}
|
||||||
@@ -136,9 +136,9 @@ function AddJob({ popUpHandler, categories }) {
|
|||||||
{/* Price */}
|
{/* Price */}
|
||||||
<div className="field w-full">
|
<div className="field w-full">
|
||||||
<InputCom
|
<InputCom
|
||||||
fieldClass="px-6 text-right"
|
fieldClass="px-6 text-right flex"
|
||||||
label="Price"
|
label="Price"
|
||||||
labelClass="tracking-wide"
|
labelClass=""
|
||||||
type="number"
|
type="number"
|
||||||
name="price"
|
name="price"
|
||||||
placeholder="0"
|
placeholder="0"
|
||||||
@@ -159,7 +159,7 @@ function AddJob({ popUpHandler, categories }) {
|
|||||||
<InputCom
|
<InputCom
|
||||||
fieldClass="px-6"
|
fieldClass="px-6"
|
||||||
label="Title"
|
label="Title"
|
||||||
labelClass="tracking-wide"
|
labelClass=""
|
||||||
type="text"
|
type="text"
|
||||||
name="title"
|
name="title"
|
||||||
value={props.values.title}
|
value={props.values.title}
|
||||||
@@ -178,7 +178,7 @@ function AddJob({ popUpHandler, categories }) {
|
|||||||
<InputCom
|
<InputCom
|
||||||
fieldClass="px-6"
|
fieldClass="px-6"
|
||||||
label="Description"
|
label="Description"
|
||||||
labelClass="tracking-wide"
|
labelClass=""
|
||||||
type="text"
|
type="text"
|
||||||
name="description"
|
name="description"
|
||||||
value={props.values.description}
|
value={props.values.description}
|
||||||
@@ -197,7 +197,7 @@ function AddJob({ popUpHandler, categories }) {
|
|||||||
<div className="sm:w-[60%] w-full">
|
<div className="sm:w-[60%] w-full">
|
||||||
<label
|
<label
|
||||||
htmlFor="Job Delivery Details"
|
htmlFor="Job Delivery Details"
|
||||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1"
|
className="job-label job-label-flex"
|
||||||
>
|
>
|
||||||
Job Delivery Details
|
Job Delivery Details
|
||||||
{props.errors.job_detail &&
|
{props.errors.job_detail &&
|
||||||
@@ -220,13 +220,13 @@ function AddJob({ popUpHandler, categories }) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="sm:w-[35%] w-full">
|
<div className="sm:w-[35%] w-full">
|
||||||
<div
|
<label
|
||||||
htmlFor="Job Categories"
|
htmlFor="Job Categories"
|
||||||
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'
|
className='job-label'
|
||||||
id="checked-group"
|
id="checked-group"
|
||||||
>
|
>
|
||||||
Categories
|
Categories
|
||||||
</div>
|
</label>
|
||||||
<div
|
<div
|
||||||
className="sm:flex-col flex flex-wrap px-3 mt-3"
|
className="sm:flex-col flex flex-wrap px-3 mt-3"
|
||||||
role="group"
|
role="group"
|
||||||
@@ -266,7 +266,7 @@ function AddJob({ popUpHandler, categories }) {
|
|||||||
<div className="field w-full mb-[5px]">
|
<div className="field w-full mb-[5px]">
|
||||||
<div className={`flex items-center justify-between mb-2.5`}>
|
<div className={`flex items-center justify-between mb-2.5`}>
|
||||||
<label
|
<label
|
||||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
|
className="job-label"
|
||||||
htmlFor="timeline_days"
|
htmlFor="timeline_days"
|
||||||
>
|
>
|
||||||
Timeline
|
Timeline
|
||||||
@@ -328,10 +328,10 @@ function AddJob({ popUpHandler, categories }) {
|
|||||||
<div className="flex items-center space-x-4 mr-9">
|
<div className="flex items-center space-x-4 mr-9">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="text-18 text-light-red tracking-wide "
|
className="text-18 tracking-wide h-11 flex justify-center items-center border border-light-red text-base rounded-full text-light-red cursor-pointer"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="border-b dark:border-[#5356fb29] border-light-red"
|
className="px-2"
|
||||||
onClick={popUpHandler}
|
onClick={popUpHandler}
|
||||||
>
|
>
|
||||||
{" "}
|
{" "}
|
||||||
|
|||||||
@@ -145,8 +145,9 @@ export default function Login() {
|
|||||||
localStorage.setItem("member_id", `${res.data.member_id}`);
|
localStorage.setItem("member_id", `${res.data.member_id}`);
|
||||||
localStorage.setItem("uid", `${res.data.uid}`);
|
localStorage.setItem("uid", `${res.data.uid}`);
|
||||||
localStorage.setItem("session_token", `${res.data.session}`);
|
localStorage.setItem("session_token", `${res.data.session}`);
|
||||||
if (name === "family") {
|
if (res.data?.account_type == "FAMILY") {
|
||||||
sessionStorage.setItem("family_uid", res.data?.family_uid);
|
sessionStorage.setItem("family_uid", res.data?.family_uid);
|
||||||
|
sessionStorage.setItem("parent_uid", res.data?.parent_uid);
|
||||||
}
|
}
|
||||||
// localStorage.setItem("session", `${res.data.session}`);
|
// localStorage.setItem("session", `${res.data.session}`);
|
||||||
dispatch(updateUserDetails({ ...res.data }));
|
dispatch(updateUserDetails({ ...res.data }));
|
||||||
|
|||||||
@@ -1,22 +1,25 @@
|
|||||||
import React from 'react'
|
import React from "react";
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
export default function CustomBreadcrumb({title, breadcrumb}) {
|
export default function CustomBreadcrumb({ title, breadcrumb }) {
|
||||||
return (
|
return (
|
||||||
<div className="">
|
<div className="">
|
||||||
<h3 className="text-26 font-bold text-dark-gray dark:text-white">{title}</h3>
|
<h3 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||||
<nav aria-label="breadcrumb" className='text-base text-dark-gray dark:text-white flex items-center'>
|
{title}
|
||||||
|
</h3>
|
||||||
|
<nav
|
||||||
|
aria-label="breadcrumb"
|
||||||
|
className="text-base text-dark-gray dark:text-white flex items-center"
|
||||||
|
>
|
||||||
{breadcrumb.map((value, index) => (
|
{breadcrumb.map((value, index) => (
|
||||||
<p key={index}>
|
<React.Fragment key={index}>
|
||||||
<Link className={`${value.active ? 'opacity-60' : ''}`} to={value.link}>{value.title}</Link>
|
<Link className={value.active ? "opacity-60" : ""} to={value.link}>
|
||||||
{index != breadcrumb.length - 1 ?
|
{value.title}
|
||||||
<span className='px-1'>/</span>
|
</Link>
|
||||||
:
|
{index !== breadcrumb.length - 1 && <span className="px-1">\</span>}
|
||||||
null
|
</React.Fragment>
|
||||||
}
|
|
||||||
</p>
|
|
||||||
))}
|
))}
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
import React, { createContext, useContext, useEffect, useState } from "react";
|
||||||
|
import { tableReload } from "../../store/TableReloads";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
||||||
|
import io from "socket.io-client";
|
||||||
|
|
||||||
|
let SocketIOContext = createContext({})
|
||||||
|
|
||||||
|
export default function SocketIOContextProvider({children}) {
|
||||||
|
const {userDetails} = useSelector((state) => state?.userDetails); // CHECKS IF USER UID, to determine if user is active
|
||||||
|
|
||||||
|
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 });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const marketUpdate = (message, room) => {
|
||||||
|
if(message && room){
|
||||||
|
socket.emit("marketjob_added", { message, room });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const parentAssignJobToKid = (message, room) => {
|
||||||
|
if(message && room){
|
||||||
|
socket.emit("family", { message:{...message}, room });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const sendJobInterestToOwner = (message, room) => {
|
||||||
|
if(message && room){
|
||||||
|
socket.emit("marketjob", { message:{...message}, room });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
socket.on("receive_message", (data) => {
|
||||||
|
// setSocketMsgReceived(data.message);
|
||||||
|
dispatch(tableReload({type:'CHATMESSAGELIST'})) // dispatches to update chat message sending from owner to worker and vice versa
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("received_refreshmarket_jobs", (data) => {
|
||||||
|
// setSocketMsgReceived(data.message);
|
||||||
|
dispatch(tableReload({type:'MARKETTABLELIST'})) // dispatches to update market list on full account
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("family_actions", (data) => {
|
||||||
|
// setSocketMsgReceived(data.message);
|
||||||
|
let user_uid = userDetails.account_type == 'FULL' ? userDetails.uid : sessionStorage.getItem('family_uid') // gets user UID
|
||||||
|
let {message} = data
|
||||||
|
if(message.action == "REFRESH_OFFER" && message.family_uid == user_uid && message.audience == "MEMBER"){ // for refreshing child account when parent assigns a job
|
||||||
|
dispatch(tableReload({type:'FAMILYOFFERLIST'})) // dispatches to update family pending/offer list on family side
|
||||||
|
}
|
||||||
|
if(message.action == "REFRESH_TASK" && message.audience == "PARENT"){ // for refreshing parent account when child accepts or rejects a job
|
||||||
|
dispatch(tableReload({type:'PARENTFAMILYTASKLIST'})) // dispatches to update parent family task list on parent side
|
||||||
|
}
|
||||||
|
if(message.action == "REFRESH_WALLET" && message.family_uid == user_uid && message.audience == "MEMBER"){ // for refreshing child wallet account when parent sends money to kid
|
||||||
|
dispatch(tableReload({type:'WALLETTABLE'})) // dispatches to update wallet balance on family side
|
||||||
|
}
|
||||||
|
// console.log('DATA', data)
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("marketjob_actions", (data) => { // Triggers refresh on owner side, when somebody sends/shows interest in a job
|
||||||
|
// let user_uid = userDetails.account_type == 'FULL' ? userDetails.uid : sessionStorage.getItem('family_uid') // gets user UID
|
||||||
|
let {message} = data
|
||||||
|
if(message.action == "REFRESH_OFFERS" && message.audience == "MERCHANT"){ // for refreshing job owner offer interest list when any worker sends interest
|
||||||
|
dispatch(tableReload({type:'OFFERINTERESTLISTRELOAD'}))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}, [socket]);
|
||||||
|
|
||||||
|
let values = {
|
||||||
|
socket,
|
||||||
|
sendMessage,
|
||||||
|
joinRoom,
|
||||||
|
setSocketMsgReceived,
|
||||||
|
marketUpdate,
|
||||||
|
parentAssignJobToKid,
|
||||||
|
sendJobInterestToOwner,
|
||||||
|
socketMsgReceived,
|
||||||
|
// room,
|
||||||
|
// setRoom,
|
||||||
|
// message,
|
||||||
|
// setMessage,
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SocketIOContext.Provider value={values}>
|
||||||
|
{children}
|
||||||
|
</SocketIOContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const SocketValues = () => {
|
||||||
|
return useContext(SocketIOContext)
|
||||||
|
}
|
||||||
@@ -29,14 +29,15 @@ const AccountDashboard = ({ className, bannerList }) => {
|
|||||||
props;
|
props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div key={idx}>
|
||||||
<TopBanner
|
<TopBanner
|
||||||
btn={short_button_text}
|
btn={short_button_text}
|
||||||
image={image}
|
image={image}
|
||||||
title={short_title}
|
title={short_title}
|
||||||
desc={short_description}
|
desc={short_description}
|
||||||
link_path={link_path}
|
link_path={link_path}
|
||||||
key={idx}
|
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
@@ -48,14 +49,15 @@ const AccountDashboard = ({ className, bannerList }) => {
|
|||||||
props;
|
props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div key={idx}>
|
||||||
<LowerBanner
|
<LowerBanner
|
||||||
btn={short_button_text}
|
btn={short_button_text}
|
||||||
image={image}
|
image={image}
|
||||||
title={short_title}
|
title={short_title}
|
||||||
desc={short_description}
|
desc={short_description}
|
||||||
link_path={link_path}
|
link_path={link_path}
|
||||||
key={idx}
|
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
import React, { Suspense, useMemo, useState } from "react";
|
import React, { Suspense } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import usersService from "../../services/UsersService";
|
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||||
import Layout from "../Partials/Layout";
|
import Layout from "../Partials/Layout";
|
||||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
import FamilyTableNew from "./FamilyTableNew";
|
import FamilyTableNew from "./FamilyTableNew";
|
||||||
|
|
||||||
export default function FamilyActivities() {
|
export default function FamilyActivities() {
|
||||||
const [familyList, setFamilyList] = useState({});
|
|
||||||
const [loader, setLoader] = useState(false);
|
|
||||||
|
|
||||||
const apiCall = useMemo(() => new usersService(), []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
{/*<CommonHead />*/}
|
{/*<CommonHead />*/}
|
||||||
@@ -19,11 +14,26 @@ export default function FamilyActivities() {
|
|||||||
{/* heading */}
|
{/* heading */}
|
||||||
<div className="sm:flex justify-between items-center mb-6">
|
<div className="sm:flex justify-between items-center mb-6">
|
||||||
<div className="mb-5 sm:mb-0">
|
<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">
|
<CustomBreadcrumb
|
||||||
<span className={``}>Tasks & Chores</span>
|
title={"Tasks & Chores"}
|
||||||
</h1>
|
breadcrumb={[
|
||||||
|
{ link: "/", title: "Home" },
|
||||||
|
{
|
||||||
|
link: "/acc-family",
|
||||||
|
title: "Family Account",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link: "/acc-family/activities",
|
||||||
|
title: "Tasks & Chores",
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</div>
|
</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
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
fill="none"
|
fill="none"
|
||||||
@@ -42,12 +52,14 @@ export default function FamilyActivities() {
|
|||||||
<span>Family</span>
|
<span>Family</span>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<Suspense fallback={<LoadingSpinner color="sky-blue" size="16" />}>
|
<Suspense
|
||||||
<FamilyTableNew
|
fallback={
|
||||||
familyList={familyList?.result_list}
|
<div className="bg-white">
|
||||||
loader={loader}
|
<LoadingSpinner color="sky-blue" size="16" height='h-[30rem]' />
|
||||||
imageServer={familyList?.session_image_server}
|
</div>
|
||||||
/>
|
}
|
||||||
|
>
|
||||||
|
<FamilyTableNew />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useLocation, useNavigate } from "react-router-dom";
|
import { Link, useLocation, useNavigate } from "react-router-dom";
|
||||||
import Layout from "../Partials/Layout";
|
import Layout from "../Partials/Layout";
|
||||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
import FamilyManageTabs from "./FamilyManageTabs";
|
import FamilyManageTabs from "./FamilyManageTabs";
|
||||||
|
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||||
|
|
||||||
export default function FamilyManage() {
|
export default function FamilyManage() {
|
||||||
const [selectTab, setValue] = useState("today");
|
const [selectTab, setValue] = useState("today");
|
||||||
@@ -34,7 +35,7 @@ export default function FamilyManage() {
|
|||||||
<div className="notification-page w-full mb-10">
|
<div className="notification-page w-full mb-10">
|
||||||
<div className="notification-wrapper w-full">
|
<div className="notification-wrapper w-full">
|
||||||
{/* heading */}
|
{/* heading */}
|
||||||
<div className="sm:flex justify-between items-center mb-6">
|
{/* <div className="sm:flex justify-between items-center mb-6">
|
||||||
<div className="mb-5 sm:mb-0">
|
<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">
|
<h1 className="text-26 font-bold inline-flex gap-3 text-dark-gray dark:text-white items-center">
|
||||||
<span
|
<span
|
||||||
@@ -50,6 +51,40 @@ export default function FamilyManage() {
|
|||||||
className="relative"
|
className="relative"
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
|
</div> */}
|
||||||
|
<div className="w-full mb-5 flex justify-between items-center">
|
||||||
|
<div className="">
|
||||||
|
<CustomBreadcrumb
|
||||||
|
title = {'Manage Family'}
|
||||||
|
breadcrumb={
|
||||||
|
[
|
||||||
|
{ link: "/", title: "Home" },
|
||||||
|
{ link: "/manage-family", title: "Manage Family", active: true},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<span>Family</span>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<FamilyManageTabs accountDetails={accountDetails} />
|
<FamilyManageTabs accountDetails={accountDetails} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -187,6 +187,7 @@ export default function FamilyManageTabs({
|
|||||||
familyData={details.familyWaitList.data}
|
familyData={details.familyWaitList.data}
|
||||||
accountDetails={accountDetails}
|
accountDetails={accountDetails}
|
||||||
loader={details.familyWaitList.loading}
|
loader={details.familyWaitList.loading}
|
||||||
|
setUpdatePage={setUpdatePage}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
Pending: (
|
Pending: (
|
||||||
|
|||||||
@@ -4,39 +4,29 @@ import MyOffersFamilyTable from '../MyTasks/MyOffersFamilyTable'
|
|||||||
import LoadingSpinner from '../Spinners/LoadingSpinner';
|
import LoadingSpinner from '../Spinners/LoadingSpinner';
|
||||||
import usersService from '../../services/UsersService';
|
import usersService from '../../services/UsersService';
|
||||||
import CustomBreadcrumb from '../Breadcrumb/CustomBreadcrumb';
|
import CustomBreadcrumb from '../Breadcrumb/CustomBreadcrumb';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
export default function FamilyPendingOffer() {
|
export default function FamilyPendingOffer() {
|
||||||
const userApi = new usersService();
|
const userApi = new usersService();
|
||||||
|
|
||||||
|
const {familyOfferList} = useSelector((state) => state.tableReload)
|
||||||
|
|
||||||
const [myOffersList, setMyOffersList] = useState({loading: true, data: []});
|
const [myOffersList, setMyOffersList] = useState({loading: true, data: []});
|
||||||
|
|
||||||
const getMyOffersList = async () => {
|
const getMyOffersList = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await userApi.getOffersList();
|
const res = await userApi.getOffersList();
|
||||||
setMyOffersList({loading:false, data:res.data});
|
setMyOffersList({loading:false, data:res.data});
|
||||||
console.log('SAME', res.data)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setMyOffersList({loading:false, data:[]});
|
setMyOffersList({loading:false, data:[]});
|
||||||
console.log("Error getting offers", error);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
getMyOffersList()
|
getMyOffersList()
|
||||||
},[])
|
},[familyOfferList])
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<div className="mb-5">
|
|
||||||
<CustomBreadcrumb
|
|
||||||
title = {'Ready to Start'}
|
|
||||||
breadcrumb={
|
|
||||||
[
|
|
||||||
{ link: "/", title: "Home" },
|
|
||||||
{ link: "/pending", title: "Pending", active: true},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{myOffersList.loading ?
|
{myOffersList.loading ?
|
||||||
<div className='w-full flex justify-center items-center rounded-2xl bg-white'>
|
<div className='w-full flex justify-center items-center rounded-2xl bg-white'>
|
||||||
<LoadingSpinner size='10' color='sky-blue' height='h-[20rem]' />
|
<LoadingSpinner size='10' color='sky-blue' height='h-[20rem]' />
|
||||||
@@ -49,9 +39,22 @@ export default function FamilyPendingOffer() {
|
|||||||
className="mb-10"
|
className="mb-10"
|
||||||
/>
|
/>
|
||||||
:
|
:
|
||||||
|
<>
|
||||||
|
<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'>
|
<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>
|
<p className='text-black dark:text-white'>No Record Found!</p>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
</Layout>
|
</Layout>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
import React, { useState } from "react";
|
import React, { Suspense, useEffect, useState } from "react";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import { useLocation } from "react-router-dom";
|
||||||
import usersService from "../../../services/UsersService";
|
import usersService from "../../../services/UsersService";
|
||||||
|
import { tableReload } from "../../../store/TableReloads";
|
||||||
import ModalCom from "../../Helpers/ModalCom";
|
import ModalCom from "../../Helpers/ModalCom";
|
||||||
import { PriceFormatter } from "../../Helpers/PriceFormatter";
|
import { PriceFormatter } from "../../Helpers/PriceFormatter";
|
||||||
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||||
import Detail from "../../jobPopout/popoutcomponent/Detail";
|
import Detail from "../../jobPopout/popoutcomponent/Detail";
|
||||||
import { NewTasks } from "./forms";
|
import { NewTasks } from "./forms";
|
||||||
import { tableReload } from "../../../store/TableReloads";
|
import { SocketValues } from "../../Contexts/SocketIOContext";
|
||||||
import { useDispatch } from "react-redux";
|
|
||||||
|
|
||||||
const AssignTaskPopout = React.memo(
|
const AssignTaskPopout = ({
|
||||||
({
|
|
||||||
action,
|
action,
|
||||||
details,
|
details,
|
||||||
situation,
|
situation,
|
||||||
@@ -17,11 +18,34 @@ const AssignTaskPopout = React.memo(
|
|||||||
familyTask,
|
familyTask,
|
||||||
activeTask,
|
activeTask,
|
||||||
setActiveTask,
|
setActiveTask,
|
||||||
setUpdatePage
|
setUpdatePage,
|
||||||
}) => {
|
assignTaskChecker,
|
||||||
|
|
||||||
|
}) => {
|
||||||
|
const {parentAssignJobToKid} = SocketValues()
|
||||||
|
|
||||||
const apiCall = new usersService();
|
const apiCall = new usersService();
|
||||||
|
|
||||||
const dispatch = useDispatch()
|
let { pathname, state } = useLocation();
|
||||||
|
|
||||||
|
const {userDetails} = useSelector((state) => state?.userDetails); // CHECKS IF USER Details are avaliable, to determine if user is active
|
||||||
|
|
||||||
|
const [selectedFamilyUid, setSelectedFamilyUid] = useState('');
|
||||||
|
|
||||||
|
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({
|
let [requestStatus, setRequestStatus] = useState({
|
||||||
loading: false,
|
loading: false,
|
||||||
@@ -56,6 +80,14 @@ const AssignTaskPopout = React.memo(
|
|||||||
|
|
||||||
const assignFamilyTask = () => {
|
const assignFamilyTask = () => {
|
||||||
setRequestStatus({ loading: true, status: false, message: "" });
|
setRequestStatus({ loading: true, status: false, message: "" });
|
||||||
|
|
||||||
|
if(!selectedFamilyUid){ // If no family found, throw error
|
||||||
|
setRequestStatus({ loading: false, status: false, message: "Please Select a Kid" });
|
||||||
|
return setTimeout(() => {
|
||||||
|
setRequestStatus({ loading: false, status: false, message: "" });
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
let reqData = {};
|
let reqData = {};
|
||||||
if (taskType == "select") {
|
if (taskType == "select") {
|
||||||
// RUNS HERE IF TASK TYPE IS SELECT
|
// RUNS HERE IF TASK TYPE IS SELECT
|
||||||
@@ -73,7 +105,9 @@ const AssignTaskPopout = React.memo(
|
|||||||
// API PAYLOADS
|
// API PAYLOADS
|
||||||
job_id: activeTask.data?.job_id,
|
job_id: activeTask.data?.job_id,
|
||||||
job_uid: activeTask.data?.job_uid,
|
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,
|
job_description: activeTask.data?.description,
|
||||||
assign_mode: 110011,
|
assign_mode: 110011,
|
||||||
};
|
};
|
||||||
@@ -94,11 +128,11 @@ const AssignTaskPopout = React.memo(
|
|||||||
const requiredFields = {
|
const requiredFields = {
|
||||||
banner,
|
banner,
|
||||||
// category,
|
// category,
|
||||||
currency:country,
|
currency: country,
|
||||||
description,
|
description,
|
||||||
'job detail':job_detail,
|
"job detail": job_detail,
|
||||||
price,
|
price,
|
||||||
timeline:timeline_days,
|
timeline: timeline_days,
|
||||||
title,
|
title,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -108,7 +142,9 @@ const AssignTaskPopout = React.memo(
|
|||||||
setRequestStatus({
|
setRequestStatus({
|
||||||
loading: false,
|
loading: false,
|
||||||
status: 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(() => {
|
return setTimeout(() => {
|
||||||
setRequestStatus({ loading: false, status: false, message: "" });
|
setRequestStatus({ loading: false, status: false, message: "" });
|
||||||
@@ -126,7 +162,9 @@ const AssignTaskPopout = React.memo(
|
|||||||
timeline_days,
|
timeline_days,
|
||||||
title,
|
title,
|
||||||
assign_mode: 110055,
|
assign_mode: 110055,
|
||||||
family_uid: details?.family_uid || familyDetailsData?.uid,
|
family_uid: selectedFamilyUid
|
||||||
|
? selectedFamilyUid
|
||||||
|
: familyDetailsData?.uid || details?.family_uid,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,21 +177,38 @@ const AssignTaskPopout = React.memo(
|
|||||||
status: false,
|
status: false,
|
||||||
message: "failed to assign task",
|
message: "failed to assign task",
|
||||||
});
|
});
|
||||||
|
|
||||||
return setTimeout(() => {
|
return setTimeout(() => {
|
||||||
setRequestStatus({ loading: false, status: false, message: "" });
|
setRequestStatus({ loading: false, status: false, message: "" });
|
||||||
}, 5000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
|
if (res.status === 200) {
|
||||||
|
|
||||||
setRequestStatus({
|
setRequestStatus({
|
||||||
loading: false,
|
loading: false,
|
||||||
status: true,
|
status: true,
|
||||||
message: "action successful",
|
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
|
dispatch(tableReload({ type: "WALLETTABLE" })); // RELOADS USER WALLET
|
||||||
|
|
||||||
|
//SENDS MESSAGE TO SOCKET TO UPDATE CHILD ACCOUNT
|
||||||
|
// message, room
|
||||||
|
let socketMsg = {
|
||||||
|
"audience": "MEMBER",
|
||||||
|
"action": "REFRESH_OFFER",
|
||||||
|
"family_uid": reqData.family_uid,
|
||||||
|
}
|
||||||
|
let socketRoom = `FAMILY-${userDetails.uid}`
|
||||||
|
parentAssignJobToKid(socketMsg, socketRoom) //SENDS MESSAGE TO SOCKET TO UPDATE CHILD ACCOUNT
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setRequestStatus({ loading: false, status: false, message: "" });
|
setRequestStatus({ loading: false, status: false, message: "" });
|
||||||
action(); // FUNCTION THAT CLOSES THE MODAL BOX
|
action(); // FUNCTION THAT CLOSES THE MODAL BOX
|
||||||
}, 5000);
|
}, 5000);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
setRequestStatus({
|
setRequestStatus({
|
||||||
@@ -161,27 +216,60 @@ const AssignTaskPopout = React.memo(
|
|||||||
status: false,
|
status: false,
|
||||||
message: "An Error occured, try again",
|
message: "An Error occured, try again",
|
||||||
});
|
});
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setRequestStatus({ loading: false, status: false, message: "" });
|
setRequestStatus({ loading: false, status: false, message: "" });
|
||||||
}, 5000);
|
}, 5000);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let imageSrc = (localStorage.getItem("session_token")
|
||||||
|
? `${userDetails?.session_image_server}${localStorage.getItem("session_token")}/job/${activeTask.data.job_uid}` : ""); // FOR GETTING JOB IMAGE
|
||||||
|
|
||||||
|
useEffect(()=>{ // effect to update family UID when components mounts
|
||||||
|
if(familyDetailsData?.uid){
|
||||||
|
setSelectedFamilyUid(familyDetailsData?.uid)
|
||||||
|
}else if(details?.family_uid){
|
||||||
|
setSelectedFamilyUid(details?.family_uid)
|
||||||
|
}else{
|
||||||
|
setSelectedFamilyUid('')
|
||||||
|
}
|
||||||
|
},[])
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ModalCom
|
<ModalCom action={action} situation={situation}>
|
||||||
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-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">
|
<div className="modal-header-con">
|
||||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="modal-title">
|
||||||
Assign task to{" "}
|
{details ? (
|
||||||
{familyDetailsData?.firstname || details?.firstName}
|
` Assign ${details?.firstname}'s Task`
|
||||||
|
) : familyDetailsData ? (
|
||||||
|
` Assign ${familyDetailsData.firstname}'s Task`
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="text-black">Assign task to{" "}</span>
|
||||||
|
<div className="w-[270px] h-[40px] flex items-center">
|
||||||
|
<select
|
||||||
|
name=""
|
||||||
|
id=""
|
||||||
|
className="text-lg text-black/80 px-2 tracking-wide font-semibold transition-all cursor-pointer bg-white focus:outline-none border border-gray-200 rounded-full w-full h-full"
|
||||||
|
onChange={handleFamChange}
|
||||||
|
value={selectedFamilyUid}
|
||||||
|
>
|
||||||
|
<option value="" className="">
|
||||||
|
Select a kid
|
||||||
|
</option>
|
||||||
|
{familyList}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</h1>
|
</h1>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="text-[#374557] dark:text-red-500"
|
className="modal-close-btn"
|
||||||
onClick={action}
|
onClick={action}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
@@ -249,9 +337,7 @@ const AssignTaskPopout = React.memo(
|
|||||||
<div
|
<div
|
||||||
key={item.job_uid}
|
key={item.job_uid}
|
||||||
className="mb-2 flex justify-start items-center gap-2 text-sky-blue text-base cursor-pointer"
|
className="mb-2 flex justify-start items-center gap-2 text-sky-blue text-base cursor-pointer"
|
||||||
onClick={() =>
|
onClick={() => handleActiveTask(item.job_uid, item)}
|
||||||
handleActiveTask(item.job_uid, item)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
@@ -302,9 +388,10 @@ const AssignTaskPopout = React.memo(
|
|||||||
value={activeTask?.data?.description}
|
value={activeTask?.data?.description}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center">
|
<div className="grid grid-cols-2">
|
||||||
|
<div className="w-full">
|
||||||
<div className="my-3 w-full flex items-center gap-1">
|
<div className="my-3 w-full flex items-center gap-1">
|
||||||
<label className="text-slate-900 dark:text-white tracking-wide font-semibold">
|
<label className="job-label">
|
||||||
Price
|
Price
|
||||||
</label>
|
</label>
|
||||||
<p className="p-1 text-sm text-slate-900 dark:text-white">
|
<p className="p-1 text-sm text-slate-900 dark:text-white">
|
||||||
@@ -317,22 +404,34 @@ const AssignTaskPopout = React.memo(
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="my-3 w-full flex items-center gap-1">
|
<div className="my-3 w-full flex items-center gap-1">
|
||||||
<label className="text-slate-900 dark:text-white tracking-wide font-semibold">
|
<label className="job-label">
|
||||||
Timeline
|
Timeline
|
||||||
</label>
|
</label>
|
||||||
<p className="p-1 text-sm text-slate-900 dark:text-white">{`${activeTask?.data?.timeline_days} day(s)`}</p>
|
<p className="p-1 text-sm text-slate-900 dark:text-white">{`${activeTask?.data?.timeline_days} day(s)`}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="w-full flex items-center justify-center">
|
||||||
|
<div className="w-28 h-28 rounded-2xl flex items-center justify-center">
|
||||||
|
<img
|
||||||
|
className="w-full h-auto"
|
||||||
|
loading="lazy"
|
||||||
|
src={imageSrc}
|
||||||
|
alt='job image'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="my-3 sm:flex items-center">
|
{/* Dummy, no value found for created! thus commented*/}
|
||||||
|
{/* <div className="my-3 sm:flex items-center">
|
||||||
<Detail
|
<Detail
|
||||||
label="Created"
|
label="Created"
|
||||||
value={`Dummy, no value found for created!`}
|
value={`Dummy, no value found for created!`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="my-3">
|
<div className="my-3">
|
||||||
<label className="w-full text-slate-900 dark:text-white tracking-wide font-semibold">
|
<label className="w-full job-label">
|
||||||
Delivery Detail
|
Delivery Detail
|
||||||
</label>
|
</label>
|
||||||
<textarea
|
<textarea
|
||||||
@@ -354,7 +453,7 @@ const AssignTaskPopout = React.memo(
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* BTN */}
|
{/* BTN */}
|
||||||
<div className="py-2 px-4 border-t-2 flex justify-between items-center">
|
<div className="modal-footer-wrapper">
|
||||||
{/* error or success display */}
|
{/* error or success display */}
|
||||||
<div className="w-auto h-auto flex items-center">
|
<div className="w-auto h-auto flex items-center">
|
||||||
{requestStatus.message != "" &&
|
{requestStatus.message != "" &&
|
||||||
@@ -376,39 +475,43 @@ const AssignTaskPopout = React.memo(
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* End of error or success display */}
|
{/* End of error or success display */}
|
||||||
<div className="w-auto h-auto flex items-center gap-3">
|
<div className="w-auto h-auto flex items-center gap-20">
|
||||||
<button
|
<button
|
||||||
disabled={requestStatus.loading}
|
disabled={requestStatus.loading}
|
||||||
onClick={action}
|
onClick={action}
|
||||||
type="button"
|
type="button"
|
||||||
className="w-20 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white cursor-pointer"
|
className="custom-btn border-gradient"
|
||||||
>
|
>
|
||||||
<span className="text-gradient">Close</span>
|
<span className="text-gradient">Close</span>
|
||||||
</button>
|
</button>
|
||||||
<div className="">
|
<div className="">
|
||||||
{requestStatus.loading ? (
|
{requestStatus.loading ? (
|
||||||
<LoadingSpinner color="sky-blue" size="8" />
|
<LoadingSpinner color="sky-blue" size="8" />
|
||||||
) : taskType == "select" ? (
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
disabled={requestStatus.loading}
|
|
||||||
onClick={assignFamilyTask}
|
|
||||||
className="px-1 w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white cursor-pointer"
|
|
||||||
>
|
|
||||||
Assign
|
|
||||||
</button>
|
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
disabled={requestStatus.loading}
|
disabled={requestStatus.loading}
|
||||||
onClick={assignFamilyTask}
|
onClick={assignFamilyTask}
|
||||||
className="px-1 w-40 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white cursor-pointer"
|
className="custom-btn btn-gradient text-white"
|
||||||
>
|
>
|
||||||
{`Assign to ${
|
Assign
|
||||||
familyDetailsData?.firstname || details?.firstName
|
|
||||||
}`}
|
|
||||||
</button>
|
</button>
|
||||||
)}
|
)
|
||||||
|
// : (
|
||||||
|
// <button
|
||||||
|
// type="button"
|
||||||
|
// disabled={requestStatus.loading}
|
||||||
|
// onClick={assignFamilyTask}
|
||||||
|
// className="px-1 w-40 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white cursor-pointer"
|
||||||
|
// >
|
||||||
|
// {details
|
||||||
|
// ? `Assign task to ${details?.firstname}`
|
||||||
|
// : familyDetailsData
|
||||||
|
// ? `Assign task to ${familyDetailsData.firstname}`
|
||||||
|
// : "Assign"}
|
||||||
|
// </button>
|
||||||
|
// )
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -418,7 +521,6 @@ const AssignTaskPopout = React.memo(
|
|||||||
</ModalCom>
|
</ModalCom>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
);
|
|
||||||
|
|
||||||
export default AssignTaskPopout;
|
export default AssignTaskPopout;
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export default function NewTasks({ formState, setFormState }) {
|
|||||||
<div className="field w-full mb-6 xl:mb-0">
|
<div className="field w-full mb-6 xl:mb-0">
|
||||||
<label
|
<label
|
||||||
htmlFor="country"
|
htmlFor="country"
|
||||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex item-center gap-1"
|
className="job-label"
|
||||||
>
|
>
|
||||||
Currency
|
Currency
|
||||||
{/* {props.errors.country && props.touched.country && <span className="text-[12px] text-red-500">{props.errors.country}</span>} */}
|
{/* {props.errors.country && props.touched.country && <span className="text-[12px] text-red-500">{props.errors.country}</span>} */}
|
||||||
@@ -98,10 +98,11 @@ export default function NewTasks({ formState, setFormState }) {
|
|||||||
|
|
||||||
{/* Price */}
|
{/* Price */}
|
||||||
<div className="field w-full">
|
<div className="field w-full">
|
||||||
|
<label htmlFor="price" className="job-label">Price</label>
|
||||||
<InputCom
|
<InputCom
|
||||||
fieldClass="px-6 text-right"
|
fieldClass="px-6 text-right"
|
||||||
label="Price"
|
// label="Price"
|
||||||
labelClass="tracking-wide"
|
// labelClass="tracking-wide"
|
||||||
inputBg="bg-slate-100"
|
inputBg="bg-slate-100"
|
||||||
type="number"
|
type="number"
|
||||||
name="price"
|
name="price"
|
||||||
@@ -117,7 +118,7 @@ export default function NewTasks({ formState, setFormState }) {
|
|||||||
<div className="field w-full mb-6 xl:mb-0">
|
<div className="field w-full mb-6 xl:mb-0">
|
||||||
<label
|
<label
|
||||||
htmlFor="timeline_days"
|
htmlFor="timeline_days"
|
||||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex item-center gap-1"
|
className="job-label"
|
||||||
>
|
>
|
||||||
Timeline
|
Timeline
|
||||||
{/* {props.errors.country && props.touched.country && <span className="text-[12px] text-red-500">{props.errors.country}</span>} */}
|
{/* {props.errors.country && props.touched.country && <span className="text-[12px] text-red-500">{props.errors.country}</span>} */}
|
||||||
@@ -151,10 +152,11 @@ export default function NewTasks({ formState, setFormState }) {
|
|||||||
|
|
||||||
{/* Title */}
|
{/* Title */}
|
||||||
<div className="field w-full mb-[5px]">
|
<div className="field w-full mb-[5px]">
|
||||||
|
<label htmlFor="title" className="job-label">Title</label>
|
||||||
<InputCom
|
<InputCom
|
||||||
fieldClass="px-6"
|
fieldClass="px-6"
|
||||||
label="Title"
|
// label="Title"
|
||||||
labelClass="tracking-wide"
|
// labelClass="tracking-wide"
|
||||||
inputBg="bg-slate-100"
|
inputBg="bg-slate-100"
|
||||||
type="text"
|
type="text"
|
||||||
name="title"
|
name="title"
|
||||||
@@ -167,10 +169,11 @@ export default function NewTasks({ formState, setFormState }) {
|
|||||||
|
|
||||||
{/* Description */}
|
{/* Description */}
|
||||||
<div className="field w-full mb-[5px]">
|
<div className="field w-full mb-[5px]">
|
||||||
|
<label htmlFor="description" className="job-label">Description</label>
|
||||||
<InputCom
|
<InputCom
|
||||||
fieldClass="px-6"
|
fieldClass="px-6"
|
||||||
label="Description"
|
// label="Description"
|
||||||
labelClass="tracking-wide"
|
// labelClass="tracking-wide"
|
||||||
inputBg="bg-slate-100"
|
inputBg="bg-slate-100"
|
||||||
type="text"
|
type="text"
|
||||||
name="description"
|
name="description"
|
||||||
@@ -186,7 +189,7 @@ export default function NewTasks({ formState, setFormState }) {
|
|||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label
|
<label
|
||||||
htmlFor="Job Delivery Details"
|
htmlFor="Job Delivery Details"
|
||||||
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1'
|
className='job-label'
|
||||||
>
|
>
|
||||||
Job Delivery Details
|
Job Delivery Details
|
||||||
{/* {props.errors.job_detail && props.touched.job_detail && <span className="text-[12px] text-red-500">{props.errors.job_detail}</span>} */}
|
{/* {props.errors.job_detail && props.touched.job_detail && <span className="text-[12px] text-red-500">{props.errors.job_detail}</span>} */}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { Link, useLocation } from "react-router-dom";
|
import { Link, useLocation } from "react-router-dom";
|
||||||
|
import CustomBreadcrumb from "../../Breadcrumb/CustomBreadcrumb";
|
||||||
import Icons from "../../Helpers/Icons";
|
import Icons from "../../Helpers/Icons";
|
||||||
import Layout from "../../Partials/Layout";
|
import Layout from "../../Partials/Layout";
|
||||||
import { AddFamily, FamilyBanner, Relatives } from "./Tabs";
|
import { AddFamily, FamilyBanner, Relatives } from "./Tabs";
|
||||||
|
|
||||||
const FamilySettings = () => {
|
const FamilySettings = () => {
|
||||||
let {state} = useLocation()
|
let { state } = useLocation();
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
@@ -58,15 +59,42 @@ const FamilySettings = () => {
|
|||||||
{/* heading */}
|
{/* heading */}
|
||||||
<div className="sm:flex justify-between items-center mb-6">
|
<div className="sm:flex justify-between items-center mb-6">
|
||||||
<div className="mb-5 sm:mb-0">
|
<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">
|
<CustomBreadcrumb
|
||||||
<span className={``}>Family Settings</span>
|
title={"Family Settings"}
|
||||||
</h1>
|
breadcrumb={[
|
||||||
|
{ link: "/", title: "Home" },
|
||||||
|
{
|
||||||
|
link: "/acc-family",
|
||||||
|
title: "Family Account",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
link: "/familysettings",
|
||||||
|
title: "Family Settings",
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Link to="/acc-family" className="flex gap-2 items-center text-dark-gray dark:text-white">
|
<Link
|
||||||
<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">
|
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%)]"
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" d="M6.75 15.75L3 12m0 0l3.75-3.75M3 12h18" />
|
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>
|
</svg>
|
||||||
Family
|
|
||||||
|
<span>Family</span>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,37 +1,32 @@
|
|||||||
import React, {
|
import React, { Suspense, lazy, useEffect, useMemo, useState } from "react";
|
||||||
Suspense,
|
import { useLocation } from "react-router-dom";
|
||||||
lazy,
|
import { apiConst } from "../../lib/apiConst";
|
||||||
useEffect,
|
import usersService from "../../services/UsersService";
|
||||||
useMemo,
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
useRef,
|
import AssignTaskPopout from "./FamilyPopout/AssignTaskPopout";
|
||||||
useState,
|
import { useSelector } from "react-redux";
|
||||||
} 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
|
// Lazy Imports for components
|
||||||
const FamilyWaitlist = lazy(() => import("./Tabs/FamilyWaitlist"));
|
const FamilyWaitlist = lazy(() => import("./Tabs/FamilyNewWaitlist"));
|
||||||
const FamilyAccount = lazy(() => import("./Tabs/FamilyAccount"));
|
const FamilyTasks = lazy(() => import("./Tabs/FamilyNewTasks"));
|
||||||
const FamilyProfile = lazy(() => import("./Tabs/FamilyProfile"));
|
const FamilyPending = lazy(() => import("./Tabs/FamilyNewPending"));
|
||||||
const FamilyTasks = lazy(() => import("./Tabs/FamilyTasks"));
|
|
||||||
const FamilyPending = lazy(() => import("./Tabs/FamilyPending"));
|
export default function FamilyTableNew() {
|
||||||
|
|
||||||
|
const { parentFamilyTaskList } = useSelector((state) => state.tableReload);
|
||||||
|
console.log('parentFamilyTaskList', parentFamilyTaskList)
|
||||||
|
|
||||||
|
let { pathname } = useLocation();
|
||||||
|
|
||||||
export default function FamilyTableNew({
|
|
||||||
className,
|
|
||||||
accountDetails,
|
|
||||||
listReload,
|
|
||||||
loader,
|
|
||||||
}) {
|
|
||||||
// Initial state for family details
|
// Initial state for family details
|
||||||
const initialDetailState = {
|
const initialDetailState = {
|
||||||
loading: false,
|
loading: true,
|
||||||
data: null,
|
data: null,
|
||||||
|
link: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [assignTaskChecker, setAssignTaskChecker] = useState(false);
|
||||||
|
|
||||||
// console.log('accountDetails',accountDetails)
|
// console.log('accountDetails',accountDetails)
|
||||||
// State for family details, tasks, waitlist, and pending
|
// State for family details, tasks, waitlist, and pending
|
||||||
const [details, setDetails] = useState({
|
const [details, setDetails] = useState({
|
||||||
@@ -51,7 +46,7 @@ import React, {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const [updatePage, setUpdatePage] = useState(false) // State to determine when to update the page
|
const [updatePage, setUpdatePage] = useState(false); // State to determine when to update the page
|
||||||
|
|
||||||
// State for family task data
|
// State for family task data
|
||||||
const [familyTask, setFamilyTask] = useState({ loading: false, data: [] });
|
const [familyTask, setFamilyTask] = useState({ loading: false, data: [] });
|
||||||
@@ -73,15 +68,6 @@ import React, {
|
|||||||
setFamilyTaskPopout((prev) => !prev);
|
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
|
// Array of tab names
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{ id: 1, name: "Tasks" },
|
{ id: 1, name: "Tasks" },
|
||||||
@@ -101,47 +87,31 @@ import React, {
|
|||||||
const tabComponents = {
|
const tabComponents = {
|
||||||
Tasks: (
|
Tasks: (
|
||||||
<FamilyTasks
|
<FamilyTasks
|
||||||
className={className}
|
image_link={details.familyTasks.link}
|
||||||
loader={details.familyTasks.loading}
|
loader={details.familyTasks.loading}
|
||||||
familyData={details.familyTasks.data}
|
familyData={details.familyTasks.data}
|
||||||
accountDetails={accountDetails}
|
action={familyPopUpHandler}
|
||||||
|
setAssignTaskChecker={setAssignTaskChecker}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
Waiting: (
|
Waiting: (
|
||||||
<FamilyWaitlist
|
<FamilyWaitlist
|
||||||
|
image_link={details.familyWaitList.link}
|
||||||
familyData={details.familyWaitList.data}
|
familyData={details.familyWaitList.data}
|
||||||
accountDetails={accountDetails}
|
|
||||||
loader={details.familyWaitList.loading}
|
loader={details.familyWaitList.loading}
|
||||||
|
setUpdatePage={setUpdatePage}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
Pending: (
|
Pending: (
|
||||||
<FamilyPending
|
<FamilyPending
|
||||||
|
image_link={details.familyPending.link}
|
||||||
familyData={details.familyPending.data}
|
familyData={details.familyPending.data}
|
||||||
accountDetails={accountDetails}
|
|
||||||
loader={details.familyPending.loading}
|
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 = tabComponents.Tasks;
|
||||||
const defaultTabComponent = (
|
|
||||||
<FamilyTasks
|
|
||||||
className={className}
|
|
||||||
loader={details.familyTasks.loading}
|
|
||||||
familyData={details.familyTasks.data}
|
|
||||||
accountDetails={accountDetails}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
// Selected tab component based on the current 'tab'
|
// Selected tab component based on the current 'tab'
|
||||||
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
|
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
|
||||||
@@ -150,51 +120,67 @@ import React, {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const manageFamily = async () => {
|
const manageFamily = async () => {
|
||||||
try {
|
try {
|
||||||
resetDetails();
|
// resetDetails();
|
||||||
|
|
||||||
setDetails({
|
// setDetails({
|
||||||
familyDetails: { loading: true },
|
// familyTasks: { loading: true },
|
||||||
familyTasks: { loading: true },
|
// familyWaitList: { loading: true },
|
||||||
familyWaitList: { loading: true },
|
// familyPending: { loading: true },
|
||||||
familyPending: { loading: true },
|
// });
|
||||||
});
|
|
||||||
|
|
||||||
const { family_uid } = accountDetails;
|
// const { family_uid } = accountDetails;
|
||||||
const reqData = { family_uid };
|
// const reqData = { family_uid };
|
||||||
|
|
||||||
const [familyRes, tasksRes, familyWaitRes, familyPending] =
|
const [familyTasksData, familyWaitingRes, familyPendingRes] =
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
apiCall.ManageFamily(reqData),
|
apiCall.getMyActiveJobList(),
|
||||||
apiCall.ManageTasks(reqData),
|
apiCall.ManageFamilyNewWaitlist(),
|
||||||
apiCall.ManageFamilyWaitlist(),
|
|
||||||
apiCall.ManageFamilyPending(),
|
apiCall.ManageFamilyPending(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const familyData = familyRes.data;
|
let tasksData = familyTasksData?.data?.result_list;
|
||||||
const tasksData = tasksRes.data;
|
let _familyWaitData = familyWaitingRes?.data?.result_list;
|
||||||
const familyWaitData = familyWaitRes.data;
|
let familyPendingData = familyPendingRes?.data?.result_list;
|
||||||
const familyPendingData = familyPending.data;
|
|
||||||
|
// Getting the image server link
|
||||||
|
let imageServerLink = familyWaitingRes.data?.session_image_server;
|
||||||
|
|
||||||
// Function to check for errors in data
|
// Function to check for errors in data
|
||||||
const checkDataError = (data) => data?.internal_return < 0;
|
const checkDataError = (data) => data?.internal_return < 0;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
checkDataError(familyData) ||
|
|
||||||
checkDataError(tasksData) ||
|
checkDataError(tasksData) ||
|
||||||
checkDataError(familyWaitData) ||
|
checkDataError(_familyWaitData) ||
|
||||||
checkDataError(familyPendingData)
|
checkDataError(familyPendingData)
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setDetails({
|
setDetails({
|
||||||
familyDetails: { loading: false, data: familyData },
|
familyTasks: {
|
||||||
familyTasks: { loading: false, data: tasksData },
|
loading: false,
|
||||||
familyWaitList: { loading: false, data: familyWaitData },
|
data: tasksData,
|
||||||
familyPending: { loading: false, data: familyPendingData },
|
link: imageServerLink,
|
||||||
|
},
|
||||||
|
familyWaitList: {
|
||||||
|
loading: false,
|
||||||
|
data: _familyWaitData,
|
||||||
|
link: imageServerLink,
|
||||||
|
},
|
||||||
|
familyPending: {
|
||||||
|
loading: false,
|
||||||
|
data: familyPendingData,
|
||||||
|
link: imageServerLink,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
resetDetails();
|
// resetDetails();
|
||||||
|
setDetails({
|
||||||
|
familyDetails: { ...initialDetailState, loading: false, },
|
||||||
|
familyTasks: { ...initialDetailState, loading: false, },
|
||||||
|
familyWaitList: { ...initialDetailState, loading: false,},
|
||||||
|
familyPending: { ...initialDetailState, loading: false, },
|
||||||
|
})
|
||||||
setErrMsg("An error occurred");
|
setErrMsg("An error occurred");
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
}
|
}
|
||||||
@@ -202,7 +188,7 @@ import React, {
|
|||||||
|
|
||||||
// Invoke the manageFamily function when the component mounts
|
// Invoke the manageFamily function when the component mounts
|
||||||
manageFamily();
|
manageFamily();
|
||||||
}, [updatePage]);
|
}, [updatePage, parentFamilyTaskList]);
|
||||||
|
|
||||||
// Effect to manage family tasks
|
// Effect to manage family tasks
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -239,11 +225,11 @@ import React, {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// console.log(updatePage);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`w-full bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow h-full ${
|
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">
|
<div className="relative w-full sm:rounded-lg overflow-x-auto">
|
||||||
<Suspense
|
<Suspense
|
||||||
@@ -304,11 +290,12 @@ import React, {
|
|||||||
setFamilyTask={setFamilyTask}
|
setFamilyTask={setFamilyTask}
|
||||||
setActiveTask={setActiveTask}
|
setActiveTask={setActiveTask}
|
||||||
activeTask={activeTask}
|
activeTask={activeTask}
|
||||||
familyDetailsData={details.familyDetails.data}
|
|
||||||
setUpdatePage={setUpdatePage}
|
setUpdatePage={setUpdatePage}
|
||||||
|
// updateFamilyPendingTable={updateFamilyPendingTable}
|
||||||
|
pathname={pathname}
|
||||||
|
assignTaskChecker={assignTaskChecker}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</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,154 @@
|
|||||||
|
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,
|
||||||
|
setUpdatePage
|
||||||
|
}) => {
|
||||||
|
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}
|
||||||
|
setUpdatePage={setUpdatePage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FamilyNewWaitlist;
|
||||||
@@ -5,7 +5,7 @@ import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
|||||||
import AssignTaskPopout from "../FamilyPopout/AssignTaskPopout";
|
import AssignTaskPopout from "../FamilyPopout/AssignTaskPopout";
|
||||||
|
|
||||||
const FamilyWaitlist = memo(
|
const FamilyWaitlist = memo(
|
||||||
({ familyData, className, accountDetails, loader }) => {
|
({ familyData, className, accountDetails, loader, setUpdatePage }) => {
|
||||||
const [popUp, setPopUp] = useState({ show: false, data: {} });
|
const [popUp, setPopUp] = useState({ show: false, data: {} });
|
||||||
const [continueTaskPopup, setContinueTaskPopup] = useState({
|
const [continueTaskPopup, setContinueTaskPopup] = useState({
|
||||||
show: false,
|
show: false,
|
||||||
@@ -144,6 +144,7 @@ const FamilyWaitlist = memo(
|
|||||||
details={continueTaskPopup.data}
|
details={continueTaskPopup.data}
|
||||||
action={closeContinueTaskPopup}
|
action={closeContinueTaskPopup}
|
||||||
situation={continueTaskPopup.show}
|
situation={continueTaskPopup.show}
|
||||||
|
setUpdatePage={setUpdatePage}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -15,8 +15,10 @@ function FamilyWallet({familyData}) {
|
|||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
setFamilyWallet({loading:true, data: []})
|
setFamilyWallet({loading:true, data: []})
|
||||||
apiUrl.getFamilyWallet({family_uid:familyData?.uid}).then(res => {
|
apiUrl.getKidWallets({family_uid:familyData?.uid}).then(res => {
|
||||||
setFamilyWallet({loading:false, data: res?.data?.result_list || []})
|
setFamilyWallet({loading:false, data: res?.data?.result_list || []})
|
||||||
|
console.log('familyData', familyData, res?.data?.result_list)
|
||||||
|
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
setFamilyWallet({loading:false, data: []})
|
setFamilyWallet({loading:false, data: []})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ import usersService from "../../../../services/UsersService";
|
|||||||
import LoadingSpinner from "../../../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../../../Spinners/LoadingSpinner";
|
||||||
import { PriceFormatter } from "../../../Helpers/PriceFormatter";
|
import { PriceFormatter } from "../../../Helpers/PriceFormatter";
|
||||||
import { tableReload } from "../../../../store/TableReloads";
|
import { tableReload } from "../../../../store/TableReloads";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { apiConst } from "../../../../lib/apiConst";
|
import { apiConst } from "../../../../lib/apiConst";
|
||||||
|
import { SocketValues } from "../../../Contexts/SocketIOContext";
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
// amount: Yup.string()
|
// amount: Yup.string()
|
||||||
@@ -30,6 +31,11 @@ const validationSchema = Yup.object().shape({
|
|||||||
});
|
});
|
||||||
|
|
||||||
function FamilyAddFundPopout({ action, situation, wallet, familyData }) {
|
function FamilyAddFundPopout({ action, situation, wallet, familyData }) {
|
||||||
|
|
||||||
|
const {userDetails} = useSelector((state) => state?.userDetails); // Gets User Detail
|
||||||
|
|
||||||
|
const { parentAssignJobToKid } = SocketValues() // socket emit event from FULL account
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const apiUrl = new usersService();
|
const apiUrl = new usersService();
|
||||||
@@ -54,6 +60,7 @@ function FamilyAddFundPopout({ action, situation, wallet, familyData }) {
|
|||||||
};
|
};
|
||||||
// FUNCTION TO PERFORM FAMILY TRANSFER
|
// FUNCTION TO PERFORM FAMILY TRANSFER
|
||||||
const handleAddFund = (values) => {
|
const handleAddFund = (values) => {
|
||||||
|
|
||||||
setRequestStatus({ loading: true, status: false, message: "" });
|
setRequestStatus({ loading: true, status: false, message: "" });
|
||||||
|
|
||||||
let senderBal = startTransfer?.data?.origing_current_balance || ""; // SENDER'S ACCOUNT BALANCE
|
let senderBal = startTransfer?.data?.origing_current_balance || ""; // SENDER'S ACCOUNT BALANCE
|
||||||
@@ -132,6 +139,17 @@ function FamilyAddFundPopout({ action, situation, wallet, familyData }) {
|
|||||||
status: true,
|
status: true,
|
||||||
message: "Transfer Successful",
|
message: "Transfer Successful",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//SENDS MESSAGE TO SOCKET TO UPDATE CHILD ACCOUNT
|
||||||
|
// message, room
|
||||||
|
let socketMsg = {
|
||||||
|
"audience": "MEMBER",
|
||||||
|
"action": "REFRESH_WALLET",
|
||||||
|
"family_uid": reqData.family_uid,
|
||||||
|
}
|
||||||
|
let socketRoom = `FAMILY-${userDetails.uid}`
|
||||||
|
parentAssignJobToKid(socketMsg, socketRoom) //SENDS MESSAGE TO SOCKET TO UPDATE CHILD ACCOUNT
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setRequestStatus({ loading: false, status: false, message: "" });
|
setRequestStatus({ loading: false, status: false, message: "" });
|
||||||
dispatch(tableReload({ type: "WALLETTABLE" })); // UPDATES PARENT WALLET ACCOUNT
|
dispatch(tableReload({ type: "WALLETTABLE" })); // UPDATES PARENT WALLET ACCOUNT
|
||||||
@@ -170,13 +188,13 @@ function FamilyAddFundPopout({ action, situation, wallet, familyData }) {
|
|||||||
return (
|
return (
|
||||||
<ModalCom action={action} situation={situation}>
|
<ModalCom action={action} situation={situation}>
|
||||||
<div className="relative logout-modal-wrapper lg:w-[500px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
|
<div className="relative logout-modal-wrapper lg:w-[500px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
|
||||||
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b border-light-purple dark:border-[#5356fb29] ">
|
<div className="modal-header-con">
|
||||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="modal-title">
|
||||||
Add Fund
|
Add Fund
|
||||||
</h1>
|
</h1>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="text-[#374557] dark:text-red-500"
|
className="modal-close-btn"
|
||||||
onClick={action}
|
onClick={action}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
@@ -271,7 +289,7 @@ function FamilyAddFundPopout({ action, situation, wallet, familyData }) {
|
|||||||
<div className="field w-full mb-[0.5rem]">
|
<div className="field w-full mb-[0.5rem]">
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label
|
<label
|
||||||
htmlFor="Job Delivery Details"
|
htmlFor="job-label"
|
||||||
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1"
|
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1"
|
||||||
>
|
>
|
||||||
Comment
|
Comment
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ export default function FamilyAcc() {
|
|||||||
if (data?.internal_return >= 0 && data?.status === "OK") {
|
if (data?.internal_return >= 0 && data?.status === "OK") {
|
||||||
const { result_list, session_image_server } = data;
|
const { result_list, session_image_server } = data;
|
||||||
setFamilyList({ result_list, session_image_server });
|
setFamilyList({ result_list, session_image_server });
|
||||||
|
sessionStorage.setItem("family_list", JSON.stringify(result_list))
|
||||||
setLoader(false);
|
setLoader(false);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
@@ -145,7 +146,7 @@ export default function FamilyAcc() {
|
|||||||
breadcrumb={
|
breadcrumb={
|
||||||
[
|
[
|
||||||
{ link: "/", title: "Home" },
|
{ link: "/", title: "Home" },
|
||||||
{ link: "/acc-family", title: "Family-acc", active: true},
|
{ link: "/acc-family", title: "Family Account", active: true},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -164,13 +165,13 @@ export default function FamilyAcc() {
|
|||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex gap-2 items-center">
|
<div className="flex gap-4 items-center">
|
||||||
<Link to="/acc-family/activities" className={`nav-item flex 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">
|
<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" />
|
<Icons name="pending-job" />
|
||||||
</span>
|
</span>
|
||||||
<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
|
Activities
|
||||||
</span>
|
</span>
|
||||||
@@ -178,7 +179,7 @@ export default function FamilyAcc() {
|
|||||||
<Link
|
<Link
|
||||||
to={`/familysettings`}
|
to={`/familysettings`}
|
||||||
state={{ imageServer: familyList?.session_image_server }}
|
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
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@@ -247,13 +248,13 @@ const FamilyForm = ({
|
|||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className="logout-modal-wrapper w-11/12 lg:w-[460px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
<div className="logout-modal-wrapper w-11/12 lg:w-[460px] 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:px-10 lg:py-8 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple dark:border-[#5356fb29] ">
|
<div className="modal-header-con">
|
||||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="modal-title">
|
||||||
Add Members
|
Add Members
|
||||||
</h1>
|
</h1>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="text-[#374557] dark:text-red-500"
|
className="modal-close-btn"
|
||||||
onClick={popUpHandler}
|
onClick={popUpHandler}
|
||||||
>
|
>
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
@@ -266,8 +267,8 @@ const FamilyForm = ({
|
|||||||
name="first_name"
|
name="first_name"
|
||||||
type="text"
|
type="text"
|
||||||
parentClass="flex items-center gap-1 w-full"
|
parentClass="flex items-center gap-1 w-full"
|
||||||
labelClass="flex-[0.2] mb-0"
|
labelClass="flex-[0.4] mb-0"
|
||||||
inputClass="flex-[0.8] input-curve lg border border-[#dce4e9]"
|
inputClass="flex-[0.6] input-curve lg border border-[#dce4e9]"
|
||||||
fieldClass="px-2"
|
fieldClass="px-2"
|
||||||
value={first_name}
|
value={first_name}
|
||||||
inputHandler={inputHandler}
|
inputHandler={inputHandler}
|
||||||
@@ -278,8 +279,8 @@ const FamilyForm = ({
|
|||||||
name="last_name"
|
name="last_name"
|
||||||
type="text"
|
type="text"
|
||||||
parentClass="flex items-center gap-1 w-full"
|
parentClass="flex items-center gap-1 w-full"
|
||||||
labelClass="flex-[0.2] mb-0"
|
labelClass="flex-[0.4] mb-0"
|
||||||
inputClass="flex-[0.8] input-curve lg border border-[#dce4e9]"
|
inputClass="flex-[0.6] input-curve lg border border-[#dce4e9]"
|
||||||
fieldClass="px-2"
|
fieldClass="px-2"
|
||||||
value={last_name}
|
value={last_name}
|
||||||
inputHandler={inputHandler}
|
inputHandler={inputHandler}
|
||||||
@@ -288,7 +289,7 @@ const FamilyForm = ({
|
|||||||
{/* Age dropdown */}
|
{/* Age dropdown */}
|
||||||
<div className="">
|
<div className="">
|
||||||
<label
|
<label
|
||||||
className="input-label text-[#181c32] dark:text-white text-[15px] font-semibold"
|
className="job-label"
|
||||||
htmlFor="age-selection"
|
htmlFor="age-selection"
|
||||||
>
|
>
|
||||||
Birthday: (Year/Month)
|
Birthday: (Year/Month)
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
|
import { Form, Formik } from "formik";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useLocation } from "react-router-dom";
|
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 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 DEFAULT_IMAGE = require("../../assets/images/family/default.jpg");
|
||||||
const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
||||||
@@ -51,26 +50,52 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleParentSuggestion = (values) => {
|
const handleParentSuggestion = (values) => {
|
||||||
if (suggestedNextStep == "Send Task") {
|
if (suggestedNextStep === "Send Task") {
|
||||||
let firstName = state?.firstname;
|
let firstname = state?.firstname || details?.firstname;
|
||||||
let family_uid = state?.family_uid;
|
let family_uid = state?.family_uid || details?.family_uid;
|
||||||
continuePopupData({ ...details, firstName, family_uid });
|
continuePopupData({
|
||||||
|
...details,
|
||||||
|
firstname,
|
||||||
|
family_uid,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
onClose();
|
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 (
|
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-[48rem] min-h-[500px] bg-white dark:bg-dark-white lg:rounded-2xl">
|
||||||
<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="modal-header-con">
|
||||||
<h1 className="text-base md:text-lg font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="modal-title">
|
||||||
{pathname === "/manage-family"
|
{isManageFamilyPage
|
||||||
? `${state?.firstname}'s Suggested Task`
|
? `${state?.firstname}'s Suggested Task`
|
||||||
|
: isActivitiesPage
|
||||||
|
? `${details?.firstname}'s Suggested Task`
|
||||||
: "Suggest to Parent"}
|
: "Suggest to Parent"}
|
||||||
</h1>
|
</h1>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="text-[#374557] dark:text-red-500"
|
className="modal-close-btn"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
@@ -97,19 +122,21 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
|||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
onSubmit={
|
onSubmit={
|
||||||
pathname !== "/manage-family"
|
isActivitiesPage
|
||||||
? handleSuggestedTask
|
? handleParentSuggestion
|
||||||
: handleParentSuggestion
|
: isManageFamilyPage
|
||||||
|
? handleParentSuggestion
|
||||||
|
: handleSuggestedTask
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{(props) => {
|
{(props) => {
|
||||||
return (
|
return (
|
||||||
<Form>
|
<Form className="h-[33.875rem] flex flex-col">
|
||||||
<div className="p-5 w-full bg-white rounded-md flex justify-between">
|
<div className="px-5 w-full bg-white rounded-md flex justify-between items-center h-full">
|
||||||
{/* Image Section */}
|
{/* Image Section */}
|
||||||
<div className="p-4 w-full md:w-2/4 md:border-r-2">
|
<div className="p-4 w-full md:w-2/4 md:border-r-2 h-full flex items-center">
|
||||||
<div
|
<div
|
||||||
className="w-full h-[236px] p-6 bg-gray-400 rounded-xl overflow-hidden"
|
className="w-full h-[14.75rem] p-6 bg-gray-400 rounded-xl overflow-hidden"
|
||||||
style={{
|
style={{
|
||||||
background: `url(${selectedImage}) center / contain no-repeat`,
|
background: `url(${selectedImage}) center / contain no-repeat`,
|
||||||
}}
|
}}
|
||||||
@@ -117,17 +144,22 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* ACTION SECTION */}
|
{/* ACTION SECTION */}
|
||||||
<div className="p-4 w-full md:w-2/4 h-full">
|
<div className="p-4 w-full md:w-2/4 h-full flex flex-col justify-between">
|
||||||
{/* Title */}
|
{/* Title */}
|
||||||
<div className="field w-full mb-[15px]">
|
<div className="field w-full mb-[.9375rem]">
|
||||||
<InputCom
|
<InputCom
|
||||||
fieldClass={
|
fieldClass={
|
||||||
pathname === "/manage-family" ? "px-2" : "px-6"
|
pathname === "/manage-family" ||
|
||||||
|
pathname === "/acc-family/activities"
|
||||||
|
? "px-2"
|
||||||
|
: "px-6"
|
||||||
}
|
}
|
||||||
label="Title"
|
label="Title"
|
||||||
|
labalClass="text-[1.125rem]"
|
||||||
labelClass="tracking-wide"
|
labelClass="tracking-wide"
|
||||||
inputBg={
|
inputBg={
|
||||||
pathname === "/manage-family"
|
pathname === "/manage-family" ||
|
||||||
|
pathname === "/acc-family/activities"
|
||||||
? "bg-white"
|
? "bg-white"
|
||||||
: "bg-slate-100"
|
: "bg-slate-100"
|
||||||
}
|
}
|
||||||
@@ -147,15 +179,15 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Description */}
|
{/* Description */}
|
||||||
<div className="field w-full mb-[5px]">
|
<div className="w-full mb-[.3125rem]">
|
||||||
<label
|
<label
|
||||||
htmlFor="description"
|
htmlFor="description"
|
||||||
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1'
|
className='job-label'
|
||||||
>
|
>
|
||||||
Description
|
Description
|
||||||
{props.errors.description &&
|
{props.errors.description &&
|
||||||
props.touched.description && (
|
props.touched.description && (
|
||||||
<span className="text-[12px] text-red-500">
|
<span className="text-[.75rem] text-red-500">
|
||||||
{props.errors.description}
|
{props.errors.description}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
@@ -164,9 +196,10 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
|||||||
id="description"
|
id="description"
|
||||||
rows="5"
|
rows="5"
|
||||||
className={`input-field pt-2 placeholder:text-base text-dark-gray dark:text-white w-full ${
|
className={`input-field pt-2 placeholder:text-base text-dark-gray dark:text-white w-full ${
|
||||||
pathname === "/manage-family"
|
pathname === "/manage-family" ||
|
||||||
? "px-2 h-[110px]"
|
pathname === "/acc-family/activities"
|
||||||
: "bg-slate-100 px-3 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[10px] h-[130px]"
|
? "px-2 h-[6.875rem]"
|
||||||
|
: "bg-slate-100 px-3 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[.625rem] h-[8.125rem]"
|
||||||
}`}
|
}`}
|
||||||
style={{ resize: "none" }}
|
style={{ resize: "none" }}
|
||||||
name="description"
|
name="description"
|
||||||
@@ -177,8 +210,9 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Radio buttons for family */}
|
{/* Radio buttons for family */}
|
||||||
{pathname === "/manage-family" ? (
|
{pathname === "/manage-family" ||
|
||||||
<div className="h-[20px] w-full border-t dark:border-[#5356fb29] border-light-purple relative">
|
pathname === "/acc-family/activities" ? (
|
||||||
|
<div className="h-[3.75rem] w-full border-t dark:border-[#5356fb29] border-light-purple relative">
|
||||||
<div id="my-radio-group" className="sr-only">
|
<div id="my-radio-group" className="sr-only">
|
||||||
Parent suggested next step
|
Parent suggested next step
|
||||||
</div>
|
</div>
|
||||||
@@ -196,7 +230,7 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
|||||||
role="group"
|
role="group"
|
||||||
key={idx}
|
key={idx}
|
||||||
htmlFor={`parent-suggested-${idx}`}
|
htmlFor={`parent-suggested-${idx}`}
|
||||||
className={`transition duration-150 ease-in-out parent-suggest group cursor-pointer`}
|
className={`transition duration-150 ease-in-out parent-suggest group cursor-pointer flex items-center`}
|
||||||
onClick={() => setSuggestedNextStep(title)}
|
onClick={() => setSuggestedNextStep(title)}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
@@ -205,19 +239,19 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
|||||||
value={title}
|
value={title}
|
||||||
checked={suggestedNextStep === title}
|
checked={suggestedNextStep === title}
|
||||||
onChange={switchNextStep}
|
onChange={switchNextStep}
|
||||||
className={`transition duration-150 ease-in-out parent-suggest pointer-events-none`}
|
className={`transition duration-150 ease-in-out parent-suggest pointer-events-none w-[1.125rem] h-[1.125rem]`}
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
onClick={() => setSuggestedNextStep(title)}
|
onClick={() => setSuggestedNextStep(title)}
|
||||||
id={`parent-suggested-${idx}`}
|
id={`parent-suggested-${idx}`}
|
||||||
name="parent-suggested"
|
name="parent-suggested"
|
||||||
className={`ml-1 ${
|
className={`ml-1 ${
|
||||||
title == "Not Now"
|
title === "Not Now"
|
||||||
? "text-red-500"
|
? "text-red-500"
|
||||||
: title == "Duplicate"
|
: title === "Duplicate"
|
||||||
? "text-purple"
|
? "text-purple"
|
||||||
: "text-black"
|
: "text-black"
|
||||||
} font-semibold`}
|
} font-semibold text-[1.125rem]`}
|
||||||
>
|
>
|
||||||
{title}
|
{title}
|
||||||
</span>
|
</span>
|
||||||
@@ -229,7 +263,7 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-full h-[70px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
|
<div className="w-full h-[4.375rem] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
|
||||||
<div className="flex items-center space-x-4 mr-9">
|
<div className="flex items-center space-x-4 mr-9">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -243,19 +277,31 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
|||||||
disabled={props.isSubmitting}
|
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"
|
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 === "/acc-family/activities" ? (
|
||||||
|
<>
|
||||||
|
{suggestedNextStep === "Send Task" ? (
|
||||||
|
<>
|
||||||
|
Continue <Icons name="chevron-right" />
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
"Complete"
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
{pathname !== "/manage-family" ? (
|
{pathname !== "/manage-family" ? (
|
||||||
<>
|
<>
|
||||||
{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"}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{suggestedNextStep == "Send Task" ? (
|
{suggestedNextStep === "Send Task" ? (
|
||||||
<>
|
<>
|
||||||
Continue <Icons name="chevron-right" />
|
Continue <Icons name="chevron-right" />
|
||||||
</>
|
</>
|
||||||
@@ -264,6 +310,9 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
</>
|
||||||
|
)} */}
|
||||||
|
{getButtonText()}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ function DataIteration(props) {
|
|||||||
{datas &&
|
{datas &&
|
||||||
datas?.length >= endLength &&
|
datas?.length >= endLength &&
|
||||||
datas?.slice(startLength, endLength)
|
datas?.slice(startLength, endLength)
|
||||||
.map((value) => children({ datas: value }))}
|
.map((value, index) => children({ datas: value, index }))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export default function InputCom({
|
|||||||
<div className={`flex items-center justify-between mb-2.5 ${labelClass}`}>
|
<div className={`flex items-center justify-between mb-2.5 ${labelClass}`}>
|
||||||
{label && (
|
{label && (
|
||||||
<label
|
<label
|
||||||
className={`input-label text-[#181c32] text-[13.975px] leading-[20.9625px] font-semibold flex items-center gap-1 ${labalClass}`}
|
className={`job-label ${error && 'job-label-flex'} ${labalClass}`}
|
||||||
htmlFor={name}
|
htmlFor={name}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
|
|||||||
@@ -89,13 +89,13 @@ export default function AddGroup({ action, situation, setUpdateList }) {
|
|||||||
return (
|
return (
|
||||||
<ModalCom action={action} situation={situation}>
|
<ModalCom action={action} situation={situation}>
|
||||||
<div className="logout-modal-wrapper lg:w-[500px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
|
<div className="logout-modal-wrapper lg:w-[500px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
|
||||||
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b border-light-purple dark:border-[#5356fb29] ">
|
<div className="modal-header-con">
|
||||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="modal-title">
|
||||||
Add Group
|
Add Group
|
||||||
</h1>
|
</h1>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="text-[#374557] dark:text-red-500"
|
className="modal-close-btn"
|
||||||
onClick={action}
|
onClick={action}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
@@ -139,9 +139,9 @@ export default function AddGroup({ action, situation, setUpdateList }) {
|
|||||||
<button
|
<button
|
||||||
onClick={action}
|
onClick={action}
|
||||||
type="button"
|
type="button"
|
||||||
className="text-base text-light-red tracking-wide "
|
className="w-[152px] h-[46px] flex justify-center items-center rounded-full text-base text-light-red tracking-wide border border-light-red"
|
||||||
>
|
>
|
||||||
<span className="border-b dark:border-[#5356fb29] border-light-red">
|
<span className="">
|
||||||
Cancel
|
Cancel
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -21,13 +21,13 @@ export default function DeleteMember({action, situation, details}) {
|
|||||||
situation={situation}
|
situation={situation}
|
||||||
>
|
>
|
||||||
<div className="logout-modal-wrapper lg:w-[500px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
|
<div className="logout-modal-wrapper lg:w-[500px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
|
||||||
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b border-light-purple dark:border-[#5356fb29] ">
|
<div className="modal-header-con">
|
||||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="modal-title">
|
||||||
Remove Member
|
Remove Member
|
||||||
</h1>
|
</h1>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="text-[#374557] dark:text-red-500"
|
className="modal-close-btn"
|
||||||
onClick={action}
|
onClick={action}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
|||||||
@@ -24,12 +24,6 @@ export default function MemberList({
|
|||||||
|
|
||||||
const handleFieldsChange = ({ target: { name, value } }) => {
|
const handleFieldsChange = ({ target: { name, value } }) => {
|
||||||
setFields((prev) => ({ ...prev, [name]: value }));
|
setFields((prev) => ({ ...prev, [name]: value }));
|
||||||
// let error = requestState?.errors?.indexOf(name) //// checks if the input field was in error array and removes it when the input changes
|
|
||||||
// if(error >= 0){
|
|
||||||
// let oldErrorArr = requestState.errors
|
|
||||||
// let newErrorArr = oldErrorArr.splice(error, 1)
|
|
||||||
// setRequestState(prev => ({...prev, errors:oldErrorArr}))
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (value == "") {
|
if (value == "") {
|
||||||
setRequestState({
|
setRequestState({
|
||||||
@@ -89,6 +83,63 @@ export default function MemberList({
|
|||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
if(fields.firstname.length > 25){ // checks if firstname length is more than 25
|
||||||
|
setRequestState({
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
message: "Firstname must not be more than 25 characters",
|
||||||
|
data: [],
|
||||||
|
errors: [],
|
||||||
|
});
|
||||||
|
return setTimeout(() => {
|
||||||
|
setRequestState({
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
message: "",
|
||||||
|
data: [],
|
||||||
|
errors: [],
|
||||||
|
});
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fields.lastname.length > 25){ // checks if lastname length is more than 25
|
||||||
|
setRequestState({
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
message: "Lastname must not be more than 25 characters",
|
||||||
|
data: [],
|
||||||
|
errors: [],
|
||||||
|
});
|
||||||
|
return setTimeout(() => {
|
||||||
|
setRequestState({
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
message: "",
|
||||||
|
data: [],
|
||||||
|
errors: [],
|
||||||
|
});
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fields.email.length > 45){ // checks if email length is more than 45
|
||||||
|
setRequestState({
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
message: "Email must not be more than 45 characters",
|
||||||
|
data: [],
|
||||||
|
errors: [],
|
||||||
|
});
|
||||||
|
return setTimeout(() => {
|
||||||
|
setRequestState({
|
||||||
|
loading: false,
|
||||||
|
status: false,
|
||||||
|
message: "",
|
||||||
|
data: [],
|
||||||
|
errors: [],
|
||||||
|
});
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
//checks if email is a valid email address
|
//checks if email is a valid email address
|
||||||
let regEx = /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/;
|
let regEx = /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/;
|
||||||
if (!EmailValidator(fields.email)) {
|
if (!EmailValidator(fields.email)) {
|
||||||
@@ -201,7 +252,7 @@ export default function MemberList({
|
|||||||
{selectedGroup?.name}
|
{selectedGroup?.name}
|
||||||
</h1>
|
</h1>
|
||||||
<div className="w-full flex flex-col-reverse lg:flex-col">
|
<div className="w-full flex flex-col-reverse lg:flex-col">
|
||||||
<div className="py-3 w-full">
|
<div className="relative py-3 w-full">
|
||||||
<div className="relative grid grid-cols-1 sm:grid-cols-2 gap-2 place-content-center">
|
<div className="relative grid grid-cols-1 sm:grid-cols-2 gap-2 place-content-center">
|
||||||
<div className="input-item">
|
<div className="input-item">
|
||||||
<InputCom
|
<InputCom
|
||||||
@@ -229,13 +280,15 @@ export default function MemberList({
|
|||||||
// iconName="message"
|
// iconName="message"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-item w-full">
|
</div>
|
||||||
|
<div className="sm:flex gap-2 items-center">
|
||||||
|
<div className="input-item my-2 w-full sm:w-9/12">
|
||||||
<InputCom
|
<InputCom
|
||||||
labelClass="tracking-wider"
|
labelClass="tracking-wider"
|
||||||
fieldClass="sm:px-6 px-2"
|
fieldClass="sm:px-6 px-2"
|
||||||
value={fields.email}
|
value={fields.email}
|
||||||
inputHandler={handleFieldsChange}
|
inputHandler={handleFieldsChange}
|
||||||
inputClass="xl:w-[16rem] 2xl:w-full"
|
inputClass=""
|
||||||
placeholder="Email"
|
placeholder="Email"
|
||||||
// label="Email"
|
// label="Email"
|
||||||
name="email"
|
name="email"
|
||||||
@@ -243,7 +296,7 @@ export default function MemberList({
|
|||||||
// iconName="message"
|
// iconName="message"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-end items-end">
|
<div className="flex justify-end items-end w-full sm:w-3/12">
|
||||||
{requestState.loading ? (
|
{requestState.loading ? (
|
||||||
<LoadingSpinner size="8" color="sky-blue" />
|
<LoadingSpinner size="8" color="sky-blue" />
|
||||||
) : (
|
) : (
|
||||||
@@ -266,10 +319,11 @@ export default function MemberList({
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="absolute top-full w-full my-1 text-center">
|
||||||
{!requestState.loading && requestState.message && (
|
{!requestState.loading && requestState.message && (
|
||||||
<p
|
<p
|
||||||
className={`text-lg absolute -bottom-7 left-0 ${
|
className={`text-base ${
|
||||||
requestState.status ? "text-green-500" : "text-red-500"
|
requestState.status ? "text-green-500" : "text-red-500"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import ListView from "../../assets/images/list-view.png";
|
|||||||
import AvailableJobsCard from "../Cards/AvailableJobsCard";
|
import AvailableJobsCard from "../Cards/AvailableJobsCard";
|
||||||
import DataIteration from "../Helpers/DataIteration";
|
import DataIteration from "../Helpers/DataIteration";
|
||||||
import SelectBox from "../Helpers/SelectBox";
|
import SelectBox from "../Helpers/SelectBox";
|
||||||
|
import NewPaginatedList from "../Pagination/NewPaginatedList";
|
||||||
|
|
||||||
export default function MainSection({
|
export default function MainSection({
|
||||||
className,
|
className,
|
||||||
@@ -108,8 +109,8 @@ export default function MainSection({
|
|||||||
startLength={process.env.REACT_APP_ZERO_STATE}
|
startLength={process.env.REACT_APP_ZERO_STATE}
|
||||||
endLength={products?.length}
|
endLength={products?.length}
|
||||||
>
|
>
|
||||||
{({ datas }) => (
|
{({ datas, index }) => (
|
||||||
<div key={datas.job_uid}>
|
<div key={datas.job_uid+index}>
|
||||||
<AvailableJobsCard
|
<AvailableJobsCard
|
||||||
contentDisplay={contentDisplay}
|
contentDisplay={contentDisplay}
|
||||||
image_server={image_server}
|
image_server={image_server}
|
||||||
@@ -120,6 +121,40 @@ export default function MainSection({
|
|||||||
</DataIteration>
|
</DataIteration>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{/* {products?.length &&
|
||||||
|
<NewPaginatedList
|
||||||
|
data={products}
|
||||||
|
itemsPerPage={6}
|
||||||
|
filterItem=''
|
||||||
|
tableTitle=''
|
||||||
|
>
|
||||||
|
{
|
||||||
|
({data})=>(
|
||||||
|
<div className="filter-navigate-content w-full min-h-[600px]">
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
contentDisplay == "grid"
|
||||||
|
? "grid lg:grid-cols-3 sm:grid-cols-2 gap-[30px]"
|
||||||
|
: "w-full"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
data.map((datum, index) => (
|
||||||
|
<div key={datum.job_uid+index}>
|
||||||
|
<AvailableJobsCard
|
||||||
|
contentDisplay={contentDisplay}
|
||||||
|
image_server={image_server}
|
||||||
|
datas={datum}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</NewPaginatedList>
|
||||||
|
} */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,11 +1,26 @@
|
|||||||
import { useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import usersService from "../../../services/UsersService";
|
import usersService from "../../../services/UsersService";
|
||||||
import ModalCom from "../../Helpers/ModalCom";
|
import ModalCom from "../../Helpers/ModalCom";
|
||||||
import { PriceFormatter } from "../../Helpers/PriceFormatter";
|
import { PriceFormatter } from "../../Helpers/PriceFormatter";
|
||||||
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../../Spinners/LoadingSpinner";
|
||||||
|
import { SocketValues } from "../../Contexts/SocketIOContext";
|
||||||
|
|
||||||
const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
||||||
|
|
||||||
|
let {sendJobInterestToOwner} = SocketValues() // function to emit job interest request
|
||||||
|
const emitOfferInterest = () => {
|
||||||
|
let message = {
|
||||||
|
"audience": "MERCHANT",
|
||||||
|
"action": "REFRESH_OFFERS",
|
||||||
|
"offer_code": details?.offer_code,
|
||||||
|
"offer_uid": details?.offer_uid,
|
||||||
|
"job_uid": details?.job_uid,
|
||||||
|
}
|
||||||
|
let room = `INTEREST-${details?.market_uid}`
|
||||||
|
sendJobInterestToOwner(message, room)
|
||||||
|
}
|
||||||
|
|
||||||
const [textValue, setTextValue] = useState("");
|
const [textValue, setTextValue] = useState("");
|
||||||
const [errMsg, setErrMsg] = useState({
|
const [errMsg, setErrMsg] = useState({
|
||||||
market: false,
|
market: false,
|
||||||
@@ -88,7 +103,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
|||||||
state: true,
|
state: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
emitOfferInterest() // FUNCTIONS TO EMIT EVENT INDICATING SOMEONE SENDS AN INTEREST IN YOUR JOB
|
||||||
setTimeout(() => setManageInt({ msg: "" }), 3000);
|
setTimeout(() => setManageInt({ msg: "" }), 3000);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
@@ -118,9 +133,9 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalCom action={onClose} situation={situation}>
|
<ModalCom action={onClose} situation={situation}>
|
||||||
<div className="logout-modal-wrapper w-11/12 md:w-[650px] md:h-[580px] h-full bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
<div className="w-11/12 md:w-[650px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
||||||
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px]">
|
<div className="modal-header-con">
|
||||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="modal-title">
|
||||||
{details.offer_code}
|
{details.offer_code}
|
||||||
</h1>
|
</h1>
|
||||||
<CloseIcon onClose={onClose} />
|
<CloseIcon onClose={onClose} />
|
||||||
@@ -128,7 +143,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
|||||||
|
|
||||||
<div className="md:flex bg-white dark:bg-dark-white text-slate-900 dark:text-white rounded-lg">
|
<div className="md:flex bg-white dark:bg-dark-white text-slate-900 dark:text-white rounded-lg">
|
||||||
<div className="p-4 w-full md:w-[75%] md:border-r-1">
|
<div className="p-4 w-full md:w-[75%] md:border-r-1">
|
||||||
<div className="max-h-[240px] h-full">
|
<div className="min-h-[240px]">
|
||||||
<h2 className="font-semibold text-slate-900 dark:text-white tracking-wide">
|
<h2 className="font-semibold text-slate-900 dark:text-white tracking-wide">
|
||||||
{details?.title}
|
{details?.title}
|
||||||
</h2>
|
</h2>
|
||||||
@@ -153,7 +168,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
|||||||
},
|
},
|
||||||
].map(({ name, content, danger }, idx) => (
|
].map(({ name, content, danger }, idx) => (
|
||||||
<div className={`my-3 md:flex items-center`} key={idx}>
|
<div className={`my-3 md:flex items-center`} key={idx}>
|
||||||
<label className="w-full md:w-[19%] tracking-wide font-semibold whitespace-pre-wrap">
|
<label className="job-label w-full md:w-[19%]">
|
||||||
{name}
|
{name}
|
||||||
</label>
|
</label>
|
||||||
<div
|
<div
|
||||||
@@ -198,7 +213,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
|||||||
<hr />
|
<hr />
|
||||||
<div className="w-full flex flex-col gap-3">
|
<div className="w-full flex flex-col gap-3">
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label className="w-full text-slate-900 dark:text-white tracking-wide font-semibold">
|
<label className="job-label w-full">
|
||||||
If you have any questions about this task:
|
If you have any questions about this task:
|
||||||
</label>
|
</label>
|
||||||
<textarea
|
<textarea
|
||||||
@@ -218,7 +233,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
|||||||
{errMsg.market && "Something went wrong"}
|
{errMsg.market && "Something went wrong"}
|
||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
className="self-end w-[150px] h-[48px] rounded-full text-base bg-yellow-500 text-white"
|
className="custom-btn self-end bg-yellow-500 text-white"
|
||||||
name="market-message"
|
name="market-message"
|
||||||
onClick={MarketDetail}
|
onClick={MarketDetail}
|
||||||
>
|
>
|
||||||
@@ -235,7 +250,7 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
|||||||
<div className="w-full md:w-[23%] h-full flex flex-col">
|
<div className="w-full md:w-[23%] h-full flex flex-col">
|
||||||
<div className="mx-auto bg-[#f1f8ff] dark:bg-[#C2C8D3] px-4 rounded-md md:min-h-[420px] flex flex-col justify-between">
|
<div className="mx-auto bg-[#f1f8ff] dark:bg-[#C2C8D3] px-4 rounded-md md:min-h-[420px] flex flex-col justify-between">
|
||||||
<div className="w-full flex flex-col justify-center pb-4 gap-2">
|
<div className="w-full flex flex-col justify-center pb-4 gap-2">
|
||||||
<p className="w-full text-slate-900 tracking-wide my-1 font-semibold">
|
<p className="job-label w-full">
|
||||||
Interested in the task?
|
Interested in the task?
|
||||||
</p>
|
</p>
|
||||||
<hr />
|
<hr />
|
||||||
@@ -270,33 +285,39 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
|
|||||||
|
|
||||||
<div className="text-slate-900">
|
<div className="text-slate-900">
|
||||||
<p className="flex items-center tracking-wide">
|
<p className="flex items-center tracking-wide">
|
||||||
Interest: <b className="ml-1">{details.interest_count}</b>
|
<span className="job-label">Interest: </span> <b className="ml-1">{details.interest_count}</b>
|
||||||
</p>
|
</p>
|
||||||
<hr />
|
<hr />
|
||||||
<p className="my-1">Expire: {details.expire}</p>
|
<p className="my-1 flex flex-col">
|
||||||
|
<span className="job-label">Expire: </span>
|
||||||
|
<span> {new Date(details.expire).toLocaleString()} </span>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* END OF ACTION SECTION */}
|
||||||
|
</div>
|
||||||
|
<div className="modal-footer-wrapper">
|
||||||
<button
|
<button
|
||||||
className="self-center w-[150px] mt-2 h-[48px] rounded-full text-base bg-transparent border border-red-500 text-red-500 mx-auto"
|
className="custom-btn bg-transparent border border-red-500 text-red-500 ml-auto"
|
||||||
name="cancel"
|
name="cancel"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{/* END OF ACTION SECTION */}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</ModalCom>
|
</ModalCom>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export default MarketPopUp;
|
export default MarketPopUp;
|
||||||
|
|
||||||
const CloseIcon = ({ onClose }) => (
|
const CloseIcon = ({ onClose }) => (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="text-[#374557] dark:text-red-500"
|
className="modal-close-btn"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
|||||||
@@ -11,8 +11,11 @@ import IndexJobActions from "./JobActions/IndexJobActions";
|
|||||||
|
|
||||||
import usersService from "../../services/UsersService";
|
import usersService from "../../services/UsersService";
|
||||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||||
|
import { SocketValues } from "../Contexts/SocketIOContext";
|
||||||
|
|
||||||
function ActiveJobs(props) {
|
function ActiveJobs(props) {
|
||||||
|
let {sendMessage, joinRoom} = SocketValues() // destructures 'SEND MESSAGE' and 'JOIN ROOM' FUNCTIONS FROM SOCKET
|
||||||
|
|
||||||
const ApiCall = new usersService();
|
const ApiCall = new usersService();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@@ -139,6 +142,9 @@ function ActiveJobs(props) {
|
|||||||
status: true,
|
status: true,
|
||||||
message: "Message Sent Successfully",
|
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
|
props.reloadActiveJobList((prev) => !prev); // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
|
||||||
setMessageToSend(""); // SENDS MESSAGE TO SEND BACK TO EMPTY STRINGS
|
setMessageToSend(""); // SENDS MESSAGE TO SEND BACK TO EMPTY STRINGS
|
||||||
})
|
})
|
||||||
@@ -255,6 +261,12 @@ function ActiveJobs(props) {
|
|||||||
props.details?.currency
|
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 (
|
return (
|
||||||
<Layout>
|
<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">
|
<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">
|
||||||
@@ -534,13 +546,13 @@ function ActiveJobs(props) {
|
|||||||
|
|
||||||
{/* MESSAGE SECTION */}
|
{/* MESSAGE SECTION */}
|
||||||
<div className="w-full lg:w-1/2">
|
<div className="w-full lg:w-1/2">
|
||||||
<div className="flex justify-between items-center gap-5">
|
<div className="flex justify-between items-center gap-5 justify-between">
|
||||||
<p className="w-full text-lg font-bold text-dark-gray dark:text-white tracking-wide flex items-center gap-2">
|
<p className="w-full text-lg font-bold text-dark-gray dark:text-white tracking-wide flex items-center gap-2 justify-between">
|
||||||
<span>Message</span>
|
<span>Message</span>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={popUpHandler}
|
onClick={popUpHandler}
|
||||||
className="text-[12px] tracking-wider text-emerald-600 dark:text-emerald-300"
|
className="text-[12px] tracking-wider text-gray-400 dark:text-slate-400"
|
||||||
>
|
>
|
||||||
View all
|
View all
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import Layout from "../Partials/Layout";
|
|||||||
import MyJobTable from "./MyJobTable";
|
import MyJobTable from "./MyJobTable";
|
||||||
import CommonHead from "../UserHeader/CommonHead";
|
import CommonHead from "../UserHeader/CommonHead";
|
||||||
import AddJobPage from "../../views/AddJobPage";
|
import AddJobPage from "../../views/AddJobPage";
|
||||||
|
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||||
|
|
||||||
export default function MyJobs(props) {
|
export default function MyJobs(props) {
|
||||||
let { state } = useLocation();
|
let { state } = useLocation();
|
||||||
@@ -32,8 +33,8 @@ export default function MyJobs(props) {
|
|||||||
<div className="notification-page w-full mb-10">
|
<div className="notification-page w-full mb-10">
|
||||||
<div className="notification-wrapper w-full">
|
<div className="notification-wrapper w-full">
|
||||||
{/* heading */}
|
{/* heading */}
|
||||||
<div className="sm:flex items-center mb-6">
|
<div className="sm:flex items-center mb-2">
|
||||||
<div className="mb-5 sm:mb-0">
|
<div className="w-full">
|
||||||
<h1 className="text-26 font-bold flex items-center space-x-1 text-dark-gray dark:text-white gap-2">
|
<h1 className="text-26 font-bold flex items-center space-x-1 text-dark-gray dark:text-white gap-2">
|
||||||
<span>My Jobs</span>
|
<span>My Jobs</span>
|
||||||
|
|
||||||
@@ -46,6 +47,17 @@ export default function MyJobs(props) {
|
|||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="mb-5">
|
||||||
|
<CustomBreadcrumb
|
||||||
|
// title = 'My Jobs'
|
||||||
|
breadcrumb={
|
||||||
|
[
|
||||||
|
{ link: "/", title: "Home" },
|
||||||
|
{ link: "/myjobs", title: "My Jobs", active: true},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<MyJobTable MyJobList={props.MyJobList} />
|
<MyJobTable MyJobList={props.MyJobList} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import OfferCard from "../Cards/OfferCard";
|
|||||||
import Icons from "../Helpers/Icons";
|
import Icons from "../Helpers/Icons";
|
||||||
import SliderCom from "../Helpers/SliderCom";
|
import SliderCom from "../Helpers/SliderCom";
|
||||||
import FamilyOfferJobPopout from "../jobPopout/FamilyOfferJobPopout";
|
import FamilyOfferJobPopout from "../jobPopout/FamilyOfferJobPopout";
|
||||||
|
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||||
|
|
||||||
export default function MyOffersFamilyTable({ className, familyOffers, image_server }) {
|
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
|
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 */}
|
{/* heading */}
|
||||||
<div className="flex justify-between items-center mb-6">
|
<div className="flex justify-between items-center mb-6">
|
||||||
<div>
|
{/* <div>
|
||||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
|
||||||
Ready to Start?
|
Ready to Start?
|
||||||
</h1>
|
</h1>
|
||||||
|
</div> */}
|
||||||
|
<div className="">
|
||||||
|
<CustomBreadcrumb
|
||||||
|
title = {'Ready to Start'}
|
||||||
|
breadcrumb={
|
||||||
|
[
|
||||||
|
{ link: "/", title: "Home" },
|
||||||
|
{ link: "/pending", title: "Pending", active: true},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="slider-btns flex space-x-3">
|
<div className="slider-btns flex space-x-3">
|
||||||
<button onClick={nextHandler} type="button">
|
<button onClick={nextHandler} type="button">
|
||||||
|
|||||||
@@ -2,33 +2,109 @@ import { useSelector } from "react-redux";
|
|||||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
import WalletItemCard from "./WalletItemCard";
|
import WalletItemCard from "./WalletItemCard";
|
||||||
import WalletItemCardFamily from "./WalletItemCardFamily";
|
import WalletItemCardFamily from "./WalletItemCardFamily";
|
||||||
|
import { useEffect, 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.
|
* 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 { loading, data } = wallet;
|
||||||
|
|
||||||
const { userDetails } = useSelector((state) => state.userDetails);
|
// const { userDetails } = useSelector((state) => state.userDetails);
|
||||||
const accountType = userDetails?.account_type === "FAMILY";
|
// const accountType = userDetails?.account_type === "FAMILY";
|
||||||
|
|
||||||
|
const [selectedWallet, setSelectedWallet] = useState('')
|
||||||
|
|
||||||
|
const [activeWalletBtn, setActiveWalletBtn] = useState('')
|
||||||
|
|
||||||
|
const handleChangeWallet = ({target:{name}}) => { // FUNCTION TO SWITCH WALLET IF USER HAS MORE THAN TWO WALLETS
|
||||||
|
const currentWalletSelected = wallet?.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";
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
setSelectedWallet(wallet.data[0])
|
||||||
|
setActiveWalletBtn(wallet?.data[0]?.code)
|
||||||
|
},[wallet])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="my-wallet-wrapper w-full mb-10">
|
<div className="w-full">
|
||||||
<div className="main-wrapper w-full">
|
<div className="my-wallet-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">
|
<div className="main-wrapper w-full mb-10">
|
||||||
{loading ? (
|
<div className="w-full mb-10 sm:grid grid-cols-2 gap-4">
|
||||||
|
<div className="w-full mb-4 sm:mb-0 rounded-2xl bg-white dark:bg-dark-white overflow-hidden">
|
||||||
|
{wallet?.loading ?
|
||||||
<div className="w-full h-full flex items-center justify-center bg-white">
|
<div className="w-full h-full flex items-center justify-center bg-white">
|
||||||
<LoadingSpinner size="16" color="sky-blue" height='h-[30rem]' />
|
<LoadingSpinner size="16" color="sky-blue" height='min-h-[240px]' />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
: wallet?.data.length > 0 ?
|
||||||
data.length > 0 && data.map((item) => (
|
<>
|
||||||
<div key={item.wallet_uid} className="lg:w-full h-full mb-10 lg:mb-0">
|
{wallet?.data?.length > 1 &&
|
||||||
<WalletItemCardFamily walletItem={item} payment={payment} countries={countries} />
|
<div className="wal-selection px-5 py-2 text-black dark:text-white flex items-center gap-2">
|
||||||
|
{wallet?.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>
|
||||||
))
|
}
|
||||||
)}
|
<div className="p-5 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-[100px] max-h-min md:max-h-[100px] 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 className="w-full h-full flex justify-center items-center rounded-2xl bg-white">
|
||||||
|
<p>No Wallet Record Found</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>
|
||||||
|
<div className="w-full">
|
||||||
|
<FamilyWalletRedeemOptions />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
||||||
|
// ))
|
||||||
|
|||||||
+25
-36
@@ -6,9 +6,12 @@ import LoadingSpinner from "../Spinners/LoadingSpinner";
|
|||||||
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
import CustomBreadcrumb from "../Breadcrumb/CustomBreadcrumb";
|
||||||
const FamilyWalletBox = lazy(() => import("./FamilyWalletBox"));
|
const FamilyWalletBox = lazy(() => import("./FamilyWalletBox"));
|
||||||
|
|
||||||
const FamilyWallet = () => {
|
const FamilyWalletCon = () => {
|
||||||
const apiCall = new usersService();
|
const apiCall = new usersService();
|
||||||
const { walletDetails } = useSelector((state) => state?.walletDetails); // WALLET STORE
|
// const { walletDetails } = useSelector((state) => state?.walletDetails); // WALLET STORE
|
||||||
|
|
||||||
|
const {userDetails} = useSelector((state) => state?.userDetails); // GETS USER INFO
|
||||||
|
|
||||||
const { walletTable } = useSelector((state) => state.tableReload);
|
const { walletTable } = useSelector((state) => state.tableReload);
|
||||||
|
|
||||||
const [paymentHistory, setPaymentHistory] = useState({
|
const [paymentHistory, setPaymentHistory] = useState({
|
||||||
@@ -16,12 +19,20 @@ const FamilyWallet = () => {
|
|||||||
data: [],
|
data: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
const [allCountries, setAllCountries] = useState({
|
const [familyWalletBal, setFamilyWalletBal] = useState({
|
||||||
// STATE TO HOLD LIST OF COUNTRIES
|
|
||||||
loading: true,
|
loading: true,
|
||||||
data: [],
|
data: []
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const getFamilyWalletBal = () => {
|
||||||
|
setFamilyWalletBal({loading:true, data: []})
|
||||||
|
apiCall.getFamilyWallet({family_uid: userDetails.uid}).then(res => {
|
||||||
|
setFamilyWalletBal({loading:false, data: res?.data?.result_list})
|
||||||
|
}).catch(error => {
|
||||||
|
setFamilyWalletBal({loading:false, data: []})
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
const getPaymentHistory = () => {
|
const getPaymentHistory = () => {
|
||||||
apiCall
|
apiCall
|
||||||
.getPaymentHx()
|
.getPaymentHx()
|
||||||
@@ -30,6 +41,7 @@ const FamilyWallet = () => {
|
|||||||
setPaymentHistory({ loading: false, data: [] });
|
setPaymentHistory({ loading: false, data: [] });
|
||||||
} else {
|
} else {
|
||||||
setPaymentHistory({ loading: false, data: res.data?.result_list });
|
setPaymentHistory({ loading: false, data: res.data?.result_list });
|
||||||
|
// console.log('Hist', res.data?.result_list)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
@@ -37,37 +49,11 @@ 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(() => {
|
useEffect(() => {
|
||||||
getCountry();
|
|
||||||
getPaymentHistory();
|
getPaymentHistory();
|
||||||
|
getFamilyWalletBal()
|
||||||
}, [walletTable]);
|
}, [walletTable]);
|
||||||
|
|
||||||
console.log(
|
|
||||||
"Testing all country: ",
|
|
||||||
allCountries,
|
|
||||||
"Testing wallet: ",
|
|
||||||
walletDetails
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<div className='mb-4'>
|
<div className='mb-4'>
|
||||||
@@ -81,15 +67,18 @@ const FamilyWallet = () => {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Suspense fallback={<LoadingSpinner size="16" color="sky-blue" />}>
|
<Suspense fallback={
|
||||||
|
<div className="bg-white rounded-2xl">
|
||||||
|
<LoadingSpinner size="16" color="sky-blue" height='h-[30rem]' />
|
||||||
|
</div>
|
||||||
|
}>
|
||||||
<FamilyWalletBox
|
<FamilyWalletBox
|
||||||
wallet={walletDetails}
|
wallet={familyWalletBal}
|
||||||
payment={paymentHistory}
|
payment={paymentHistory}
|
||||||
countries={allCountries.data}
|
|
||||||
/>
|
/>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default FamilyWallet;
|
export default FamilyWalletCon;
|
||||||
@@ -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>
|
||||||
|
: familyWalletRedeemOptList?.data && 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 localImgLoad from "../../lib/localImgLoad";
|
||||||
import { tableReload } from "../../store/TableReloads";
|
import { tableReload } from "../../store/TableReloads";
|
||||||
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
import { PriceFormatter } from "../Helpers/PriceFormatter";
|
||||||
import CreditPopup from "./Popup/CreditPopup";
|
|
||||||
import WalletAction from "./WalletAction";
|
import WalletAction from "./WalletAction";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -13,26 +12,15 @@ import WalletAction from "./WalletAction";
|
|||||||
export default function WalletItemCardFamily({ walletItem, payment, countries }) {
|
export default function WalletItemCardFamily({ walletItem, payment, countries }) {
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [creditPopup, setCreditPopup] = useState({ show: false, data: {} });
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the credit popup.
|
* Opens the credit popup.
|
||||||
* @param {Object} value - The value object.
|
* @param {Object} value - The value object.
|
||||||
*/
|
*/
|
||||||
const openPopUp = (value) => {
|
|
||||||
setCreditPopup({
|
|
||||||
show: true,
|
|
||||||
data: { ...value },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the credit popup and dispatches a table reload action.
|
* 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);
|
const currentWalletCurrency = countries?.filter((country) => country.code === walletItem.country);
|
||||||
|
|
||||||
@@ -43,10 +31,10 @@ export default function WalletItemCardFamily({ walletItem, payment, countries })
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
className="current-balance-widget w-full h-full rounded-2xl overflow-hidden flex flex-col items-center gap-2 p-8 justify-between"
|
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={{
|
// style={{
|
||||||
background: `url(${background}) 0% 0% / cover no-repeat`,
|
// background: `url(${background}) 0% 0% / cover no-repeat`,
|
||||||
}}
|
// }}
|
||||||
>
|
>
|
||||||
<div className="wallet w-full flex justify-between items-center gap-3">
|
<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">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="my-2 w-full h-[1px] bg-white"></div>
|
|
||||||
|
|
||||||
{/* <WalletAction
|
|
||||||
walletItem={{ ...walletItem, walletCountry: currentWalletCurrency }}
|
|
||||||
payment={payment}
|
|
||||||
openPopUp={openPopUp}
|
|
||||||
/> */}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{creditPopup.show && (
|
|
||||||
<CreditPopup
|
|
||||||
details={creditPopup.data}
|
|
||||||
walletItem={walletItem}
|
|
||||||
onClose={closePopUp}
|
|
||||||
situation={openPopUp}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ export default function OffersInterestTable({offerInterestList, className}) {
|
|||||||
handlePagingFunc(e, setCurrentPage);
|
handlePagingFunc(e, setCurrentPage);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let imgServer = offerInterestList?.imgServer // FOR RENDERING IMAGE FROM SERVER
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`update-table w-full my-8 p-8 bg-white dark:bg-dark-white rounded-2xl section-shadow min-h-[520px] ${
|
className={`update-table w-full my-8 p-8 bg-white dark:bg-dark-white rounded-2xl section-shadow min-h-[520px] ${
|
||||||
@@ -54,14 +55,19 @@ export default function OffersInterestTable({offerInterestList, className}) {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody className="h-full">
|
<tbody className="h-full">
|
||||||
{currentOfferInterestList?.map((item, index) => {
|
{currentOfferInterestList?.map((item, index) => {
|
||||||
let image = item.banner ? item.banner : 'default.jpg'
|
// let image = item.banner ? item.banner : 'default.jpg'
|
||||||
|
const image = localStorage.getItem("session_token")
|
||||||
|
? `${imgServer}${localStorage.getItem("session_token")}/job/${
|
||||||
|
item.job_uid
|
||||||
|
}`
|
||||||
|
: "";
|
||||||
return (
|
return (
|
||||||
<tr key={index} className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
|
<tr key={index} className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
|
||||||
<td className=" py-4">
|
<td className=" py-4">
|
||||||
<div className="flex space-x-2 items-center">
|
<div className="flex space-x-2 items-center">
|
||||||
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
|
<div className="min-w-[60px] max-w-[60px] min-h-[60px] max-h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
|
||||||
<img
|
<img
|
||||||
src={localImgLoad(`images/taskbanners/${image}`)}
|
src={`${image}`}
|
||||||
alt="data"
|
alt="data"
|
||||||
className="w-full h-full rounded-full"
|
className="w-full h-full rounded-full"
|
||||||
/>
|
/>
|
||||||
@@ -90,7 +96,7 @@ export default function OffersInterestTable({offerInterestList, className}) {
|
|||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate("/manage-offer", {
|
navigate("/manage-offer", {
|
||||||
state: { ...item, pathname },
|
state: { ...item, pathname, jobImage:image },
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@@ -56,13 +56,18 @@ export default function OthersInterestTable({othersInterestedList, className}) {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody className="h-full">
|
<tbody className="h-full">
|
||||||
{currentOthersInterestedList?.map((item, index) => {
|
{currentOthersInterestedList?.map((item, index) => {
|
||||||
|
const image = localStorage.getItem("session_token")
|
||||||
|
? `${othersInterestedList.imageServer}${localStorage.getItem("session_token")}/job/${
|
||||||
|
item.job_uid
|
||||||
|
}`
|
||||||
|
: "";
|
||||||
return (
|
return (
|
||||||
<tr key={index} className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
|
<tr key={index} className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50">
|
||||||
<td className=" py-4">
|
<td className=" py-4">
|
||||||
<div className="flex space-x-2 items-center">
|
<div className="flex space-x-2 items-center">
|
||||||
<div className="min-w-[60px] min-h-[60px] rounded-full overflow-hidden flex justify-center items-center">
|
<div className="min-w-[60px] min-h-[60px] rounded-full overflow-hidden flex justify-center items-center">
|
||||||
<img
|
<img
|
||||||
src={dataImage1}
|
src={image}
|
||||||
alt="data"
|
alt="data"
|
||||||
className="w-full h-full"
|
className="w-full h-full"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export default function OffersInterest(props) {
|
|||||||
const filterHandler = (value) => {
|
const filterHandler = (value) => {
|
||||||
setValue(value);
|
setValue(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<CommonHead
|
<CommonHead
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
const data1 = [];
|
||||||
|
|
||||||
|
export default function NewPaginatedList({
|
||||||
|
data = data1,
|
||||||
|
itemsPerPage = 5,
|
||||||
|
filterItem,
|
||||||
|
tableTitle,
|
||||||
|
children,
|
||||||
|
}) {
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [filteredData, setFilteredData] = useState(data);
|
||||||
|
|
||||||
|
const [currentPage, setCurrentPage] = useState(0);
|
||||||
|
const [newData, setNewData] = useState([]);
|
||||||
|
|
||||||
|
const numberOfSelection = itemsPerPage;
|
||||||
|
|
||||||
|
const handlePrev = () => {
|
||||||
|
if (currentPage != 0) {
|
||||||
|
setCurrentPage((prev) => prev - numberOfSelection);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleNext = () => {
|
||||||
|
if (currentPage < data.length) {
|
||||||
|
setCurrentPage((prev) => prev + numberOfSelection);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSearch = ({ target: { value } }, name) => {
|
||||||
|
setSearchTerm(value);
|
||||||
|
let newFilteredData = data.filter((item) =>
|
||||||
|
item[name].toLowerCase().startsWith(value.toLowerCase())
|
||||||
|
);
|
||||||
|
setFilteredData(newFilteredData);
|
||||||
|
setCurrentPage(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setNewData(
|
||||||
|
filteredData?.slice(currentPage, numberOfSelection + currentPage)
|
||||||
|
);
|
||||||
|
}, [currentPage, filteredData]);
|
||||||
|
console.log("newData", newData, filteredData);
|
||||||
|
return (
|
||||||
|
<div className="w-full">
|
||||||
|
<h1 className="text-2xl mb-5 font-semibold">{tableTitle}</h1>
|
||||||
|
|
||||||
|
{data.length > 0 && filterItem && (
|
||||||
|
<div className="mb-10 flex justify-end items-center gap-2">
|
||||||
|
{filterItem.map((item, index) => (
|
||||||
|
<label
|
||||||
|
key={index}
|
||||||
|
className="flex flex-col sm:flex-row items-center gap-2 text-slate-600 dark:text-slate-100 transition-all duration-500"
|
||||||
|
>
|
||||||
|
Search by {item[0].toUpperCase() + item.slice(1)}
|
||||||
|
<input
|
||||||
|
name={item}
|
||||||
|
type="text"
|
||||||
|
className="py-1 px-2 text-sm min-w-[100px] text-black dark:text-white bg-white dark:bg-slate-800 rounded-full border-0 outline-none ring-1 ring-slate-300 dark:ring-white transition-all duration-500"
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => {
|
||||||
|
handleSearch(e, item);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{children({ data: newData })}
|
||||||
|
|
||||||
|
{/* show prev and next button if data exist */}
|
||||||
|
{data.length > 0 && (
|
||||||
|
<div className="mt-10 w-full flex gap-4 justify-center items-center">
|
||||||
|
<button
|
||||||
|
onClick={handlePrev}
|
||||||
|
className={`w-12 h-12 rounded-full flex justify-center items-center border ${
|
||||||
|
currentPage == 0
|
||||||
|
? "text-slate-300 border-slate-300 dark:text-slate-400 dark:border-slate-400 pointer-events-none"
|
||||||
|
: "text-slate-600 border-slate-600 dark:text-slate-300 dark:border-slate-300"
|
||||||
|
} transition-all duration-500`}
|
||||||
|
>
|
||||||
|
<
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={handleNext}
|
||||||
|
className={`w-12 h-12 rounded-full flex justify-center items-center border ${
|
||||||
|
currentPage + numberOfSelection >= data.length
|
||||||
|
? "text-slate-300 border-slate-300 dark:text-slate-400 dark:border-slate-400 pointer-events-none"
|
||||||
|
: "text-slate-600 border-slate-600 dark:text-slate-300 dark:border-slate-300"
|
||||||
|
} transition-all duration-500`}
|
||||||
|
>
|
||||||
|
>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -20,10 +20,7 @@ export default function Layout({ children }) {
|
|||||||
};
|
};
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const logOut = () => {
|
const logOut = () => {
|
||||||
localStorage.removeItem("session_token");
|
sessionStorage.clear();
|
||||||
localStorage.removeItem("member_id");
|
|
||||||
localStorage.removeItem("uid");
|
|
||||||
sessionStorage.removeItem("family_uid");
|
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
// toast.success("Come Back Soon", {
|
// toast.success("Come Back Soon", {
|
||||||
// icon: `🙂`,
|
// icon: `🙂`,
|
||||||
|
|||||||
@@ -89,7 +89,9 @@ export default function MobileSidebar({
|
|||||||
<ul className="flex flex-col space-y-6">
|
<ul className="flex flex-col space-y-6">
|
||||||
{/* Using mini component reduces the bulk amount of html */}
|
{/* Using mini component reduces the bulk amount of html */}
|
||||||
<ListItem
|
<ListItem
|
||||||
title= {userDetails?.account_type == "FULL" ? "Dashboard" : "Home"}
|
title={
|
||||||
|
userDetails?.account_type == "FULL" ? "Dashboard" : "Home"
|
||||||
|
}
|
||||||
route="/"
|
route="/"
|
||||||
sidebar={sidebar}
|
sidebar={sidebar}
|
||||||
iconName="new-dashboard"
|
iconName="new-dashboard"
|
||||||
@@ -190,17 +192,21 @@ export default function MobileSidebar({
|
|||||||
<div className="items">
|
<div className="items">
|
||||||
<ul className="flex flex-col space-y-6">
|
<ul className="flex flex-col space-y-6">
|
||||||
{[
|
{[
|
||||||
{ name: "List", path: "/myjobs", iconName: "job-list" },
|
{
|
||||||
|
name: "List",
|
||||||
|
path: "/myjobs",
|
||||||
|
iconName: "job-list",
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// name: "Waiting",
|
||||||
|
// path: "/pend-interest",
|
||||||
|
// iconName: "pending-job",
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
name: "Offers",
|
name: "Offers",
|
||||||
path: "/my-offers",
|
path: "/my-offers",
|
||||||
iconName: "pending-job",
|
iconName: "pending-job",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "Waiting",
|
|
||||||
path: "/pend-interest",
|
|
||||||
iconName: "pending-job",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "Active",
|
name: "Active",
|
||||||
path: "/my-active-jobs",
|
path: "/my-active-jobs",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { NavLink } from "react-router-dom";
|
|||||||
//import SideStatistics from "./SideStatistics";
|
//import SideStatistics from "./SideStatistics";
|
||||||
import { localImgLoad } from "../../lib";
|
import { localImgLoad } from "../../lib";
|
||||||
import DarkModeContext from "../Contexts/DarkModeContext";
|
import DarkModeContext from "../Contexts/DarkModeContext";
|
||||||
|
import Icons from "../Helpers/Icons";
|
||||||
|
|
||||||
export default function RightSideBar({ myJobList }) {
|
export default function RightSideBar({ myJobList }) {
|
||||||
const filterDatas = ["Last 15 days", "Last Month", "Last 6 month"];
|
const filterDatas = ["Last 15 days", "Last Month", "Last 6 month"];
|
||||||
@@ -81,6 +82,19 @@ export default function RightSideBar({ myJobList }) {
|
|||||||
{/* action */}
|
{/* action */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="item flex space-x-3 items-center mb-4">
|
||||||
|
{/* image */}
|
||||||
|
<div className="w-8 h-8 rounded-full flex items-center justify-center">
|
||||||
|
<Icons name="pending-job" />
|
||||||
|
</div>
|
||||||
|
{/* name */}
|
||||||
|
<div>
|
||||||
|
<p className="text-thin-light-gray text-base font-medium">
|
||||||
|
<NavLink to="/pend-interest">Waiting</NavLink>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{/* action */}
|
||||||
|
</div>
|
||||||
<div className="item flex space-x-3 items-center mb-4">
|
<div className="item flex space-x-3 items-center mb-4">
|
||||||
{/* image */}
|
{/* image */}
|
||||||
<div className="w-8 h-8 rounded-full">
|
<div className="w-8 h-8 rounded-full">
|
||||||
@@ -235,6 +249,7 @@ export default function RightSideBar({ myJobList }) {
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
<p className="text-thin-light-gray text-base font-medium">
|
<p className="text-thin-light-gray text-base font-medium">
|
||||||
{darkMode.theme === "light" ? "Dark" : "Light"} Mode
|
{darkMode.theme === "light" ? "Dark" : "Light"} Mode
|
||||||
@@ -274,6 +289,24 @@ export default function RightSideBar({ myJobList }) {
|
|||||||
{/* action */}
|
{/* action */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="px-8 item flex space-x-3 items-center mb-4">
|
||||||
|
{/* image */}
|
||||||
|
<div className="w-8 h-8 p-[4px] rounded-full">
|
||||||
|
<img
|
||||||
|
src={localImgLoad("images/icons/job_active.svg")}
|
||||||
|
className="w-full h-full"
|
||||||
|
alt="Active Task"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/* name */}
|
||||||
|
<div>
|
||||||
|
<p className="text-thin-light-gray text-base font-medium">
|
||||||
|
<NavLink to="/offer-interest">Offers Interest</NavLink>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{/* action */}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="px-8 item flex space-x-3 items-center mb-4">
|
<div className="px-8 item flex space-x-3 items-center mb-4">
|
||||||
{/* image */}
|
{/* image */}
|
||||||
<div className="w-8 h-8 p-[4px] rounded-full">
|
<div className="w-8 h-8 p-[4px] rounded-full">
|
||||||
|
|||||||
@@ -216,11 +216,11 @@ export default function Sidebar({
|
|||||||
path: "/myjobs",
|
path: "/myjobs",
|
||||||
iconName: "job-list",
|
iconName: "job-list",
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
name: "Waiting",
|
// name: "Waiting",
|
||||||
path: "/pend-interest",
|
// path: "/pend-interest",
|
||||||
iconName: "pending-job",
|
// iconName: "pending-job",
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
name: "Offers",
|
name: "Offers",
|
||||||
path: "/my-offers",
|
path: "/my-offers",
|
||||||
|
|||||||
@@ -64,13 +64,13 @@ function DeleteJobPopout({ details, onClose, situation }) {
|
|||||||
return (
|
return (
|
||||||
<ModalCom action={onClose} situation={situation}>
|
<ModalCom action={onClose} situation={situation}>
|
||||||
<div className="logout-modal-wrapper lg:w-[600px] bg-white dark:bg-dark-white lg:rounded-2xl">
|
<div className="logout-modal-wrapper lg:w-[600px] bg-white dark:bg-dark-white lg:rounded-2xl">
|
||||||
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b border-light-purple dark:border-[#5356fb29] ">
|
<div className="modal-header-con">
|
||||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="modal-title">
|
||||||
Delete Job
|
Delete Job
|
||||||
</h1>
|
</h1>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="text-[#374557] dark:text-red-500"
|
className="modal-close-btn"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
@@ -119,10 +119,10 @@ function DeleteJobPopout({ details, onClose, situation }) {
|
|||||||
{details.title}
|
{details.title}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-lg tracking-wide text-dark-gray dark:text-white flex items-start gap-1">
|
<p className="text-lg tracking-wide text-dark-gray dark:text-white flex items-start gap-1">
|
||||||
Price: {details.thePrice}
|
<span className="job-label">Price: </span>{details.thePrice}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-lg tracking-wide text-dark-gray dark:text-white">
|
<p className="text-lg tracking-wide text-dark-gray dark:text-white">
|
||||||
Duration: {details.timeline_days} day(s)
|
<span className="job-label">Duration: </span>{details.timeline_days} day(s)
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex space-x-2.5">
|
<div className="flex space-x-2.5">
|
||||||
|
|||||||
@@ -212,13 +212,13 @@ const EditJobPopOut = ({
|
|||||||
return (
|
return (
|
||||||
<ModalCom action={onClose} situation={situation}>
|
<ModalCom action={onClose} situation={situation}>
|
||||||
<div className="logout-modal-wrapper w-11/12 lg:w-[600px] bg-white dark:bg-dark-white lg:rounded-2xl">
|
<div className="logout-modal-wrapper w-11/12 lg:w-[600px] bg-white dark:bg-dark-white lg:rounded-2xl">
|
||||||
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] border-b border-light-purple dark:border-[#5356fb29] ">
|
<div className="modal-header-con">
|
||||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="modal-title">
|
||||||
Edit Job
|
Edit Job
|
||||||
</h1>
|
</h1>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="text-[#374557] dark:text-red-500"
|
className="modal-close-btn"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
@@ -328,8 +328,8 @@ const EditJobPopOut = ({
|
|||||||
<div className="field flex flex-col sm:flex-row w-full mb-[5px] gap-2">
|
<div className="field flex flex-col sm:flex-row w-full mb-[5px] gap-2">
|
||||||
<div className="sm:w-[60%] w-full">
|
<div className="sm:w-[60%] w-full">
|
||||||
<label
|
<label
|
||||||
htmlFor="Job Delivery Details"
|
htmlFor="job-label"
|
||||||
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'
|
className='job-label'
|
||||||
>
|
>
|
||||||
Job Delivery Details
|
Job Delivery Details
|
||||||
</label>
|
</label>
|
||||||
@@ -352,7 +352,7 @@ const EditJobPopOut = ({
|
|||||||
<div className="sm:w-[35%] w-full">
|
<div className="sm:w-[35%] w-full">
|
||||||
<div
|
<div
|
||||||
htmlFor="Job Categories"
|
htmlFor="Job Categories"
|
||||||
className='className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"'
|
className='job-label'
|
||||||
id="checked-group"
|
id="checked-group"
|
||||||
>
|
>
|
||||||
Categories
|
Categories
|
||||||
@@ -422,7 +422,7 @@ const EditJobPopOut = ({
|
|||||||
<div className="field w-1/2">
|
<div className="field w-1/2">
|
||||||
<div className={`flex items-center justify-between`}>
|
<div className={`flex items-center justify-between`}>
|
||||||
<label
|
<label
|
||||||
className="w-full input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold flex flex-col"
|
className="job-label flex flex-col"
|
||||||
htmlFor="timeline_days"
|
htmlFor="timeline_days"
|
||||||
>
|
>
|
||||||
Timeline -
|
Timeline -
|
||||||
|
|||||||
@@ -10,7 +10,12 @@ import localImgLoad from "../../lib/localImgLoad";
|
|||||||
import { tableReload } from "../../store/TableReloads";
|
import { tableReload } from "../../store/TableReloads";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
|
|
||||||
|
import { SocketValues } from "../Contexts/SocketIOContext";
|
||||||
|
|
||||||
function FamilyOfferJobPopout({ details, onClose, situation }) {
|
function FamilyOfferJobPopout({ details, onClose, situation }) {
|
||||||
|
|
||||||
|
const {parentAssignJobToKid} = SocketValues()
|
||||||
|
|
||||||
const apiUrl = new usersService();
|
const apiUrl = new usersService();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@@ -69,6 +74,18 @@ function FamilyOfferJobPopout({ details, onClose, situation }) {
|
|||||||
message: `Offer ${name}ed Successfully`,
|
message: `Offer ${name}ed Successfully`,
|
||||||
trigger: "",
|
trigger: "",
|
||||||
});
|
});
|
||||||
|
// trigger socket event to refresh parent side
|
||||||
|
//SENDS MESSAGE TO SOCKET TO UPDATE PARENT ACCOUNT WHEN CHILD ACCEPTS OR REJECTS A JOB ASSIGNED BY PARENT
|
||||||
|
// message, room
|
||||||
|
let socketMsg = {
|
||||||
|
"audience": "PARENT",
|
||||||
|
"action": "REFRESH_TASK",
|
||||||
|
"family_uid": sessionStorage.getItem('family_uid'),
|
||||||
|
}
|
||||||
|
let socketRoom = `FAMILY-${sessionStorage.getItem('parent_uid')}`
|
||||||
|
parentAssignJobToKid(socketMsg, socketRoom) //SENDS MESSAGE TO SOCKET TO UPDATE CHILD ACCOUNT
|
||||||
|
// end of socket event trigger
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
onClose();
|
onClose();
|
||||||
dispatch(tableReload({ type: "MYTASKTABLE" }));
|
dispatch(tableReload({ type: "MYTASKTABLE" }));
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import InputCom from "../Helpers/Inputs/InputCom/index";
|
|||||||
import ModalCom from "../Helpers/ModalCom";
|
import ModalCom from "../Helpers/ModalCom";
|
||||||
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
import LoadingSpinner from "../Spinners/LoadingSpinner";
|
||||||
import Detail from "./popoutcomponent/Detail";
|
import Detail from "./popoutcomponent/Detail";
|
||||||
|
import { SocketValues } from "../Contexts/SocketIOContext";
|
||||||
|
|
||||||
const validationSchema = Yup.object().shape({
|
const validationSchema = Yup.object().shape({
|
||||||
family: Yup.string().required("This is required "),
|
family: Yup.string().required("This is required "),
|
||||||
@@ -29,6 +30,9 @@ function JobListPopout({
|
|||||||
openWallet,
|
openWallet,
|
||||||
setWalletItem,
|
setWalletItem,
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
|
let {marketUpdate} = SocketValues() // destructures 'SEND MESSAGE' and 'JOIN ROOM' FUNCTIONS FROM SOCKET
|
||||||
|
|
||||||
const [selectedTab, setSelectedTab] = useState("public");
|
const [selectedTab, setSelectedTab] = useState("public");
|
||||||
const tabs = ["public", "individual", "group"];
|
const tabs = ["public", "individual", "group"];
|
||||||
|
|
||||||
@@ -201,7 +205,9 @@ function JobListPopout({
|
|||||||
setRequestStatus({ message: "", status: false });
|
setRequestStatus({ message: "", status: false });
|
||||||
}, 3000);
|
}, 3000);
|
||||||
}
|
}
|
||||||
dispatch(tableReload({ type: "JOBTABLE" }));
|
marketUpdate('market', 'full-markets-jobs') // sends an event to the socket to update market lists
|
||||||
|
dispatch(tableReload({ type: "JOBTABLE" })); // reloads my job page
|
||||||
|
dispatch(tableReload({ type: "MARKETTABLELIST" })); // reloads market page
|
||||||
setRequestStatus({ message: data?.status_msg ? data?.status_msg : "Offer Assigned Successful", status: true });
|
setRequestStatus({ message: data?.status_msg ? data?.status_msg : "Offer Assigned Successful", status: true });
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setLoader({ jobFields: false });
|
setLoader({ jobFields: false });
|
||||||
@@ -224,6 +230,12 @@ function JobListPopout({
|
|||||||
members: [],
|
members: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const DetailsSection = ({ label, value }) => (
|
||||||
|
<div className="my-3 md:flex">
|
||||||
|
<Detail label={label} value={value} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
// FUNCTION TO POPULATE USER GROUP LIST
|
// FUNCTION TO POPULATE USER GROUP LIST
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// setGroupList({loading: true, groups: [], members: []})
|
// setGroupList({loading: true, groups: [], members: []})
|
||||||
@@ -250,12 +262,6 @@ function JobListPopout({
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const DetailsSection = ({ label, value }) => (
|
|
||||||
<div className="my-3 md:flex">
|
|
||||||
<Detail label={label} value={value} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const DetailsComponent = () => {
|
const DetailsComponent = () => {
|
||||||
const detailsArray = [
|
const detailsArray = [
|
||||||
{ label: "Description", value: details.description },
|
{ label: "Description", value: details.description },
|
||||||
@@ -297,13 +303,13 @@ function JobListPopout({
|
|||||||
return (
|
return (
|
||||||
<ModalCom action={onClose} situation={situation} className="">
|
<ModalCom action={onClose} situation={situation} className="">
|
||||||
<div className="logout-modal-wrapper w-[90%] md:w-[768px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
<div className="logout-modal-wrapper w-[90%] md:w-[768px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
||||||
<div className="logout-modal-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="modal-header-con">
|
||||||
<h1 className="text-base md:text-lg font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="modal-title">
|
||||||
{details.title}
|
{details.title}
|
||||||
</h1>
|
</h1>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="text-[#374557] dark:text-red-500"
|
className="modal-close-btn"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
|||||||
@@ -135,13 +135,13 @@ function PendingJobsPopout({ details, onClose, situation }) {
|
|||||||
return (
|
return (
|
||||||
<ModalCom action={onClose} situation={situation}>
|
<ModalCom action={onClose} situation={situation}>
|
||||||
<div className="logout-modal-wrapper w-[90%] md:w-[768px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
|
<div className="logout-modal-wrapper w-[90%] md:w-[768px] 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="modal-header-con">
|
||||||
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="modal-title">
|
||||||
Manage Pending Item
|
Manage Pending Item
|
||||||
</h1>
|
</h1>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="text-[#374557] dark:text-red-500"
|
className="modal-close-btn"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
@@ -170,7 +170,7 @@ function PendingJobsPopout({ details, onClose, situation }) {
|
|||||||
<p className="text-base font-semibold text-slate-900 dark:text-white tracking-wide">
|
<p className="text-base font-semibold text-slate-900 dark:text-white tracking-wide">
|
||||||
{details.title}
|
{details.title}
|
||||||
</p>
|
</p>
|
||||||
<div className="my-2 p-2 flex justify-start items-center space-x-2 bg-red-100 border-2 border-red-300">
|
<div className="my-2 p-2 flex justify-start items-center space-x-2 bg-red-100 border-2 border-red-300 rounded-2xl">
|
||||||
<span className="w-8 h-8 text-center text-sm rounded-full flex justify-center items-center text-red-300 bg-yellow-100">
|
<span className="w-8 h-8 text-center text-sm rounded-full flex justify-center items-center text-red-300 bg-yellow-100">
|
||||||
!
|
!
|
||||||
</span>
|
</span>
|
||||||
@@ -236,7 +236,7 @@ function PendingJobsPopout({ details, onClose, situation }) {
|
|||||||
|
|
||||||
{/* ACTION SECTION */}
|
{/* ACTION SECTION */}
|
||||||
<div className="p-4 w-full md:w-1/4 h-full">
|
<div className="p-4 w-full md:w-1/4 h-full">
|
||||||
<p className="mb-6 text-sm dark:text-white">Actions</p>
|
<p className="job-label mb-6 dark:text-white">Actions</p>
|
||||||
|
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<p className="px-2 py-1 text-sm bg-slate-100">
|
<p className="px-2 py-1 text-sm bg-slate-100">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from 'react'
|
|||||||
function Detail({label, value, bg,}) {
|
function Detail({label, value, bg,}) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<label className='w-full md:w-1/4 text-slate-900 dark:text-white tracking-wide font-semibold'>{label}</label>
|
<label className='job-label w-full md:w-1/4'>{label}</label>
|
||||||
<p className={`p-1 w-full md:w-3/4 text-sm text-slate-900 dark:text-white ${bg ? bg : null}`}>{value}</p>
|
<p className={`p-1 w-full md:w-3/4 text-sm text-slate-900 dark:text-white ${bg ? bg : null}`}>{value}</p>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -152,6 +152,38 @@
|
|||||||
--toastify-color-success: #f539f8;
|
--toastify-color-success: #f539f8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@layer components{
|
||||||
|
.job-label{
|
||||||
|
@apply text-base text-slate-900 dark:text-white tracking-wide font-semibold
|
||||||
|
}
|
||||||
|
.job-label-flex{
|
||||||
|
@apply flex items-center gap-2
|
||||||
|
}
|
||||||
|
|
||||||
|
/* STYLES FOR MODAL */
|
||||||
|
/* Modal Header */
|
||||||
|
.modal-header-con{
|
||||||
|
@apply w-full flex items-center justify-between lg:px-10 lg:py-8 px-[30px] py-[23px] bg-sky-blue/50 border-b dark:border-[#5356fb29] border-light-purple
|
||||||
|
}
|
||||||
|
.modal-title{
|
||||||
|
@apply text-2xl leading-8 font-bold text-dark-gray dark:text-white tracking-wide flex items-center
|
||||||
|
}
|
||||||
|
.modal-close-btn{
|
||||||
|
@apply text-[#000] dark:text-red-500
|
||||||
|
}
|
||||||
|
|
||||||
|
/* modal footer */
|
||||||
|
.modal-footer-wrapper{
|
||||||
|
@apply py-2 px-4 border-t-2 flex justify-between items-center
|
||||||
|
}
|
||||||
|
/* END OF STYLES FOR MODAL BOX */
|
||||||
|
|
||||||
|
/* STYLES FOR BUTTON */
|
||||||
|
.custom-btn {
|
||||||
|
@apply px-2 min-w-[80px] h-11 flex justify-center items-center text-base rounded-full cursor-pointer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ===================== EXTRA ===================== */
|
/* ===================== EXTRA ===================== */
|
||||||
.bottomMargin {
|
.bottomMargin {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
|
|||||||
@@ -13,8 +13,13 @@ import { updateUserJobList } from "../store/userJobList";
|
|||||||
import { updateWalletDetails } from "../store/walletDetails";
|
import { updateWalletDetails } from "../store/walletDetails";
|
||||||
import { familyBannersList } from "../store/FamilyBannerList";
|
import { familyBannersList } from "../store/FamilyBannerList";
|
||||||
import { familyResources } from "../store/FamilyResources";
|
import { familyResources } from "../store/FamilyResources";
|
||||||
|
import {familyWalletRedeemOptList} from '../store/FamilyWalletRedeemOpt'
|
||||||
|
import { SocketValues } from "../components/Contexts/SocketIOContext";
|
||||||
|
|
||||||
const AuthRoute = ({ redirectPath = "/login", children }) => {
|
const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||||
|
|
||||||
|
let {joinRoom} = SocketValues() // destructures 'SEND MESSAGE' and 'JOIN ROOM' FUNCTIONS FROM SOCKET
|
||||||
|
|
||||||
const apiCall = useMemo(() => new usersService(), []);
|
const apiCall = useMemo(() => new usersService(), []);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [lastActivityTime, setLastActivityTime] = useState(Date.now());
|
const [lastActivityTime, setLastActivityTime] = useState(Date.now());
|
||||||
@@ -22,12 +27,12 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
|||||||
const [loadProfileDetails, setLoadProfileDetails] = useState([]);
|
const [loadProfileDetails, setLoadProfileDetails] = useState([]);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const { jobListTable, walletTable, familyBannersListTable } = useSelector(
|
const { jobListTable, marketTableList, walletTable, familyBannersListTable } = useSelector(
|
||||||
(state) => state.tableReload
|
(state) => state.tableReload
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
userDetails: { username, uid, session, account_type },
|
userDetails: { username, uid, session, account_type, parent_uid },
|
||||||
} = useSelector((state) => state?.userDetails); // CHECKS IF USER Details are avaliable, to determine if user is active
|
} = useSelector((state) => state?.userDetails); // CHECKS IF USER Details are avaliable, to determine if user is active
|
||||||
|
|
||||||
let loggedIn = username && session && uid ? true : false; // variable to determine if user is logged in
|
let loggedIn = username && session && uid ? true : false; // variable to determine if user is logged in
|
||||||
@@ -35,10 +40,7 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
//Removing Data stored at localStorage after session expires
|
//Removing Data stored at localStorage after session expires
|
||||||
const expireSession = () => {
|
const expireSession = () => {
|
||||||
localStorage.removeItem("uid");
|
sessionStorage.clear();
|
||||||
localStorage.removeItem("member_id");
|
|
||||||
localStorage.removeItem("session_token");
|
|
||||||
sessionStorage.removeItem("family_uid");
|
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
navigate("/login", { replace: true }); // redirects user to login page after session expires
|
navigate("/login", { replace: true }); // redirects user to login page after session expires
|
||||||
};
|
};
|
||||||
@@ -104,6 +106,8 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
loadProfile();
|
loadProfile();
|
||||||
|
}else{
|
||||||
|
setIsLogin({ loading: false, status: true });
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -188,6 +192,9 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
|||||||
}, [jobListTable, isLogin.status]);
|
}, [jobListTable, isLogin.status]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if((!loggedIn && !isLogin.status) || account_type == 'FAMILY'){ // DO NOT CALL THIS, IF USER ACCOUNT TYPE IS FAMILY
|
||||||
|
return
|
||||||
|
}
|
||||||
const getMyWalletList = async () => {
|
const getMyWalletList = async () => {
|
||||||
dispatch(updateWalletDetails({ loading: true, data: [] }));
|
dispatch(updateWalletDetails({ loading: true, data: [] }));
|
||||||
try {
|
try {
|
||||||
@@ -202,7 +209,7 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
getMyWalletList();
|
getMyWalletList();
|
||||||
}, [walletTable]);
|
}, [walletTable, isLogin.status]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if((!loggedIn && !isLogin.status) || account_type == 'FAMILY'){ // DO NOT CALL THIS, IF USER ACCOUNT TYPE IS FAMILY
|
if((!loggedIn && !isLogin.status) || account_type == 'FAMILY'){ // DO NOT CALL THIS, IF USER ACCOUNT TYPE IS FAMILY
|
||||||
@@ -218,7 +225,7 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
getMarketActiveJobList();
|
getMarketActiveJobList();
|
||||||
}, [apiCall, dispatch, jobListTable, isLogin.status]);
|
}, [apiCall, dispatch, marketTableList, isLogin.status]);
|
||||||
|
|
||||||
//FUNCTION TO GET COMMON HEAD DATA
|
//FUNCTION TO GET COMMON HEAD DATA
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -228,7 +235,7 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
|||||||
apiCall
|
apiCall
|
||||||
.getHeroJBanners()
|
.getHeroJBanners()
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.data.internal_return < 0) {
|
if (res.data?.internal_return < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch(commonHeadBanner(res.data));
|
dispatch(commonHeadBanner(res.data));
|
||||||
@@ -240,6 +247,9 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
|||||||
|
|
||||||
//FUNCTION TO GET COMMON HEAD DATA
|
//FUNCTION TO GET COMMON HEAD DATA
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if((!loggedIn && !isLogin.status) || account_type == 'FAMILY'){ // DO NOT CALL THIS, IF USER ACCOUNT TYPE IS FAMILY
|
||||||
|
return
|
||||||
|
}
|
||||||
apiCall
|
apiCall
|
||||||
.getRecentActivitiedData()
|
.getRecentActivitiedData()
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
@@ -252,7 +262,7 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
|||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.log("ERROR ", error);
|
console.log("ERROR ", error);
|
||||||
});
|
});
|
||||||
}, []);
|
}, [isLogin.status]);
|
||||||
|
|
||||||
|
|
||||||
//FUNCTION TO GET FAMILY BANNERS
|
//FUNCTION TO GET FAMILY BANNERS
|
||||||
@@ -291,6 +301,34 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
|||||||
}, [isLogin.status]);
|
}, [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]);
|
||||||
|
|
||||||
|
useEffect(()=>{ // sends an event to the socket to enable user join a room to be able to receive update when jobs enters the market
|
||||||
|
joinRoom('full-markets-jobs')
|
||||||
|
},[isLogin.status])
|
||||||
|
|
||||||
|
useEffect(()=>{ // sends an event to the socket to enable user join a room to be able to receive update for parent child job assign
|
||||||
|
if(loggedIn || isLogin.status){
|
||||||
|
joinRoom(`FAMILY-${account_type == 'FULL' ? uid : sessionStorage.getItem('parent_uid')}`)
|
||||||
|
console.log(`Room joined for parent child task assign as ${account_type} with ${account_type == 'FULL' ? uid : sessionStorage.getItem('parent_uid')}}`)
|
||||||
|
}
|
||||||
|
},[isLogin.status])
|
||||||
|
|
||||||
// RENDER PAGE
|
// RENDER PAGE
|
||||||
return isLogin.loading && !loggedIn ? (
|
return isLogin.loading && !loggedIn ? (
|
||||||
<LoadingSpinner size="32" color="sky-blue" height="h-screen" />
|
<LoadingSpinner size="32" color="sky-blue" height="h-screen" />
|
||||||
|
|||||||
@@ -388,13 +388,26 @@ class usersService {
|
|||||||
uid: localStorage.getItem("uid"),
|
uid: localStorage.getItem("uid"),
|
||||||
member_id: localStorage.getItem("member_id"),
|
member_id: localStorage.getItem("member_id"),
|
||||||
sessionid: localStorage.getItem("session_token"),
|
sessionid: localStorage.getItem("session_token"),
|
||||||
action: apiConst.WRENCHBOARD_JOB_CREATEJOB,
|
action: apiConst.WRENCHBOARD_JOB_CREATEJOB || apiConst.WRENCHBOARD_FAMILY_LIST,
|
||||||
limit: 30,
|
limit: 30,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
};
|
};
|
||||||
return this.postAuxEnd("/familywaitingtasks", postData);
|
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() {
|
ManageFamilyPending() {
|
||||||
var postData = {
|
var postData = {
|
||||||
uuid: localStorage.getItem("uid"),
|
uuid: localStorage.getItem("uid"),
|
||||||
@@ -1161,7 +1174,7 @@ class usersService {
|
|||||||
return this.postAuxEnd("/suggeststatus", postData);
|
return this.postAuxEnd("/suggeststatus", postData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION TO GET FAMILY WALLET
|
// FUNCTION TO GET FAMILY WALLET AS A KID
|
||||||
getFamilyWallet(reqData) {
|
getFamilyWallet(reqData) {
|
||||||
var postData = {
|
var postData = {
|
||||||
uid: localStorage.getItem("uid"),
|
uid: localStorage.getItem("uid"),
|
||||||
@@ -1173,6 +1186,18 @@ class usersService {
|
|||||||
return this.postAuxEnd("/familywallet", postData);
|
return this.postAuxEnd("/familywallet", postData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FUNCTION TO GET FAMILY WALLET AS A PARENT
|
||||||
|
getKidWallets(reqData) {
|
||||||
|
var postData = {
|
||||||
|
uid: localStorage.getItem("uid"),
|
||||||
|
member_id: localStorage.getItem("member_id"),
|
||||||
|
sessionid: localStorage.getItem("session_token"),
|
||||||
|
action: apiConst.WRENCHBOARD_FAMILY_WALLET,
|
||||||
|
...reqData,
|
||||||
|
};
|
||||||
|
return this.postAuxEnd("/kidwallets", postData);
|
||||||
|
}
|
||||||
|
|
||||||
// FUNCTION TO START FAMILY TRANSFER
|
// FUNCTION TO START FAMILY TRANSFER
|
||||||
familyTransferStart(reqData) {
|
familyTransferStart(reqData) {
|
||||||
var postData = {
|
var postData = {
|
||||||
@@ -1293,6 +1318,19 @@ class usersService {
|
|||||||
return this.postAuxEnd("/blogdata", postData);
|
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)
|
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(username)
|
||||||
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(password)
|
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(password)
|
||||||
|
|||||||
@@ -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,11 @@ const initialState = {
|
|||||||
walletTable: false,
|
walletTable: false,
|
||||||
uploadsTable: false,
|
uploadsTable: false,
|
||||||
familyBannersListTable: false,
|
familyBannersListTable: false,
|
||||||
|
chatMessageList: false,
|
||||||
|
marketTableList: false,
|
||||||
|
familyOfferList: false,
|
||||||
|
parentFamilyTaskList: false,
|
||||||
|
offerInterestListReload: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const tableReloadSlice = createSlice({
|
export const tableReloadSlice = createSlice({
|
||||||
@@ -41,6 +46,21 @@ export const tableReloadSlice = createSlice({
|
|||||||
case "FAMILYBANNERSLIST":
|
case "FAMILYBANNERSLIST":
|
||||||
state.familyBannersListTable = !state.familyBannersListTable;
|
state.familyBannersListTable = !state.familyBannersListTable;
|
||||||
return;
|
return;
|
||||||
|
case "CHATMESSAGELIST":
|
||||||
|
state.chatMessageList = !state.chatMessageList;
|
||||||
|
return;
|
||||||
|
case "MARKETTABLELIST":
|
||||||
|
state.marketTableList = !state.marketTableList;
|
||||||
|
return;
|
||||||
|
case "FAMILYOFFERLIST":
|
||||||
|
state.familyOfferList = !state.familyOfferList;
|
||||||
|
return;
|
||||||
|
case "PARENTFAMILYTASKLIST": // reloads list of active family task on parent side
|
||||||
|
state.parentFamilyTaskList = !state.parentFamilyTaskList;
|
||||||
|
return;
|
||||||
|
case "OFFERINTERESTLISTRELOAD": // to reload offer interest list of owner when a worker sends interest in a job
|
||||||
|
state.offerInterestListReload = !state.offerInterestListReload;
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -10,6 +10,7 @@ import userJobListReducer from "./userJobList";
|
|||||||
import walletDetails from "./walletDetails";
|
import walletDetails from "./walletDetails";
|
||||||
import familyBannerListReducer from "./FamilyBannerList"
|
import familyBannerListReducer from "./FamilyBannerList"
|
||||||
import familyResourcesReducer from './FamilyResources'
|
import familyResourcesReducer from './FamilyResources'
|
||||||
|
import familyWalletRedeemOptListReducer from './FamilyWalletRedeemOpt'
|
||||||
|
|
||||||
export default configureStore({
|
export default configureStore({
|
||||||
reducer: {
|
reducer: {
|
||||||
@@ -22,6 +23,7 @@ export default configureStore({
|
|||||||
notifications: notificationsReducer,
|
notifications: notificationsReducer,
|
||||||
walletDetails: walletDetails,
|
walletDetails: walletDetails,
|
||||||
familyBannersList: familyBannerListReducer,
|
familyBannersList: familyBannerListReducer,
|
||||||
familyResources: familyResourcesReducer
|
familyResources: familyResourcesReducer,
|
||||||
|
familyWalletRedeemOptList: familyWalletRedeemOptListReducer
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ function AddJobPage({ action, situation, categories }) {
|
|||||||
return (
|
return (
|
||||||
<ModalCom action={action} situation={situation}>
|
<ModalCom action={action} situation={situation}>
|
||||||
<div className="lg:w-[600px] w-11/12 lg:overflow-hidden lg:rounded-2xl bg-white dark:bg-dark-white dark:text-white">
|
<div className="lg:w-[600px] w-11/12 lg:overflow-hidden lg:rounded-2xl bg-white dark:bg-dark-white dark:text-white">
|
||||||
<div className="heading flex justify-between items-center py-6 md:px-[30px] px-[23px] border-b border-light-purple dark:border-[#5356fb29] ">
|
<div className="modal-header-con">
|
||||||
<p className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
|
<h1 className="modal-title">
|
||||||
Create New Job
|
New Job
|
||||||
</p>
|
</h1>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="text-[#374557] dark:text-red-500"
|
className="modal-close-btn"
|
||||||
onClick={action}
|
onClick={action}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import FamilyWallet from "../components/MyWallet/FamilyWallet";
|
import FamilyWalletCon from "../components/MyWallet/FamilyWalletCon";
|
||||||
|
|
||||||
export default function FamilyWalletPage() {
|
export default function FamilyWalletPage() {
|
||||||
return <FamilyWallet />;
|
return <FamilyWalletCon />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,17 @@ import React, { useEffect, useState } from "react";
|
|||||||
import { useLocation, useNavigate } from "react-router-dom";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import ActiveJobs from "../components/MyActiveJobs/ActiveJobs";
|
import ActiveJobs from "../components/MyActiveJobs/ActiveJobs";
|
||||||
import usersService from "../services/UsersService";
|
import usersService from "../services/UsersService";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This code defines a React functional component called `ManageActiveJobs`.
|
* 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.
|
* It fetches a list of active job messages and renders the `ActiveJobs` component with the necessary props.
|
||||||
*/
|
*/
|
||||||
function ManageActiveJobs() {
|
function ManageActiveJobs() {
|
||||||
|
const { chatMessageList } = useSelector(
|
||||||
|
(state) => state.tableReload
|
||||||
|
);
|
||||||
|
|
||||||
const ApiCall = new usersService();
|
const ApiCall = new usersService();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -54,7 +59,7 @@ function ManageActiveJobs() {
|
|||||||
}
|
}
|
||||||
setDetails(state);
|
setDetails(state);
|
||||||
getActiveJobMesList();
|
getActiveJobMesList();
|
||||||
}, [activeJobMesListReload]);
|
}, [activeJobMesListReload, chatMessageList]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ActiveJobs
|
<ActiveJobs
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export default function MyReviewDueJobsPage() {
|
|||||||
let { othersInterestedTable } = useSelector((state) => state.tableReload); // FOR OTHERS INTERESTED TABLE RELOAD
|
let { othersInterestedTable } = useSelector((state) => state.tableReload); // FOR OTHERS INTERESTED TABLE RELOAD
|
||||||
|
|
||||||
const apiCall = new usersService();
|
const apiCall = new usersService();
|
||||||
const [othersInterestedList, setOthersInterestedList] = useState({loading: true, data: []})
|
const [othersInterestedList, setOthersInterestedList] = useState({loading: true, data: [], imageServer:''})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if(!state){
|
if(!state){
|
||||||
@@ -26,9 +26,9 @@ export default function MyReviewDueJobsPage() {
|
|||||||
}else{
|
}else{
|
||||||
newData = []
|
newData = []
|
||||||
}
|
}
|
||||||
setOthersInterestedList({loading: false, data: newData})
|
setOthersInterestedList({loading: false, data: newData, imageServer:res.data.session_image_server})
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
setOthersInterestedList({loading: false, data: []})
|
setOthersInterestedList({loading: false, data: [], imageServer:''})
|
||||||
console.log('Error: ', err)
|
console.log('Error: ', err)
|
||||||
})
|
})
|
||||||
}, [othersInterestedTable]);
|
}, [othersInterestedTable]);
|
||||||
|
|||||||
@@ -5,20 +5,33 @@ import OffersInterest from "../components/OffersInterest";
|
|||||||
|
|
||||||
import usersService from "../services/UsersService";
|
import usersService from "../services/UsersService";
|
||||||
|
|
||||||
|
import { SocketValues } from "../components/Contexts/SocketIOContext"; // for reading socket context values
|
||||||
|
|
||||||
export default function OffersInterestPage() {
|
export default function OffersInterestPage() {
|
||||||
|
|
||||||
|
const { offerInterestListReload } = useSelector((state) => state.tableReload); // table/list reload variable
|
||||||
|
|
||||||
|
const {userDetails} = useSelector((state) => state?.userDetails); // Gets USER Details
|
||||||
|
|
||||||
|
let {joinRoom} = SocketValues() // function to join room for socket
|
||||||
|
|
||||||
const apiCall = new usersService()
|
const apiCall = new usersService()
|
||||||
|
|
||||||
let {commonHeadBanner} = useSelector(state => state.commonHeadBanner)
|
let {commonHeadBanner} = useSelector(state => state.commonHeadBanner)
|
||||||
|
|
||||||
let [offerInterestList, setOfferInterestList] = useState({loading: true, data: []})
|
let [offerInterestList, setOfferInterestList] = useState({loading: true, data: [], imgServer:''})
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
apiCall.offersInterestList().then(res => {
|
apiCall.offersInterestList().then(res => {
|
||||||
setOfferInterestList({loading: false, data: res.data.result_list})
|
setOfferInterestList({loading: false, data: res.data.result_list, imgServer:res.data.session_image_server})
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
setOfferInterestList({loading: false, data: []})
|
setOfferInterestList({loading: false, data: [], imgServer:''})
|
||||||
console.log('Error: ', err)
|
console.log('Error: ', err)
|
||||||
})
|
})
|
||||||
|
},[offerInterestListReload])
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
joinRoom(`INTEREST-${userDetails?.uid}`)
|
||||||
},[])
|
},[])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user