parent
c71bac5bd2
commit
31ba7bead1
File diff suppressed because it is too large
Load Diff
|
|
@ -6,7 +6,7 @@
|
||||||
"@emotion/react": "^11.11.3",
|
"@emotion/react": "^11.11.3",
|
||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@fontsource/roboto": "^5.0.8",
|
"@fontsource/roboto": "^5.0.8",
|
||||||
"@mui/icons-material": "^5.15.7",
|
"@mui/icons-material": "^5.15.8",
|
||||||
"@mui/material": "^5.15.7",
|
"@mui/material": "^5.15.7",
|
||||||
"@reduxjs/toolkit": "^2.1.0",
|
"@reduxjs/toolkit": "^2.1.0",
|
||||||
"axios": "^1.6.7",
|
"axios": "^1.6.7",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
function getWindowDimensions() {
|
||||||
|
const { innerWidth: width, innerHeight: height } = window;
|
||||||
|
return { width, height };
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function useWindowDimensions() {
|
||||||
|
const [windowDimensions, setWindowDimensions] = useState(
|
||||||
|
getWindowDimensions()
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
function handleResize() {
|
||||||
|
setWindowDimensions(getWindowDimensions());
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("resize", handleResize);
|
||||||
|
return () => window.removeEventListener("resize", handleResize);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return windowDimensions;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { BottomNavigation, BottomNavigationAction, Paper } from "@mui/material";
|
||||||
|
import { useState } from "react";
|
||||||
|
import FeedIcon from "@mui/icons-material/Feed";
|
||||||
|
import GlobalIcon from "@mui/icons-material/Public";
|
||||||
|
import AddIcon from "@mui/icons-material/Add";
|
||||||
|
import SearchIcon from "@mui/icons-material/Search";
|
||||||
|
|
||||||
|
export default function BottomAppBar() {
|
||||||
|
const [value, setValue] = useState(0);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper
|
||||||
|
sx={{ position: "fixed", bottom: 0, left: 0, right: 0 }}
|
||||||
|
elevation={8}
|
||||||
|
>
|
||||||
|
<BottomNavigation
|
||||||
|
showLabels
|
||||||
|
value={value}
|
||||||
|
onChange={(event, newValue) => {
|
||||||
|
setValue(newValue);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<BottomNavigationAction label="My Feed" icon={<FeedIcon />} />
|
||||||
|
<BottomNavigationAction label="Global Feed" icon={<GlobalIcon />} />
|
||||||
|
<BottomNavigationAction label="New Post" icon={<AddIcon />} />
|
||||||
|
<BottomNavigationAction label="Search" icon={<SearchIcon />} />
|
||||||
|
</BottomNavigation>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
import NotificationsIcon from "@mui/icons-material/Notifications";
|
||||||
|
import { Badge, Tooltip } from "@mui/material";
|
||||||
|
|
||||||
|
export default function NotificationBell() {
|
||||||
|
return (
|
||||||
|
<Badge badgeContent={4} color="secondary">
|
||||||
|
<Tooltip title="Notifications">
|
||||||
|
<NotificationsIcon />
|
||||||
|
</Tooltip>
|
||||||
|
</Badge>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
import {
|
||||||
|
Divider,
|
||||||
|
Drawer,
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
|
ListItemButton,
|
||||||
|
ListItemIcon,
|
||||||
|
ListItemText,
|
||||||
|
Toolbar,
|
||||||
|
} from "@mui/material";
|
||||||
|
|
||||||
|
import FeedIcon from "@mui/icons-material/Feed";
|
||||||
|
import GlobalIcon from "@mui/icons-material/Public";
|
||||||
|
import AddIcon from "@mui/icons-material/Add";
|
||||||
|
import SearchIcon from "@mui/icons-material/Search";
|
||||||
|
|
||||||
|
export interface SideAppBarProps {
|
||||||
|
drawerWidth: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function SideAppBar(props: SideAppBarProps) {
|
||||||
|
const { drawerWidth } = props;
|
||||||
|
return (
|
||||||
|
<Drawer
|
||||||
|
sx={{
|
||||||
|
width: drawerWidth,
|
||||||
|
flexShrink: 0,
|
||||||
|
"& .MuiDrawer-paper": {
|
||||||
|
width: drawerWidth,
|
||||||
|
boxSizing: "border-box",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
variant="permanent"
|
||||||
|
anchor="left"
|
||||||
|
>
|
||||||
|
<Toolbar />
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
<List>
|
||||||
|
<ListItem key={"myfeed"} disablePadding>
|
||||||
|
<ListItemButton>
|
||||||
|
<ListItemIcon>
|
||||||
|
<FeedIcon />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary={"My feed"} />
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
<ListItem key={"globalfeed"} disablePadding>
|
||||||
|
<ListItemButton>
|
||||||
|
<ListItemIcon>
|
||||||
|
<GlobalIcon />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary={"Global feed"} />
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
<ListItem key={"newpost"} disablePadding>
|
||||||
|
<ListItemButton>
|
||||||
|
<ListItemIcon>
|
||||||
|
<AddIcon />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary={"New Post"} />
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
<ListItem key={"search"} disablePadding>
|
||||||
|
<ListItemButton>
|
||||||
|
<ListItemIcon>
|
||||||
|
<SearchIcon />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary={"Search"} />
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
</List>
|
||||||
|
</Drawer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import AppBar from "@mui/material/AppBar";
|
||||||
|
import Box from "@mui/material/Box";
|
||||||
|
import Toolbar from "@mui/material/Toolbar";
|
||||||
|
import IconButton from "@mui/material/IconButton";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
import Menu from "@mui/material/Menu";
|
||||||
|
import Container from "@mui/material/Container";
|
||||||
|
import Avatar from "@mui/material/Avatar";
|
||||||
|
import Tooltip from "@mui/material/Tooltip";
|
||||||
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
|
import NotificationBell from "./notificationBell";
|
||||||
|
import {useSelector} from "react-redux";
|
||||||
|
import {selectUserInfo} from "../app/loginSlice";
|
||||||
|
|
||||||
|
const settings = ["Profile", "Account", "Dashboard", "Logout"];
|
||||||
|
|
||||||
|
function TopAppBar() {
|
||||||
|
|
||||||
|
const userInfo = useSelector(selectUserInfo);
|
||||||
|
const [anchorElUser, setAnchorElUser] = React.useState<null | HTMLElement>(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(userInfo)
|
||||||
|
|
||||||
|
const handleOpenUserMenu = (event: React.MouseEvent<HTMLElement>) => {
|
||||||
|
setAnchorElUser(event.currentTarget);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCloseUserMenu = () => {
|
||||||
|
setAnchorElUser(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppBar position="static">
|
||||||
|
<Container maxWidth="xl" sx={{ zIndex: 2500 }}>
|
||||||
|
<Toolbar disableGutters>
|
||||||
|
<Typography
|
||||||
|
variant="h6"
|
||||||
|
noWrap
|
||||||
|
component="a"
|
||||||
|
href="#app-bar-with-responsive-menu"
|
||||||
|
sx={{
|
||||||
|
mr: 2,
|
||||||
|
display: "flex",
|
||||||
|
fontFamily: "monospace",
|
||||||
|
fontWeight: 700,
|
||||||
|
letterSpacing: ".3rem",
|
||||||
|
color: "inherit",
|
||||||
|
textDecoration: "none",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
DevSpace
|
||||||
|
</Typography>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
flexGrow: 1,
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "right",
|
||||||
|
padding: "1rem",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<NotificationBell />
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box sx={{ flexGrow: 0 }}>
|
||||||
|
<Tooltip title="Open settings">
|
||||||
|
<IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}>
|
||||||
|
<Avatar alt={userInfo.firstName} src="/static/images/avatar/2.jpg" />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Menu
|
||||||
|
sx={{ mt: "45px" }}
|
||||||
|
id="menu-appbar"
|
||||||
|
anchorEl={anchorElUser}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: "top",
|
||||||
|
horizontal: "right",
|
||||||
|
}}
|
||||||
|
keepMounted
|
||||||
|
transformOrigin={{
|
||||||
|
vertical: "top",
|
||||||
|
horizontal: "right",
|
||||||
|
}}
|
||||||
|
open={Boolean(anchorElUser)}
|
||||||
|
onClose={handleCloseUserMenu}
|
||||||
|
>
|
||||||
|
{settings.map((setting) => (
|
||||||
|
<MenuItem key={setting} onClick={handleCloseUserMenu}>
|
||||||
|
<Typography textAlign="center">{setting}</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Menu>
|
||||||
|
</Box>
|
||||||
|
</Toolbar>
|
||||||
|
</Container>
|
||||||
|
</AppBar>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export default TopAppBar;
|
||||||
|
|
@ -1,16 +1,21 @@
|
||||||
import ResponsiveDrawer from "../components/Drawer";
|
import { Outlet, useNavigate } from "react-router-dom";
|
||||||
import { Outlet, useActionData, useNavigate } from "react-router-dom";
|
import { Box } from "@mui/material";
|
||||||
import { Button, Grid } from "@mui/material";
|
|
||||||
import { postLogout, selectLoggedIn, selectUserInfo } from "../app/loginSlice";
|
import { postLogout, selectLoggedIn, selectUserInfo } from "../app/loginSlice";
|
||||||
import { useAppDispatch } from "../app/store";
|
import { useAppDispatch } from "../app/store";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
import useWindowDimensions from "../app/hooks/useWindowDimensions";
|
||||||
|
import SideAppBar from "../components/sideAppBar";
|
||||||
|
import BottomAppBar from "../components/bottomAppBar";
|
||||||
|
import TopAppBar from "../components/topAppBar";
|
||||||
|
|
||||||
|
const drawerWidth = 240;
|
||||||
|
|
||||||
export default function Root() {
|
export default function Root() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const loggedIn = useSelector(selectLoggedIn);
|
const loggedIn = useSelector(selectLoggedIn);
|
||||||
const userInfo = useSelector(selectUserInfo);
|
const { width } = useWindowDimensions();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!loggedIn) {
|
if (!loggedIn) {
|
||||||
|
|
@ -24,9 +29,39 @@ export default function Root() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button color="primary" variant="contained" onClick={handleClick}>
|
<Box>
|
||||||
Log Off
|
<TopAppBar />
|
||||||
</Button>
|
</Box>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
flexDirection: { xs: "column", sm: "row" },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{width > 600 && (
|
||||||
|
<Box sx={{ flexBasis: { sm: "auto" } }}>
|
||||||
|
<SideAppBar drawerWidth={drawerWidth} />
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Box
|
||||||
|
component="main"
|
||||||
|
sx={{
|
||||||
|
flexGrow: 1,
|
||||||
|
p: 3,
|
||||||
|
width: { sm: `calc(100% - ${width > 600 ? drawerWidth : 0}px)` },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Outlet />
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{width <= 600 && (
|
||||||
|
<Box sx={{ flexBasis: "100%" }}>
|
||||||
|
<BottomAppBar />
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue