Skip to content

Instantly share code, notes, and snippets.

@muhsinazmal9
Created July 9, 2025 12:22
Show Gist options
  • Select an option

  • Save muhsinazmal9/bd80669c77a2b5923aa40ed16f91a7b5 to your computer and use it in GitHub Desktop.

Select an option

Save muhsinazmal9/bd80669c77a2b5923aa40ed16f91a7b5 to your computer and use it in GitHub Desktop.
previous and cluttered one
'use client';
import { userDashboardSidebarMenuItems } from '@/localization/localization';
import Link from 'next/link';
import React, { useState, useEffect, useRef } from 'react';
import { FiMinus } from 'react-icons/fi';
import { FaChevronRight } from 'react-icons/fa6';
import { FaChevronLeft } from 'react-icons/fa';
import { useDispatch, useSelector } from 'react-redux';
import { miniSidebar } from '@/app/redux/sidebarSlice/sidebarSlice';
import { useRouter, usePathname, useSearchParams } from 'next/navigation';
import { apiCall, filterMenuByPermissions } from '../utils/utls';
import { useFilteredSidebar } from '@/hooks/useFilteredSidebar';
import { useGetPremiumCoursesQuery } from '@/app/redux/api/coursesApi';
import Skeleton from 'react-loading-skeleton';
import { useSidebar } from '@/hooks/useSidebar';
function Sidebar({ offCanvas = false, setShowSidebar = '' }) {
// console.log('useSidebar', useSidebar());
// const sidebarItems = useSidebar();
const [loading, setLoading] = useState(false);
const [resumeBuilderPage, setResumeBuilderPage] = useState(false);
const searchParams = useSearchParams();
const [pagesList, setPagesList] = useState(null);
const router = useRouter();
const pathname = usePathname();
const dispatch = useDispatch();
const [activeMenu, setActiveMenu] = useState(0);
const [menuSelected, setMenuSelected] = useState(null);
const [activeSubMenu, setActiveSubMenu] = useState(null);
const [isMiniSidebar, setIsMiniSidebar] = useState(false);
const is_amplify_for_cognify_enabled = useSelector(
(state) =>
state?.aptitude?.aptitude?.category?.is_amplify_for_cognify_enabled ??
false
);
const [finalMenuItems, setFinalMenuItems] = useState([]);
const heightRef = useRef(null);
const [height, setHeight] = useState('auto');
const { category } = useSelector((state) => state.aptitude.aptitude);
const { setting } = useSelector((state) => state.settings);
const { loggedInUser } = useSelector((state) => state.user);
const { permissions } = useSelector((state) => state.user.userPermissions);
const { active_campaign_permissions } = useSelector(
(state) => state.user.loggedInUser
);
const shouldShowMyCourses = permissions?.some(
(item) => item.name === 'view_courses'
);
// console.log('Sidebar permissions:', permissions);
// console.log('active_campaign_permissions:', active_campaign_permissions);
useEffect(() => {
const params = new URLSearchParams(searchParams.toString());
const pageNumber = params.get('page');
userDashboardSidebarMenuItems.forEach((menu) => {
if (menu.link === pathname) {
setActiveMenu(menu.id);
}
menu.submenu?.forEach((subitem) => {
if (subitem.link === pathname) {
setActiveMenu(menu.id);
setActiveSubMenu(subitem.id);
}
if (
pathname.startsWith('/dashboard/resume/builder') &&
subitem.link.startsWith('/dashboard/resume/builder')
) {
if (pageNumber == subitem.id) {
setActiveSubMenu(subitem.id);
}
}
});
});
if (pathname.startsWith('/dashboard/resume/builder')) {
if (activeMenu != 5) {
setActiveMenu(5);
}
setResumeBuilderPage(true);
} else {
setResumeBuilderPage(false);
}
}, [category?.id, pathname, searchParams]);
const handleResetScroll = () => {
window.scrollTo({ top: 0, behavior: 'auto' });
};
const handleMenuClick = (menu) => {
setActiveSubMenu(null);
setActiveMenu(activeMenu === menu.id ? null : menu.id);
setMenuSelected(activeMenu === menu.id ? activeMenu : null);
dispatch(miniSidebar(false));
setIsMiniSidebar(false);
if (menu?.submenu?.length > 0) {
const filteredSubMenu = menu.submenu.filter((subItem) => {
if (
subItem.name === 'Fire Service Exams' &&
is_amplify_for_cognify_enabled
) {
return false;
}
if (
subItem.name === 'Amplify for Cognify' &&
!is_amplify_for_cognify_enabled
) {
return false;
}
if (
menu.title == 'Aptitude' &&
subItem.name === 'Exam Results' &&
is_amplify_for_cognify_enabled
) {
return false;
}
if (
subItem.name === 'Aptitude Specials' &&
loggedInUser?.membership?.toLowerCase() !== 'elite'
) {
return false;
}
return true;
});
}
if (menu.title === 'Interview') {
handleResetScroll();
const section = document.getElementById('interview');
if (section) {
const offset = 170;
const sectionTop =
section.getBoundingClientRect().top + window.scrollY - offset;
window.scrollTo({ top: sectionTop, behavior: 'smooth' });
}
}
if (menu.title === 'Personality') {
handleResetScroll();
const section = document.getElementById('personality');
if (section) {
const offset = 170;
const sectionTop =
section.getBoundingClientRect().top + window.scrollY - offset;
window.scrollTo({ top: sectionTop, behavior: 'smooth' });
}
}
if (menu.title === 'Aptitude') {
handleResetScroll();
const section = document.getElementById('aptitude');
if (section) {
const offset = 170;
const sectionTop =
section.getBoundingClientRect().top + window.scrollY - offset;
window.scrollTo({ top: sectionTop, behavior: 'smooth' });
}
}
};
const handleActiveSubMenu = (subitem) => {
dispatch(miniSidebar(false));
setIsMiniSidebar(false);
setActiveSubMenu(activeSubMenu === subitem.id ? subitem.id : subitem.id);
setShowSidebar(false);
router.push(subitem.link);
};
const handleMiniSidebar = () => {
setIsMiniSidebar(!isMiniSidebar);
dispatch(miniSidebar(!isMiniSidebar));
setActiveMenu(null);
};
const { data, isLoading } = useGetPremiumCoursesQuery();
// my courses menu items
const myCoursesMenu = {
id: 2,
title: 'My Courses',
iconBlack: '/assets/images/course.svg',
iconWhite: '/assets/images/course-white.svg',
link: '/dashboard/courses',
permission: '',
submenu: isLoading
? Array(4).fill({ isSkeleton: true })
: data?.data?.map((course) => ({
id: course.id,
name: course.title,
link: `/dashboard/courses/${course.id}`,
permission: 'view_courses',
})),
};
// user role based menu items filtered
const allowedMenuItems = useFilteredSidebar();
// Insert myCoursesMenu at index 1 or as a second item
const updatedMenuItems = shouldShowMyCourses
? [
...allowedMenuItems.slice(0, 1),
myCoursesMenu,
...allowedMenuItems.slice(1),
]
: [...allowedMenuItems];
const fullMenuList = [...updatedMenuItems];
useEffect(() => {
if (pagesList == null) return;
if (pagesList.length == 0) {
setFinalMenuItems([...fullMenuList]);
return;
}
fullMenuList.push(
...pagesList.map((pageMenu, index) => ({
id: index + 11,
order: pageMenu.order,
title: pageMenu.name,
iconBlack: '/assets/images/page.svg',
iconWhite: '/assets/images/page-white.svg',
link: '',
submenu: pageMenu?.pages?.map((page) => ({
id: page.id,
name: page.title,
link: `/dashboard/pages/${page.slug}`,
permission: 'page_builder_section',
})),
}))
);
let nextOrder = 1;
const assignOrders = () => {
const used = new Set(
fullMenuList
.map((i) => (i.order >= 1000 ? delete i.order : i.order))
.filter(Boolean)
);
for (const item of fullMenuList) {
if (item.order == null) {
while (used.has(nextOrder)) nextOrder++;
item.order = nextOrder++;
} else {
nextOrder = Math.max(nextOrder, item.order + 1);
}
}
fullMenuList.sort((a, b) => a.order - b.order);
setFinalMenuItems([...fullMenuList]);
};
assignOrders();
}, [pagesList, data?.data?.length]);
const getPagesList = async () => {
if (!category?.id) return;
const { success, data } = await apiCall(
`/api/v2/page-menus`,
'GET',
{},
setLoading
);
if (success) {
setPagesList(data);
setLoading(false);
return;
} else {
setPagesList([]);
setLoading(false);
}
};
useEffect(() => {
getPagesList();
}, [category?.id]);
useEffect(() => {
if (heightRef.current) {
const baseHeight = heightRef.current.scrollHeight;
setHeight(`${baseHeight + 500}px`);
}
}, []);
return (
<div
className={`${
offCanvas ? 'max-w-full' : 'max-w-[286px]'
} !w-full h-full max-h-[92vh] overflow-y-auto scrollbar-custom`}
>
<aside className={`flex flex-col`}>
<nav className="flex h-min pb-40 text-lg 2xl:text-xl font-medium text-colorBlack max-md:mt-5">
<div
className={`flex flex-col grow shrink-0 px-4 xl:pt-11 pb-10 rounded-2xl basis-0 w-fit max-md:px-5 max-md:pb-24 relative ${
isMiniSidebar ? '!max-w-[100px]' : '!max-w-[286px] w-full '
}`}
>
{finalMenuItems?.length > 0
? finalMenuItems.map((menu, index) => (
<div key={menu.id} className="menu-item">
<div
className={`flex self-start justify-between items-center mb-4 md:mb-5 py-2 transition ease-linear duration-300 rounded-[30px] bg-white px-2 cursor-pointer select-none ${
activeMenu === menu.id || menuSelected === menu.id
? 'activeSidebarItem '
: ''
}`}
onClick={() => handleMenuClick(menu)}
>
<Link
href={menu.link}
className={`flex items-center transition ease-linear duration-200 ${
isMiniSidebar ? 'justify-center ps-5' : 'ps-0'
} gap-3 2xl:gap-5 w-full`}
>
<img
loading="lazy"
src={
activeMenu === menu.id || menuSelected === menu.id
? menu.iconWhite
: menu.iconBlack
}
alt="icon"
className="object-contain shrink-0 my-auto w-7 aspect-[1.4]"
/>
{
<span
className={`${
activeMenu === menu.id
? '-'
: ' hover:text-colorOrange'
} hover-animate whitespace-nowrap `}
style={{
opacity: !isMiniSidebar ? 1 : 0,
visibility: !isMiniSidebar ? 'visible' : 'hidden',
height: !isMiniSidebar ? 'auto' : 0,
}}
>
{!isMiniSidebar ? menu.title : ''}
</span>
}
</Link>
{menu.submenu?.length > 0 &&
activeMenu === menu.id &&
!(menu.title === 'Resume' && !resumeBuilderPage) && (
<FiMinus />
)}
</div>
{menu.submenu && (
<div
className="sub-menu-item flex flex-col max-w-full text-base 2xl:text-lg text-colorBlackSecond transition ease-linear duration-500 whitespace-nowrap ml-4 relative rounded"
style={{
opacity: activeMenu === menu.id ? 1 : 0,
visibility:
activeMenu === menu.id ? 'visible' : 'hidden',
height: activeMenu === menu.id ? 'auto' : 0,
}}
>
{menu.submenu.map((subitem, subIndex) => {
if (menu.id == 2 && subitem.isSkeleton) {
return (
<div
key={`skeleton-${subIndex}`}
className="self-start mb-6 ps-[6px] w-[180px]"
>
<Skeleton height={20} borderRadius={4} />
</div>
);
}
if (
(subitem.name === 'Fire Service Exams' && is_amplify_for_cognify_enabled) ||(subitem.name === 'Fire Service Exams' && !setting?.exam_visibility)
) {
return null;
}
if (
subitem.name === 'Amplify for Cognify' &&
!is_amplify_for_cognify_enabled
) {
return null;
}
if (
menu.title == 'Aptitude' &&
subitem.name === 'Exam Results' &&
is_amplify_for_cognify_enabled
) {
return null;
}
if (
subitem.name === 'Aptitude Specials' &&
loggedInUser?.membership?.toLowerCase() !== 'elite'
) {
return null;
}
if (
subitem.type === 'resume_builder' &&
!resumeBuilderPage
) {
return null;
}
const isLastItem =
subIndex == menu.submenu.length - 1;
return (
<Link
onClick={() => handleActiveSubMenu(subitem)}
key={subIndex}
href={subitem.link || '/dashboard'}
className={`self-start mb-5 hover:text-colorOrange hover-animate relative ps-[25px] ${
activeSubMenu === subitem.id
? 'font-bold text-colorOrange'
: ''
}`}
>
<img
className="absolute -left-[4px] top-[50%] translate-y-[-50%]"
src="/assets/images/icons/curve.svg"
alt="curve"
/>
<span
className={`absolute -left-[3px] top-[50%] translate-y-[-50%] border-l border-[1.75px] border-[#D1D1D1] h-[48px] ${
isLastItem ? '!h-[20px] !top-0' : ''
}`}
></span>
<span className="block max-w-[220px] truncate whitespace-nowrap overflow-hidden text-ellipsis">
{subitem.name}
</span>
</Link>
);
})}
</div>
)}
</div>
))
: Array(10)
.fill({ isSkeleton: true })
.map((item, index) => (
<div key={index} className="menu-item mb-5">
<Skeleton height={40} borderRadius={8} />
</div>
))}
</div>
</nav>
</aside>
{!offCanvas && (
<div onClick={handleMiniSidebar} className="mini-sidebar-toggler">
{isMiniSidebar ? (
<FaChevronRight size={16} />
) : (
<FaChevronLeft size={16} />
)}
</div>
)}
</div>
);
}
export default Sidebar;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment