You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nx-guitar-school/apps/website/components/header/header.tsx

229 lines
10 KiB

import {Collapse, Dropdown} from "flowbite";
import {useEffect} from "react";
import delve from "dlv";
import {signOut, useSession} from "next-auth/react";
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
import {getBackendImg, hasAvatar} from "../../libs/api";
import {faBagShopping, faRightToBracket, faUserPlus} from "@fortawesome/free-solid-svg-icons";
import {siteConfig} from "../../config";
export function Header({items = []}) {
const {data: session} = useSession();
useEffect(() => {
if (session == null) {
return;
}
}, [session]);
useEffect(function mount() {
const menuButton = document.getElementById('menu-dropdown-button');
const menuZone = document.getElementById('menu-dropdown');
if (menuButton && menuZone) {
new Dropdown(menuZone, menuButton);
}
const userButton = document.getElementById('user-menu-button');
const userZone = document.getElementById('user-dropdown');
if (userButton && userZone) {
new Dropdown(userZone, userButton);
}
const burgerButton = document.getElementById('menu-button');
const megaZone = document.getElementById('navbar-dropdown');
if (burgerButton && megaZone) {
new Collapse(megaZone, burgerButton);
}
});
const renderGenerateItem = (item, index, isActive = false) => {
const value = delve(item, 'attributes', {});
return (
<li key={value.title + index}>
{value.children.data.length > 0 ? renderDropdownItem(value, isActive) : renderRegularItem(value, isActive)}
</li>
);
}
const renderRegularItem = (item, isActive = false) => {
return (
<a href={item.url}
target={item.target}
className={"text-gray-900 hover:text-blue-600 dark:text-gray-400 dark:hover:bg-transparent dark:hover:text-gray-500 " + (isActive ? 'text-blue-600 dark:text-gray-500' : '') + " block py-2 pl-3 pr-4 border-b border-gray-100 hover:bg-gray-50 md:hover:bg-transparent md:border-0 md:p-0"}
aria-current="page">{item.title}</a>
)
}
const renderRegularDropdownItem = (item, index) => {
const value = delve(item, 'attributes', {});
return (
<li key={value.title + index}>
<a href={value.url}
className="text-gray-900 dark:text-gray-400 hover:text-blue-600 dark:hover:text-gray-500">
{value.title}
</a>
</li>
);
}
const renderDropdownItem = (item, isActive = false) => {
return (
<>
<button id="menu-dropdown-button"
data-dropdown-toggle="mega-menu-dropdown"
className={"flex items-center justify-between w-full py-2 pl-3 pr-4 text-gray-900 dark:text-gray-400 " + (isActive ? 'text-blue-600 dark:text-gray-500' : '') + " font-medium border-b border-gray-100 md:w-auto hover:bg-gray-50 md:p-0 dark:border-transparent dark:hover:bg-transparent dark:hover:text-gray-500"}>
{item.title}
<svg aria-hidden="true"
className="w-5 h-5 ml-1 md:w-4 md:h-4"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clipRule="evenodd"></path>
</svg>
</button>
<div id="menu-dropdown"
className="absolute z-10 grid hidden w-auto text-sm bg-white border border-gray-100 rounded-lg shadow-md dark:border-gray-700 dark:bg-gray-700">
<div className="p-4 pb-0 text-gray-900 md:pb-4 dark:text-white">
<ul className="space-y-4" aria-labelledby="mega-menu-dropdown-button">
{item.children.data.map((children, index) => renderRegularDropdownItem(children, index))}
</ul>
</div>
</div>
</>
)
}
const renderAnonymousUser = () => {
return (
<>
<a href="/sign-in"
className="text-gray-800 dark:text-white hover:bg-gray-50 focus:ring-4 focus:ring-gray-300 font-medium rounded-lg text-sm px-4 py-2 md:px-5 md:py-2.5 mr-1 md:mr-2 dark:hover:bg-gray-700 focus:outline-none dark:focus:ring-gray-800">
<span className="hidden lg:block">Connexion</span>
<span className="block lg:hidden">
<FontAwesomeIcon icon={faRightToBracket}/>
</span>
</a>
<a href="/sign-up"
className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2 md:px-5 md:py-2.5 mr-1 md:mr-2 dark:bg-dark-600 dark:hover:bg-dark-500 focus:outline-none dark:focus:ring-blue-800">
<span className="hidden lg:block">Inscription</span>
<span className="block lg:hidden">
<FontAwesomeIcon icon={faUserPlus}/>
</span>
</a>
</>
);
}
const renderConnectedUser = () => {
return (
<>
<button type="button"
className="flex mr-3 text-sm bg-gray-800 rounded-full md:mr-0 focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600"
id="user-menu-button"
aria-expanded="false"
data-dropdown-toggle="user-dropdown"
data-dropdown-placement="bottom">
<span className="sr-only">Open user menu</span>
<img className="w-8 h-8 rounded-full"
src={hasAvatar((session.user as any)) ? getBackendImg((session.user as any).avatar.formats.thumbnail.url) : siteConfig.defaultUserAvatar}
alt="user photo"/>
</button>
<div
className="z-50 hidden my-4 text-base list-none bg-white divide-y divide-gray-100 rounded shadow dark:bg-gray-700 dark:divide-gray-600"
id="user-dropdown">
<div className="px-4 py-3">
<span className="block text-sm text-gray-900 dark:text-white">{(session.user as any).username}</span>
<span
className="block text-sm font-medium text-gray-500 truncate dark:text-gray-400">{session.user.email}</span>
</div>
<ul className="py-1" aria-labelledby="user-menu-button">
<li>
<a href="#"
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">
Dashboard
</a>
</li>
<li>
<a href="#"
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">
Settings
</a>
</li>
<li>
<a href="#"
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">
Earnings
</a>
</li>
<li>
<a href="#"
// @ts-ignore
onClick={signOut}
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">
Sign out
</a>
</li>
</ul>
</div>
</>
);
}
return (
<nav
className="bg-white fixed border-gray-200 rounded dark:bg-gray-800 w-full z-10 border-b-2 border-b-gray-50 dark:border-b-gray-700">
<div className="flex mx-auto">
<main className="w-full">
<section
className="bg-white dark:bg-gray-900 w-full md:w-auto p-2 md:p-4"
id="navbar-default">
<div className="container max-w-screen-xl flex flex-wrap items-center justify-between mx-auto">
<a href="/" className="flex items-center">
<img src="https://flowbite.com/docs/images/logo.svg" className="h-6 mr-3 sm:h-9" alt="Flowbite Logo"/>
<span className="self-center text-xl font-semibold whitespace-nowrap dark:text-white">Flowbite</span>
</a>
<div className="flex items-center">
<button
className="text-gray-700 border border-transparent hover:bg-gray-200 hover:text-white focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm p-2.5 text-center inline-flex items-center mr-2 dark:text-blue-500 dark:hover:text-white dark:focus:ring-blue-800">
<FontAwesomeIcon icon={faBagShopping}/>
</button>
{session ? renderConnectedUser() : renderAnonymousUser()}
<button id="menu-button"
data-collapse-toggle="navbar-sticky"
type="button"
className="inline-flex items-center p-2 text-sm text-gray-500 rounded-lg md:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600"
aria-controls="navbar-sticky"
aria-expanded="false">
<span className="sr-only">Open main menu</span>
<svg className="w-6 h-6" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd"
d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 15a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z"
clipRule="evenodd"></path>
</svg>
</button>
</div>
</div>
</section>
<hr className="border-gray-100 sm:mx-auto dark:border-gray-700 container mx-auto"/>
<section className="hidden w-full md:block md:w-auto" id="navbar-dropdown">
<div className="container max-w-screen-xl mx-auto">
<ul className="flex flex-col md:p-4 font-medium md:flex-row md:space-x-8 md:mt-0">
{items.map((item, index: number) => renderGenerateItem(item, index))}
</ul>
</div>
</section>
<hr className="border-gray-100 sm:mx-auto dark:border-gray-700"/>
</main>
</div>
</nav>
);
}
export default Header;