118 lines
3.7 KiB
TypeScript
118 lines
3.7 KiB
TypeScript
import React, { useEffect, useState } from 'react'
|
|
import { mdiMinus, mdiPlus } from '@mdi/js'
|
|
import BaseIcon from './BaseIcon'
|
|
import Link from 'next/link'
|
|
import { getButtonColor } from '../colors'
|
|
import AsideMenuList from './AsideMenuList'
|
|
import { MenuAsideItem } from '../interfaces'
|
|
import { useAppSelector } from '../stores/hooks'
|
|
import { useRouter } from 'next/router'
|
|
|
|
type Props = {
|
|
item: MenuAsideItem
|
|
isDropdownList?: boolean
|
|
}
|
|
|
|
const AsideMenuItem = ({ item, isDropdownList = false }: Props) => {
|
|
const [isLinkActive, setIsLinkActive] = useState(false)
|
|
const [isDropdownActive, setIsDropdownActive] = useState(Boolean(item.isOpenByDefault))
|
|
|
|
const asideMenuItemStyle = useAppSelector((state) => state.style.asideMenuItemStyle)
|
|
const asideMenuItemActiveStyle = useAppSelector((state) => state.style.asideMenuItemActiveStyle)
|
|
const borders = useAppSelector((state) => state.style.borders);
|
|
const activeLinkColor = useAppSelector(
|
|
(state) => state.style.activeLinkColor,
|
|
);
|
|
const activeClassAddon = !item.color && isLinkActive ? asideMenuItemActiveStyle : ''
|
|
|
|
const { asPath, isReady } = useRouter()
|
|
|
|
useEffect(() => {
|
|
if (item.href && isReady) {
|
|
const linkPathName = new URL(item.href, location.href).pathname + '/';
|
|
const activePathname = new URL(asPath, location.href).pathname
|
|
|
|
const activeView = activePathname.split('/')[1];
|
|
const linkPathNameView = linkPathName.split('/')[1];
|
|
|
|
setIsLinkActive(linkPathNameView === activeView);
|
|
}
|
|
|
|
if (item.menu && isReady) {
|
|
const activePathname = new URL(asPath, location.href).pathname
|
|
const activeView = activePathname.split('/')[1];
|
|
const hasActiveChild = item.menu.some((menuItem) => {
|
|
if (!menuItem.href) {
|
|
return false;
|
|
}
|
|
|
|
const childPathName = new URL(menuItem.href, location.href).pathname + '/';
|
|
const childView = childPathName.split('/')[1];
|
|
return childView === activeView;
|
|
});
|
|
|
|
if (hasActiveChild) {
|
|
setIsDropdownActive(true);
|
|
}
|
|
}
|
|
}, [item.href, isReady, asPath])
|
|
|
|
const asideMenuItemInnerContents = (
|
|
<>
|
|
{item.icon && (
|
|
<BaseIcon path={item.icon} className={`flex-none ${activeClassAddon}`} size="18" />
|
|
)}
|
|
<span
|
|
className={`min-w-0 flex-1 whitespace-normal break-words leading-5 ${activeClassAddon}`}
|
|
>
|
|
{item.label}
|
|
</span>
|
|
{item.menu && (
|
|
<BaseIcon
|
|
path={isDropdownActive ? mdiMinus : mdiPlus}
|
|
className={`flex-none ${activeClassAddon}`}
|
|
w="w-5"
|
|
/>
|
|
)}
|
|
</>
|
|
)
|
|
|
|
const componentClass = [
|
|
'flex min-w-0 cursor-pointer items-center gap-3 rounded-lg px-3 py-2.5 transition-colors',
|
|
isDropdownList ? 'text-sm' : 'text-[15px] font-medium',
|
|
item.color
|
|
? getButtonColor(item.color, false, true)
|
|
: `${asideMenuItemStyle}`,
|
|
isLinkActive
|
|
? `text-[#0E1A2B] ${activeLinkColor} dark:text-white dark:bg-dark-800`
|
|
: '',
|
|
].join(' ');
|
|
|
|
return (
|
|
<li className={isDropdownList ? 'px-0 py-1' : 'px-3 py-1'}>
|
|
{item.withDevider && <hr className={`${borders} mb-3`} />}
|
|
{item.href && (
|
|
<Link href={item.href} target={item.target} className={componentClass}>
|
|
{asideMenuItemInnerContents}
|
|
</Link>
|
|
)}
|
|
{!item.href && (
|
|
<div className={componentClass} onClick={() => setIsDropdownActive(!isDropdownActive)}>
|
|
{asideMenuItemInnerContents}
|
|
</div>
|
|
)}
|
|
{item.menu && (
|
|
<AsideMenuList
|
|
menu={item.menu}
|
|
className={`mb-2 ml-7 mt-1 border-l border-[#DDD5C7] pl-3 dark:border-slate-700 ${
|
|
isDropdownActive ? 'block' : 'hidden'
|
|
}`}
|
|
isDropdownList
|
|
/>
|
|
)}
|
|
</li>
|
|
)
|
|
}
|
|
|
|
export default AsideMenuItem
|