Files
KLC-Website-Frontend/src/components/Navigation.tsx

616 lines
18 KiB
TypeScript

import klcLogo from '../assets/klc-logo-dark.png';
import {
ArrowRight,
BookMarked,
ChevronDown,
ChevronRight,
Eye,
GraduationCap,
Heart,
LayoutDashboard,
Lightbulb,
LogOut,
Menu,
Podcast,
Settings,
ShoppingCart,
Star,
Target,
TrendingUp,
User,
Users
} from 'lucide-react';
import { useEffect, useState } from 'react';
import { useAuth } from './AuthContext';
import { useCart } from './CartContext';
import { navigateTo } from './Router';
import { Avatar, AvatarFallback, AvatarImage } from './ui/avatar';
import { Button } from './ui/button';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from './ui/collapsible';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from './ui/dropdown-menu';
import {
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
SheetTrigger,
} from './ui/sheet';
import { useLocation, useNavigate } from 'react-router-dom';
interface NavigationProps {
currentPage?: string;
}
interface NavLink {
label: string;
href?: string;
items?: { label: string; href: string; description?: string; icon?: any }[];
icon?: any;
}
const navigationItems: NavLink[] = [
{
label: 'Services',
// items: [
// {
// label: 'Leadership Development',
// href: '/services/leadership-development',
// description: 'Executive and senior leadership programs',
// icon: Target
// },
// {
// label: 'Management Development',
// href: '/services/management-development',
// description: 'Middle management and team leader training',
// icon: Users
// },
// {
// label: 'Culture Competence',
// href: '/services/culture-competence',
// description: 'Building inclusive and high-performance cultures',
// icon: Heart
// },
// {
// label: 'Consulting',
// href: '/services/consulting',
// description: 'Strategic organizational transformation',
// icon: Lightbulb
// },
// {
// label: 'Executive Coaching',
// href: '/services/executive-coaching',
// description: 'Personalized leadership development',
// icon: GraduationCap
// }
// ]
// label: 'Online Courses',
href: '/services'
},
{
label: 'About Us',
// items: [
// {
// label: 'Our Vision',
// href: '/about/our-vision',
// description: 'Our mission to transform leadership globally',
// icon: Eye
// },
// {
// label: 'Our Impact',
// href: '/about/our-impact',
// description: 'Real results and measurable outcomes',
// icon: TrendingUp
// },
// {
// label: 'Our Expertise',
// href: '/about/our-expertise',
// description: 'Industry-leading knowledge and experience',
// icon: Star
// }
// ]
href: '/about-us'
},
{
label: 'Learning Facility',
href: '/learning-facility'
},
{
label: 'Resources',
items: [
{
label: 'Article Blog',
href: '/learning/articles',
description: 'Latest insights and thought leadership',
icon: BookMarked
},
{
label: 'Webcast',
href: '/learning/webcast',
description: 'Live and recorded leadership sessions',
icon: Podcast
}
]
},
{
label: 'Online Courses',
href: '/learning-online'
},
{
label: 'Contact Us',
href: '/contact'
}
];
const signInOptions = [
{
label: 'Corporate HR',
href: '/signin/corporate-hr',
description: 'HR dashboard, team management, and bulk enrollment tools'
},
{
label: 'Corporate Learner',
href: '/signin/corporate-learner',
description: 'Employee learning dashboard and assigned programs'
},
{
label: 'Self-Learner',
href: '/signin/self-learner',
description: 'Individual professional development access'
}
];
function NavLink({ item, isMobile = false }: { item: NavLink; isMobile?: boolean }) {
const navigate = useNavigate();
const location = useLocation();
const [isOpen, setIsOpen] = useState(false);
if (item.href) {
return (
<Button
variant="ghost"
onClick={() => navigate(item.href!)}
className={isMobile ? "w-full justify-start min-h-[44px]" : "min-h-[44px]"}
style={{
fontSize: '14px',
fontWeight: 'normal',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
{item.icon && <item.icon className="w-4 h-4 mr-2" />}
{item.label}
</Button>
);
}
if (isMobile) {
return (
<Collapsible open={isOpen} onOpenChange={setIsOpen}>
<CollapsibleTrigger asChild>
<Button
variant="ghost"
className="w-full justify-between min-h-[44px]"
style={{
fontSize: '14px',
fontWeight: 'normal',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
<span className="flex items-center">
{item.icon && <item.icon className="w-4 h-4 mr-2" />}
{item.label}
</span>
<ChevronRight className={`w-4 h-4 transition-transform ${isOpen ? 'rotate-90' : ''}`} />
</Button>
</CollapsibleTrigger>
<CollapsibleContent className="pl-4 space-y-1">
{item.items?.map((subItem) => (
<Button
key={subItem.href}
variant="ghost"
onClick={() => navigate(subItem.href)}
className="w-full justify-start min-h-[44px] pl-6"
style={{
fontSize: '14px',
fontWeight: 'normal',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
{subItem.icon && <subItem.icon className="w-4 h-4 mr-2" />}
{subItem.label}
</Button>
))}
</CollapsibleContent>
</Collapsible>
);
}
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
className="flex items-center gap-1 min-h-[44px] transition-all duration-300 hover:transform hover:-translate-y-1"
style={{
fontSize: '14px',
fontWeight: 'normal',
fontFamily: 'var(--font-family-base)',
color: 'var(--color-black)'
}}
>
{item.icon && <item.icon className="w-4 h-4 mr-2" />}
{item.label}
<ChevronDown className="w-4 h-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
align="start"
className="w-80"
style={{
backgroundColor: 'var(--color-bg-white)',
border: `1px solid var(--color-border)`,
borderRadius: '12px',
boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
fontFamily: 'var(--font-family-base)'
}}
>
{item.items?.map((subItem) => (
<DropdownMenuItem
key={subItem.href}
onClick={() => navigate(subItem.href)}
className="flex items-start gap-3 p-4 cursor-pointer transition-all duration-300 hover:transform hover:-translate-y-1"
style={{
fontFamily: 'var(--font-family-base)'
}}
>
{subItem.icon && (
<div
className="w-8 h-8 rounded-lg flex items-center justify-center flex-shrink-0 mt-1"
style={{
backgroundColor: 'rgba(4, 4, 91, 0.1)',
color: 'var(--color-brand-primary)'
}}
>
<subItem.icon className="w-4 h-4" />
</div>
)}
<div className="flex-1">
<div
className="font-medium"
style={{
fontSize: '14px',
fontWeight: '400',
color: 'var(--color-black)',
fontFamily: 'var(--font-family-base)'
}}
>
{subItem.label}
</div>
{subItem.description && (
<div
className="mt-1"
style={{
fontSize: '12px',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)',
lineHeight: 'var(--line-height-small)'
}}
>
{subItem.description}
</div>
)}
</div>
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
);
}
function ProfileDropdown({ user }: { user: any }) {
const { signOut } = useAuth();
const navigate = useNavigate();
const handleSignOut = () => {
signOut();
navigate('/');
};
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
className="flex items-center gap-3 px-3 py-2 h-auto min-h-[44px]"
style={{
fontSize: '14px',
fontFamily: 'var(--font-family-base)'
}}
>
<Avatar className="h-8 w-8">
<AvatarImage src={user.avatar} alt={user.name} />
<AvatarFallback
className="text-sm"
style={{ fontFamily: 'var(--font-family-base)' }}
>
{user.name.split(' ').map((n: string) => n[0]).join('')}
</AvatarFallback>
</Avatar>
<div className="text-left">
<div
className="font-medium"
style={{
fontSize: '14px',
fontWeight: '400',
fontFamily: 'var(--font-family-base)'
}}
>
{user.corporateName}
</div>
<div
style={{
fontSize: '12px',
color: 'var(--color-gray-muted)',
fontFamily: 'var(--font-family-base)'
}}
>
{user.name}
</div>
</div>
<ChevronDown className="w-4 h-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
align="end"
className="w-64"
style={{
backgroundColor: 'var(--color-bg-white)',
border: `1px solid var(--color-border)`,
borderRadius: '12px',
fontFamily: 'var(--font-family-base)'
}}
>
<DropdownMenuLabel
style={{
fontSize: '14px',
fontFamily: 'var(--font-family-base)'
}}
>
<div
className="font-medium"
style={{ fontWeight: '400' }}
>
{user.corporateName}
</div>
<div
className="font-normal"
style={{
fontSize: '12px',
color: 'var(--color-gray-muted)'
}}
>
{user.email}
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem
onClick={() => navigate('/dashboard')}
className="min-h-[44px]"
style={{
fontSize: '14px',
fontFamily: 'var(--font-family-base)'
}}
>
<LayoutDashboard className="w-4 h-4 mr-2" />
Dashboard
</DropdownMenuItem>
{/* ... rest of the dropdown items with navigate() */}
</DropdownMenuContent>
</DropdownMenu>
);
}
function CartIcon() {
const { cartCount } = useCart();
const navigate = useNavigate();
const handleCartClick = () => {
navigate('/cart');
};
return (
<Button
variant="ghost"
size="icon"
onClick={handleCartClick}
className="relative min-h-[44px] min-w-[44px] hover:bg-gray-100 transition-all duration-300"
aria-label={`Shopping cart with ${cartCount} items`}
>
<ShoppingCart className="w-5 h-5 text-gray-600" />
{cartCount > 0 && (
<div
className="absolute -top-1 -right-1 min-w-[18px] h-[18px] flex items-center justify-center rounded-full text-xs font-medium text-white animate-in fade-in zoom-in duration-300"
style={{
backgroundColor: '#dc2626',
fontSize: '11px',
fontFamily: 'var(--font-family-base)',
lineHeight: '1'
}}
>
{cartCount > 9 ? '9+' : cartCount}
</div>
)}
</Button>
);
}
export function Navigation({ currentPage }: NavigationProps) {
const [isScrolled, setIsScrolled] = useState(false);
const { user, isAuthenticated, signOut } = useAuth();
const navigate = useNavigate();
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 10);
};
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
const handleMobileSignOut = () => {
signOut();
navigate('/');
};
return (
<>
{/* Top notification bar */}
<div className="notification-strip">
<span className="notification-text">
Join Our Upcoming Leadership Webinars - Transform Your Leadership Journey
</span>
<Button
variant="ghost"
size="sm"
onClick={() => navigate('/enroll')}
className="notification-button"
>
Enroll Now
<ChevronRight className="w-4 h-4 ml-1" />
</Button>
</div>
{/* Main navigation header */}
<header
className={`w-full border-b transition-all duration-300 navbar-sticky ${isScrolled ? 'shadow-lg scrolled' : 'shadow-sm'}`}
style={{
borderColor: 'var(--color-border)'
}}
>
<nav className="container mx-auto px-4 lg:px-8">
<div className="flex items-center justify-between h-20">
{/* Logo */}
<div className="flex items-center">
<Button
variant="ghost"
className="p-2 hover:bg-transparent"
onClick={() => navigate('/')}
>
<img
src={klcLogo}
alt="Kautilya Leadership Centre"
className="h-12 w-auto object-contain"
/>
</Button>
</div>
{/* Desktop Navigation */}
<div className="hidden lg:flex items-center gap-0">
{navigationItems.map((item) => (
<NavLink key={item.label} item={item} />
))}
</div>
{/* Right Side Actions */}
<div className="flex items-center gap-4">
<CartIcon />
{isAuthenticated && user ? (
<div className="hidden md:flex">
<ProfileDropdown user={user} />
</div>
) : (
<div className="hidden md:flex items-center">
<Button
onClick={() => navigate('/leadership-journey')}
className="management-dev-glassmorphic-btn text-body px-8 py-4 min-h-[52px] border transition-all duration-300 group"
style={{
fontFamily: 'var(--font-family-base)',
color: '#04045B',
backgroundColor: '#04045b',
}}
>
Start Leadership Journey
<ArrowRight
className="w-5 h-5 ml-2 transition-transform duration-300 group-hover:translate-x-1"
style={{ color: '#04045B' }}
/>
</Button>
</div>
)}
{/* Mobile Menu */}
<Sheet>
<SheetTrigger asChild>
<Button variant="ghost" size="icon" className="lg:hidden min-h-[44px] min-w-[44px]">
<Menu className="w-6 h-6" />
</Button>
</SheetTrigger>
<SheetContent
side="right"
className="w-80"
style={{
backgroundColor: 'var(--color-bg-white)',
fontFamily: 'var(--font-family-base)',
zIndex: 10000
}}
>
<SheetHeader>
<SheetTitle>
Navigation
</SheetTitle>
</SheetHeader>
<div className="mt-6 space-y-4">
{navigationItems.map((item) => (
<NavLink key={item.label} item={item} isMobile />
))}
<div className="pt-4 border-t space-y-3">
{isAuthenticated && user ? (
<div className="space-y-3">
{/* ... mobile user info and buttons with navigate() */}
</div>
) : (
<div className="space-y-2">
<Button
onClick={() => navigate('/leadership-journey')}
className="management-dev-glassmorphic-btn text-body px-8 py-4 min-h-[52px] border transition-all duration-300 w-full group"
style={{
fontFamily: 'var(--font-family-base)',
color: '#04045B'
}}
>
Start Leadership Journey
<ArrowRight
className="w-5 h-5 ml-2 transition-transform duration-300 group-hover:translate-x-1"
style={{ color: '#04045B' }}
/>
</Button>
</div>
)}
</div>
</div>
</SheetContent>
</Sheet>
</div>
</div>
</nav>
</header>
</>
);
}