Skip to content

Commit

Permalink
Merge branch 'refs/heads/dev' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
aaroncurtisyoga committed Dec 9, 2024
2 parents 479f9fe + 6b24952 commit bf74870
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 105 deletions.
53 changes: 53 additions & 0 deletions _components/Header/DesktopNavbarContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"use client";

import { FC } from "react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { SignedIn, SignedOut, UserButton } from "@clerk/nextjs";
import { NavbarContent, NavbarItem } from "@nextui-org/react";

interface DesktopNavbarContentProps {
isLoaded: boolean;
menuItems: { name: string; href: string; testId: string }[];
}

const DesktopNavbarContent: FC<DesktopNavbarContentProps> = ({
isLoaded,
menuItems,
}) => {
const pathname = usePathname();

return (
<NavbarContent className="hidden sm:flex gap-4" justify="end">
{isLoaded && (
<>
{menuItems.map((link, index) => (
<NavbarItem
data-testid={`navbar-item-${link.testId}`}
key={`${link.name}-${index}`}
isActive={pathname.includes(link.href)}
>
<Link className="w-full" href={link.href}>
{link.name}
</Link>
</NavbarItem>
))}
<NavbarItem
data-testid="navbar-login"
isActive={pathname.includes("/sign-in")}
className="min-w-[32px]"
>
<SignedIn>
<UserButton />
</SignedIn>
<SignedOut>
<Link href={"/sign-in"}>Login</Link>
</SignedOut>
</NavbarItem>
</>
)}
</NavbarContent>
);
};

export default DesktopNavbarContent;
25 changes: 25 additions & 0 deletions _components/Header/Logo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { FC } from "react";
import Link from "next/link";
import { NavbarBrand, NavbarContent } from "@nextui-org/react";
import { merriweather } from "@/app/fonts";

interface LogoProps {
setIsMenuOpen: (isOpen: boolean) => void;
}
const Logo: FC<LogoProps> = ({ setIsMenuOpen }) => {
return (
<NavbarContent>
<NavbarBrand data-testid="navbar-brand">
<Link href={"/"} onClick={() => setIsMenuOpen(false)}>
<h1
className={`sm:flex font-extrabold text-xl ${merriweather.className}`}
>
Aaron Curtis Yoga
</h1>
</Link>
</NavbarBrand>
</NavbarContent>
);
};

export default Logo;
123 changes: 19 additions & 104 deletions _components/Header.tsx → _components/Header/MobileNavbarContent.tsx
Original file line number Diff line number Diff line change
@@ -1,119 +1,33 @@
"use client";

import { FC, useEffect, useState } from "react";
import { FC, useEffect } from "react";
import Link from "next/link";
import { useRouter, usePathname } from "next/navigation";
import { usePathname, useRouter } from "next/navigation";
import { SignedIn, SignedOut, useClerk } from "@clerk/nextjs";
import {
SignedIn,
SignedOut,
useClerk,
UserButton,
useUser,
} from "@clerk/nextjs";
import {
Navbar,
NavbarBrand,
NavbarContent,
NavbarItem,
NavbarMenuToggle,
NavbarMenu,
NavbarMenuItem,
NavbarMenuToggle,
} from "@nextui-org/react";
import {
adminLinks,
authenticatedLinks,
unauthenticatedLinks,
} from "@/_lib/constants";
import { merriweather } from "@/app/fonts";

