diff --git a/frontend2/public/battlecode-logo-horiz-white.png b/frontend2/public/battlecode-logo-horiz-white.png new file mode 100644 index 000000000..3fa49c58e Binary files /dev/null and b/frontend2/public/battlecode-logo-horiz-white.png differ diff --git a/frontend2/public/battlecode-logo-vert-white.png b/frontend2/public/battlecode-logo-vert-white.png new file mode 100644 index 000000000..9b54b7a4d Binary files /dev/null and b/frontend2/public/battlecode-logo-vert-white.png differ diff --git a/frontend2/public/favicon.ico b/frontend2/public/favicon.ico deleted file mode 100644 index a11777cc4..000000000 Binary files a/frontend2/public/favicon.ico and /dev/null differ diff --git a/frontend/public/favicon.png b/frontend2/public/favicon.png similarity index 100% rename from frontend/public/favicon.png rename to frontend2/public/favicon.png diff --git a/frontend2/public/logo192.png b/frontend2/public/logo192.png deleted file mode 100644 index fc44b0a37..000000000 Binary files a/frontend2/public/logo192.png and /dev/null differ diff --git a/frontend2/public/logo512.png b/frontend2/public/logo512.png deleted file mode 100644 index a4e47a654..000000000 Binary files a/frontend2/public/logo512.png and /dev/null differ diff --git a/frontend2/src/App.tsx b/frontend2/src/App.tsx index 1417ce3f4..1cd57f1f4 100644 --- a/frontend2/src/App.tsx +++ b/frontend2/src/App.tsx @@ -13,6 +13,7 @@ import { RouterProvider, createBrowserRouter, Navigate, + redirect, } from "react-router-dom"; import { DEFAULT_EPISODE } from "./utils/constants"; import NotFound from "./views/NotFound"; @@ -38,31 +39,38 @@ const router = createBrowserRouter([ { path: "/register", element: }, { path: "/password_forgot", element: }, { path: "/password_change", element: }, - // Pages that will contain the episode specific sidebar and navbar - { - element: , - children: [ - // Pages that should always be visible - // TODO: /:episodeId/resources, /:episodeId/tournaments, /:episodeId/queue - { path: "/:episodeId/home", element: }, - { path: "/:episodeId/quickstart", element: }, - { path: "/:episodeId/*", element: }, - { path: "/:episodeId/rankings", element: }, - ], - }, // Pages that should only be visible when logged in { element: , children: [ + { path: "/account", element: }, { element: , children: [ // TODO: /:episodeId/team, /:episodeId/submissions, /:episodeId/scrimmaging ], }, - { path: "/account", element: }, ], }, + // Pages that will contain the episode specific sidebar and navbar + { + element: , + children: [ + // Pages that should always be visible + // TODO: /:episodeId/resources, /:episodeId/tournaments, /:episodeId/queue + { path: "/:episodeId/home", element: }, + { + path: "/:episodeId/", + loader: ({ params }) => { + return redirect(`/${params.episodeId as string}/home`); + }, + }, + { path: "/:episodeId/quickstart", element: }, + { path: "/:episodeId/*", element: }, + { path: "/:episodeId/rankings", element: }, + ], + }, + // Pages that should redirect { path: "/*", element: }, ]); diff --git a/frontend2/src/components/CurrentUserProvider.tsx b/frontend2/src/components/CurrentUserProvider.tsx index 7d3035681..297cc4f66 100644 --- a/frontend2/src/components/CurrentUserProvider.tsx +++ b/frontend2/src/components/CurrentUserProvider.tsx @@ -8,6 +8,7 @@ import { import { removeApiTokens } from "../utils/cookies"; import { loginCheck } from "../utils/api/auth"; import { getUserUserProfile } from "../utils/api/user"; +import Cookies from "js-cookie"; export const CurrentUserProvider: React.FC<{ children: React.ReactNode }> = ({ children, @@ -26,6 +27,8 @@ export const CurrentUserProvider: React.FC<{ children: React.ReactNode }> = ({ }); }; const logout = (): void => { + Cookies.remove("access"); + Cookies.remove("refresh"); setUserData({ authState: AuthStateEnum.NOT_AUTHENTICATED, }); diff --git a/frontend2/src/components/EpisodeLayout.tsx b/frontend2/src/components/EpisodeLayout.tsx index 6729ccbd7..15c040199 100644 --- a/frontend2/src/components/EpisodeLayout.tsx +++ b/frontend2/src/components/EpisodeLayout.tsx @@ -1,10 +1,10 @@ import React, { useContext } from "react"; -import Navbar from "./Navbar"; +import Header from "./Header"; import Sidebar from "./sidebar"; import { Outlet, useParams } from "react-router-dom"; import { EpisodeContext } from "../contexts/EpisodeContext"; -// This component contains the NavBar and SideBar. +// This component contains the Header and SideBar. // Child route components are rendered with const EpisodeLayout: React.FC = () => { const episodeContext = useContext(EpisodeContext); @@ -14,7 +14,7 @@ const EpisodeLayout: React.FC = () => { } return (
- +
diff --git a/frontend2/src/components/Header.tsx b/frontend2/src/components/Header.tsx new file mode 100644 index 000000000..95ddbbb2e --- /dev/null +++ b/frontend2/src/components/Header.tsx @@ -0,0 +1,148 @@ +import React, { Fragment, useContext } from "react"; +import { Menu, Transition } from "@headlessui/react"; +import { Link, NavLink } from "react-router-dom"; +import { AuthStateEnum, useCurrentUser } from "../contexts/CurrentUserContext"; +import Icon from "./elements/Icon"; +import { EpisodeContext } from "../contexts/EpisodeContext"; +import { SIDEBAR_ITEM_DATA } from "./sidebar"; + +const Header: React.FC = () => { + const { authState, logout, user } = useCurrentUser(); + const { episodeId } = useContext(EpisodeContext); + + return ( + + ); +}; + +export default Header; diff --git a/frontend2/src/components/Navbar.tsx b/frontend2/src/components/Navbar.tsx deleted file mode 100644 index 5b80434ab..000000000 --- a/frontend2/src/components/Navbar.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from "react"; - -const Navbar: React.FC = () => { - return

navbar here

; -}; - -export default Navbar; diff --git a/frontend2/src/components/elements/Button.tsx b/frontend2/src/components/elements/Button.tsx index 85f910cb8..e02d4251c 100644 --- a/frontend2/src/components/elements/Button.tsx +++ b/frontend2/src/components/elements/Button.tsx @@ -1,6 +1,13 @@ import React from "react"; import Icon, { type IconName } from "./Icon"; +const VARIANTS: Record = { + "": "bg-gray-50 text-gray-800 hover:bg-gray-100 hover:ring-gray-900 hover:text-black ring-gray-500 ring-1 ring-inset", + dark: "bg-cyan-700 text-white hover:bg-cyan-800", + "light-outline": + "ring-2 ring-inset ring-gray-200 text-gray-200 hover:bg-gray-100/20", +} as const; + interface ButtonProps extends React.ComponentPropsWithoutRef<"button"> { variant?: string; label?: string; @@ -9,11 +16,6 @@ interface ButtonProps extends React.ComponentPropsWithoutRef<"button"> { className?: string; } -const variants: Record = { - "": "bg-gray-50 text-gray-800 hover:bg-gray-100 hover:ring-gray-900 hover:text-black ring-gray-500 ring-1 ring-inset", - dark: "bg-cyan-700 text-white hover:bg-cyan-800", -}; - const Button: React.FC = ({ variant = "", label, @@ -22,14 +24,15 @@ const Button: React.FC = ({ className = "", ...rest }) => { - const variantStyle = `${variants[variant]} ${ + const variantStyle = `${VARIANTS[variant]} ${ fullWidth ? "w-full" : "" } ${className}`; return (
-
-
+
+
Need an account?{" "} Register for one!