191 lines
5.5 KiB
TypeScript
191 lines
5.5 KiB
TypeScript
'use client'
|
|
|
|
import styles from './styles.module.scss'
|
|
import MenuIcon from './menu.svg'
|
|
import Image from 'next/image'
|
|
import classNames from 'classnames'
|
|
import { MegaMenuItemProps, Menu as MenuType, MenuItem as MenuItemType, SimpleItemProps } from './menu.types'
|
|
import { Logo } from '@/components/Logo/Logo'
|
|
import { Fragment, useCallback, useState } from 'react'
|
|
import { MegaMenu } from '@/components/MegaMenu/MegaMenu'
|
|
import { CollapsibleArrow } from '@/components/CollapsibleArrow/CollapsibleArrow'
|
|
import Link from 'next/link'
|
|
|
|
/**
|
|
* Represents a simple item component.
|
|
*
|
|
* @param {Object} SimpleItemProps - The properties for the SimpleItem component.
|
|
* @param {string} SimpleItemProps.text - The text to display for the item.
|
|
* @param {string} SimpleItemProps.href - The URL to navigate to when the item is clicked.
|
|
* @param {string} SimpleItemProps.type - The type of the item ("default" or "button").
|
|
* @param {function} SimpleItemProps.onItemClick - The function to call when the item is clicked.
|
|
* @returns {JSX.Element} A Link component with the specified text, href, type, and onItemClick function.
|
|
*/
|
|
const SimpleItem = ({text, href, type, onItemClick}: SimpleItemProps) => {
|
|
const className = classNames({
|
|
[styles.menuLink]: type === "default",
|
|
[styles.button]: type === "button"
|
|
});
|
|
|
|
return (
|
|
<span>
|
|
<Link
|
|
className={className}
|
|
href={href}
|
|
onClick={onItemClick}
|
|
>
|
|
{text}
|
|
</Link>
|
|
</span>
|
|
)
|
|
}
|
|
|
|
|
|
/**
|
|
* Represents a mega menu item component.
|
|
* @param {Object} MegaMenuItemProps - The props for the MegaMenuItem component.
|
|
* @param {string} MegaMenuItemProps.text - The text to display in the menu item.
|
|
* @param {string} MegaMenuItemProps.quote - The quote to display in the mega menu.
|
|
* @param {string} MegaMenuItemProps.source - The source of the quote.
|
|
* @param {Array<string>} MegaMenuItemProps.groups - The groups associated with the menu item.
|
|
* @param {Function} MegaMenuItemProps.onItemClick - The function to handle item click event.
|
|
* @returns {JSX.Element} A JSX element representing the MegaMenuItem component.
|
|
*/
|
|
const MegaMenuItem = ({text, quote, source, groups, onItemClick}: MegaMenuItemProps) => {
|
|
|
|
const [isActive, setIsActive] = useState<boolean>(false);
|
|
const itemClicked = useCallback(() => {
|
|
setIsActive(false);
|
|
if (onItemClick) {
|
|
onItemClick();
|
|
}
|
|
}, [setIsActive, onItemClick]);
|
|
|
|
return (
|
|
<span
|
|
onMouseEnter={() => setIsActive(true)}
|
|
onMouseLeave={() => setIsActive(false)}
|
|
>
|
|
<Link
|
|
href={""}
|
|
className={styles.menuLink}
|
|
>
|
|
{text} <CollapsibleArrow direction={isActive ? "UP" : "DOWN"} stroke={1.5} />
|
|
</Link>
|
|
|
|
<div
|
|
className={classNames({
|
|
[styles.megaMenu]: true,
|
|
[styles.megaMenuActive]: isActive
|
|
})}
|
|
>
|
|
<MegaMenu
|
|
bibleText={quote}
|
|
bibleBook={source}
|
|
groups={groups}
|
|
onItemClick={itemClicked}
|
|
/>
|
|
</div>
|
|
</span>
|
|
)
|
|
}
|
|
|
|
type MenuItemsProps = {
|
|
items: MenuItemType[]
|
|
onItemClick: () => void
|
|
}
|
|
|
|
/**
|
|
* Renders a list of menu items based on the provided props.
|
|
*
|
|
* @param {Object} items - An array of menu items to render.
|
|
* @param {Function} onItemClick - Callback function to handle item click events.
|
|
*/
|
|
const MenuItems = ({items, onItemClick}: MenuItemsProps) => {
|
|
return (
|
|
<>
|
|
{items.map(item => (
|
|
<Fragment key={item.id}>
|
|
{ item.blockType === "simple-item" &&
|
|
<SimpleItem
|
|
text={item.text}
|
|
href={item.href}
|
|
type={item.type}
|
|
blockType={item.blockType}
|
|
onItemClick={onItemClick}
|
|
/>
|
|
}
|
|
|
|
{
|
|
item.blockType === "mega-menu" &&
|
|
<MegaMenuItem
|
|
text={item.text}
|
|
quote={item.quote}
|
|
source={item.source}
|
|
blockType={item.blockType}
|
|
groups={item.groups}
|
|
onItemClick={onItemClick}
|
|
/>
|
|
}
|
|
</Fragment>
|
|
)
|
|
)}
|
|
</>
|
|
)
|
|
}
|
|
|
|
type MenuProps = {
|
|
menu: MenuType
|
|
}
|
|
|
|
/**
|
|
* Represents a menu component that displays navigation items on the screen.
|
|
* @param {Object} MenuProps - The props object containing menu items for left and right side of the menu.
|
|
* @returns The rendered menu component.
|
|
*/
|
|
export const Menu = ({menu}: MenuProps) => {
|
|
|
|
const [displayMenuMobile, setDisplayMenuMobile] = useState(false)
|
|
|
|
|
|
return (
|
|
<>
|
|
<nav className={classNames(styles.nav, {[styles.full]: displayMenuMobile})}>
|
|
<div className={styles.navMobile}>
|
|
<Link
|
|
href={"/"} onClick={() => setDisplayMenuMobile(false)}
|
|
className={styles.logoLink}
|
|
>
|
|
<Logo withText={false} height={30} color={"#426156"}/>
|
|
</Link>
|
|
<Image
|
|
src={MenuIcon}
|
|
width={25}
|
|
height={25}
|
|
alt={'Menu'}
|
|
onClick={() => setDisplayMenuMobile(!displayMenuMobile)}
|
|
/>
|
|
</div>
|
|
|
|
<div className={classNames(styles.itemsLeft, {[styles.hide]: !displayMenuMobile})}>
|
|
<MenuItems
|
|
items={menu.leftItems}
|
|
onItemClick={() => setDisplayMenuMobile(false)}
|
|
/>
|
|
</div>
|
|
|
|
<div className={classNames(styles.itemsRight, {[styles.hide]: !displayMenuMobile})}>
|
|
<MenuItems
|
|
items={menu.rightItems}
|
|
onItemClick={() => setDisplayMenuMobile(false)}
|
|
/>
|
|
</div>
|
|
|
|
</nav>
|
|
|
|
</>
|
|
|
|
)
|
|
}
|
|
|
|
|