Now that we have basic routing available for our projects, let's work on making the Dashboard a bit more functional. We'll start with the imports.

Dashboard imports

import React, { useState} from 'react';
import { Drawer as MUIDrawer, 
    ListItem, 
    List, 
    ListItemIcon, 
    ListItemText, 
    Theme,
    useTheme, 
    makeStyles, 
    createStyles,
    AppBar,
    Toolbar,
    IconButton,
    Typography,
    Divider,
    Button
} from '@material-ui/core';
import CssBaseline from '@material-ui/core/CssBaseline';
import MenuIcon from '@material-ui/icons/Menu'
import ChevronLeftIcon from '@material-ui/icons/ChevronLeft';
import ChevronRightIcon from '@material-ui/icons/ChevronRight'
import clsx from 'clsx';
import { RouteComponentProps, withRouter, Switch, Route } from "react-router-dom";

<aside> 💡 The following imports give our project access to the components inside of Material-UI, our first react hook, Material-UI icons, and a small component called clsx that allows our component the ability to parse class names that are nested inside of objects. Lastly, we will need access to the router for our dashboard, so we also import some of the needed components available there. (Specifically, we will need to use withRouter to pass routing props down to our component).

</aside>

Drawer Size and Creation of Styles

We will now need to add the following class declarations for our Material-UI styled component. Again, we will employ the use of the createStyles hook, but this time we add a bit more flavor with the makeStyles hook. The makeStyles hook allows us to add an overall theme from Material-UI (we're using the default violet theme) for a better styling experience overall. However, we still need some custom CSS for the look and feel we're going for.

const drawerWidth = 240;

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    root: {
      display: 'flex',
    },
    appBar: {
      transition: theme.transitions.create(['margin', 'width'], {
        easing: theme.transitions.easing.sharp,
        duration: theme.transitions.duration.leavingScreen,
      }),
    },
    appBarShift: {
      width: `calc(100% - ${drawerWidth}px)`,
      marginLeft: drawerWidth,
      transition: theme.transitions.create(['margin', 'width'], {
        easing: theme.transitions.easing.easeOut,
        duration: theme.transitions.duration.enteringScreen,
      }),
    },
    menuButton: {
      marginRight: theme.spacing(2),
    },
    hide: {
      display: 'none',
    },
    drawer: {
      width: drawerWidth,
      flexShrink: 0,
    },
    drawerPaper: {
      width: drawerWidth,
    },
    drawerHeader: {
      display: 'flex',
      alignItems: 'center',
      padding: theme.spacing(0, 1),
      // necessary for content to be below app bar
      ...theme.mixins.toolbar,
      justifyContent: 'flex-end',
    },
    content: {
      flexGrow: 1,
      padding: theme.spacing(3),
      transition: theme.transitions.create('margin', {
        easing: theme.transitions.easing.sharp,
        duration: theme.transitions.duration.leavingScreen,
      }),
      marginLeft: -drawerWidth,
    },
    contentShift: {
      transition: theme.transitions.create('margin', {
        easing: theme.transitions.easing.easeOut,
        duration: theme.transitions.duration.enteringScreen,
      }),
      marginLeft: 0,
    },
    toolbar:{
      display: 'flex',
    },
    toolbar_button: {
      marginLeft: 'auto'
    }
  }),
);

Interface for the Dashboard props

interface DashProps{
  history: RouteComponentProps["history"];
  location: RouteComponentProps['location'];
  match: RouteComponentProps['match'];
}

<aside> 💡 This ensures that we are using the correct DataType inside of our Dashboard's props object. This is the benefit of using TypeScript. We can make sure our data will look a certain way...BEFORE we try to run it.

</aside>

Let's take a look at what our potential Dashboard props object could look like:

history: {length: 2, action: "PUSH", location: {…}, createHref: ƒ, push: ƒ, …}
location: {pathname: "/dashboard", search: "", hash: "", state: undefined, key: "w4tfi5"}
match: {path: "/dashboard", url: "/dashboard", isExact: true, params: {…}}
staticContext: undefined
__proto__: Object

Dashboard Layout

Alright! With all of the other stuff out of the way now, we can finally add/update our Dashboard. We'll do this with the following code(There's a lot btw):

export const Dashboard = withRouter(( props:DashProps ) => {
  console.log(props)
  const { history } = props;
  const classes = useStyles();
  const theme = useTheme();
  const [open, setOpen] = useState(false);

  const handleDrawerOpen = () => {
    setOpen(true);
  };

  const handleDrawerClose = () => {
    setOpen(false);
  };

  const itemsList = [
    {
      text: 'Home',
      onClick: () => history.push('/')
    },
    {
      text: 'Sign In',
      onClick: () => history.push('/signin')
    }
  ]

  return (
    <div className={classes.root}>
      <CssBaseline />
      <AppBar
        position="fixed"
        className={clsx(classes.appBar, {
          [classes.appBarShift]: open,
        })}
      >
        <Toolbar className={classes.toolbar}>
          <IconButton
            color="inherit"
            aria-label="open drawer"
            onClick={handleDrawerOpen}
            edge="start"
            className={clsx(classes.menuButton, open && classes.hide)}
          >
            <MenuIcon />
          </IconButton>
          <Typography variant="h6" noWrap>
            Dashboard
          </Typography>
          <Button className={classes.toolbar_button}>Create New Drone</Button>
        </Toolbar>
      </AppBar>
      <MUIDrawer
        className={classes.drawer}
        variant="persistent"
        anchor="left"
        open={open}
        classes={{
          paper: classes.drawerPaper,
        }}
      >
        <div className={classes.drawerHeader}>
          <IconButton onClick={handleDrawerClose}>
            {theme.direction === 'ltr' ? <ChevronLeftIcon /> : <ChevronRightIcon />}
          </IconButton>
        </div>
        <Divider />
        <List>
        {itemsList.map((item, index) => {
          const { text, onClick } = item;
          return (
            <ListItem button key={text} onClick={onClick}>
              <ListItemText primary={text} />
            </ListItem>
          );
        })}
        </List>
      </MUIDrawer>
      <main
        className={clsx(classes.content, {
          [classes.contentShift]: open,
        })}
      >
        <div className={classes.drawerHeader} />

        <h1>Hello World Until Data Shows Up</h1>
        {/* <DataTable /> We will add this shortly*/}
      </main>
    </div>
    )
});

Ok, now let's break down what's going on. First, we will look at the beginning of our component function. There are a few things happening here.

console.log(props)
  const { history } = props;
  const classes = useStyles();
  const theme = useTheme();
  const [open, setOpen] = useState(false);

  const handleDrawerOpen = () => {
    setOpen(true);
  };

  const handleDrawerClose = () => {
    setOpen(false);
  };