Files
ThriveX-Admin/src/components/Sidebar/index.tsx

313 lines
12 KiB
TypeScript
Raw Normal View History

2024-07-25 18:49:59 +08:00
import React, { useEffect, useRef, useState } from 'react';
import { NavLink, useLocation } from 'react-router-dom';
import SidebarLinkGroup from './SidebarLinkGroup';
import Logo from '../../images/logo/logo.svg';
2024-08-08 15:27:57 +08:00
import { BiEditAlt, BiFolderOpen, BiHomeSmile, BiSliderAlt } from "react-icons/bi";
2024-08-05 02:42:35 +08:00
import { BiCategoryAlt } from "react-icons/bi";
2024-08-14 19:17:32 +08:00
import { LiaRssSolid } from "react-icons/lia";
2024-08-15 16:57:03 +08:00
import { IoIosStats } from "react-icons/io";
2024-07-25 18:49:59 +08:00
interface SidebarProps {
sidebarOpen: boolean;
setSidebarOpen: (arg: boolean) => void;
}
const Sidebar = ({ sidebarOpen, setSidebarOpen }: SidebarProps) => {
const location = useLocation();
const { pathname } = location;
const trigger = useRef<any>(null);
const sidebar = useRef<any>(null);
const storedSidebarExpanded = localStorage.getItem('sidebar-expanded');
const [sidebarExpanded, setSidebarExpanded] = useState(
storedSidebarExpanded === null ? false : storedSidebarExpanded === 'true'
);
// close on click outside
useEffect(() => {
const clickHandler = ({ target }: MouseEvent) => {
if (!sidebar.current || !trigger.current) return;
if (
!sidebarOpen ||
sidebar.current.contains(target) ||
trigger.current.contains(target)
)
return;
setSidebarOpen(false);
};
document.addEventListener('click', clickHandler);
return () => document.removeEventListener('click', clickHandler);
});
// close if the esc key is pressed
useEffect(() => {
const keyHandler = ({ keyCode }: KeyboardEvent) => {
if (!sidebarOpen || keyCode !== 27) return;
setSidebarOpen(false);
};
document.addEventListener('keydown', keyHandler);
return () => document.removeEventListener('keydown', keyHandler);
});
useEffect(() => {
localStorage.setItem('sidebar-expanded', sidebarExpanded.toString());
if (sidebarExpanded) {
document.querySelector('body')?.classList.add('sidebar-expanded');
} else {
document.querySelector('body')?.classList.remove('sidebar-expanded');
}
}, [sidebarExpanded]);
2024-08-05 02:42:35 +08:00
// 导航项样式
const sidebarItemSty = "group relative flex items-center gap-2.5 rounded-sm py-2 px-4 font-medium text-bodydark1 duration-300 ease-in-out hover:bg-graydark dark:hover:bg-meta-4"
// 导航选中样式
const sidebarItemActiveSty = "bg-graydark dark:bg-meta-4"
2024-08-08 15:27:57 +08:00
const Arrow = ({ open }: { open: boolean }) => {
return <svg
className={`absolute right-4 top-1/2 -translate-y-1/2 fill-current ${open && 'rotate-180'
}`}
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M4.41107 6.9107C4.73651 6.58527 5.26414 6.58527 5.58958 6.9107L10.0003 11.3214L14.4111 6.91071C14.7365 6.58527 15.2641 6.58527 15.5896 6.91071C15.915 7.23614 15.915 7.76378 15.5896 8.08922L10.5896 13.0892C10.2641 13.4147 9.73651 13.4147 9.41107 13.0892L4.41107 8.08922C4.08563 7.76378 4.08563 7.23614 4.41107 6.9107Z"
fill=""
/>
</svg>
}
2024-07-25 18:49:59 +08:00
return (
<aside
ref={sidebar}
2024-07-25 20:22:04 +08:00
className={`absolute left-0 top-0 z-9999 flex h-screen w-64 flex-col overflow-y-hidden bg-black duration-300 ease-linear dark:bg-boxdark lg:static lg:translate-x-0 ${sidebarOpen ? 'translate-x-0' : '-translate-x-full'
2024-07-25 18:49:59 +08:00
}`}
>
2024-07-25 20:22:04 +08:00
<div className="flex justify-center items-center justify-between gap-2 px-6 py-5.5 lg:py-6.5">
2024-07-25 18:49:59 +08:00
<NavLink to="/">
<img src={Logo} alt="Logo" />
</NavLink>
<button
ref={trigger}
onClick={() => setSidebarOpen(!sidebarOpen)}
aria-controls="sidebar"
aria-expanded={sidebarOpen}
className="block lg:hidden"
>
<svg
className="fill-current"
width="20"
height="18"
viewBox="0 0 20 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19 8.175H2.98748L9.36248 1.6875C9.69998 1.35 9.69998 0.825 9.36248 0.4875C9.02498 0.15 8.49998 0.15 8.16248 0.4875L0.399976 8.3625C0.0624756 8.7 0.0624756 9.225 0.399976 9.5625L8.16248 17.4375C8.31248 17.5875 8.53748 17.7 8.76248 17.7C8.98748 17.7 9.17498 17.625 9.36248 17.475C9.69998 17.1375 9.69998 16.6125 9.36248 16.275L3.02498 9.8625H19C19.45 9.8625 19.825 9.4875 19.825 9.0375C19.825 8.55 19.45 8.175 19 8.175Z"
fill=""
/>
</svg>
</button>
</div>
<div className="no-scrollbar flex flex-col overflow-y-auto duration-300 ease-linear">
2024-07-25 20:22:04 +08:00
<nav className="py-4 px-4 lg:px-6">
2024-07-25 18:49:59 +08:00
<div>
<h3 className="mb-4 ml-4 text-sm font-semibold text-bodydark2">
2024-08-05 02:42:35 +08:00
Menu
2024-07-25 18:49:59 +08:00
</h3>
<ul className="mb-6 flex flex-col gap-1.5">
<li>
<NavLink
to="/"
2024-08-05 02:42:35 +08:00
className={`${sidebarItemSty} ${pathname.includes('dashboard') && sidebarItemActiveSty}`}
2024-07-25 18:49:59 +08:00
>
2024-07-25 23:03:12 +08:00
<BiHomeSmile className='text-[22px]' />
2024-07-25 18:49:59 +08:00
</NavLink>
</li>
<li>
<NavLink
to="/create"
2024-08-05 02:42:35 +08:00
className={`${sidebarItemSty} ${pathname.includes('create') && sidebarItemActiveSty}`}
2024-07-25 18:49:59 +08:00
>
2024-08-05 02:42:35 +08:00
<BiEditAlt className='text-[22px]' />
2024-07-25 18:49:59 +08:00
</NavLink>
</li>
<SidebarLinkGroup
2024-08-08 12:47:44 +08:00
activeCondition={false}
2024-07-25 18:49:59 +08:00
>
{(handleClick, open) => {
return (
<React.Fragment>
<NavLink
to="#"
2024-08-08 15:27:57 +08:00
className={`${sidebarItemSty}`}
2024-07-25 18:49:59 +08:00
onClick={(e) => {
e.preventDefault();
2024-08-08 15:27:57 +08:00
2024-07-25 18:49:59 +08:00
sidebarExpanded
? handleClick()
: setSidebarExpanded(true);
}}
>
2024-08-08 12:47:44 +08:00
<BiCategoryAlt className='text-[22px]' />
2024-08-05 02:42:35 +08:00
2024-08-08 15:27:57 +08:00
<Arrow open={open} />
2024-07-25 18:49:59 +08:00
</NavLink>
2024-08-08 15:27:57 +08:00
2024-07-25 18:49:59 +08:00
<div
className={`translate transform overflow-hidden ${!open && 'hidden'
}`}
>
<ul className="mt-4 mb-5.5 flex flex-col gap-2.5 pl-6">
<li>
<NavLink
2024-08-06 21:02:06 +08:00
to="/article"
2024-07-25 18:49:59 +08:00
className={({ isActive }) =>
'group relative flex items-center gap-2.5 rounded-md px-4 font-medium text-bodydark2 duration-300 ease-in-out hover:text-white ' +
(isActive && '!text-white')
}
>
2024-08-06 21:02:06 +08:00
2024-07-25 18:49:59 +08:00
</NavLink>
</li>
2024-08-08 12:47:44 +08:00
2024-08-08 23:24:20 +08:00
<li>
<NavLink
to="/tag"
className={({ isActive }) =>
'group relative flex items-center gap-2.5 rounded-md px-4 font-medium text-bodydark2 duration-300 ease-in-out hover:text-white ' +
(isActive && '!text-white')
}
>
</NavLink>
</li>
2024-07-25 18:49:59 +08:00
<li>
<NavLink
2024-08-06 23:21:42 +08:00
to="/comment"
2024-07-25 18:49:59 +08:00
className={({ isActive }) =>
'group relative flex items-center gap-2.5 rounded-md px-4 font-medium text-bodydark2 duration-300 ease-in-out hover:text-white ' +
(isActive && '!text-white')
}
>
2024-08-06 23:21:42 +08:00
2024-07-25 18:49:59 +08:00
</NavLink>
</li>
2024-08-07 19:35:28 +08:00
2024-08-08 12:47:44 +08:00
<li>
<NavLink
to="/cate"
className={({ isActive }) =>
'group relative flex items-center gap-2.5 rounded-md px-4 font-medium text-bodydark2 duration-300 ease-in-out hover:text-white ' +
(isActive && '!text-white')
}
>
</NavLink>
</li>
2024-08-07 19:35:28 +08:00
<li>
<NavLink
to="/web"
className={({ isActive }) =>
'group relative flex items-center gap-2.5 rounded-md px-4 font-medium text-bodydark2 duration-300 ease-in-out hover:text-white ' +
(isActive && '!text-white')
}
>
</NavLink>
</li>
2024-08-08 13:46:28 +08:00
<li>
<NavLink
to="/swiper"
className={({ isActive }) =>
'group relative flex items-center gap-2.5 rounded-md px-4 font-medium text-bodydark2 duration-300 ease-in-out hover:text-white ' +
(isActive && '!text-white')
}
>
</NavLink>
</li>
2024-07-25 18:49:59 +08:00
</ul>
</div>
{/* <!-- Dropdown Menu End --> */}
</React.Fragment>
);
}}
</SidebarLinkGroup>
2024-08-08 15:27:57 +08:00
<li>
<NavLink
to="/setup"
className={`${sidebarItemSty} ${pathname.includes('setup') && sidebarItemActiveSty}`}
>
<BiSliderAlt className='text-[22px]' />
</NavLink>
</li>
2024-07-25 18:49:59 +08:00
</ul>
</div>
<div>
<h3 className="mb-4 ml-4 text-sm font-semibold text-bodydark2">
2024-08-05 02:42:35 +08:00
New
2024-07-25 18:49:59 +08:00
</h3>
<ul className="mb-6 flex flex-col gap-1.5">
2024-08-14 14:46:08 +08:00
<li>
<NavLink
to="/rss"
2024-08-15 15:39:37 +08:00
className={`${sidebarItemSty} ${pathname.includes('rss') && 'bg-graydark dark:bg-meta-4'
2024-08-14 14:46:08 +08:00
}`}
>
2024-08-14 19:17:32 +08:00
<LiaRssSolid className='text-[22px]' />
2024-08-14 14:46:08 +08:00
</NavLink>
</li>
2024-07-25 18:49:59 +08:00
<li>
<NavLink
to="/chart"
2024-08-05 02:42:35 +08:00
className={`${sidebarItemSty} ${pathname.includes('chart') && 'bg-graydark dark:bg-meta-4'
2024-07-25 18:49:59 +08:00
}`}
>
2024-08-05 02:42:35 +08:00
<BiFolderOpen className='text-[22px]' />
2024-07-25 18:49:59 +08:00
</NavLink>
</li>
2024-08-15 15:39:37 +08:00
<li>
<NavLink
2024-08-15 16:57:03 +08:00
to="/stats"
className={`${sidebarItemSty} ${pathname.includes('stats') && 'bg-graydark dark:bg-meta-4'
2024-08-15 15:39:37 +08:00
}`}
>
2024-08-15 16:57:03 +08:00
<IoIosStats className='text-[22px]' />
2024-08-15 15:39:37 +08:00
</NavLink>
</li>
2024-07-25 18:49:59 +08:00
</ul>
</div>
</nav>
</div>
</aside>
);
};
export default Sidebar;