Skip to content
Snippets Groups Projects
Menu.tsx 8.07 KiB
Newer Older
Toavina's avatar
Toavina committed
import React from "react"
import { graphql, useStaticQuery } from "gatsby"
Julien MARGAIL's avatar
Julien MARGAIL committed
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"
Tojo's avatar
Tojo committed

interface Imenu {
    className?: string
Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed
    name: string
    userMenu?: boolean
Manoa Harinjo's avatar
Manoa Harinjo committed
    options: any
Manoa Harinjo's avatar
Manoa Harinjo committed

const Menu = (props: Imenu) => {
Manoa Harinjo's avatar
Manoa Harinjo committed
    const { className, name, userMenu = false } = props
Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed

Julien MARGAIL's avatar
Julien MARGAIL committed
    const location = useLocation()

Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed
    const data = useStaticQuery(graphql`
        fragment MenuItem on DirectusData_menus {
Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed
            name
Julien MARGAIL's avatar
Julien MARGAIL committed
            type
Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed
            url
            page {
                slug
            }
Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed
        }

        fragment MenusRecursive on DirectusData_menus {
            children(filter: { status: { _eq: "published" } }, sort: "sort") {
Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed
                ...MenuItem
                children(
                    filter: { status: { _eq: "published" } }
                    sort: "sort"
                ) {
Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed
                    ...MenuItem
                    children(
                        filter: { status: { _eq: "published" } }
                        sort: "sort"
                    ) {
Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed
                        ...MenuItem
                    }
                }
            }
        }

Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed
            directus {
Manoa Harinjo's avatar
Manoa Harinjo committed
                menus(
                    filter: {
                        status: { _eq: "published" }
                        parent_id: { id: { _null: true } }
Manoa Harinjo's avatar
Manoa Harinjo committed
                    }
Manoa Harinjo's avatar
Manoa Harinjo committed
                ) {
Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed
                    name
Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed
                    ...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 || {}
Manoa Harinjo's avatar
Manoa Harinjo committed
    const oClass = options.class || {}
    const oItem = oClass.items || {}
    const oSubitem = oClass.subitems || {}
Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed

    const menu = menuSelected?.children || []
Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed

Julien MARGAIL's avatar
Julien MARGAIL committed
    const goto = (item) => {
        if (!item) return ""
        if (item?.type === "none") return ""
Julien MARGAIL's avatar
Julien MARGAIL committed
        if (item?.type === "page") {
            const slug = item?.page?.slug || ""
            if (slug.at(0) === "/") return slug
            return "/" + slug
        }
        return item?.url || ""
Julien MARGAIL's avatar
Julien MARGAIL committed
    }
Manoa Harinjo's avatar
Manoa Harinjo committed
    const isActive = (item) => {
Julien MARGAIL's avatar
Julien MARGAIL committed
        // 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
Manoa Harinjo's avatar
Manoa Harinjo committed

        // Get last part of location pathname without '/'
Julien MARGAIL's avatar
Julien MARGAIL committed
        const path =
            pathname
                .split("/")
                .slice(2) // remove first empty entry & pathPrefix
                .filter((entry) => entry !== "")
                .at(-1) || ""
Manoa Harinjo's avatar
Manoa Harinjo committed

Julien MARGAIL's avatar
Julien MARGAIL committed
        // console.log("isActive path", pathname, "(", path, ")")
Manoa Harinjo's avatar
Manoa Harinjo committed

        return url === path
    }

    const subitems = (item: any) => {
Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed
        return (
Manoa Harinjo's avatar
Manoa Harinjo committed
            <ul
                className={twMerge(
                    "bg-base-100 z-50 p-2 shadow-md",
                    oSubitem.main
                )}
            >
Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed
                {item.children.map((itemChild: any, idx: number) => {
                    return (
Manoa Harinjo's avatar
Manoa Harinjo committed
                        <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 (
Manoa Harinjo's avatar
Manoa Harinjo committed
            <ul
                className={twMerge(
Julien MARGAIL's avatar
Julien MARGAIL committed
                    "menu rounded-box bg-base-100 z-50 min-w-[12rem] p-2 shadow-md",
Manoa Harinjo's avatar
Manoa Harinjo committed
                    oItem.main
                )}
            >
                {item.children.map((itemChild: any, idx: number) => {
                    return (
Manoa Harinjo's avatar
Manoa Harinjo committed
                        <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 && (
Manoa Harinjo's avatar
Manoa Harinjo committed
                                    <ChevronRightIcon
                                        className={twMerge(
                                            "h-5 w-5",
                                            oItem.icon
                                        )}
                                    />
Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed
                            </Link>
Julien MARGAIL's avatar
Julien MARGAIL committed
                            {itemChild?.children?.length > 0 &&
                                subitems(itemChild)}
Tojo Andrianomentsoaniaina's avatar
Tojo Andrianomentsoaniaina committed
                        </li>
                    )
                })}
            </ul>
        )
    }
Tojo's avatar
Tojo committed

Toavina's avatar
Toavina committed
    return (
Manoa Harinjo's avatar
Manoa Harinjo committed
        <ul className={twMerge(className, oClass.main)}>
            {menu?.map((item: any, key: number) => {
Julien MARGAIL's avatar
Julien MARGAIL committed
                const isItemActive = isActive(item)
Manoa Harinjo's avatar
Manoa Harinjo committed
                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,
Julien MARGAIL's avatar
Julien MARGAIL committed
                                    isItemActive
Manoa Harinjo's avatar
Manoa Harinjo committed
                                        ? //border-primary
                                          twMerge(
                                              "text-primary font-semibold",
                                              oClass.active
                                          )
                                        : ""
Toavina's avatar
Toavina committed
                                )}
Manoa Harinjo's avatar
Manoa Harinjo committed
                            >
                                {item.name}
                            </span>
Manoa Harinjo's avatar
Manoa Harinjo committed
                            {item.children?.length > 0 && (
                                <ChevronDownIcon
                                    className={twMerge("h-5 w-5", oClass.icon)}
                                />
Manoa Harinjo's avatar
Manoa Harinjo committed
                            )}
                        </Link>
                        {item.children?.length > 0 && items(item)}
                    </li>
                )
            })}
            {userMenu ? <UserMenu /> : null}
        </ul>
Tojo's avatar
Tojo committed

Toavina's avatar
Toavina committed
export default Menu