146 lines
5.5 KiB
TypeScript
146 lines
5.5 KiB
TypeScript
|
|
import React from 'react';
|
|||
|
|
import { NAV_LINKS, ABOUT_CONTEXT_NAV_LINKS, BUSINESS_CONTEXT_NAV_LINKS, EDUCATION_CONTEXT_NAV_LINKS, ACCELERATOR_CONTEXT_NAV_LINKS, SECTION_IDS, APP_NAME, FOOTER_CONTENT } from '../constants';
|
|||
|
|
import { NavLinkItem, CurrentView } from '../types';
|
|||
|
|
import { ChevronRightIcon } from './icons';
|
|||
|
|
import Logo from './Logo'; // Import the new Logo component
|
|||
|
|
|
|||
|
|
interface SidebarProps {
|
|||
|
|
isOpen: boolean;
|
|||
|
|
onClose: () => void;
|
|||
|
|
currentView: CurrentView;
|
|||
|
|
setCurrentView: (view: CurrentView) => void;
|
|||
|
|
isDesktopCollapsed: boolean;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const Sidebar: React.FC<SidebarProps> = ({ isOpen, onClose, currentView, setCurrentView, isDesktopCollapsed }) => {
|
|||
|
|
|
|||
|
|
const scrollToSection = (hash: string) => {
|
|||
|
|
if (hash.startsWith('#')) {
|
|||
|
|
const sectionId = hash.substring(1);
|
|||
|
|
const element = document.getElementById(sectionId);
|
|||
|
|
if (element) {
|
|||
|
|
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|||
|
|
} else {
|
|||
|
|
console.warn(`Element with ID ${sectionId} not found for scrolling.`);
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
console.warn(`Invalid hash for scrolling: ${hash}`);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const handleNavLinkClick = (item: NavLinkItem) => {
|
|||
|
|
if (item.targetView) {
|
|||
|
|
setCurrentView(item.targetView);
|
|||
|
|
setTimeout(() => scrollToSection(item.href), 50); // Increased delay
|
|||
|
|
} else {
|
|||
|
|
setCurrentView('main');
|
|||
|
|
setTimeout(() => scrollToSection(item.href), 50); // Increased delay
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (window.innerWidth < 768) { // md breakpoint
|
|||
|
|
onClose();
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const isAboutContextView = ['about', 'mission', 'careers'].includes(currentView);
|
|||
|
|
const isBusinessContextView = ['businessLanding', 'businessServices'].includes(currentView);
|
|||
|
|
const isEducationContextView = ['educationBusiness', 'educationStudents'].includes(currentView);
|
|||
|
|
const isAcceleratorContextView = ['acceleratorAbout', 'acceleratorProjects', 'acceleratorInvestment'].includes(currentView);
|
|||
|
|
|
|||
|
|
let linksToRender: NavLinkItem[];
|
|||
|
|
if (isAboutContextView) {
|
|||
|
|
linksToRender = ABOUT_CONTEXT_NAV_LINKS;
|
|||
|
|
} else if (isBusinessContextView) {
|
|||
|
|
linksToRender = BUSINESS_CONTEXT_NAV_LINKS;
|
|||
|
|
} else if (isEducationContextView) {
|
|||
|
|
linksToRender = EDUCATION_CONTEXT_NAV_LINKS;
|
|||
|
|
} else if (isAcceleratorContextView) {
|
|||
|
|
linksToRender = ACCELERATOR_CONTEXT_NAV_LINKS;
|
|||
|
|
} else {
|
|||
|
|
linksToRender = NAV_LINKS;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const getLinkClasses = (item: NavLinkItem) => {
|
|||
|
|
let baseClasses = `relative flex items-center p-3 rounded-lg hover:bg-slate-100
|
|||
|
|
transition-colors duration-150
|
|||
|
|
focus:outline-none focus:ring-2 focus:ring-slate-400 focus:bg-slate-100`;
|
|||
|
|
|
|||
|
|
if (item.label === 'На Главную') {
|
|||
|
|
baseClasses += ' text-slate-500 hover:text-slate-700';
|
|||
|
|
} else {
|
|||
|
|
baseClasses += ' text-slate-700 hover:text-slate-900';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const isActive = (isAboutContextView || isBusinessContextView || isEducationContextView || isAcceleratorContextView) && item.targetView === currentView;
|
|||
|
|
|
|||
|
|
if (isActive) {
|
|||
|
|
baseClasses += ' bg-slate-200 text-slate-900 font-semibold';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return baseClasses;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const sidebarClasses = `h-screen w-72 flex flex-col p-6 transform transition-all duration-300 ease-in-out
|
|||
|
|
fixed top-0 left-0 z-40
|
|||
|
|
bg-white/95 backdrop-blur-sm
|
|||
|
|
md:bg-white md:z-30
|
|||
|
|
${isOpen ? 'translate-x-0' : '-translate-x-full'}
|
|||
|
|
${isDesktopCollapsed ? 'md:-translate-x-full' : 'md:translate-x-0'}`;
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<aside
|
|||
|
|
id="sidebar-drawer"
|
|||
|
|
className={sidebarClasses}
|
|||
|
|
aria-label="Sidebar"
|
|||
|
|
>
|
|||
|
|
<div className="flex items-center justify-start mb-8 pl-1">
|
|||
|
|
<a
|
|||
|
|
href={`#${SECTION_IDS.hero}`}
|
|||
|
|
onClick={(e) => {
|
|||
|
|
e.preventDefault();
|
|||
|
|
setCurrentView('main');
|
|||
|
|
setTimeout(() => scrollToSection(`#${SECTION_IDS.hero}`), 50);
|
|||
|
|
if (window.innerWidth < 768) onClose();
|
|||
|
|
}}
|
|||
|
|
className="flex items-center gap-3"
|
|||
|
|
>
|
|||
|
|
<Logo width={32} height={32} />
|
|||
|
|
<span className={`font-quicksand text-2xl font-bold text-slate-900 transition-opacity duration-200 ${isDesktopCollapsed ? 'opacity-0' : 'opacity-100'}`}>
|
|||
|
|
{APP_NAME}
|
|||
|
|
</span>
|
|||
|
|
</a>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<nav className="flex-grow flex flex-col justify-center overflow-y-auto no-scrollbar">
|
|||
|
|
<ul className="space-y-2 font-medium">
|
|||
|
|
{linksToRender.map((item: NavLinkItem) => (
|
|||
|
|
<li key={item.id} className="group relative">
|
|||
|
|
<a
|
|||
|
|
href={item.href}
|
|||
|
|
onClick={(e) => {
|
|||
|
|
e.preventDefault();
|
|||
|
|
handleNavLinkClick(item);
|
|||
|
|
}}
|
|||
|
|
className={`${getLinkClasses(item)}`}
|
|||
|
|
>
|
|||
|
|
{item.icon && <item.icon className="w-5 h-5 shrink-0 text-slate-500 group-hover:text-slate-700 transition-colors duration-150 mr-4" />}
|
|||
|
|
<span className="font-quicksand text-base whitespace-nowrap">{item.label}</span>
|
|||
|
|
{item.children && (
|
|||
|
|
<ChevronRightIcon className="w-4 h-4 ml-auto opacity-50 group-hover:opacity-100 transition-opacity" />
|
|||
|
|
)}
|
|||
|
|
</a>
|
|||
|
|
</li>
|
|||
|
|
))}
|
|||
|
|
</ul>
|
|||
|
|
</nav>
|
|||
|
|
|
|||
|
|
<div className="pt-4 mt-8 border-t border-slate-200">
|
|||
|
|
<p className="text-xs text-center text-slate-500">
|
|||
|
|
{FOOTER_CONTENT.copyrightText(new Date().getFullYear())}
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
</aside>
|
|||
|
|
);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
export default Sidebar;
|