import React from "react" import { graphql, useStaticQuery } from "gatsby" import { useLocation } from "@reach/router" import { twMerge } from "tailwind-merge" import { ChevronRightIcon, ChevronDownIcon } from "@heroicons/react/solid" import { Link, isBrowser } from "@onegeo-suite/gatsby-theme-onegeo" import { UserMenu } from "@onegeo-suite/gatsby-plugin-auth" interface Imenu { className?: string name: string userMenu?: boolean options: any } const Menu = (props: Imenu) => { const { className, name, userMenu = false } = props const location = useLocation() const data = useStaticQuery(graphql` fragment MenuItem on DirectusData_menus { sort name type url page { slug } options } fragment MenusRecursive on DirectusData_menus { children(filter: { status: { _eq: "published" } }, sort: "sort") { ...MenuItem children( filter: { status: { _eq: "published" } } sort: "sort" ) { ...MenuItem children( filter: { status: { _eq: "published" } } sort: "sort" ) { ...MenuItem } } } } query Menus { directus { menus( filter: { status: { _eq: "published" } parent_id: { id: { _null: true } } } sort: "sort" ) { sort name options ...MenusRecursive } } } `) const menuContent = data.directus.menus const menuSelected = menuContent.find( (menu: any) => name?.toLowerCase() === menu.name?.toLowerCase() ) // const options = props.options ?? (menuSelected?.options || {}) const options = menuSelected?.options || {} const oClass = options.class || {} const oItem = oClass.items || {} const oSubitem = oClass.subitems || {} const menu = menuSelected?.children || [] const goto = (item) => { if (!item) return "" if (item?.type === "none") return "" if (item?.type === "page") { const slug = item?.page?.slug || "" if (slug.at(0) === "/") return slug return "/" + slug } return item?.url || "" } const isActive = (item) => { // Get last part of item url without '/' const url = goto(item) .split("/") .filter((entry) => entry !== "") .at(-1) || "" // console.log("isActive url", goto(item), "(", url, ")") // manage default style at build time and style at run time const pathname = isBrowser ? window.location.pathname : location.pathname // Get last part of location pathname without '/' const path = pathname .split("/") .slice(2) // remove first empty entry & pathPrefix .filter((entry) => entry !== "") .at(-1) || "" // console.log("isActive path", pathname, "(", path, ")") return url === path } const subitems = (item: any) => { return ( <ul className={twMerge( "bg-base-100 z-50 p-2 shadow-md", oSubitem.main )} > {item.children.map((itemChild: any, idx: number) => { return ( <li key={"M_" + name + "_L2_" + idx} className={twMerge("", oSubitem.item)} > <Link to={goto(itemChild)} target="_blank" className={twMerge("", oSubitem.link)} > <span className={twMerge("", oSubitem.name)}> {itemChild.name} </span> </Link> </li> ) })} </ul> ) } const items = (item: any) => { return ( <ul className={twMerge( "menu rounded-box bg-base-100 z-50 min-w-[12rem] p-2 shadow-md", oItem.main )} > {item.children.map((itemChild: any, idx: number) => { return ( <li key={"M_" + name + "_L1_" + idx} className={twMerge("", oItem.item)} > <Link to={goto(itemChild)} target="_blank" className={twMerge("", oItem.link)} > <span className={twMerge("grow", oItem.name)}> {itemChild.name} </span> {itemChild?.children.length > 0 && ( <ChevronRightIcon className={twMerge( "h-5 w-5", oItem.icon )} /> )} </Link> {itemChild?.children?.length > 0 && subitems(itemChild)} </li> ) })} </ul> ) } return ( <ul className={twMerge(className, oClass.main)}> {menu?.map((item: any, key: number) => { const isItemActive = isActive(item) return ( <li key={"M_" + name + "_L0_" + key} className={twMerge("", oClass.item)} > <Link to={goto(item)} target="_blank" className={twMerge( "", oClass.link, item.options?.link )} > {/* TODO: option to change active bordered / color / bg */} <span className={twMerge( //"border-b-4 border-transparent", oClass.name, item.options?.name, isItemActive ? //border-primary twMerge( "text-primary font-semibold", oClass.active ) : "" )} > {item.name} </span> {item.children?.length > 0 && ( <ChevronDownIcon className={twMerge("h-5 w-5", oClass.icon)} /> )} </Link> {item.children?.length > 0 && items(item)} </li> ) })} {userMenu ? <UserMenu /> : null} </ul> ) } export default Menu