diff --git a/src/ProtectedRoute.tsx b/src/ProtectedRoute.tsx index 0288f33..3f30da5 100644 --- a/src/ProtectedRoute.tsx +++ b/src/ProtectedRoute.tsx @@ -2,21 +2,72 @@ import { useLocation, Outlet, Navigate } from "react-router-dom"; import useAuth from "./hooks/useAuth"; import Navbar from "./components/navbar/Navbar"; import Sidebar from "./components/sidebar/Sidebar"; +import { Alert, AlertTitle, Box, Snackbar, Typography } from "@mui/material"; +import { store } from "./redux/store"; +import { fetchFavorites } from "./redux/slices/favoritesSlice"; +import { fetchMeetings, selectMeetings } from "./redux/slices/meetingsAndUserStatusSlice"; +import { fetchUsers, selectMe } from "./redux/slices/usersSlice"; +import { useAppDispatch, useAppSelector, useInterval } from "./redux/hooks"; +import DetailedMeeting from "./api-bodies/DetailedMeeting"; +import React, { useState } from "react"; import { Box } from "@mui/material"; const ProtectedRoute = () => { const auth = useAuth(); const location = useLocation(); - /* Temporary data */ - // if (auth?.isLoggedIn != undefined && auth?.isLoggedIn == true) { - // store.dispatch(fetchMeetings(auth?.uuid)); - // store.dispatch(fetchUsers(auth?.uuid)); - // store.dispatch(fetchFavorites(auth?.uuid)); - // store.dispatch(socketActions.startConnecting()); - // } + useAppDispatch(); + const currentUserUuid: string = useAppSelector(selectMe); + const meetings: DetailedMeeting[] = useAppSelector(selectMeetings); + const currentUserMeetings = meetings.filter((m) => m.registrantIds.includes(currentUserUuid)); + + const [open, setOpen] = useState(false); + const [notifMeetings, setNotifMeetings] = useState([""]); + + const sixtySec = 60000; + // polls the current time against meeting times + useInterval( + () => { + console.log("polling"); + const currentTime = Math.floor(Date.now() / sixtySec); // in minutes + const upcomingMeetings = currentUserMeetings.filter((meeting) => + (currentTime == Math.floor(Date.parse(meeting.start) / sixtySec) - 15) || // 15 mins before meeting time + (currentTime == Math.floor(Date.parse(meeting.start) / sixtySec) - 30) // or 30 mins before meeting time + ); + if (upcomingMeetings.length != 0) { + setOpen(true); + const newNotifMeetings: string[] = upcomingMeetings.map((m) => { + if (currentTime == Math.floor(Date.parse(m.start) / sixtySec) - 15) { + return m.topic + " in 15 minutes"; + } else { + return m.topic + " in 30 minutes"; + } + }); + setNotifMeetings(newNotifMeetings); + } + }, + sixtySec // poll time + ); + + const handleClose = (event?: React.SyntheticEvent | Event, reason?: string) => { + if (reason == "clickaway") { + return; + } + setOpen(false); + }; + return auth?.isLoggedIn ? ( <> + {/* ----- */} + + + Upcoming Meetings + {notifMeetings.map((m, i) => + {m} + )} + + + {/* ----- */} diff --git a/src/redux/hooks.tsx b/src/redux/hooks.tsx index 36b5ea2..797f6a6 100644 --- a/src/redux/hooks.tsx +++ b/src/redux/hooks.tsx @@ -1,6 +1,30 @@ +import { useLayoutEffect, useEffect, useRef } from "react"; import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux"; import type { RootState, AppDispatch } from "./store"; // Use throughout your app instead of plain `useDispatch` and `useSelector` export const useAppDispatch = () => useDispatch(); export const useAppSelector: TypedUseSelectorHook = useSelector; + +const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect; +export function useInterval(callback: () => void, delay: number | null) { + const savedCallback = useRef(callback); + + // Remember the latest callback if it changes. + useIsomorphicLayoutEffect(() => { + savedCallback.current = callback; + }, [callback]); + + // Set up the interval. + useEffect(() => { + // Don't schedule if no delay is specified. + // Note: 0 is a valid value for delay. + if (!delay && delay !== 0) { + return; + } + + const id = setInterval(() => savedCallback.current(), delay); + + return () => clearInterval(id); + }, [delay]); +} \ No newline at end of file