Merge pull request #24 from aaronpo97/navbar-update

Update navbar, implement useNavbar hook, style updates
This commit is contained in:
Aaron Po
2023-04-15 22:20:55 -04:00
committed by GitHub
6 changed files with 147 additions and 109 deletions

View File

@@ -1,54 +1,15 @@
/* eslint-disable jsx-a11y/no-noninteractive-tabindex */
/* eslint-disable jsx-a11y/label-has-associated-control */
/* eslint-disable jsx-a11y/label-has-for */
import UserContext from '@/contexts/userContext';
import useMediaQuery from '@/hooks/useMediaQuery';
import useNavbar from '@/hooks/useNavbar';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { useContext, useEffect, useState } from 'react';
import { FC } from 'react';
interface Page {
slug: string;
name: string;
}
const Navbar = () => {
const router = useRouter();
const [currentURL, setCurrentURL] = useState('/');
import { GiHamburgerMenu } from 'react-icons/gi';
const { user } = useContext(UserContext);
useEffect(() => {
setCurrentURL(router.asPath);
}, [router.asPath]);
const authenticatedPages: readonly Page[] = [
{ slug: '/account', name: 'Account' },
{ slug: '/api/users/logout', name: 'Logout' },
];
const unauthenticatedPages: readonly Page[] = [
{ slug: '/login', name: 'Login' },
{ slug: '/register', name: 'Register' },
];
const otherPages: readonly Page[] = [
{ slug: '/beers', name: 'Beers' },
{ slug: '/breweries', name: 'Breweries' },
];
const pages: readonly Page[] = [
...otherPages,
...(user ? authenticatedPages : unauthenticatedPages),
];
const DesktopLinks: FC = () => {
const { pages, currentURL } = useNavbar();
return (
<nav className="navbar sticky top-0 z-50 bg-primary text-primary-content">
<div className="flex-1">
<Link className="btn-ghost btn normal-case" href="/">
<span className="cursor-pointer text-lg font-bold">The Biergarten App</span>
</Link>
</div>
<div className="hidden flex-none lg:block">
<div className="block flex-none">
<ul className="menu menu-horizontal p-0">
{pages.map((page) => {
return (
@@ -67,24 +28,16 @@ const Navbar = () => {
})}
</ul>
</div>
);
};
const MobileLinks: FC = () => {
const { pages } = useNavbar();
return (
<div className="flex-none lg:hidden">
<div className="dropdown dropdown-end">
<div className="dropdown-end dropdown">
<label tabIndex={0} className="btn-ghost btn-circle btn">
<span className="w-10 rounded-full">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
className="inline-block h-5 w-5 stroke-white"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M4 6h16M4 12h16M4 18h16"
/>
</svg>
</span>
<GiHamburgerMenu />
</label>
<ul
tabIndex={0}
@@ -100,6 +53,20 @@ const Navbar = () => {
</ul>
</div>
</div>
);
};
const Navbar = () => {
const isDesktopView = useMediaQuery('(min-width: 1024px)');
return (
<nav className="navbar sticky top-0 z-50 bg-primary text-primary-content">
<div className="flex-1">
<Link className="btn-ghost btn normal-case" href="/">
<span className="cursor-pointer text-lg font-bold">The Biergarten App</span>
</Link>
</div>
<div>{isDesktopView ? <DesktopLinks /> : <MobileLinks />}</div>
</nav>
);
};

64
src/hooks/useNavbar.ts Normal file
View File

@@ -0,0 +1,64 @@
import UserContext from '@/contexts/userContext';
import { useRouter } from 'next/router';
import { useState, useEffect, useContext } from 'react';
interface Page {
slug: string;
name: string;
}
/**
* A custom hook that returns the current URL and the pages to display in the navbar. It
* uses the user context to determine whether the user is authenticated or not.
*
* @returns An object containing the current URL and the pages to display in the navbar.
*/
const useNavbar = () => {
const router = useRouter();
const [currentURL, setCurrentURL] = useState('/');
const { user } = useContext(UserContext);
const authenticatedPages: readonly Page[] = [
{ slug: '/account', name: 'Account' },
{ slug: '/api/users/logout', name: 'Logout' },
];
const unauthenticatedPages: readonly Page[] = [
{ slug: '/login', name: 'Login' },
{ slug: '/register', name: 'Register' },
];
/** These pages are accessible to both authenticated and unauthenticated users. */
const otherPages: readonly Page[] = [
{ slug: '/beers', name: 'Beers' },
{ slug: '/breweries', name: 'Breweries' },
];
/**
* The pages to display in the navbar. If the user is authenticated, the authenticated
* pages are displayed. Otherwise, the unauthenticated pages are displayed. The other
* pages are always displayed.
*/
const pages: readonly Page[] = [
...otherPages,
...(user ? authenticatedPages : unauthenticatedPages),
];
/**
* Sets the current URL to the current URL when the router's asPath changes. This
* ensures that the current URL is always up to date. When the component unmounts, the
* current URL is set to '/'.
*/
useEffect(() => {
setCurrentURL(router.asPath);
return () => {
setCurrentURL('/');
};
}, [router.asPath]);
return { currentURL, pages };
};
export default useNavbar;

View File

@@ -29,7 +29,7 @@ interface BeerPageProps {
}
const BeerByIdPage: NextPage<BeerPageProps> = ({ beerPost, beerRecommendations }) => {
const isMd = useMediaQuery('(min-width: 768px)');
const isDesktop = useMediaQuery('(min-width: 1024px)');
return (
<>
@@ -64,7 +64,7 @@ const BeerByIdPage: NextPage<BeerPageProps> = ({ beerPost, beerRecommendations }
<div className="w-11/12 space-y-3 xl:w-9/12">
<BeerInfoHeader beerPost={beerPost} />
{isMd ? (
{isDesktop ? (
<div className="mt-4 flex flex-row space-x-3 space-y-0">
<div className="w-[60%]">
<BeerPostCommentsSection beerPost={beerPost} />
@@ -75,12 +75,12 @@ const BeerByIdPage: NextPage<BeerPageProps> = ({ beerPost, beerRecommendations }
</div>
) : (
<Tab.Group>
<Tab.List className="card flex flex-row bg-base-300">
<Tab className="ui-selected:bg-gray w-1/2 p-3 uppercase">
<Tab.List className="tabs tabs-boxed items-center justify-center rounded-2xl bg-base-300">
<Tab className="tab tab-lg w-1/2 uppercase ui-selected:tab-active">
Comments
</Tab>
<Tab className="ui-selected:bg-gray w-1/2 p-3 uppercase">
Recommendations
<Tab className="tab tab-lg w-1/2 uppercase ui-selected:tab-active">
Other Beers
</Tab>
</Tab.List>
<Tab.Panels className="mt-2">

View File

@@ -5,29 +5,33 @@ import UserContext from '@/contexts/userContext';
import { GetServerSideProps, NextPage } from 'next';
import { useContext } from 'react';
import useMediaQuery from '@/hooks/useMediaQuery';
const ProtectedPage: NextPage = () => {
const { user, isLoading } = useContext(UserContext);
const currentTime = new Date().getHours();
const isMorning = currentTime > 4 && currentTime < 12;
const isAfternoon = currentTime > 12 && currentTime < 18;
const isEvening = (currentTime > 18 && currentTime < 24) || currentTime < 4;
const isMorning = currentTime >= 3 && currentTime < 12;
const isAfternoon = currentTime >= 12 && currentTime < 18;
const isEvening = currentTime >= 18 || currentTime < 3;
const isDesktop = useMediaQuery('(min-width: 768px)');
return (
<Layout>
<div className="flex h-full flex-col items-center justify-center space-y-3">
{isLoading && <Spinner size="xl" />}
{user && (
<div className="flex h-full flex-col items-center justify-center space-y-3 text-center">
{isLoading && <Spinner size={isDesktop ? 'xl' : 'md'} />}
{user && !isLoading && (
<>
<h1 className="text-7xl font-bold">
<h1 className="text-2xl font-bold lg:text-7xl">
Good {isMorning && 'morning'}
{isAfternoon && 'afternoon'}
{isEvening && 'evening'}
{`, ${user?.firstName}!`}
</h1>
<h2 className="text-4xl font-bold">Welcome to the Biergarten App!</h2>
<h2 className="text-xl font-bold lg:text-4xl">
Welcome to the Biergarten App!
</h2>
</>
)}
</div>

View File

@@ -1,3 +1,7 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
.card {
@apply shadow-md
}

View File

@@ -1,6 +1,6 @@
//themes
const myTheme = {
const darkTheme = {
default: {
primary: 'hsl(227, 23%, 20%)',
secondary: 'hsl(255, 9%, 69%)',
@@ -20,7 +20,7 @@ const myTheme = {
const pastelTheme = {
default: {
primary: 'hsl(180, 28%, 65%)',
primary: 'hsl(180, 15%, 60%)',
secondary: 'hsl(21, 54%, 83%)',
error: 'hsl(4, 87%, 74%)',
accent: 'hsl(93, 27%, 73%)',
@@ -33,7 +33,6 @@ const pastelTheme = {
'base-100': 'hsl(0, 0%, 85%)',
'base-200': 'hsl(0, 0%, 82%)',
'base-300': 'hsl(0, 0%, 78%)',
'base-400': 'hsl(0, 0%, 75%)',
},
};
@@ -55,6 +54,6 @@ module.exports = {
daisyui: {
logs: false,
themes: [myTheme],
themes: [darkTheme, pastelTheme],
},
};