Skip to content

hamburger nav bar for participant #208

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 15, 2025
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions src/app/judging/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import NavBar from "@/components/judging/Navbar";

export default function JudgingLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="flex size-full flex-col bg-dashboard-grey">
<NavBar />
<main className="flex flex-1 flex-col gap-4">{children}</main>
</div>
);
Expand Down
18 changes: 18 additions & 0 deletions src/app/participant/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"use client";

export default function RoleBasedLayout({
children,
}: {
children: React.ReactNode;
}) {
// For Admin layouts we might want to show a SideNavBar/TopNavBar
// You can use the same hook or control it separately if needed.
// Here we assume non-admin users only need the nav rendered by UserBasedNav.

// This example uses the UserBasedNav component in the layout:
return (
<div className="flex w-full flex-col bg-fuzzy-peach">
<main className="">{children}</main>
</div>
);
}
8 changes: 5 additions & 3 deletions src/components/Dashboard/GoToFoodTicket.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ import ParticipantTicketIcon from "@/images/dashboard/ParticipantTicketIcon.png"
import Card from "./Card";

export default function GoToFoodTicket() {
const href = "#";
return (
<Card className="flex h-full flex-row justify-start gap-8">
<Link href={href}>
<Link href="/participant/profile/food-ticket">
<Image
className="transition duration-300 hover:opacity-90"
src={ParticipantTicketIcon}
Expand All @@ -21,7 +20,10 @@ export default function GoToFoodTicket() {
<div className=" text-xl font-medium">Go To My</div>
<h2 className="italic"> Food Ticket</h2>
</div>
<Link href={href} className="transition duration-300 hover:opacity-90">
<Link
href="/participant/profile/food-ticket"
className="transition duration-300 hover:opacity-90"
>
<FaCircleArrowRight size={48} color="grey" />
</Link>
</Card>
Expand Down
104 changes: 104 additions & 0 deletions src/components/Dashboard/UserBasedNav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
"use client";

import Link from "next/link";
import { useState } from "react";

import { useUser } from "@/components/contexts/UserContext";

interface NavItem {
name: string;
route: string;
}

const navigationMap: Record<string, NavItem[]> = {
Admin: [
{ name: "Dashboard", route: "/admin" },
{ name: "View All Participants", route: "/admin/users" },
{ name: "View All Teams", route: "/admin/teams" },
{ name: "Scan Food Tickets", route: "/admin/scan-food-tickets" },
{ name: "Create Food Event", route: "/admin/create-food-event" },
{ name: "Judging Schedule", route: "/admin/schedule" },
],
Judge: [
{ name: "Dashboard", route: "/judging" },
{ name: "Schedule", route: "/judging/schedule" },
{ name: "Assigned Teams", route: "/judging/assigned-teams" },
{ name: "Rubric", route: "/judging/rubric" },
],
Participant: [
{ name: "Dashboard", route: "/participant" },
{ name: "Food Ticket", route: "/participant/profile/food-ticket" },
{ name: "Important Information", route: "/participant/important-info" },
{ name: "Teams Judging Information", route: "/participant/judging-info" },
],
};

function GenericNav({ navItems }: { navItems: NavItem[] }) {
const [isMenuOpen, setIsMenuOpen] = useState(false);

const toggleMenu = () => setIsMenuOpen(!isMenuOpen);

return (
<>
{!isMenuOpen && (
<button
onClick={toggleMenu}
className="absolute left-8 top-12 z-50 p-2 text-awesomer-purple"
aria-label="Toggle menu"
>
<div className="relative flex size-8 flex-col justify-center space-y-1.5">
<span className="block h-[2.5px] w-8 bg-current"></span>
<span className="block h-[2.5px] w-8 bg-current"></span>
<span className="block h-[2.5px] w-8 bg-current"></span>
</div>
</button>
)}

{isMenuOpen && (
<div className="fixed inset-0 z-40 bg-black/50" onClick={toggleMenu} />
)}

<div
className={`fixed left-0 top-0 z-40 h-full w-64 bg-white shadow-lg transition-transform duration-300 ease-in-out ${
isMenuOpen ? "translate-x-0" : "-translate-x-full"
}`}
>
<button
onClick={toggleMenu}
className="absolute left-4 top-4 z-50 p-2 text-awesomer-purple"
aria-label="Close menu"
>
<div className="relative size-6">
<span className="absolute left-0 top-1/2 h-0.5 w-6 -translate-y-1/2 rotate-45 bg-current"></span>
<span className="absolute left-0 top-1/2 h-0.5 w-6 -translate-y-1/2 -rotate-45 bg-current"></span>
</div>
</button>
<div className="flex flex-col px-4 pt-20">
{navItems.map((item) => (
<Link
key={item.name}
href={item.route}
className="rounded px-2 py-3 text-xl text-awesomer-purple hover:bg-gray-100"
onClick={() => setIsMenuOpen(false)}
>
{item.name}
</Link>
))}
</div>
</div>
</>
);
}

export default function UserBasedNav() {
const { currentUser } = useUser();

if (!currentUser) {
return <div className="p-4 text-center">Loading...</div>;
}

const role = currentUser?.role || "Participant";
const navItems = navigationMap[role] || navigationMap.Participant;

return <GenericNav navItems={navItems} />;
}
18 changes: 14 additions & 4 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ import { CgProfile } from "react-icons/cg";

import { type Schema } from "@/amplify/data/resource";
import { client } from "@/app/QueryProvider";
import { UserType, useUser } from "@/components/contexts/UserContext";
import { useUser } from "@/components/contexts/UserContext";
import { useQuery } from "@tanstack/react-query";

import UserBasedNav from "./Dashboard/UserBasedNav";

export default function Header() {
const user = useUser().currentUser;

const userId = useUser().currentUser.username as string;

const { data } = useQuery({
useQuery({
initialData: {} as Schema["Team"]["type"],
initialDataUpdatedAt: 0,
queryKey: ["Team", userId],
Expand Down Expand Up @@ -51,13 +53,14 @@ export default function Header() {
};
return (
<div className="flex h-36 w-dvw flex-row items-center justify-between bg-white px-8 text-awesomer-purple">
<div className="flex w-48 font-semibold">
{/* Dont think we need this anymore because we have userbased nav */}
{/* <div className="flex w-48 font-semibold">
{user.username ? (
<>
{user.type === UserType.Participant ? (
<>
{data ? (
<Link href="/participant">Dashboard</Link>
<Link href="/participant"></Link>
) : (
<Link href="/register/team">Join a Team</Link>
)}
Expand All @@ -71,6 +74,13 @@ export default function Header() {
) : (
<a href="/login">Join Hackathon</a>
)}
</div> */}
<div className="flex w-48">
{user?.username ? (
<UserBasedNav />
) : (
<Link href="/login">Join Hackathon</Link>
)}
</div>

<div className="flex w-48 justify-center">
Expand Down
Loading