|
import React, { useState, useEffect, useMemo } from "react"; |
|
import { Link, useLocation } from "react-router-dom"; |
|
import cn from "classnames"; |
|
import { Icon } from "antd"; |
|
|
|
import { ArrowNav } from "../../NavSVGS"; |
|
|
|
import s from "./style.scss"; |
|
|
|
interface Props { |
|
id: string; |
|
label: string; |
|
icon: string | React.ReactNode | null; |
|
link: string | null; |
|
isRoot: boolean | null; |
|
data: IMenuItems; |
|
} |
|
|
|
|
|
interface IMenuItems { |
|
id: string; |
|
label: string; |
|
icon?: string | React.ReactNode; |
|
link?: string; |
|
isRoot?: boolean; |
|
nodes: IMenuItems[]; |
|
} |
|
|
|
|
|
function NavItem({ data, id, label, link, icon, isRoot }: Props) { |
|
const [open, setOpen] = useState<boolean>(false); |
|
const { pathname } = useLocation(); |
|
|
|
useEffect(() => { |
|
setOpen(() => { |
|
if (isRoot && pathname.includes(id)) return true; |
|
return ( |
|
data.nodes.some(item => item.link === pathname) || link === pathname |
|
); |
|
}); |
|
}, []); |
|
|
|
const isActive = useMemo(() => { |
|
return link === pathname; |
|
}, [link, pathname]); |
|
|
|
function generateIcon(icon: any) { |
|
if (typeof icon === "string") { |
|
return <Icon type={icon} />; |
|
} |
|
return <Icon component={icon} />; |
|
} |
|
|
|
return ( |
|
<li |
|
className={cn(s.listItem, { |
|
[s.listItemActive as string]: open && isRoot && data.nodes.length, |
|
})} |
|
> |
|
<div |
|
className={cn(s.listItemLabelContainer, { |
|
[s.listItemLabelContainer_root as string]: isRoot, |
|
[s.listItemLabelContainer_root_active as string]: |
|
(isRoot && open && data.nodes.length) || |
|
(isRoot && isActive && !data.nodes.length), |
|
})} |
|
> |
|
{generateIcon(icon)} |
|
<span onClick={() => setOpen(!open)} className={s.listItemLabel}> |
|
{Boolean(!isRoot && data.nodes.length) && ( |
|
<span className={open ? s.arrowNavOpen : s.arrowNavClose}> |
|
<ArrowNav /> |
|
</span> |
|
)} |
|
|
|
{link ? ( |
|
<Link |
|
to={link} |
|
className={cn({ |
|
[s.linkActive as string]: isActive && !isRoot, |
|
})} |
|
> |
|
{label} |
|
</Link> |
|
) : ( |
|
label |
|
)} |
|
</span> |
|
</div> |
|
{Boolean(open && data.nodes.length) && ( |
|
<ul className={s.list}> |
|
{data.nodes.map(d => ( |
|
<NavItem |
|
key={d.label} |
|
data={d} |
|
id={d.id} |
|
label={d.label} |
|
link={d.link ?? null} |
|
icon={d.icon ?? null} |
|
isRoot={d.isRoot ?? null} |
|
/> |
|
))} |
|
</ul> |
|
)} |
|
</li> |
|
); |
|
} |
|
|
|
export default NavItem; |