Compare commits

...

11 Commits

9 changed files with 109 additions and 32 deletions
+2 -1
View File
@@ -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 }));
+27 -4
View File
@@ -1,12 +1,14 @@
import React, { createContext, useContext, useEffect, useState } from "react"; import React, { createContext, useContext, useEffect, useState } from "react";
import { tableReload } from "../../store/TableReloads"; import { tableReload } from "../../store/TableReloads";
import { useDispatch } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import io from "socket.io-client"; import io from "socket.io-client";
let SocketIOContext = createContext({}) let SocketIOContext = createContext({})
export default function SocketIOContextProvider({children}) { 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 dispatch = useDispatch()
const socket = io.connect(process.env.REACT_APP_PRIMARY_SOCKET); const socket = io.connect(process.env.REACT_APP_PRIMARY_SOCKET);
@@ -36,14 +38,34 @@ export default function SocketIOContextProvider({children}) {
} }
}; };
const parentAssignJobToKid = (message, room) => {
if(message && room){
socket.emit("family", { message:{...message}, room });
}
};
useEffect(() => { useEffect(() => {
socket.on("receive_message", (data) => { socket.on("receive_message", (data) => {
// setSocketMsgReceived(data.message); // setSocketMsgReceived(data.message);
dispatch(tableReload({type:'CHATMESSAGELIST'})) dispatch(tableReload({type:'CHATMESSAGELIST'})) // dispatches to update chat message sending from owner to worker and vice versa
}); });
socket.on("received_refreshmarket_jobs", (data) => { socket.on("received_refreshmarket_jobs", (data) => {
// setSocketMsgReceived(data.message); // setSocketMsgReceived(data.message);
dispatch(tableReload({type:'MARKETTABLELIST'})) 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
}
// console.log('DATA', data)
}); });
}, [socket]); }, [socket]);
@@ -52,8 +74,9 @@ export default function SocketIOContextProvider({children}) {
sendMessage, sendMessage,
joinRoom, joinRoom,
setSocketMsgReceived, setSocketMsgReceived,
socketMsgReceived,
marketUpdate, marketUpdate,
parentAssignJobToKid,
socketMsgReceived,
// room, // room,
// setRoom, // setRoom,
// message, // message,
@@ -4,26 +4,27 @@ 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>
{myOffersList.loading ? {myOffersList.loading ?
@@ -1,5 +1,5 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useDispatch } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { useLocation } from "react-router-dom"; import { useLocation } from "react-router-dom";
import usersService from "../../../services/UsersService"; import usersService from "../../../services/UsersService";
import { tableReload } from "../../../store/TableReloads"; import { tableReload } from "../../../store/TableReloads";
@@ -8,6 +8,7 @@ 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 { SocketValues } from "../../Contexts/SocketIOContext";
const AssignTaskPopout = ({ const AssignTaskPopout = ({
action, action,
@@ -21,9 +22,12 @@ const AssignTaskPopout = ({
assignTaskChecker, assignTaskChecker,
}) => { }) => {
const {parentAssignJobToKid} = SocketValues()
const apiCall = new usersService(); const apiCall = new usersService();
let { pathname, state } = useLocation(); 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 [selectedFamilyUid, setSelectedFamilyUid] = useState('');
const handleFamChange = (event) => { const handleFamChange = (event) => {
@@ -188,6 +192,16 @@ const AssignTaskPopout = ({
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
@@ -228,17 +242,17 @@ const AssignTaskPopout = ({
) : familyDetailsData ? ( ) : familyDetailsData ? (
` Assign ${familyDetailsData.firstname}'s Task` ` Assign ${familyDetailsData.firstname}'s Task`
) : ( ) : (
<div className="flex items-center"> <div className="flex items-center gap-2">
<span className="text-black">Assign task to{" "}</span> <span className="text-black">Assign task to{" "}</span>
<div className="w-[270px] h-[40px] ml-2"> <div className="w-[270px] h-[40px] flex items-center relative after:absolute after:content-['▼'] active:after:rotate-180 after:transition-all after:duration-300 after:z-20 after:right-2 after:top-1/2 after:-translate-y-1/2 after:text-white after:text-lg">
<select <select
name="" name=""
id="" id=""
className="text-white px-2 transition-all cursor-pointer bg-blue-900 focus:outline-none border border-gray-200 rounded-lg w-full h-full py-1" className="relative z-10 appearance-none text-lg text-white px-2 tracking-wide font-semibold transition-all cursor-pointer bg-blue-900 focus:outline-none border border-gray-200 rounded-full w-full h-full"
onChange={handleFamChange} onChange={handleFamChange}
value={selectedFamilyUid} value={selectedFamilyUid}
> >
<option value=""> <option value="" className="">
Select a kid Select a kid
</option> </option>
{familyList} {familyList}
+20 -9
View File
@@ -4,6 +4,7 @@ import { apiConst } from "../../lib/apiConst";
import usersService from "../../services/UsersService"; import usersService from "../../services/UsersService";
import LoadingSpinner from "../Spinners/LoadingSpinner"; import LoadingSpinner from "../Spinners/LoadingSpinner";
import AssignTaskPopout from "./FamilyPopout/AssignTaskPopout"; import AssignTaskPopout from "./FamilyPopout/AssignTaskPopout";
import { useSelector } from "react-redux";
// Lazy Imports for components // Lazy Imports for components
const FamilyWaitlist = lazy(() => import("./Tabs/FamilyNewWaitlist")); const FamilyWaitlist = lazy(() => import("./Tabs/FamilyNewWaitlist"));
@@ -11,11 +12,15 @@ const FamilyTasks = lazy(() => import("./Tabs/FamilyNewTasks"));
const FamilyPending = lazy(() => import("./Tabs/FamilyNewPending")); const FamilyPending = lazy(() => import("./Tabs/FamilyNewPending"));
export default function FamilyTableNew() { export default function FamilyTableNew() {
const { parentFamilyTaskList } = useSelector((state) => state.tableReload);
console.log('parentFamilyTaskList', parentFamilyTaskList)
let { pathname } = useLocation(); let { pathname } = useLocation();
// Initial state for family details // Initial state for family details
const initialDetailState = { const initialDetailState = {
loading: false, loading: true,
data: null, data: null,
link: "", link: "",
}; };
@@ -115,13 +120,13 @@ export default function FamilyTableNew() {
useEffect(() => { useEffect(() => {
const manageFamily = async () => { const manageFamily = async () => {
try { try {
resetDetails(); // resetDetails();
setDetails({ // setDetails({
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 };
@@ -169,7 +174,13 @@ export default function FamilyTableNew() {
}, },
}); });
} 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);
} }
@@ -177,7 +188,7 @@ export default function FamilyTableNew() {
// 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(() => {
+1 -4
View File
@@ -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: `🙂`,
@@ -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" }));
+10 -5
View File
@@ -32,7 +32,7 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
); );
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
@@ -40,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
}; };
@@ -109,6 +106,8 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
}); });
}; };
loadProfile(); loadProfile();
}else{
setIsLogin({ loading: false, status: true });
} }
}, []); }, []);
@@ -323,6 +322,12 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
joinRoom('full-markets-jobs') joinRoom('full-markets-jobs')
},[isLogin.status]) },[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 ? (
+8
View File
@@ -11,6 +11,8 @@ const initialState = {
familyBannersListTable: false, familyBannersListTable: false,
chatMessageList: false, chatMessageList: false,
marketTableList: false, marketTableList: false,
familyOfferList: false,
parentFamilyTaskList: false,
}; };
export const tableReloadSlice = createSlice({ export const tableReloadSlice = createSlice({
@@ -49,6 +51,12 @@ export const tableReloadSlice = createSlice({
case "MARKETTABLELIST": case "MARKETTABLELIST":
state.marketTableList = !state.marketTableList; state.marketTableList = !state.marketTableList;
return; return;
case "FAMILYOFFERLIST":
state.familyOfferList = !state.familyOfferList;
return;
case "PARENTFAMILYTASKLIST": // reloads list of active family task on parent side
state.parentFamilyTaskList = !state.parentFamilyTaskList;
return;
default: default:
return state; return state;
} }