const Header: FC = () => {
interface MobileNavbarContentProps {
isMenuOpen: boolean;
menuItems: { name: string; href: string; testId: string }[];
setIsMenuOpen: (open: boolean) => void;
}

const MobileNavbarContent: FC<MobileNavbarContentProps> = ({
isMenuOpen,
menuItems,
setIsMenuOpen,
}) => {
const router = useRouter();
const pathname = usePathname();
const { signOut } = useClerk();
const { isSignedIn, isLoaded, user } = useUser();
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [menuItems, setMenuItems] = useState([...unauthenticatedLinks]);

useEffect(() => {
if (!isLoaded) return;

if (isSignedIn) {
const isAdmin = user?.publicMetadata.role === "admin";
setMenuItems(() => [
...unauthenticatedLinks,
...authenticatedLinks,
...(isAdmin ? adminLinks : []),
]);
} else {
setMenuItems([...unauthenticatedLinks]);
}
}, [isLoaded, user, isSignedIn]);

return (
<Navbar
data-testid="navbar"
onMenuOpenChange={setIsMenuOpen}
isBordered
maxWidth="xl"
classNames={{
item: [
"flex",
"relative",
"h-full",
"items-center",
"data-[active=true]:after:content-['']",
"data-[active=true]:after:absolute",
"data-[active=true]:after:bottom-0",
"data-[active=true]:after:left-0",
"data-[active=true]:after:right-0",
"data-[active=true]:after:h-[2px]",
"data-[active=true]:after:rounded-[2px]",
"data-[active=true]:after:bg-primary",
],
}}
>
<NavbarContent>
<NavbarBrand data-testid="navbar-brand">
<Link href={"/"}>
<h1
className={`sm:flex font-extrabold text-xl ${merriweather.className}`}
>
Aaron Curtis Yoga
</h1>
</Link>
</NavbarBrand>
</NavbarContent>

<NavbarContent className="hidden sm:flex gap-4" justify="end">
{isLoaded && (
<>
{menuItems.map((link, index) => (
<NavbarItem
data-testid={`navbar-item-${link.testId}`}
key={`${link.name}-${index}`}
isActive={pathname.includes(link.href)}
>
<Link className="w-full" href={link.href}>
{link.name}
</Link>
</NavbarItem>
))}
<NavbarItem
data-testid="navbar-login"
isActive={pathname.includes("/sign-in")}
className="min-w-[32px]"
>
<SignedIn>
<UserButton />
</SignedIn>
<SignedOut>
<Link href={"/sign-in"}>Login</Link>
</SignedOut>
</NavbarItem>
</>
)}
</NavbarContent>

<>
<NavbarContent className="sm:hidden" justify="end">
<NavbarMenuToggle
data-testid="menu-toggle"
Expand Down Expand Up @@ -153,6 +67,7 @@ const Header: FC = () => {
>
<Link
href={link.href}
onClick={() => setIsMenuOpen(false)}
className="block w-full text-lg font-medium text-gray-800"
>
{link.name}
Expand Down Expand Up @@ -182,8 +97,8 @@ const Header: FC = () => {
</SignedOut>
</NavbarMenuItem>
</NavbarMenu>
</Navbar>
</>
);
};

export default Header;
export default MobileNavbarContent;
70 changes: 70 additions & 0 deletions _components/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"use client";

import { FC, useEffect, useState } from "react";
import { useUser } from "@clerk/nextjs";
import { Navbar } from "@nextui-org/react";
import DesktopNavbarContent from "@/_components/Header/DesktopNavbarContent";
import Logo from "@/_components/Header/Logo";
import MobileNavbarContent from "@/_components/Header/MobileNavbarContent";
import {
adminLinks,
authenticatedLinks,
unauthenticatedLinks,
} from "@/_lib/constants";

const Header: FC = () => {
const { isSignedIn, isLoaded, user } = useUser();
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [menuItems, setMenuItems] = useState([...unauthenticatedLinks]);

useEffect(() => {
if (!isLoaded) return;

if (isSignedIn) {
const isAdmin = user?.publicMetadata.role === "admin";
setMenuItems(() => [
...unauthenticatedLinks,
...authenticatedLinks,
...(isAdmin ? adminLinks : []),
]);
} else {
setMenuItems([...unauthenticatedLinks]);
}
}, [isLoaded, user, isSignedIn]);

return (
<Navbar
data-testid="navbar"
onMenuOpenChange={setIsMenuOpen}
isMenuOpen={isMenuOpen}
isBordered
maxWidth="xl"
classNames={{
item: [
"flex",
"relative",
"h-full",
"items-center",
"data-[active=true]:after:content-['']",
"data-[active=true]:after:absolute",
"data-[active=true]:after:bottom-0",
"data-[active=true]:after:left-0",
"data-[active=true]:after:right-0",
"data-[active=true]:after:h-[2px]",
"data-[active=true]:after:rounded-[2px]",
"data-[active=true]:after:bg-primary",
],
}}
>
<Logo setIsMenuOpen={setIsMenuOpen} />
<MobileNavbarContent
isMenuOpen={isMenuOpen}
menuItems={menuItems}
setIsMenuOpen={setIsMenuOpen}
/>
<DesktopNavbarContent isLoaded={isLoaded} menuItems={menuItems} />
</Navbar>
);
};

export default Header;
2 changes: 1 addition & 1 deletion tests/components/header.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { test, expect } from "@playwright/test";

test.describe("Header Component", () => {
test.describe("Index Component", () => {
// Tests for Desktop
test.describe("Desktop MenuItems", () => {
test.beforeEach(async ({ page }) => {
Expand Down

0 comments on commit bf74870

Please sign in to comment.