diff options
Diffstat (limited to 'src/web/components/nav_bar/NavBar.jsx')
| -rw-r--r-- | src/web/components/nav_bar/NavBar.jsx | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/src/web/components/nav_bar/NavBar.jsx b/src/web/components/nav_bar/NavBar.jsx new file mode 100644 index 0000000..3c22851 --- /dev/null +++ b/src/web/components/nav_bar/NavBar.jsx @@ -0,0 +1,174 @@ +import React, {useState, Fragment, useContext, useEffect} from "react"; +import {Link, useLocation} from "react-router-dom"; + +import Button from "components/button/Button.jsx"; +import Login from "components/login/Login.jsx"; +import Darken from "components/darken/Darken.jsx"; +import {UserContext} from "contexts/UserContext.jsx"; +import {StateContext} from "contexts/StateContext.jsx"; +import {refreshToken, logout} from "helpers/Auth.jsx"; +import {getSubreactFromLocation, getInfoFromSubreact} from "helpers/Location.jsx"; + +import styles from "./NavBar.css" +import logo from "assets/images/logo.png" +import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; +import {faUser, faPlay} from "@fortawesome/free-solid-svg-icons"; + +function AccountInfoItem({title, onClick, path, className}) { + return ( + <Link className={styles.accountInfoItem + (className ? " " + className : "")} + onClick={onClick} + to={path}> + + <h3>{title}</h3> + </Link> + ); +} + +function AccountInfo({user, setUser}) { + // At this stage the user is logged in and we keep them logged in by periodically + // refreshing our token. + useEffect(() => { + const interval = setInterval(() => { + refreshToken(user, setUser); + }, 58 * 60 * 1000); // refresh every 58 minutes, expires every sixty. + return () => clearInterval(interval); + }, []); + const [active, setActive] = useState(false); + + return ( + <div className={styles.accountContainer + (active ? " " + styles.accountContainerActive : "")} + onClick={() => {setActive(!active);}}> + <FontAwesomeIcon icon={faUser} className={styles.accountIcon} /> + <h2>{user.username ?? "anonymous"}</h2> + <FontAwesomeIcon icon={faPlay} className={styles.accountArrow + (active ? " " + styles.accountArrowActive : "")} /> + <div className={styles.accountInfoItemList + (active ? " " + styles.accountInfoItemListActive : "")}> + <AccountInfoItem title="Profile" path="/settings" /> + <AccountInfoItem title="Settings" path="/settings" /> + <AccountInfoItem title="Logout" path="/" onClick={() => {logout(setUser);}} /> + </div> + </div> + ); +} + +function LoginStatus({loginActive, setLoginActive}) { + const [user, setUser] = useContext(UserContext); + + // Not logged in, request a login. + if (user == null) { + return ( + <Button className={styles.loginStatus} + onClick={() => {setLoginActive(!loginActive);}}> + + <h2>Not Logged In</h2> + </Button> + ); + } + + return <AccountInfo user={user} setUser={setUser} />; +} + +function Account() { + const [state, setState] = useContext(StateContext); + const {loginActive} = state; + const setLoginActive = (isActive) => {setState({...state, loginActive: isActive});}; + + return ( + <Fragment> + <Login active={loginActive} setActive={setLoginActive} /> + <LoginStatus loginActive={loginActive} setLoginActive={setLoginActive} /> + </Fragment> + ); +} + +function Banner({navBarActive, setNavBarActive, shouldToggleNavBar}) { + + return ( + <div className={styles.bannerContainer}> + <button className={styles.burgerButton} + onClick={() => setNavBarActive(!navBarActive)} /> + + <Link to="/" + onClick={shouldToggleNavBar ? () => setNavBarActive(!navBarActive) : null}> + + <img className={styles.logo} src={logo} /> + <h1>GoReact</h1> + </Link> + </div> + ); +} + +function Item({path, setNavBarActive}) { + const location = useLocation(); + const subreact = path.replace("/", ""); // "a", "m" etc + const {icon, name} = getInfoFromSubreact(subreact); + + return ( + <Link to={path} + className={styles.item + (getSubreactFromLocation(location) === subreact ? " " + styles.itemActive : "")} + onClick={() => setNavBarActive(false)}> + <FontAwesomeIcon icon={icon} className={styles.itemIcon} /> + <h4>{name}</h4> + </Link> + ); +} + +function ItemList({children, title}) { + + return ( + <div className={styles.itemList}> + <div className={styles.titleContainer}> + <h3>{title}</h3> + </div> + {children && React.Children.count(children) > 0 ? children : <p>There's nothing here...</p>} + </div> + ); +} + +function Menu({navBarActive, setNavBarActive}) { + + return ( + <div className={styles.container}> + <nav className={styles.menu + (navBarActive ? " " + styles.menuActive : "")}> + <Banner navBarActive={navBarActive} setNavBarActive={setNavBarActive} shouldToggleNavBar /> + <div className={styles.itemListContainer}> + <ItemList title="Subreacts"> + <Item path="/" setNavBarActive={setNavBarActive} /> + <Item path="/t" setNavBarActive={setNavBarActive} /> + <Item path="/g" setNavBarActive={setNavBarActive} /> + <Item path="/k" setNavBarActive={setNavBarActive} /> + <Item path="/p" setNavBarActive={setNavBarActive} /> + <Item path="/a" setNavBarActive={setNavBarActive} /> + <Item path="/pr" setNavBarActive={setNavBarActive} /> + <Item path="/m" setNavBarActive={setNavBarActive} /> + </ItemList> + + {/*TODO*/} + <ItemList title="Watched Threads"> + </ItemList> + <ItemList title="Your Threads"> + </ItemList> + <ItemList title="Recent Threads"> + </ItemList> + + <span> + <p>GoReact 2022-2023</p> + </span> + </div> + </nav> + <Account /> + </div> + ); +} + +export default function NavBar() { + const [active, setActive] = useState(false); + + return ( + <header className={styles.navBar}> + <Darken active={active} onClick={() => setActive(false)} className={styles.darken} /> + <Banner setNavBarActive={setActive} /> + <Menu navBarActive={active} setNavBarActive={setActive} /> + </header> + ); +}
\ No newline at end of file |
