616 lines
18 KiB
TypeScript
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>
|
|
</>
|
|
);
|
|
} |