From e46f6efed2a8bedb6676cce39d924b1d751c8635 Mon Sep 17 00:00:00 2001 From: David Nunez Date: Tue, 13 Aug 2024 10:29:41 -0400 Subject: [PATCH 1/6] setup header fixes --- .../Shared/layout/Header/AppBarActions.tsx | 80 +++++++++++++++++++ .../Shared/layout/Header/EAOAppBar.tsx | 49 ++++++++++++ .../Shared/layout/Header/MobileNav.tsx | 38 +++++++++ submit-web/src/routes/__root.tsx | 2 +- 4 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 submit-web/src/components/Shared/layout/Header/AppBarActions.tsx create mode 100644 submit-web/src/components/Shared/layout/Header/EAOAppBar.tsx create mode 100644 submit-web/src/components/Shared/layout/Header/MobileNav.tsx diff --git a/submit-web/src/components/Shared/layout/Header/AppBarActions.tsx b/submit-web/src/components/Shared/layout/Header/AppBarActions.tsx new file mode 100644 index 00000000..e2555597 --- /dev/null +++ b/submit-web/src/components/Shared/layout/Header/AppBarActions.tsx @@ -0,0 +1,80 @@ +import { useIsMobile } from "@/hooks/common"; +import { + Box, + Typography, + Button, + Menu, + IconButton, + MenuItem, +} from "@mui/material"; +import { useAuth } from "react-oidc-context"; +import AccountCircleIcon from "@mui/icons-material/AccountCircle"; +import { theme } from "@/styles/theme"; +import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; +import { useState } from "react"; + +export default function AppBarActions() { + const auth = useAuth(); + const [anchorEl, setAnchorEl] = useState(null); + const open = Boolean(anchorEl); + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + const handleClose = () => { + setAnchorEl(null); + }; + + return ( + <> + {!auth.isAuthenticated ? ( + <> + + + Hi, Johnny Sins + + + + + + + + My Profile + Sign Out + + + ) : ( + <> + + + )} + + ); +} diff --git a/submit-web/src/components/Shared/layout/Header/EAOAppBar.tsx b/submit-web/src/components/Shared/layout/Header/EAOAppBar.tsx new file mode 100644 index 00000000..fff6ced9 --- /dev/null +++ b/submit-web/src/components/Shared/layout/Header/EAOAppBar.tsx @@ -0,0 +1,49 @@ +import { AppBar, Grid, Typography } from "@mui/material"; +import EAO_Logo from "@/assets/images/EAO_Logo.png"; +import { AppConfig } from "@/utils/config"; +import { useAuth } from "react-oidc-context"; +import AppBarActions from "./AppBarActions"; +import { useIsMobile } from "@/hooks/common"; +import MobileNav from "./MobileNav"; + +export default function EAOAppBar() { + const auth = useAuth(); + const isMobile = useIsMobile(); + return ( + <> + + + + + {!isMobile && ( + + {AppConfig.appTitle} + + )} + + + + + + + {isMobile && } + + ); +} diff --git a/submit-web/src/components/Shared/layout/Header/MobileNav.tsx b/submit-web/src/components/Shared/layout/Header/MobileNav.tsx new file mode 100644 index 00000000..7334a290 --- /dev/null +++ b/submit-web/src/components/Shared/layout/Header/MobileNav.tsx @@ -0,0 +1,38 @@ +import { Box, Typography } from "@mui/material"; +import React from "react"; +import { AppConfig } from "@/utils/config"; +import MenuIcon from "@mui/icons-material/Menu"; +import { theme } from "@/styles/theme"; + +export default function MobileNav() { + return ( + + + {AppConfig.appTitle} + + + + Menu + + + + + ); +} diff --git a/submit-web/src/routes/__root.tsx b/submit-web/src/routes/__root.tsx index e34f08dd..14e75e67 100644 --- a/submit-web/src/routes/__root.tsx +++ b/submit-web/src/routes/__root.tsx @@ -1,4 +1,4 @@ -import EAOAppBar from "@/components/Shared/EAOAppBar"; +import EAOAppBar from "@/components/Shared/layout/Header/EAOAppBar"; import Footer from "@/components/Shared/layout/Footer"; import PageNotFound from "@/components/Shared/PageNotFound"; import { Box } from "@mui/system"; From 4d3d9b3b96817df51d33d5051a51d895c9b63e03 Mon Sep 17 00:00:00 2001 From: David Nunez Date: Thu, 15 Aug 2024 12:09:25 -0400 Subject: [PATCH 2/6] setup drawer provider, and add drawer for mobile nav --- submit-web/src/App.tsx | 2 + .../Shared/Drawers/DrawerProvider.tsx | 15 ++ .../components/Shared/Drawers/DrawerStore.ts | 63 ++++++ .../Shared/layout/Header/AppBarActions.tsx | 27 +-- .../Shared/layout/Header/EAOAppBar.tsx | 10 +- .../Shared/layout/Header/MobileNav.tsx | 16 +- .../Shared/layout/SideNav/BreadcrumbNav.tsx | 2 +- .../Shared/layout/SideNav/SideNavBar.tsx | 188 +++++++++--------- submit-web/src/routes/__root.tsx | 2 + .../src/routes/_authenticated/_dashboard.tsx | 5 +- 10 files changed, 216 insertions(+), 114 deletions(-) create mode 100644 submit-web/src/components/Shared/Drawers/DrawerProvider.tsx create mode 100644 submit-web/src/components/Shared/Drawers/DrawerStore.ts diff --git a/submit-web/src/App.tsx b/submit-web/src/App.tsx index 16d81090..636b84f4 100644 --- a/submit-web/src/App.tsx +++ b/submit-web/src/App.tsx @@ -7,6 +7,8 @@ import { theme } from "@/styles/theme"; import RouterProviderWithAuthContext from "@/router"; import ModalProvider from "./components/Shared/Modals/ModalProvider"; import SnackBarProvider from "./components/Shared/Snackbar/SnackBarProvider"; +import DrawerProvider from "./components/Shared/Drawers/DrawerProvider"; + const queryClient = new QueryClient(); function App() { diff --git a/submit-web/src/components/Shared/Drawers/DrawerProvider.tsx b/submit-web/src/components/Shared/Drawers/DrawerProvider.tsx new file mode 100644 index 00000000..467c94ac --- /dev/null +++ b/submit-web/src/components/Shared/Drawers/DrawerProvider.tsx @@ -0,0 +1,15 @@ +import React from "react"; +import { useDrawer } from "./DrawerStore"; +import { Box, Drawer } from "@mui/material"; + +const DrawerProvider: React.FC = () => { + const { drawerContent, direction, setClose, isOpen } = useDrawer(); + + return ( + + {drawerContent} + + ); +}; + +export default DrawerProvider; diff --git a/submit-web/src/components/Shared/Drawers/DrawerStore.ts b/submit-web/src/components/Shared/Drawers/DrawerStore.ts new file mode 100644 index 00000000..4876532b --- /dev/null +++ b/submit-web/src/components/Shared/Drawers/DrawerStore.ts @@ -0,0 +1,63 @@ +import { create } from "zustand"; +import { User } from "@/models/User"; +import { Plan } from "@/models/Plan"; +import React from "react"; + +// Define the DrawerData type +export type DrawerData = { + user?: User; + plan?: Plan; +}; + +// Define the store state and actions +interface DrawerStore { + data: DrawerData; + isOpen: boolean; + drawerContent: React.ReactNode | null; + direction: "left" | "right" | "top" | "bottom"; + setOpen: ( + drawer: React.ReactNode, + direction: "left" | "right" | "top" | "bottom", + fetchData?: () => Promise, + ) => Promise; + setClose: () => void; +} + +// Create the Zustand store +export const useDrawer = create((set) => ({ + data: {}, + isOpen: false, + drawerContent: null, + direction: "left", + + setOpen: async (drawer, direction, fetchData) => { + if (drawer) { + const fetchedData = fetchData ? await fetchData() : {}; + set((state) => ({ + data: { ...state.data, ...fetchedData }, + drawerContent: drawer, + isOpen: true, + direction: direction, + })); + } + }, + + setClose: () => { + set({ + isOpen: false, + data: {}, + drawerContent: null, + direction: "left", + }); + }, +})); + +// Export a function called openDrawer +export const openDrawer = async ( + drawer: React.ReactNode, + direction: "left" | "right" | "top" | "bottom", + fetchData?: () => Promise, +) => { + const { setOpen } = useDrawer.getState(); + await setOpen(drawer, direction, fetchData); +}; diff --git a/submit-web/src/components/Shared/layout/Header/AppBarActions.tsx b/submit-web/src/components/Shared/layout/Header/AppBarActions.tsx index e2555597..7b4f4bbe 100644 --- a/submit-web/src/components/Shared/layout/Header/AppBarActions.tsx +++ b/submit-web/src/components/Shared/layout/Header/AppBarActions.tsx @@ -12,6 +12,7 @@ import AccountCircleIcon from "@mui/icons-material/AccountCircle"; import { theme } from "@/styles/theme"; import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; import { useState } from "react"; +import { OidcConfig } from "@/utils/config"; export default function AppBarActions() { const auth = useAuth(); @@ -26,11 +27,11 @@ export default function AppBarActions() { return ( <> - {!auth.isAuthenticated ? ( + {auth.isAuthenticated ? ( <> - Hi, Johnny Sins + Hi, {auth.user?.profile.name} ) : ( - <> - - + )} ); diff --git a/submit-web/src/components/Shared/layout/Header/EAOAppBar.tsx b/submit-web/src/components/Shared/layout/Header/EAOAppBar.tsx index fff6ced9..353e010f 100644 --- a/submit-web/src/components/Shared/layout/Header/EAOAppBar.tsx +++ b/submit-web/src/components/Shared/layout/Header/EAOAppBar.tsx @@ -5,13 +5,21 @@ import { useAuth } from "react-oidc-context"; import AppBarActions from "./AppBarActions"; import { useIsMobile } from "@/hooks/common"; import MobileNav from "./MobileNav"; +import { theme } from "@/styles/theme"; export default function EAOAppBar() { const auth = useAuth(); const isMobile = useIsMobile(); return ( <> - + - {AppConfig.appTitle} + {AppConfig.appTitle || "App Title"} - - + + Menu openDrawer(, "left")} /> diff --git a/submit-web/src/components/Shared/layout/SideNav/BreadcrumbNav.tsx b/submit-web/src/components/Shared/layout/SideNav/BreadcrumbNav.tsx index b2e7d48d..5c4c2167 100644 --- a/submit-web/src/components/Shared/layout/SideNav/BreadcrumbNav.tsx +++ b/submit-web/src/components/Shared/layout/SideNav/BreadcrumbNav.tsx @@ -40,7 +40,7 @@ const BreadcrumbNav: React.FC = () => { diff --git a/submit-web/src/components/Shared/layout/SideNav/SideNavBar.tsx b/submit-web/src/components/Shared/layout/SideNav/SideNavBar.tsx index 08625cf4..15e589e9 100644 --- a/submit-web/src/components/Shared/layout/SideNav/SideNavBar.tsx +++ b/submit-web/src/components/Shared/layout/SideNav/SideNavBar.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import { Box, List, @@ -11,121 +11,119 @@ import { theme } from "@/styles/theme"; import { useAuth } from "react-oidc-context"; import { AuthenticatedRoutes, Routes } from "./SideNavElements"; import { alpha } from "@mui/system"; -import { useIsMobile } from "@/hooks/common"; +import { useDrawer } from "../../Drawers/DrawerStore"; export default function SideNavBar() { const { isAuthenticated } = useAuth(); const [currentPath, setCurrentPath] = useState(window.location.pathname); - const isMobile = useIsMobile(); - + const { isOpen, setClose } = useDrawer(); let routeMenuItems = Routes; if (isAuthenticated) { routeMenuItems = routeMenuItems.concat(AuthenticatedRoutes); } + const handleRouteChange = (path: string) => { + setCurrentPath(path); + if (isOpen) setClose(); + }; + return (
- {!isMobile && ( - - - {routeMenuItems.map((route) => ( - <> - - setCurrentPath(route.path)} - style={{ - color: theme.palette.primary.light, - fontWeight: "bold", - textDecoration: "none", - width: "100%", + + + {routeMenuItems.map((route) => ( + <> + + handleRouteChange(route.path)} + style={{ + color: theme.palette.primary.light, + fontWeight: "bold", + textDecoration: "none", + width: "100%", + }} + > + - - + + + + {route.routes && route.routes?.length > 0 && ( + + {route.routes?.map((subRoute) => ( + + handleRouteChange(route.path)} style={{ - color: alpha(theme.palette.primary.main, 0.8), + textDecoration: "none", + margin: 0, + padding: 0, + color: "inherit", + }} + activeProps={{ + style: { + color: theme.palette.primary.main, + fontWeight: + currentPath === subRoute.path ? "bold" : "normal", + width: "100%", + }, }} > - {route.name} - - - - - {route.routes && route.routes?.length > 0 && ( - - {route.routes?.map((subRoute) => ( - - setCurrentPath(subRoute.path)} - style={{ - textDecoration: "none", - margin: 0, - padding: 0, - color: "inherit", - }} - activeProps={{ - style: { - color: theme.palette.primary.main, - fontWeight: - currentPath === subRoute.path - ? "bold" - : "normal", - width: "100%", - }, + - - - - {subRoute.name} - - - - - - ))} - - )} - - ))} - - - )} + + + {subRoute.name} + + + + + + ))} + + )} + + ))} + +
); } diff --git a/submit-web/src/routes/__root.tsx b/submit-web/src/routes/__root.tsx index fd7b8150..1f448f30 100644 --- a/submit-web/src/routes/__root.tsx +++ b/submit-web/src/routes/__root.tsx @@ -6,6 +6,7 @@ import { createRootRouteWithContext, Outlet } from "@tanstack/react-router"; import { TanStackRouterDevtools } from "@tanstack/router-devtools"; import { AuthContextProps } from "react-oidc-context"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; +import DrawerProvider from "@/components/Shared/Drawers/DrawerProvider"; type RouterContext = { authentication: AuthContextProps; @@ -21,6 +22,7 @@ function Layout() { return ( <> + diff --git a/submit-web/src/routes/_authenticated/_dashboard.tsx b/submit-web/src/routes/_authenticated/_dashboard.tsx index 26d881b8..d9d37009 100644 --- a/submit-web/src/routes/_authenticated/_dashboard.tsx +++ b/submit-web/src/routes/_authenticated/_dashboard.tsx @@ -1,5 +1,6 @@ import BreadcrumbNav from "@/components/Shared/layout/SideNav/BreadcrumbNav"; import SideNavBar from "@/components/Shared/layout/SideNav/SideNavBar"; +import { useIsMobile } from "@/hooks/common"; import { Box } from "@mui/material"; import { Outlet, createFileRoute } from "@tanstack/react-router"; @@ -9,11 +10,13 @@ export const Route = createFileRoute("/_authenticated/_dashboard")({ }); function DashboardLayout() { + const isMobile = useIsMobile(); + return (
- + {!isMobile && }
From 78a1ad1bdad13e6dcb653292c4e34f92c43337ab Mon Sep 17 00:00:00 2001 From: David Nunez Date: Thu, 15 Aug 2024 12:14:44 -0400 Subject: [PATCH 3/6] remove unused imports --- submit-web/src/App.tsx | 1 - .../src/components/Shared/EAOAppBar.tsx | 89 ------------------- .../Shared/layout/Header/AppBarActions.tsx | 1 - .../Shared/layout/Header/EAOAppBar.tsx | 2 - .../Shared/layout/SideNav/SideNavBar.tsx | 2 +- 5 files changed, 1 insertion(+), 94 deletions(-) delete mode 100644 submit-web/src/components/Shared/EAOAppBar.tsx diff --git a/submit-web/src/App.tsx b/submit-web/src/App.tsx index 636b84f4..34942312 100644 --- a/submit-web/src/App.tsx +++ b/submit-web/src/App.tsx @@ -7,7 +7,6 @@ import { theme } from "@/styles/theme"; import RouterProviderWithAuthContext from "@/router"; import ModalProvider from "./components/Shared/Modals/ModalProvider"; import SnackBarProvider from "./components/Shared/Snackbar/SnackBarProvider"; -import DrawerProvider from "./components/Shared/Drawers/DrawerProvider"; const queryClient = new QueryClient(); diff --git a/submit-web/src/components/Shared/EAOAppBar.tsx b/submit-web/src/components/Shared/EAOAppBar.tsx deleted file mode 100644 index 640d7a9e..00000000 --- a/submit-web/src/components/Shared/EAOAppBar.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { AppBar, Box, Button, Grid, Typography } from "@mui/material"; -import EAO_Logo from "@/assets/images/EAO_Logo.png"; -import AccountCircleIcon from "@mui/icons-material/AccountCircle"; -import { AppConfig, OidcConfig } from "@/utils/config"; -import { useAuth } from "react-oidc-context"; -import { theme } from "@/styles/theme"; - -export default function EAOAppBar() { - const auth = useAuth(); - return ( - <> - - - - - - {AppConfig.appTitle} - - - - {auth.isAuthenticated ? ( - <> - - - Hi, {auth.user?.profile.name} - - - {auth.user?.profile.email} - - - - - ) : ( - - )} - - - - - - ); -} diff --git a/submit-web/src/components/Shared/layout/Header/AppBarActions.tsx b/submit-web/src/components/Shared/layout/Header/AppBarActions.tsx index 7b4f4bbe..1de49b34 100644 --- a/submit-web/src/components/Shared/layout/Header/AppBarActions.tsx +++ b/submit-web/src/components/Shared/layout/Header/AppBarActions.tsx @@ -1,4 +1,3 @@ -import { useIsMobile } from "@/hooks/common"; import { Box, Typography, diff --git a/submit-web/src/components/Shared/layout/Header/EAOAppBar.tsx b/submit-web/src/components/Shared/layout/Header/EAOAppBar.tsx index 353e010f..dba6f7ba 100644 --- a/submit-web/src/components/Shared/layout/Header/EAOAppBar.tsx +++ b/submit-web/src/components/Shared/layout/Header/EAOAppBar.tsx @@ -1,14 +1,12 @@ import { AppBar, Grid, Typography } from "@mui/material"; import EAO_Logo from "@/assets/images/EAO_Logo.png"; import { AppConfig } from "@/utils/config"; -import { useAuth } from "react-oidc-context"; import AppBarActions from "./AppBarActions"; import { useIsMobile } from "@/hooks/common"; import MobileNav from "./MobileNav"; import { theme } from "@/styles/theme"; export default function EAOAppBar() { - const auth = useAuth(); const isMobile = useIsMobile(); return ( <> diff --git a/submit-web/src/components/Shared/layout/SideNav/SideNavBar.tsx b/submit-web/src/components/Shared/layout/SideNav/SideNavBar.tsx index 15e589e9..02f5e245 100644 --- a/submit-web/src/components/Shared/layout/SideNav/SideNavBar.tsx +++ b/submit-web/src/components/Shared/layout/SideNav/SideNavBar.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useState } from "react"; import { Box, List, From 672ef97101c8c331b9db6606720ef62112e79bdc Mon Sep 17 00:00:00 2001 From: David Nunez Date: Thu, 15 Aug 2024 12:28:25 -0400 Subject: [PATCH 4/6] remove unused variables --- .../components/Shared/Drawers/DrawerStore.ts | 21 +++---------------- 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/submit-web/src/components/Shared/Drawers/DrawerStore.ts b/submit-web/src/components/Shared/Drawers/DrawerStore.ts index 4876532b..061ec62c 100644 --- a/submit-web/src/components/Shared/Drawers/DrawerStore.ts +++ b/submit-web/src/components/Shared/Drawers/DrawerStore.ts @@ -1,40 +1,27 @@ import { create } from "zustand"; -import { User } from "@/models/User"; -import { Plan } from "@/models/Plan"; import React from "react"; -// Define the DrawerData type -export type DrawerData = { - user?: User; - plan?: Plan; -}; - // Define the store state and actions interface DrawerStore { - data: DrawerData; isOpen: boolean; drawerContent: React.ReactNode | null; direction: "left" | "right" | "top" | "bottom"; setOpen: ( drawer: React.ReactNode, direction: "left" | "right" | "top" | "bottom", - fetchData?: () => Promise, ) => Promise; setClose: () => void; } // Create the Zustand store export const useDrawer = create((set) => ({ - data: {}, isOpen: false, drawerContent: null, direction: "left", - setOpen: async (drawer, direction, fetchData) => { + setOpen: async (drawer, direction) => { if (drawer) { - const fetchedData = fetchData ? await fetchData() : {}; - set((state) => ({ - data: { ...state.data, ...fetchedData }, + set(() => ({ drawerContent: drawer, isOpen: true, direction: direction, @@ -45,7 +32,6 @@ export const useDrawer = create((set) => ({ setClose: () => { set({ isOpen: false, - data: {}, drawerContent: null, direction: "left", }); @@ -56,8 +42,7 @@ export const useDrawer = create((set) => ({ export const openDrawer = async ( drawer: React.ReactNode, direction: "left" | "right" | "top" | "bottom", - fetchData?: () => Promise, ) => { const { setOpen } = useDrawer.getState(); - await setOpen(drawer, direction, fetchData); + await setOpen(drawer, direction); }; From 412c81ed7bd6197b92d5862df6e114c9565acbb6 Mon Sep 17 00:00:00 2001 From: David Nunez Date: Thu, 15 Aug 2024 12:38:00 -0400 Subject: [PATCH 5/6] remove unsued modal data --- .../components/Shared/Modals/modalStore.ts | 33 ++++++------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/submit-web/src/components/Shared/Modals/modalStore.ts b/submit-web/src/components/Shared/Modals/modalStore.ts index 448a722d..dadcbfe5 100644 --- a/submit-web/src/components/Shared/Modals/modalStore.ts +++ b/submit-web/src/components/Shared/Modals/modalStore.ts @@ -1,21 +1,11 @@ -import {create} from 'zustand' -import { User } from "@/models/User"; -import { Plan } from '@/models/Plan'; - - -// Define the ModalData type -export type ModalData = { - user?: User - plan?: Plan -} +import { create } from "zustand"; // Define the store state and actions interface ModalStore { - data: ModalData - isOpen: boolean - modalContent: React.ReactNode | null - setOpen: (modal: React.ReactNode, fetchData?: () => Promise) => Promise - setClose: () => void + isOpen: boolean; + modalContent: React.ReactNode | null; + setOpen: (modal: React.ReactNode) => Promise; + setClose: () => void; } // Create the Zustand store @@ -24,22 +14,19 @@ export const useModal = create((set) => ({ isOpen: false, modalContent: null, - setOpen: async (modal, fetchData) => { + setOpen: async (modal) => { if (modal) { - const fetchedData = fetchData ? await fetchData() : {} - set((state) => ({ - data: { ...state.data, ...fetchedData }, + set(() => ({ modalContent: modal, isOpen: true, - })) + })); } }, setClose: () => { set({ isOpen: false, - data: {}, modalContent: null, - }) + }); }, -})) +})); From b3fc35b38d80c94e34ecf64cbbf255098f8f9d7e Mon Sep 17 00:00:00 2001 From: David Nunez Date: Thu, 15 Aug 2024 12:38:29 -0400 Subject: [PATCH 6/6] remove data --- submit-web/src/components/Shared/Modals/modalStore.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/submit-web/src/components/Shared/Modals/modalStore.ts b/submit-web/src/components/Shared/Modals/modalStore.ts index dadcbfe5..dead923a 100644 --- a/submit-web/src/components/Shared/Modals/modalStore.ts +++ b/submit-web/src/components/Shared/Modals/modalStore.ts @@ -10,7 +10,6 @@ interface ModalStore { // Create the Zustand store export const useModal = create((set) => ({ - data: {}, isOpen: false, modalContent: null,