Skip to content

Commit

Permalink
feat: spotlights (#702)
Browse files Browse the repository at this point in the history
Co-authored-by: tiago-bacelar <[email protected]>
  • Loading branch information
ruilopesm and tiago-bacelar authored Feb 5, 2024
1 parent d100082 commit 19985a3
Show file tree
Hide file tree
Showing 22 changed files with 1,009 additions and 250 deletions.
2 changes: 1 addition & 1 deletion components/Dashboard/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Dialog, Transition } from "@headlessui/react";

import Return from "/components/Return";

const navigation = ["dashboard", "spotlight"];
const navigation = ["dashboard", "spotlights"];

export default function Dashboard(props) {
const [sidebarOpen, setSidebarOpen] = useState(false);
Expand Down
288 changes: 103 additions & 185 deletions components/Layout/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,54 @@ import { ReactNode, useState } from "react";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";

import { Dialog, Transition } from "@headlessui/react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faBars, faTimes } from "@fortawesome/free-solid-svg-icons";

import { useAuth } from "@context/Auth";

const roleNavigations = {
sponsor: ["scanner", "visitors"],
attendee: [
"profile",
"slots",
"wheel",
"badgedex",
"leaderboard",
"store",
"inventory",
"identifier",
],
admin: ["scanner", "visitors", "badges", "leaderboard", "users", "events"],
staff: ["badges", "leaderboard", "prizes", "identifier", "cv"],
import { faBars } from "@fortawesome/free-solid-svg-icons";

import { IStaff, IUser, useAuth } from "@context/Auth";
import { ROLES } from "@lib/user";
import MobileNavbar from "./components/MobileNavbar";
import ActiveLink from "./components/ActiveLink";
import Banner from "./components/Banner";
import spotlights from "pages/staff/spotlights";

// FIXME: Normalize user type between moonstone and safira
const basePahts = {
[ROLES.ATTENDEE]: "attendee",
[ROLES.SPONSOR]: "sponsor",
[ROLES.STAFF]: "staff",
};

const roleNavigation = (user: IUser) => {
switch (user.type) {
case ROLES.SPONSOR:
return ["scanner", "visitors"];

case ROLES.ATTENDEE:
return [
"profile",
"wheel",
"badgedex",
"leaderboard",
"store",
"inventory",
"identifier",
];

case ROLES.STAFF:
return [
"leaderboard",
"badges",
"prizes",
"identifier",
"cv",
...((user as IStaff).is_admin ? ["spotlights"] : []),
];

default:
throw new Error(`Unknown USER TYPE: ${user.type}`);
}
};

type LayoutProps = {
Expand All @@ -34,27 +62,20 @@ type LayoutProps = {

export default function Layout({ title, description, children }: LayoutProps) {
const { user, logout } = useAuth();
const [isNavbarOpen, setIsNavbarOpen] = useState(false);
const router = useRouter();

const currentHref = router.asPath;
// FIXME: normalize user type between moonstone and safira
const links =
user.type === "company"
? roleNavigations["sponsor"]
: roleNavigations[user.type];
const basePath = user.type === "company" ? "sponsor" : user.type;

const openNavbar = () => {
setIsNavbarOpen(true);
};
const [isNavbarOpen, setIsNavbarOpen] = useState(false);
const openNavbar = () => setIsNavbarOpen(true);
const closeNavbar = () => setIsNavbarOpen(false);

const closeNavbar = () => {
setIsNavbarOpen(false);
};
const currentHref = router.asPath;
const links = roleNavigation(user);
const basePath = basePahts[user.type];

return (
<div className="text-white lg:flex">
<div className="text-white">
<Banner />

<MobileNavbar
isOpen={isNavbarOpen}
links={links}
Expand All @@ -64,162 +85,59 @@ export default function Layout({ title, description, children }: LayoutProps) {
onLogout={logout}
/>

{/* NAVBAR */}
<aside className="no-scrollbar inset-y-0 hidden w-72 select-none overflow-y-auto border-r-2 bg-secondary px-8 py-5 lg:fixed lg:flex lg:flex-col">
<div className="flex flex-1">
<nav className="mt-8 flex flex-col">
<Link href="/" className="pb-8">
<Image
src="/images/sei-logo.svg"
alt="SEI Logo"
width="220"
height="120"
/>
</Link>

{links.map((link) => (
<ActiveLink
key={link}
link={link}
basePath={basePath}
href={currentHref}
/>
))}
</nav>
</div>
<div className="relative lg:flex">
{/* NAVBAR */}
<aside className="no-scrollbar inset-y-0 hidden w-72 select-none overflow-y-auto border-r-2 bg-secondary px-8 py-5 lg:fixed lg:flex lg:flex-col">
<div className="flex flex-1">
<nav className="mt-8 flex flex-col">
<Link href="/" className="pb-8">
<Image
src="/images/sei-logo.svg"
alt="SEI Logo"
width="220"
height="120"
/>
</Link>

{links.map((link) => (
<ActiveLink
key={link}
link={link}
basePath={basePath}
href={currentHref}
/>
))}
</nav>
</div>

<button
onClick={() => logout()}
className="mt-4 w-full text-left font-iregular text-quinary"
>
Log out 👋
</button>
</aside>

{/* OPEN SIDEBAR ON MOBILE */}
<button
onClick={() => logout()}
className="mt-4 w-full text-left font-iregular text-quinary"
type="button"
onClick={openNavbar}
className="absolute top-4 right-4 text-gray-500 lg:hidden"
>
Log out 👋
<span className="sr-only">Open sidebar</span>
<FontAwesomeIcon icon={faBars} />
</button>
</aside>

{/* OPEN SIDEBAR ON MOBILE */}
<button
type="button"
onClick={openNavbar}
className="absolute top-4 right-4 text-gray-500 lg:hidden"
>
<span className="sr-only">Open sidebar</span>
<FontAwesomeIcon icon={faBars} />
</button>

{/* CONTENT */}
<main className="w-full px-4 pb-6 pt-20 lg:ml-72 lg:px-20">
<h2 className="select-none font-ibold text-4xl sm:text-5xl">{title}</h2>
<p className="mt-2 font-iregular text-lg">{description}</p>

{children}
</main>
</div>
);
}

interface IMobileNavbarProps {
isOpen: boolean;
links: string[];
currentHref: string;
basePath: string;
onClose: () => void;
onLogout: () => void;
}

function MobileNavbar({
isOpen,
links,
currentHref,
basePath,
onClose,
onLogout,
}: IMobileNavbarProps) {
return (
<Transition.Root show={isOpen}>
<Dialog
onClose={onClose}
className="fixed inset-0 z-40 flex w-full text-white md:max-w-md"
>
<Dialog.Panel>
<Transition.Child
enter="transition-opacity ease-linear duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity ease-linear duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Dialog.Overlay className="-z-1 fixed inset-0 bg-gray-600 bg-opacity-75" />
</Transition.Child>

<Transition.Child
enter="transition ease-in-out duration-300 transform"
enterFrom="-translate-x-full"
enterTo="translate-x-0"
leave="transition ease-in-out duration-300 transform"
leaveFrom="translate-x-0"
leaveTo="-translate-x-full"
className="z-1 no-scrollbar absolute h-full w-full justify-between overflow-y-scroll bg-secondary p-8 "
>
<aside className="flex h-full select-none flex-col justify-between">
<div>
<div className="flex items-center justify-between">
<Link href="/" className="font-iregular text-quinary">
<Image
src="/images/sei-logo.svg"
alt="SEI Logo"
width="48"
height="32"
/>
</Link>

<button type="button" onClick={onClose} className="h-12 w-12">
<span className="sr-only">Close sidebar</span>
<FontAwesomeIcon icon={faTimes} />
</button>
</div>

<nav className="flex flex-col">
{links.map((link) => (
<ActiveLink
key={link}
link={link}
basePath={basePath}
href={currentHref}
/>
))}
</nav>
</div>

<button
onClick={onLogout}
className="w-full border-t border-quaternary pt-4 text-left font-iregular text-quinary"
>
Log out 👋
</button>
</aside>
</Transition.Child>
</Dialog.Panel>
</Dialog>
</Transition.Root>
);
}

interface IActiveLinkProps {
link: string;
href: string;
basePath: string;
}
{/* CONTENT */}
<main className="w-full px-4 pb-6 pt-20 lg:ml-72 lg:px-20">
<h2 className="select-none font-ibold text-4xl sm:text-5xl">
{title}
</h2>
<p className="mt-2 font-iregular text-lg">{description}</p>

function ActiveLink({ link, href, basePath }: IActiveLinkProps) {
const activeStyle = href === `/${basePath}/${link}` && "text-quinary";

return (
<Link
href={`/${basePath}/${link}`}
className={`py-8 font-ibold text-xs uppercase transition duration-200 hover:text-quinary ${activeStyle}`}
>
{link}
</Link>
{children}
</main>
</div>
</div>
);
}
20 changes: 20 additions & 0 deletions components/Layout/components/ActiveLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Link from "next/link";

type IActiveLinkProps = {
link: string;
href: string;
basePath: string;
};

export default function ActiveLink({ link, href, basePath }: IActiveLinkProps) {
const activeStyle = href === `/${basePath}/${link}` && "text-quinary";

return (
<Link
href={`/${basePath}/${link}`}
className={`py-8 font-ibold text-xs uppercase transition duration-200 hover:text-quinary ${activeStyle}`}
>
{link}
</Link>
);
}
Loading

0 comments on commit 19985a3

Please sign in to comment.