diff --git a/src/App.jsx b/src/App.jsx index 9cee259..299b1f7 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -5,7 +5,6 @@ import React, { useState, useCallback, useMemo, useEffect } from "react"; import _ from "lodash"; import MainMenu from "./components/MainMenu"; import NavBar from "./components/NavBar"; -import SelfServiceNavbar from "./components/SelfService/NavBar"; import { navigate, Router, useLocation } from "@reach/router"; import { useSelector } from "react-redux"; import useMatchSomeRoute from "./hooks/useMatchSomeRoute"; @@ -56,10 +55,10 @@ const App = () => { return ( <> <Router> - <SelfServiceNavbar path="/self-service/*" /> <NavBar default noThrow + profileUrl={location.pathname.includes('/self-service') ? '/self-service/profile/' : `/profile/${auth.profile.handle}`} hideSwitchTools={isNavigationDisabled} path="/*" /> diff --git a/src/components/NavBar/index.jsx b/src/components/NavBar/index.jsx index f06b5dc..919147c 100644 --- a/src/components/NavBar/index.jsx +++ b/src/components/NavBar/index.jsx @@ -22,7 +22,7 @@ import "./styles.css"; import { useMediaQuery } from "react-responsive"; import NotificationsMenu from "../NotificationsMenu"; -const NavBar = ({ hideSwitchTools }) => { +const NavBar = ({ hideSwitchTools, profileUrl }) => { // all menu options const menu = useSelector((state) => state.menu.categories); // flat list of all apps @@ -96,6 +96,7 @@ const NavBar = ({ hideSwitchTools }) => { <Fragment> <NotificationsMenu /> <UserMenu + profileUrl={profileUrl} profile={auth.profile} hideSwitchTools={hideSwitchTools} /> @@ -121,6 +122,7 @@ const NavBar = ({ hideSwitchTools }) => { <Fragment> <NotificationsMenu /> <UserMenu + profileUrl={profileUrl} profile={auth.profile} hideSwitchTools={hideSwitchTools} /> @@ -140,9 +142,11 @@ const NavBar = ({ hideSwitchTools }) => { NavBar.defaultProps = { hideSwitchTools: false, + profileUrl: '/profile/', }; NavBar.propTypes = { + profileUrl: PropTypes.string, hideSwitchTools: PropTypes.boolean, }; diff --git a/src/components/SelfService/NavBar/index.jsx b/src/components/SelfService/NavBar/index.jsx deleted file mode 100644 index 21f33c8..0000000 --- a/src/components/SelfService/NavBar/index.jsx +++ /dev/null @@ -1,112 +0,0 @@ -/** - * NavBar component. - * - * Shows global top navigation bar with all apps menu, logo and user menu. - */ -import React, { useState, useEffect, useMemo, useCallback } from "react"; -import { useSelector } from "react-redux"; -import { Link, useLocation } from "@reach/router"; -import cn from "classnames"; -import _ from "lodash"; -import { useMediaQuery } from "react-responsive"; -import Button from "../../Button"; -import NotificationsMenu from "../NotificationsMenu"; -import UserMenu from "../UserMenu"; -import TCLogo from "../../../assets/images/tc-logo.svg"; -import { getSelfServiceLoginUrl, getSelfServiceSignupUrl } from "utils"; -import { BUTTON_TYPE } from "../../../constants"; -import "./styles.css"; - -const NavBar = ({ hideSwitchTools }) => { - // all menu options - const menu = useSelector((state) => state.menu.categories); - // flat list of all apps - const apps = useMemo(() => _.flatMap(menu, "apps"), [menu]); - // Active app - const [activeApp, setActiveApp] = useState(null); - const auth = useSelector((state) => state.auth); - const isMobile = useMediaQuery({ - query: "(max-width: 1023px)", - }); - - const routerLocation = useLocation(); - - const isHomePage = routerLocation.pathname.startsWith("/self-service/home"); - - const activeAppTitle = (isHomePage ? "Topcoder" : activeApp?.title) || null; - - const onClickBtnLogIn = useCallback(() => { - window.location.href = getSelfServiceLoginUrl(); - }, []); - - const onClickBtnSignUp = useCallback(() => { - window.location.href = getSelfServiceSignupUrl(); - }, []); - - // Check app title with route activated - useEffect(() => { - const activeApp = apps.find( - (f) => routerLocation.pathname.indexOf(f.path) !== -1 - ); - setActiveApp(activeApp); - }, [routerLocation, apps]); - - const renderTopcoderLogo = hideSwitchTools ? ( - <img src={TCLogo} alt="Topcoder Logo" /> - ) : ( - <Link to="/"> - <img src={TCLogo} alt="Topcoder Logo" /> - </Link> - ); - - return ( - <div className={cn("navbar", "self-service-navbar")}> - <div className="navbar-left"> - {isMobile ? null : ( - <> - {renderTopcoderLogo} - <div className="navbar-divider" /> - <div - className={cn("navbar-app-title", { - "navbar-app-title-underlined": !isHomePage, - })} - > - {activeAppTitle} - </div> - </> - )} - </div> - <div className="navbar-center"> - {isMobile ? renderTopcoderLogo : null} - {process.env.NODE_ENV === "test" && ( - <h3 style={{ display: "none" }}>Navbar App Test</h3> - )} - </div> - <div className="navbar-right"> - {auth.isInitialized && - (auth.tokenV3 ? ( - auth.profile && ( - <> - <NotificationsMenu /> - <UserMenu profile={auth.profile} /> - </> - ) - ) : ( - <> - <Button - type={BUTTON_TYPE.TEXT_INVERTED} - onClick={onClickBtnLogIn} - > - Log In - </Button> - <Button type={BUTTON_TYPE.TEXT} onClick={onClickBtnSignUp}> - Sign Up - </Button> - </> - ))} - </div> - </div> - ); -}; - -export default NavBar; diff --git a/src/components/SelfService/NavBar/styles.css b/src/components/SelfService/NavBar/styles.css deleted file mode 100644 index 8a77d95..0000000 --- a/src/components/SelfService/NavBar/styles.css +++ /dev/null @@ -1,92 +0,0 @@ -.navbar { - align-items: center; - display: flex; - background-color: #2a2a2a; - height: var(--navbarHeight); - justify-content: space-between; - padding: 0 24px; - padding-right: 16px; - position: relative; - z-index: 1; - font-family: "Roboto", Arial, Helvetica, sans-serif; -} -.navbar.self-service-navbar { - padding: 0 24px; - background-color: #0c0c0c; -} - -.navbar-left { - display: flex; - flex-direction: row; - align-items: center; -} - -.navbar-app-title { - font-family: "Roboto", Arial, Helvetica, sans-serif; - font-weight: 500; - font-weight: normal; - text-transform: uppercase; - font-size: 22px; - text-align: left; - color: #fff; -} - -.self-service-navbar .navbar-app-title { - position: relative; - font-family: "Barlow Condensed", Arial, Helvetica, sans-serif; - font-weight: 500; - font-size: 22px; - line-height: 32px; -} -.self-service-navbar .navbar-app-title.navbar-app-title-underlined { - font-size: 20px; - line-height: 18px; -} -.self-service-navbar .navbar-app-title.navbar-app-title-underlined::after { - content: ""; - display: block; - position: absolute; - left: 8.5px; - top: 100%; - right: 8.5px; - margin: 10px 0 0; - border-radius: 2px; - height: 2px; - background-color: #0ab88a; -} -.self-service-navbar .navbar-app-title.navbar-app-title-underlined:empty:after { - display: none; -} - -.navbar-divider { - width: 1px; - height: 30px; - background-color: #555; -} - -.navbar-left .navbar-divider { - margin: 0 30px; -} -.self-service-navbar .navbar-left .navbar-divider { - margin: 0 23px; -} -.navbar-center { - left: 50%; - position: absolute; - transform: translateX(-50%); -} -.navbar-right { - display: flex; - align-items: center; - flex-direction: row; -} -.navbar-right .navbar-divider { - margin: 0 15px; -} -.navbar-right .navbar-login { - color: #fff; - font-size: 14px; - font-weight: bold; - text-decoration: none; - text-transform: uppercase; -} diff --git a/src/components/SelfService/NotificationsMenu/index.jsx b/src/components/SelfService/NotificationsMenu/index.jsx deleted file mode 100644 index 3bd4579..0000000 --- a/src/components/SelfService/NotificationsMenu/index.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from "react"; -import Bell from "../../../assets/icons/ui-bell.svg"; -import styles from "./styles.module.scss"; - -/** - * Displays self service notification bell. - * - * @returns {JSX.Element} - */ -const SelfServiceNotifications = () => { - return ( - <div className={styles.container}> - <div className={styles.button}> - <Bell className={styles.bell} /> - <div className={styles.count}>0</div> - </div> - </div> - ); -}; - -export default SelfServiceNotifications; diff --git a/src/components/SelfService/NotificationsMenu/styles.module.scss b/src/components/SelfService/NotificationsMenu/styles.module.scss deleted file mode 100644 index b3db2b2..0000000 --- a/src/components/SelfService/NotificationsMenu/styles.module.scss +++ /dev/null @@ -1,38 +0,0 @@ -.container { - position: relative; - display: flex; - margin-right: 16px; -} - -.button { - position: relative; - width: 16px; - height: 16px; - cursor: pointer; -} - -.bell { - display: block; - width: 16px; - height: auto; - - path { - fill: #fff; - } -} - -.count { - position: absolute; - top: -8px; - right: -8px; - border-radius: 8px; - width: 16px; - height: 16px; - font-family: "Roboto", Arial, Helvetica, sans-serif; - font-weight: 700; - font-size: 8px; - line-height: 16px; - text-align: center; - background-color: #E90C5A; - color: #fff; -} diff --git a/src/components/SelfService/UserMenu/index.jsx b/src/components/SelfService/UserMenu/index.jsx deleted file mode 100644 index 2470fb6..0000000 --- a/src/components/SelfService/UserMenu/index.jsx +++ /dev/null @@ -1,84 +0,0 @@ -import React, { useCallback, useState } from "react"; -import { Link } from "@reach/router"; -import PT from "prop-types"; -import cn from "classnames"; -import OutsideClickHandler from "react-outside-click-handler"; -import IconCross from "../../../assets/icons/icon-cross.svg"; -import { logout, getLogoutUrl } from "utils"; -import styles from "./styles.module.scss"; - -/** - * Displays user profile icon. - * - * @param {Object} props component properties - * @returns {JSX.Element} - */ -const SelfServiceUserMenu = ({ profile }) => { - const [isOpenMenu, setIsOpenMenu] = useState(false); - - const { firstName, lastName } = profile; - - const onClickBtn = useCallback(() => { - setIsOpenMenu((value) => !value); - }, []); - - const onClickOutsideMenu = useCallback(() => { - setIsOpenMenu(false); - }, []); - - const onClickLogout = useCallback((event) => { - event.preventDefault(); - logout(); - }, []); - - const onClickMyProfile = useCallback(() => { - setIsOpenMenu(false); - }, []); - - return ( - <div className={cn(styles.container, { [styles.menuIsOpen]: isOpenMenu })}> - <OutsideClickHandler onOutsideClick={onClickOutsideMenu}> - <div - className={styles.button} - onClick={onClickBtn} - role="button" - tabIndex={0} - > - <span className={styles.initials}> - {firstName.charAt(0)} - {lastName.charAt(0)} - </span> - <IconCross className={styles.icon} /> - </div> - {isOpenMenu && ( - <div className={styles.menu}> - <div className={styles.userInfo}> - {firstName} {lastName.charAt(0)}. - </div> - <ul className={styles.items}> - <li> - <Link onClick={onClickMyProfile} to="/self-service/profile"> - My Profile - </Link> - </li> - <li> - <a href={getLogoutUrl()} onClick={onClickLogout}> - Log Out - </a> - </li> - </ul> - </div> - )} - </OutsideClickHandler> - </div> - ); -}; - -SelfServiceUserMenu.propTypes = { - profile: PT.shape({ - firstName: PT.string.isRequired, - lastName: PT.string.isRequired, - }).isRequired, -}; - -export default SelfServiceUserMenu; diff --git a/src/components/SelfService/UserMenu/styles.module.scss b/src/components/SelfService/UserMenu/styles.module.scss deleted file mode 100644 index 31b8e19..0000000 --- a/src/components/SelfService/UserMenu/styles.module.scss +++ /dev/null @@ -1,108 +0,0 @@ -@import "styles/mixins"; - -.container { - position: relative; - display: flex; -} - -.button { - display: flex; - justify-content: center; - align-items: center; - border: 2px solid #fff; - border-radius: 16px; - padding: 0; - width: 32px; - height: 32px; - @include font-barlow-condensed; - font-weight: 700; - font-size: 14px; - line-height: 14px; - background: linear-gradient(90deg, #16679a 0%, #2c95d7 100%); - color: #fff; - user-select: none; - cursor: pointer; - - .icon { - display: none; - } -} - -.menuIsOpen { - .button { - background: #fff; - - .initials { - display: none; - } - - .icon { - display: block; - width: 14px; - height: auto; - } - } -} - -.menu { - z-index: 3; - position: absolute; - top: 100%; - right: -16px; - margin-top: 20px; - border-radius: 8px; - padding: 12px 16px 16px; - width: 168px; - white-space: nowrap; - background-color: #fff; - box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.2); - user-select: none; - - &::before { - content: ""; - display: block; - z-index: 1; - position: absolute; - left: 0; - top: -10px; - right: 0; - width: 168px; - height: 58px; - background-repeat: no-repeat; - background-position: center top; - background-image: url("../../../assets/images/user-menu-header-bg.svg"); - } -} - -.userInfo { - z-index: 2; - position: relative; - padding: 0 0 29px; - @include font-roboto; - font-size: 14px; - line-height: 16px; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - color: #fff; -} - -.items { - margin-top: 0px; - @include font-barlow-condensed; - font-weight: 500; - font-size: 14px; - line-height: 16px; - text-transform: uppercase; - - li { - margin-top: 8px; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - - &:first-child { - margin-top: 0; - } - } -} diff --git a/src/components/UserMenu/index.jsx b/src/components/UserMenu/index.jsx index e777b41..c3765fa 100644 --- a/src/components/UserMenu/index.jsx +++ b/src/components/UserMenu/index.jsx @@ -13,7 +13,7 @@ import { logout, getLogoutUrl } from "../../utils"; import "./styles.css"; import { useMediaQuery } from "react-responsive"; -const UserMenu = ({ profile, hideSwitchTools }) => { +const UserMenu = ({ profile, profileUrl }) => { const [isOpenMenu, setIsOpenMenu] = useState(false); const closeMenu = useCallback(() => { @@ -64,16 +64,14 @@ const UserMenu = ({ profile, hideSwitchTools }) => { <div className="user-menu-popover-arrow" /> <div className="user-menu-popover-content"> <ul className="user-menu-list"> - {hideSwitchTools ? null : ( - <li> - <Link - to={`/profile/${profile.handle}`} - onClick={closeMenu} - > - Profile - </Link> - </li> - )} + <li> + <Link + to={`${profileUrl}`} + onClick={closeMenu} + > + Profile + </Link> + </li> <li> <a href={getLogoutUrl()} onClick={onLogoutClick}> Log Out @@ -90,11 +88,11 @@ const UserMenu = ({ profile, hideSwitchTools }) => { }; UserMenu.defaultProps = { - hideSwitchTools: false, + profileUrl: '/profile', }; UserMenu.propTypes = { - hideSwitchTools: PropTypes.boolean, + profileUrl: PropTypes.string, }; export default UserMenu;