aboutsummaryrefslogtreecommitdiff
path: root/src/web/components/nav_bar/NavBar.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/web/components/nav_bar/NavBar.jsx')
-rw-r--r--src/web/components/nav_bar/NavBar.jsx174
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