Initial commit for iiEasy: all files included
This commit is contained in:
146
components/Sidebar.tsx
Executable file
146
components/Sidebar.tsx
Executable file
@@ -0,0 +1,146 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user