2 Commits

Author SHA1 Message Date
f9016fd732 worked on the course modal 2025-09-09 17:38:12 +05:30
31a068ae4e worked on the files arrranging 2025-09-09 15:16:05 +05:30
60 changed files with 1366 additions and 1318 deletions

76
package-lock.json generated
View File

@@ -51,7 +51,8 @@
"react-hook-form": "^7.55.0", "react-hook-form": "^7.55.0",
"react-redux": "^9.2.0", "react-redux": "^9.2.0",
"react-resizable-panels": "^2.1.7", "react-resizable-panels": "^2.1.7",
"react-router-dom": "^7.8.2", "react-router": "^6.30.1",
"react-router-dom": "^6.30.1",
"recharts": "^2.15.2", "recharts": "^2.15.2",
"sonner": "^2.0.3", "sonner": "^2.0.3",
"tailwind-merge": "*", "tailwind-merge": "*",
@@ -1919,6 +1920,15 @@
} }
} }
}, },
"node_modules/@remix-run/router": {
"version": "1.23.0",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz",
"integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@rolldown/pluginutils": { "node_modules/@rolldown/pluginutils": {
"version": "1.0.0-beta.27", "version": "1.0.0-beta.27",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
@@ -2789,7 +2799,7 @@
"version": "19.1.12", "version": "19.1.12",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.12.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.12.tgz",
"integrity": "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w==", "integrity": "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w==",
"devOptional": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"csstype": "^3.0.2" "csstype": "^3.0.2"
@@ -2799,7 +2809,7 @@
"version": "19.1.9", "version": "19.1.9",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.9.tgz", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.9.tgz",
"integrity": "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==", "integrity": "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==",
"devOptional": true, "dev": true,
"license": "MIT", "license": "MIT",
"peerDependencies": { "peerDependencies": {
"@types/react": "^19.0.0" "@types/react": "^19.0.0"
@@ -2883,15 +2893,6 @@
"react-dom": "^18 || ^19 || ^19.0.0-rc" "react-dom": "^18 || ^19 || ^19.0.0-rc"
} }
}, },
"node_modules/cookie": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
"integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/csstype": { "node_modules/csstype": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
@@ -3019,17 +3020,6 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/date-fns": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
"license": "MIT",
"peer": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/kossnocorp"
}
},
"node_modules/decimal.js-light": { "node_modules/decimal.js-light": {
"version": "2.5.1", "version": "2.5.1",
"resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
@@ -3828,41 +3818,35 @@
} }
}, },
"node_modules/react-router": { "node_modules/react-router": {
"version": "7.8.2", "version": "6.30.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.8.2.tgz", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.1.tgz",
"integrity": "sha512-7M2fR1JbIZ/jFWqelpvSZx+7vd7UlBTfdZqf6OSdF9g6+sfdqJDAWcak6ervbHph200ePlu+7G8LdoiC3ReyAQ==", "integrity": "sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"cookie": "^1.0.1", "@remix-run/router": "1.23.0"
"set-cookie-parser": "^2.6.0"
}, },
"engines": { "engines": {
"node": ">=20.0.0" "node": ">=14.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"react": ">=18", "react": ">=16.8"
"react-dom": ">=18"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
}
} }
}, },
"node_modules/react-router-dom": { "node_modules/react-router-dom": {
"version": "7.8.2", "version": "6.30.1",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.8.2.tgz", "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.1.tgz",
"integrity": "sha512-Z4VM5mKDipal2jQ385H6UBhiiEDlnJPx6jyWsTYoZQdl5TrjxEV2a9yl3Fi60NBJxYzOTGTTHXPi0pdizvTwow==", "integrity": "sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"react-router": "7.8.2" "@remix-run/router": "1.23.0",
"react-router": "6.30.1"
}, },
"engines": { "engines": {
"node": ">=20.0.0" "node": ">=14.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"react": ">=18", "react": ">=16.8",
"react-dom": ">=18" "react-dom": ">=16.8"
} }
}, },
"node_modules/react-smooth": { "node_modules/react-smooth": {
@@ -4020,12 +4004,6 @@
"loose-envify": "^1.1.0" "loose-envify": "^1.1.0"
} }
}, },
"node_modules/set-cookie-parser": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
"license": "MIT"
},
"node_modules/sonner": { "node_modules/sonner": {
"version": "2.0.7", "version": "2.0.7",
"resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz", "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz",

View File

@@ -46,7 +46,8 @@
"react-hook-form": "^7.55.0", "react-hook-form": "^7.55.0",
"react-redux": "^9.2.0", "react-redux": "^9.2.0",
"react-resizable-panels": "^2.1.7", "react-resizable-panels": "^2.1.7",
"react-router-dom": "^7.8.2", "react-router": "^6.30.1",
"react-router-dom": "^6.30.1",
"recharts": "^2.15.2", "recharts": "^2.15.2",
"sonner": "^2.0.3", "sonner": "^2.0.3",
"tailwind-merge": "*", "tailwind-merge": "*",

View File

@@ -1,34 +1,8 @@
import { Routes, Route } from "react-router-dom"; import React from "react";
// import AppLayout from "./components/AppLayout"; import { Router } from "./components/Router";
// Pages
import IndividualWebinars from "./pages/IndividualWebinars";
import Leaderboard from "./pages/Leaderboard";
import HomePage from "./pages/HomePage";
import Dashboard from "./pages/learner/Dashboard";
import { Library } from "./pages/learner/Library";
import { CourseTimeline } from "./pages/learner/CourseTimeline";
import { Settings } from "./pages/Settings";
import { Surveys } from "./pages/Surveys";
export default function App() { export default function App() {
return ( return (
<> <Router />
<Routes>
{/* Main */}
<Route path="/" element={<Dashboard />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/library" element={<Library />} />
<Route path="/course" element={<CourseTimeline />} />
<Route path="/settings" element={<Settings userType="individual" />} />
<Route path="/surveys" element={<Surveys userType="individual" />} />
<Route path="/webinars" element={<IndividualWebinars />} />
<Route path="/individual-webinars" element={<IndividualWebinars />} />
<Route path="/leaderboard" element={<Leaderboard />} />
{/* Fallback */}
<Route path="*" element={<HomePage />} />
</Routes>
</>
); );
} }

View File

@@ -0,0 +1,14 @@
import React from "react";
import { Outlet } from "react-router-dom";
export default function AppLayout() {
return (
<div className="min-h-screen">
<main>
<Outlet />
</main>
</div>
);
}

View File

@@ -20,11 +20,11 @@ import {
} from './ui/sheet'; } from './ui/sheet';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from './ui/collapsible'; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from './ui/collapsible';
// import { navigate } from './Router'; // import { navigate } from './Router';
import { useAuth } from './AuthContext'; // import { useAuth } from './AuthContext';
// import klcLogo from 'figma:asset/209958db0c439ec78be82ab4f3e335a6aed5de89.png'; // import klcLogo from 'figma:asset/209958db0c439ec78be82ab4f3e335a6aed5de89.png';
// import exampleImage from 'figma:asset/6cae567b6bf6a44cb03b767e4308c4c705340d08.png'; // import exampleImage from 'figma:asset/6cae567b6bf6a44cb03b767e4308c4c705340d08.png';
const klcLogo = 'https://res.cloudinary.com/dt3k2apqd/image/upload/v1697045531/Kautilya_Leadership_Centre_Logo_hor_uxh0v4.png'; const klcLogo = 'https://res.cloudinary.com/dt3k2apqd/image/upload/v1697045531/Kautilya_Leadership_Centre_Logo_hor_uxh0v4.png';
const exampleImage = 'https://images.unsplash.com/photo-1508214751196-bcfd4ca60f91?w=150&h=150&fit=crop&crop=face'; const exampleImage = 'https://images.unsplash.com/photo-1508214751196-bcfd4ca60f91?w=150&h=150&fit=crop&crop=face';
import { import {
Menu, Menu,
ChevronDown, ChevronDown,
@@ -54,12 +54,13 @@ import {
ArrowRight ArrowRight
} from 'lucide-react'; } from 'lucide-react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
const navigate = useNavigate(); import { useAuth } from './AuthContext';
interface NavigationProps { interface NavigationProps {
currentPage?: string; currentPage?: string;
} }
export function Navigation({ currentPage }: NavigationProps) { export function Navigation({ currentPage }: NavigationProps) {
const navigate = useNavigate();
const [isScrolled, setIsScrolled] = useState(false); const [isScrolled, setIsScrolled] = useState(false);
const [activeDropdown, setActiveDropdown] = useState<string | null>(null); const [activeDropdown, setActiveDropdown] = useState<string | null>(null);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
@@ -73,14 +74,14 @@ export function Navigation({ currentPage }: NavigationProps) {
return urlParams.get(param); return urlParams.get(param);
}; };
const isIndividualUser = getQueryParam('view') === 'individual' || const isIndividualUser = getQueryParam('view') === 'individual' ||
(!getQueryParam('view') && currentPage?.includes('/dashboard')) || (!getQueryParam('view') && currentPage?.includes('/dashboard')) ||
(!getQueryParam('view') && currentPage?.includes('/library')) || (!getQueryParam('view') && currentPage?.includes('/library')) ||
(!getQueryParam('view') && currentPage?.includes('/course')) || (!getQueryParam('view') && currentPage?.includes('/course')) ||
(!getQueryParam('view') && currentPage?.includes('/settings')) || (!getQueryParam('view') && currentPage?.includes('/settings')) ||
(!getQueryParam('view') && currentPage?.includes('/surveys')) || (!getQueryParam('view') && currentPage?.includes('/surveys')) ||
(!getQueryParam('view') && currentPage?.includes('/webinars')) || (!getQueryParam('view') && currentPage?.includes('/webinars')) ||
(!getQueryParam('view') && currentPage?.includes('/leaderboard')); (!getQueryParam('view') && currentPage?.includes('/leaderboard'));
const isCorporateUser = getQueryParam('view') === 'corporate'; const isCorporateUser = getQueryParam('view') === 'corporate';
@@ -262,451 +263,447 @@ export function Navigation({ currentPage }: NavigationProps) {
]; ];
return ( return (
<nav className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${ // <nav className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${isScrolled ? 'bg-white/95 backdrop-blur-md shadow-sm' : 'bg-white'
isScrolled ? 'bg-white/95 backdrop-blur-md shadow-sm' : 'bg-white' // }`}>
}`}> // <div className="w-full px-4 lg:px-8">
<div className="w-full px-4 lg:px-8"> // <div className="flex items-center justify-between h-[70px]">
<div className="flex items-center justify-between h-[70px]"> // {/* Logo */}
{/* Logo */} // <div className="flex-shrink-0">
<div className="flex-shrink-0"> // <button
<button // onClick={() => navigate('/')}
onClick={() => navigate('/')} // className="flex items-center space-x-2 focus:outline-none focus:ring-2 focus:ring-primary rounded-lg p-1 hover:bg-gray-50 transition-colors"
className="flex items-center space-x-2 focus:outline-none focus:ring-2 focus:ring-primary rounded-lg p-1 hover:bg-gray-50 transition-colors" // aria-label="Go to KLC homepage"
aria-label="Go to KLC homepage" // >
> // <img
<img // src={klcLogo}
src={klcLogo} // alt="Kautilya Leadership Centre"
alt="Kautilya Leadership Centre" // className="h-12 w-auto object-contain"
className="h-12 w-auto object-contain" // />
/> // </button>
</button> // </div>
</div>
{/* Desktop Navigation */} // {/* Desktop Navigation */}
<div className="hidden lg:flex items-center space-x-8"> // <div className="hidden lg:flex items-center space-x-8">
{navigationItems.map((item) => ( // {navigationItems.map((item) => (
<div key={item.title} className="relative" data-dropdown> // <div key={item.title} className="relative" data-dropdown>
<button // <button
onClick={() => handleDropdownToggle(item.title)} // onClick={() => handleDropdownToggle(item.title)}
className="flex items-center space-x-1 text-[16px] text-foreground hover:text-primary transition-colors py-2 px-3 rounded-lg hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-primary" // className="flex items-center space-x-1 text-[16px] text-foreground hover:text-primary transition-colors py-2 px-3 rounded-lg hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-primary"
aria-expanded={activeDropdown === item.title} // aria-expanded={activeDropdown === item.title}
aria-haspopup="true" // aria-haspopup="true"
> // >
<span>{item.title}</span> // <span>{item.title}</span>
<ChevronDown className={`h-4 w-4 transition-transform ${ // <ChevronDown className={`h-4 w-4 transition-transform ${activeDropdown === item.title ? 'rotate-180' : ''
activeDropdown === item.title ? 'rotate-180' : '' // }`} />
}`} /> // </button>
</button>
{activeDropdown === item.title && ( // {activeDropdown === item.title && (
<div className="absolute top-full left-0 mt-2 w-64 bg-white rounded-lg shadow-lg border border-gray-200 py-2 z-50"> // <div className="absolute top-full left-0 mt-2 w-64 bg-white rounded-lg shadow-lg border border-gray-200 py-2 z-50">
{item.items.map((subItem) => { // {item.items.map((subItem) => {
const IconComponent = subItem.icon; // const IconComponent = subItem.icon;
return ( // return (
<button // <button
key={subItem.title} // key={subItem.title}
onClick={() => { // onClick={() => {
navigate(subItem.href); // navigate(subItem.href);
setActiveDropdown(null); // setActiveDropdown(null);
}} // }}
className="w-full flex items-center space-x-3 px-4 py-3 text-[16px] text-gray-700 hover:bg-gray-50 hover:text-primary transition-colors text-left focus:outline-none focus:ring-2 focus:ring-primary" // className="w-full flex items-center space-x-3 px-4 py-3 text-[16px] text-gray-700 hover:bg-gray-50 hover:text-primary transition-colors text-left focus:outline-none focus:ring-2 focus:ring-primary"
> // >
<IconComponent className="h-4 w-4 flex-shrink-0" /> // <IconComponent className="h-4 w-4 flex-shrink-0" />
<span>{subItem.title}</span> // <span>{subItem.title}</span>
</button> // </button>
); // );
})} // })}
</div> // </div>
)} // )}
</div> // </div>
))} // ))}
<button // <button
onClick={() => navigate('/contact')} // onClick={() => navigate('/contact')}
className="text-[16px] text-foreground hover:text-primary transition-colors py-2 px-3 rounded-lg hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-primary" // className="text-[16px] text-foreground hover:text-primary transition-colors py-2 px-3 rounded-lg hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-primary"
> // >
Contact // Contact
</button> // </button>
</div> // </div>
{/* Right Section - Desktop */} // {/* Right Section - Desktop */}
<div className="hidden lg:flex items-center space-x-4"> // <div className="hidden lg:flex items-center space-x-4">
{!isAuthenticated ? ( // {!isAuthenticated ? (
<> // <>
<Button // <Button
variant="ghost" // variant="ghost"
onClick={handleLogin} // onClick={handleLogin}
className="text-[16px] min-h-[44px]" // className="text-[16px] min-h-[44px]"
> // >
Sign In // Sign In
</Button> // </Button>
<Button // <Button
onClick={handleSignup} // onClick={handleSignup}
className="text-[16px] min-h-[44px] bg-primary hover:bg-primary/90 text-primary-foreground" // className="text-[16px] min-h-[44px] bg-primary hover:bg-primary/90 text-primary-foreground"
> // >
Get Started // Get Started
</Button> // </Button>
</> // </>
) : ( // ) : (
<div className="flex items-center space-x-4"> // <div className="flex items-center space-x-4">
{/* Redesigned User Profile Dropdown */} // {/* Redesigned User Profile Dropdown */}
<DropdownMenu> // <DropdownMenu>
<DropdownMenuTrigger asChild> // <DropdownMenuTrigger asChild>
<Button // <Button
variant="ghost" // variant="ghost"
className="flex items-center gap-3 h-auto p-2 hover:bg-gray-50 transition-all duration-200 rounded-lg min-h-[44px]" // className="flex items-center gap-3 h-auto p-2 hover:bg-gray-50 transition-all duration-200 rounded-lg min-h-[44px]"
aria-label="Open user menu" // aria-label="Open user menu"
> // >
<Avatar className="h-8 w-8"> // <Avatar className="h-8 w-8">
<AvatarImage // <AvatarImage
src={currentUser.avatar} // src={currentUser.avatar}
alt={currentUser.name} // alt={currentUser.name}
/> // />
<AvatarFallback className="bg-primary/10 text-primary text-sm"> // <AvatarFallback className="bg-primary/10 text-primary text-sm">
{currentUser.name.split(' ').map(n => n[0]).join('')} // {currentUser.name.split(' ').map(n => n[0]).join('')}
</AvatarFallback> // </AvatarFallback>
</Avatar> // </Avatar>
<div className="flex flex-col items-start min-w-0"> // <div className="flex flex-col items-start min-w-0">
<span className="text-[16px] font-medium text-gray-900 truncate"> // <span className="text-[16px] font-medium text-gray-900 truncate">
{currentUser.name} // {currentUser.name}
</span> // </span>
<span className="text-[14px] text-gray-600 truncate"> // <span className="text-[14px] text-gray-600 truncate">
{isIndividualUser ? 'Individual Account' : 'Corporate Account'} // {isIndividualUser ? 'Individual Account' : 'Corporate Account'}
</span> // </span>
</div> // </div>
<ChevronDown className="h-4 w-4 text-gray-500 flex-shrink-0" /> // <ChevronDown className="h-4 w-4 text-gray-500 flex-shrink-0" />
</Button> // </Button>
</DropdownMenuTrigger> // </DropdownMenuTrigger>
<DropdownMenuContent className="w-80 p-0" align="end" forceMount> // <DropdownMenuContent className="w-80 p-0" align="end" forceMount>
{/* Header Section */} // {/* Header Section */}
<div className="p-4 border-b border-gray-100 bg-gray-50"> // <div className="p-4 border-b border-gray-100 bg-gray-50">
<div className="flex items-center gap-3"> // <div className="flex items-center gap-3">
<Avatar className="h-12 w-12"> // <Avatar className="h-12 w-12">
<AvatarImage // <AvatarImage
src={currentUser.avatar} // src={currentUser.avatar}
alt={currentUser.name} // alt={currentUser.name}
/> // />
<AvatarFallback className="bg-primary/10 text-primary text-lg"> // <AvatarFallback className="bg-primary/10 text-primary text-lg">
{currentUser.name.split(' ').map(n => n[0]).join('')} // {currentUser.name.split(' ').map(n => n[0]).join('')}
</AvatarFallback> // </AvatarFallback>
</Avatar> // </Avatar>
<div className="flex-1 min-w-0"> // <div className="flex-1 min-w-0">
<div className="flex items-center gap-2"> // <div className="flex items-center gap-2">
<p className="text-[16px] font-semibold text-gray-900 truncate"> // <p className="text-[16px] font-semibold text-gray-900 truncate">
{currentUser.name} // {currentUser.name}
</p> // </p>
<ChevronDown className="h-4 w-4 text-gray-400 flex-shrink-0" /> // <ChevronDown className="h-4 w-4 text-gray-400 flex-shrink-0" />
</div> // </div>
<p className="text-[14px] text-gray-600 truncate"> // <p className="text-[14px] text-gray-600 truncate">
{isIndividualUser ? 'Individual Account' : 'Corporate Account'} // {isIndividualUser ? 'Individual Account' : 'Corporate Account'}
</p> // </p>
</div> // </div>
</div> // </div>
</div> // </div>
{/* Account Switching Section */} // {/* Account Switching Section */}
<div className="p-4 border-b border-gray-100"> // <div className="p-4 border-b border-gray-100">
<h4 className="text-[14px] font-medium text-gray-900 mb-3">Switch Account</h4> // <h4 className="text-[14px] font-medium text-gray-900 mb-3">Switch Account</h4>
<div className="space-y-2"> // <div className="space-y-2">
{availableAccounts.map((account) => { // {availableAccounts.map((account) => {
const IconComponent = account.icon; // const IconComponent = account.icon;
return ( // return (
<div // <div
key={account.type} // key={account.type}
className={`flex items-center gap-3 p-3 rounded-lg border transition-all duration-200 ${ // className={`flex items-center gap-3 p-3 rounded-lg border transition-all duration-200 ${account.isActive
account.isActive // ? 'bg-green-50 border-green-200'
? 'bg-green-50 border-green-200' // : 'bg-gray-50 border-gray-200 hover:bg-gray-100 cursor-pointer'
: 'bg-gray-50 border-gray-200 hover:bg-gray-100 cursor-pointer' // }`}
}`} // onClick={() => !account.isActive && handleAccountSignIn(account.type as 'individual' | 'corporate')}
onClick={() => !account.isActive && handleAccountSignIn(account.type as 'individual' | 'corporate')} // >
> // <div className="relative">
<div className="relative"> // {account.type === 'individual' ? (
{account.type === 'individual' ? ( // <Avatar className="h-8 w-8">
<Avatar className="h-8 w-8"> // <AvatarImage
<AvatarImage // src={currentUser.avatar}
src={currentUser.avatar} // alt={currentUser.name}
alt={currentUser.name} // />
/> // <AvatarFallback className="bg-blue-100 text-blue-700 text-sm">
<AvatarFallback className="bg-blue-100 text-blue-700 text-sm"> // <User className="h-4 w-4" />
<User className="h-4 w-4" /> // </AvatarFallback>
</AvatarFallback> // </Avatar>
</Avatar> // ) : (
) : ( // <div className="h-8 w-8 bg-purple-100 rounded-full flex items-center justify-center">
<div className="h-8 w-8 bg-purple-100 rounded-full flex items-center justify-center"> // <Building2 className="h-4 w-4 text-purple-700" />
<Building2 className="h-4 w-4 text-purple-700" /> // </div>
</div> // )}
)} // {account.isActive && (
{account.isActive && ( // <div className="absolute -top-1 -right-1 w-4 h-4 bg-green-500 rounded-full flex items-center justify-center">
<div className="absolute -top-1 -right-1 w-4 h-4 bg-green-500 rounded-full flex items-center justify-center"> // <Check className="h-2.5 w-2.5 text-white" />
<Check className="h-2.5 w-2.5 text-white" /> // </div>
</div> // )}
)} // </div>
</div> // <div className="flex-1 min-w-0">
<div className="flex-1 min-w-0"> // <p className="text-[14px] font-medium text-gray-900 truncate">
<p className="text-[14px] font-medium text-gray-900 truncate"> // {account.title}
{account.title} // </p>
</p> // <p className="text-[14px] text-gray-600 truncate">
<p className="text-[14px] text-gray-600 truncate"> // {account.subtitle}
{account.subtitle} // </p>
</p> // </div>
</div> // {!account.isActive && (
{!account.isActive && ( // <ArrowRight className="h-4 w-4 text-gray-400 flex-shrink-0" />
<ArrowRight className="h-4 w-4 text-gray-400 flex-shrink-0" /> // )}
)} // </div>
</div> // );
); // })}
})} // </div>
</div> // </div>
</div>
<DropdownMenuSeparator /> // <DropdownMenuSeparator />
{/* Settings and Logout */} // {/* Settings and Logout */}
<div className="p-2"> // <div className="p-2">
<DropdownMenuItem // <DropdownMenuItem
className="flex items-center gap-3 px-3 py-2 cursor-pointer rounded-md hover:bg-gray-50 focus:bg-gray-50 min-h-[44px]" // className="flex items-center gap-3 px-3 py-2 cursor-pointer rounded-md hover:bg-gray-50 focus:bg-gray-50 min-h-[44px]"
onClick={() => navigate(learnerMenuItems[learnerMenuItems.length - 1].href)} // onClick={() => navigate(learnerMenuItems[learnerMenuItems.length - 1].href)}
> // >
<Settings className="h-5 w-5 text-gray-500" /> // <Settings className="h-5 w-5 text-gray-500" />
<span className="text-[16px] font-medium text-gray-900">Settings</span> // <span className="text-[16px] font-medium text-gray-900">Settings</span>
</DropdownMenuItem> // </DropdownMenuItem>
<DropdownMenuItem
className="flex items-center gap-3 px-3 py-2 cursor-pointer rounded-md text-red-600 hover:bg-red-50 focus:bg-red-50 min-h-[44px]"
onClick={handleLogout}
>
<LogOut className="h-5 w-5" />
<span className="text-[16px] font-medium">Sign Out</span>
</DropdownMenuItem>
</div>
</DropdownMenuContent>
</DropdownMenu>
</div>
)}
</div>
{/* Mobile Menu Button */} // <DropdownMenuItem
<div className="lg:hidden"> // className="flex items-center gap-3 px-3 py-2 cursor-pointer rounded-md text-red-600 hover:bg-red-50 focus:bg-red-50 min-h-[44px]"
<Sheet open={isMobileMenuOpen} onOpenChange={setIsMobileMenuOpen}> // onClick={handleLogout}
<SheetTrigger asChild> // >
<Button // <LogOut className="h-5 w-5" />
variant="ghost" // <span className="text-[16px] font-medium">Sign Out</span>
size="icon" // </DropdownMenuItem>
className="h-10 w-10" // </div>
aria-label="Open mobile menu" // </DropdownMenuContent>
> // </DropdownMenu>
<Menu className="h-6 w-6" /> // </div>
</Button> // )}
</SheetTrigger> // </div>
<SheetContent side="right" className="w-full sm:w-96 p-0">
<SheetHeader className="p-6 border-b border-gray-200">
<SheetTitle className="text-left flex items-center gap-3">
<img
src={klcLogo}
alt="KLC"
className="h-8 w-auto object-contain"
/>
<span className="text-lg font-semibold">Menu</span>
</SheetTitle>
</SheetHeader>
<div className="flex flex-col h-full"> // {/* Mobile Menu Button */}
{/* User Section for Mobile */} // <div className="lg:hidden">
{isAuthenticated && ( // <Sheet open={isMobileMenuOpen} onOpenChange={setIsMobileMenuOpen}>
<div className="p-4 border-b border-gray-200"> // <SheetTrigger asChild>
<div className="flex items-center gap-3 mb-4"> // <Button
<Avatar className="h-12 w-12"> // variant="ghost"
<AvatarImage // size="icon"
src={currentUser.avatar} // className="h-10 w-10"
alt={currentUser.name} // aria-label="Open mobile menu"
/> // >
<AvatarFallback className="bg-primary/10 text-primary"> // <Menu className="h-6 w-6" />
{currentUser.name.split(' ').map(n => n[0]).join('')} // </Button>
</AvatarFallback> // </SheetTrigger>
</Avatar> // <SheetContent side="right" className="w-full sm:w-96 p-0">
<div className="flex-1 min-w-0"> // <SheetHeader className="p-6 border-b border-gray-200">
<p className="text-[16px] font-semibold text-gray-900 truncate"> // <SheetTitle className="text-left flex items-center gap-3">
{currentUser.name} // <img
</p> // src={klcLogo}
<p className="text-[14px] text-gray-600 truncate"> // alt="KLC"
{isIndividualUser ? 'Individual Account' : 'Corporate Account'} // className="h-8 w-auto object-contain"
</p> // />
</div> // <span className="text-lg font-semibold">Menu</span>
</div> // </SheetTitle>
// </SheetHeader>
{/* Mobile Account Switching */} // <div className="flex flex-col h-full">
<div className="space-y-3"> // {/* User Section for Mobile */}
<h4 className="text-[14px] font-medium text-gray-900">Switch Account</h4> // {isAuthenticated && (
<div className="space-y-2"> // <div className="p-4 border-b border-gray-200">
{availableAccounts.map((account) => ( // <div className="flex items-center gap-3 mb-4">
<button // <Avatar className="h-12 w-12">
key={account.type} // <AvatarImage
onClick={() => !account.isActive && handleAccountSignIn(account.type as 'individual' | 'corporate')} // src={currentUser.avatar}
disabled={account.isActive} // alt={currentUser.name}
className={`w-full flex items-center gap-3 p-3 rounded-lg border text-left transition-all duration-200 ${ // />
account.isActive // <AvatarFallback className="bg-primary/10 text-primary">
? 'bg-green-50 border-green-200' // {currentUser.name.split(' ').map(n => n[0]).join('')}
: 'bg-gray-50 border-gray-200 hover:bg-gray-100' // </AvatarFallback>
}`} // </Avatar>
> // <div className="flex-1 min-w-0">
<div className="relative"> // <p className="text-[16px] font-semibold text-gray-900 truncate">
{account.type === 'individual' ? ( // {currentUser.name}
<Avatar className="h-8 w-8"> // </p>
<AvatarImage // <p className="text-[14px] text-gray-600 truncate">
src={currentUser.avatar} // {isIndividualUser ? 'Individual Account' : 'Corporate Account'}
alt={currentUser.name} // </p>
/> // </div>
<AvatarFallback className="bg-blue-100 text-blue-700 text-sm"> // </div>
<User className="h-4 w-4" />
</AvatarFallback>
</Avatar>
) : (
<div className="h-8 w-8 bg-purple-100 rounded-full flex items-center justify-center">
<Building2 className="h-4 w-4 text-purple-700" />
</div>
)}
{account.isActive && (
<div className="absolute -top-1 -right-1 w-4 h-4 bg-green-500 rounded-full flex items-center justify-center">
<Check className="h-2.5 w-2.5 text-white" />
</div>
)}
</div>
<div className="flex-1 min-w-0">
<p className="text-[14px] font-medium text-gray-900 truncate">
{account.title}
</p>
<p className="text-[14px] text-gray-600 truncate">
{account.subtitle}
</p>
</div>
{!account.isActive && (
<ArrowRight className="h-4 w-4 text-gray-400 flex-shrink-0" />
)}
</button>
))}
</div>
</div>
</div>
)}
{/* Navigation Items */} // {/* Mobile Account Switching */}
<div className="flex-1 overflow-y-auto py-4"> // <div className="space-y-3">
{/* Learner Portal Items (if authenticated) */} // <h4 className="text-[14px] font-medium text-gray-900">Switch Account</h4>
{isAuthenticated && (isIndividualUser || isCorporateUser) && ( // <div className="space-y-2">
<div className="px-4 mb-6"> // {availableAccounts.map((account) => (
<h3 className="text-[14px] font-medium text-gray-900 mb-3"> // <button
{isIndividualUser ? 'Personal Learning' : 'Corporate Learning'} // key={account.type}
</h3> // onClick={() => !account.isActive && handleAccountSignIn(account.type as 'individual' | 'corporate')}
<div className="space-y-1"> // disabled={account.isActive}
{learnerMenuItems.map((item) => { // className={`w-full flex items-center gap-3 p-3 rounded-lg border text-left transition-all duration-200 ${account.isActive
const IconComponent = item.icon; // ? 'bg-green-50 border-green-200'
return ( // : 'bg-gray-50 border-gray-200 hover:bg-gray-100'
<button // }`}
key={item.title} // >
onClick={() => { // <div className="relative">
navigate(item.href); // {account.type === 'individual' ? (
setIsMobileMenuOpen(false); // <Avatar className="h-8 w-8">
}} // <AvatarImage
className="w-full flex items-center gap-3 px-3 py-2 text-left text-[16px] text-gray-700 hover:bg-gray-50 hover:text-primary rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-primary min-h-[44px]" // src={currentUser.avatar}
> // alt={currentUser.name}
<IconComponent className="h-5 w-5 flex-shrink-0" /> // />
<div className="flex-1 min-w-0"> // <AvatarFallback className="bg-blue-100 text-blue-700 text-sm">
<div className="font-medium">{item.title}</div> // <User className="h-4 w-4" />
<div className="text-[14px] text-gray-500 truncate">{item.description}</div> // </AvatarFallback>
</div> // </Avatar>
</button> // ) : (
); // <div className="h-8 w-8 bg-purple-100 rounded-full flex items-center justify-center">
})} // <Building2 className="h-4 w-4 text-purple-700" />
</div> // </div>
</div> // )}
)} // {account.isActive && (
// <div className="absolute -top-1 -right-1 w-4 h-4 bg-green-500 rounded-full flex items-center justify-center">
// <Check className="h-2.5 w-2.5 text-white" />
// </div>
// )}
// </div>
// <div className="flex-1 min-w-0">
// <p className="text-[14px] font-medium text-gray-900 truncate">
// {account.title}
// </p>
// <p className="text-[14px] text-gray-600 truncate">
// {account.subtitle}
// </p>
// </div>
// {!account.isActive && (
// <ArrowRight className="h-4 w-4 text-gray-400 flex-shrink-0" />
// )}
// </button>
// ))}
// </div>
// </div>
// </div>
// )}
{/* Public Navigation Items */} // {/* Navigation Items */}
<div className="px-4"> // <div className="flex-1 overflow-y-auto py-4">
{navigationItems.map((item) => ( // {/* Learner Portal Items (if authenticated) */}
<Collapsible key={item.title}> // {isAuthenticated && (isIndividualUser || isCorporateUser) && (
<CollapsibleTrigger // <div className="px-4 mb-6">
onClick={() => handleMobileToggle(item.title)} // <h3 className="text-[14px] font-medium text-gray-900 mb-3">
className="w-full flex items-center justify-between p-3 text-[16px] text-gray-900 hover:bg-gray-50 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-primary min-h-[44px]" // {isIndividualUser ? 'Personal Learning' : 'Corporate Learning'}
> // </h3>
<span className="font-medium">{item.title}</span> // <div className="space-y-1">
<ChevronRight className={`h-4 w-4 transition-transform ${ // {learnerMenuItems.map((item) => {
expandedMobileSection === item.title ? 'rotate-90' : '' // const IconComponent = item.icon;
}`} /> // return (
</CollapsibleTrigger> // <button
<CollapsibleContent className="px-4 pb-2"> // key={item.title}
<div className="space-y-1"> // onClick={() => {
{item.items.map((subItem) => { // navigate(item.href);
const IconComponent = subItem.icon; // setIsMobileMenuOpen(false);
return ( // }}
<button // className="w-full flex items-center gap-3 px-3 py-2 text-left text-[16px] text-gray-700 hover:bg-gray-50 hover:text-primary rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-primary min-h-[44px]"
key={subItem.title} // >
onClick={() => { // <IconComponent className="h-5 w-5 flex-shrink-0" />
navigate(subItem.href); // <div className="flex-1 min-w-0">
setIsMobileMenuOpen(false); // <div className="font-medium">{item.title}</div>
}} // <div className="text-[14px] text-gray-500 truncate">{item.description}</div>
className="w-full flex items-center gap-3 px-3 py-2 text-left text-[16px] text-gray-600 hover:bg-gray-50 hover:text-primary rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-primary min-h-[44px]" // </div>
> // </button>
<IconComponent className="h-4 w-4 flex-shrink-0" /> // );
<span>{subItem.title}</span> // })}
</button> // </div>
); // </div>
})} // )}
</div>
</CollapsibleContent>
</Collapsible>
))}
<button
onClick={() => {
navigate('/contact');
setIsMobileMenuOpen(false);
}}
className="w-full flex items-center p-3 text-[16px] text-gray-900 hover:bg-gray-50 rounded-lg transition-colors text-left focus:outline-none focus:ring-2 focus:ring-primary min-h-[44px]"
>
<span className="font-medium">Contact</span>
</button>
</div>
</div>
{/* Mobile Authentication Actions */} // {/* Public Navigation Items */}
{!isAuthenticated && ( // <div className="px-4">
<div className="p-4 border-t border-gray-200 space-y-2"> // {navigationItems.map((item) => (
<Button // <Collapsible key={item.title}>
onClick={handleLogin} // <CollapsibleTrigger
variant="outline" // onClick={() => handleMobileToggle(item.title)}
className="w-full text-[16px] min-h-[44px]" // className="w-full flex items-center justify-between p-3 text-[16px] text-gray-900 hover:bg-gray-50 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-primary min-h-[44px]"
> // >
Sign In // <span className="font-medium">{item.title}</span>
</Button> // <ChevronRight className={`h-4 w-4 transition-transform ${expandedMobileSection === item.title ? 'rotate-90' : ''
<Button // }`} />
onClick={handleSignup} // </CollapsibleTrigger>
className="w-full text-[16px] min-h-[44px] bg-primary hover:bg-primary/90 text-primary-foreground" // <CollapsibleContent className="px-4 pb-2">
> // <div className="space-y-1">
Get Started // {item.items.map((subItem) => {
</Button> // const IconComponent = subItem.icon;
</div> // return (
)} // <button
// key={subItem.title}
// onClick={() => {
// navigate(subItem.href);
// setIsMobileMenuOpen(false);
// }}
// className="w-full flex items-center gap-3 px-3 py-2 text-left text-[16px] text-gray-600 hover:bg-gray-50 hover:text-primary rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-primary min-h-[44px]"
// >
// <IconComponent className="h-4 w-4 flex-shrink-0" />
// <span>{subItem.title}</span>
// </button>
// );
// })}
// </div>
// </CollapsibleContent>
// </Collapsible>
// ))}
{/* Mobile Logout */} // <button
{isAuthenticated && ( // onClick={() => {
<div className="p-4 border-t border-gray-200"> // navigate('/contact');
<Button // setIsMobileMenuOpen(false);
onClick={handleLogout} // }}
variant="outline" // className="w-full flex items-center p-3 text-[16px] text-gray-900 hover:bg-gray-50 rounded-lg transition-colors text-left focus:outline-none focus:ring-2 focus:ring-primary min-h-[44px]"
className="w-full text-[16px] min-h-[44px] text-red-600 border-red-200 hover:bg-red-50" // >
> // <span className="font-medium">Contact</span>
<LogOut className="h-4 w-4 mr-2" /> // </button>
Sign Out // </div>
</Button> // </div>
</div>
)} // {/* Mobile Authentication Actions */}
</div> // {!isAuthenticated && (
</SheetContent> // <div className="p-4 border-t border-gray-200 space-y-2">
</Sheet> // <Button
</div> // onClick={handleLogin}
</div> // variant="outline"
</div> // className="w-full text-[16px] min-h-[44px]"
</nav> // >
// Sign In
// </Button>
// <Button
// onClick={handleSignup}
// className="w-full text-[16px] min-h-[44px] bg-primary hover:bg-primary/90 text-primary-foreground"
// >
// Get Started
// </Button>
// </div>
// )}
// {/* Mobile Logout */}
// {isAuthenticated && (
// <div className="p-4 border-t border-gray-200">
// <Button
// onClick={handleLogout}
// variant="outline"
// className="w-full text-[16px] min-h-[44px] text-red-600 border-red-200 hover:bg-red-50"
// >
// <LogOut className="h-4 w-4 mr-2" />
// Sign Out
// </Button>
// </div>
// )}
// </div>
// </SheetContent>
// </Sheet>
// </div>
// </div>
// </div>
// </nav>
<></>
); );
} }

View File

@@ -1,4 +1,6 @@
import React from "react";
import { Routes, Route, Navigate, useSearchParams } from "react-router-dom"; import { Routes, Route, Navigate, useSearchParams } from "react-router-dom";
import AppLayout from "./AppLayout";
// Import all page components // Import all page components
import { HomePage } from "../pages/HomePage"; import { HomePage } from "../pages/HomePage";
@@ -83,136 +85,138 @@ export function Router() {
return ( return (
<div className="min-h-screen"> <div className="min-h-screen">
<Routes> <Routes>
{/* Main */} <Route path="/" element={<AppLayout />}>
<Route path="/" element={<HomePage />} /> {/* Main */}
<Route index element={<HomePage />} />
{/* Auth */} {/* Auth */}
<Route path="/auth" element={<LoginSelection />} /> <Route path="auth" element={<LoginSelection />} />
<Route path="/login-selection" element={<LoginSelection />} /> <Route path="login-selection" element={<LoginSelection />} />
<Route path="/login" element={<Login />} /> <Route path="login" element={<Login />} />
<Route path="/signup" element={<Signup />} /> <Route path="signup" element={<Signup />} />
<Route path="/corporate/auth" element={<CorporateAuth />} /> <Route path="corporate/auth" element={<CorporateAuth />} />
<Route path="/corporate/login" element={<CorporateLogin />} /> <Route path="corporate/login" element={<CorporateLogin />} />
<Route path="/corporate/signup" element={<CorporateSignup />} /> <Route path="corporate/signup" element={<CorporateSignup />} />
<Route path="/forgot-password" element={<ForgotPassword />} /> <Route path="forgot-password" element={<ForgotPassword />} />
<Route path="/email-verification" element={<EmailVerification />} /> <Route path="email-verification" element={<EmailVerification />} />
{/* Learner Portal */} {/* Learner Portal */}
<Route path="/dashboard" element={<DashboardRoute />} /> <Route path="dashboard" element={<DashboardRoute />} />
<Route path="/library" element={<Library />} /> <Route path="library" element={<Library />} />
<Route path="/course" element={<CourseTimeline />} /> <Route path="course" element={<CourseTimeline />} />
<Route path="/settings" element={<Settings />} /> <Route path="settings" element={<Settings />} />
<Route path="/surveys" element={<Surveys userType="individual" />} /> <Route path="surveys" element={<Surveys userType="individual" />} />
<Route path="/webinars" element={<WebinarsRoute />} /> <Route path="webinars" element={<WebinarsRoute />} />
<Route path="/leaderboard" element={<LeaderboardRoute />} /> <Route path="leaderboard" element={<LeaderboardRoute />} />
{/* Other Pages */} {/* Other Pages */}
<Route path="/individual-webinars" element={<IndividualWebinars />} /> <Route path="individual-webinars" element={<IndividualWebinars />} />
<Route path="/contact" element={<Contact />} /> <Route path="contact" element={<Contact />} />
<Route path="/about-klc" element={<AboutKLC />} /> <Route path="about-klc" element={<AboutKLC />} />
<Route path="/about-us/our-vision" element={<OurVision />} /> <Route path="about-us/our-vision" element={<OurVision />} />
<Route path="/about-us/our-team" element={<OurTeam />} /> <Route path="about-us/our-team" element={<OurTeam />} />
<Route path="/about-us/our-impact" element={<OurImpact />} /> <Route path="about-us/our-impact" element={<OurImpact />} />
<Route path="/about-us/our-expertise" element={<OurExpertise />} /> <Route path="about-us/our-expertise" element={<OurExpertise />} />
{/* Programmes */} {/* Programmes */}
<Route path="/programmes" element={<ProgrammeCatalogue />} /> <Route path="programmes" element={<ProgrammeCatalogue />} />
<Route path="/programmes/detail" element={<ProgrammeDetail />} /> <Route path="programmes/detail" element={<ProgrammeDetail />} />
<Route <Route
path="/programmes/executive-leadership" path="programmes/executive-leadership"
element={<ExecutiveLeadership />} element={<ExecutiveLeadership />}
/> />
<Route path="/programmes/team-leadership" element={<TeamLeadership />} /> <Route path="programmes/team-leadership" element={<TeamLeadership />} />
<Route <Route
path="/programmes/innovation-leadership" path="programmes/innovation-leadership"
element={<InnovationLeadership />} element={<InnovationLeadership />}
/> />
<Route <Route
path="/programmes/leadership-online" path="programmes/leadership-online"
element={<LeadershipOnline />} element={<LeadershipOnline />}
/> />
{/* Services */} {/* Services */}
<Route <Route
path="/services/leadership-development" path="services/leadership-development"
element={<LeadershipDevelopment />} element={<LeadershipDevelopment />}
/> />
<Route <Route
path="/services/management-development" path="services/management-development"
element={<ManagementDevelopment />} element={<ManagementDevelopment />}
/> />
<Route <Route
path="/services/executive-coaching" path="services/executive-coaching"
element={<ExecutiveCoaching />} element={<ExecutiveCoaching />}
/> />
<Route <Route
path="/services/culture-competence" path="services/culture-competence"
element={<CultureCompetence />} element={<CultureCompetence />}
/> />
<Route path="/services/consulting" element={<Consulting />} /> <Route path="services/consulting" element={<Consulting />} />
<Route path="/services/learning-facility" element={<LearningFacility />} /> <Route path="services/learning-facility" element={<LearningFacility />} />
{/* Learning */} {/* Learning */}
<Route path="/learning/articles" element={<Articles />} /> <Route path="learning/articles" element={<Articles />} />
<Route path="/learning/blog" element={<BlogListing />} /> <Route path="learning/blog" element={<BlogListing />} />
<Route path="/learning/blog/detail" element={<BlogDetail />} /> <Route path="learning/blog/detail" element={<BlogDetail />} />
<Route path="/learning/resources" element={<Resources />} /> <Route path="learning/resources" element={<Resources />} />
{/* Webinars */} {/* Webinars */}
<Route path="/webinars/listing" element={<WebinarListing />} /> <Route path="webinars/listing" element={<WebinarListing />} />
<Route path="/webinars/detail" element={<WebinarDetail />} /> <Route path="webinars/detail" element={<WebinarDetail />} />
{/* Facilities */} {/* Facilities */}
<Route path="/facilities/detail" element={<FacilityDetail />} /> <Route path="facilities/detail" element={<FacilityDetail />} />
<Route path="/facilities/booking" element={<FacilityBooking />} /> <Route path="facilities/booking" element={<FacilityBooking />} />
<Route path="/facilities/tour" element={<FacilityTour />} /> <Route path="facilities/tour" element={<FacilityTour />} />
{/* E-commerce */} {/* E-commerce */}
<Route path="/cart" element={<Cart />} /> <Route path="cart" element={<Cart />} />
<Route path="/checkout" element={<Checkout />} /> <Route path="checkout" element={<Checkout />} />
<Route path="/order-confirmation" element={<OrderConfirmation />} /> <Route path="order-confirmation" element={<OrderConfirmation />} />
<Route path="/order-failed" element={<OrderFailed />} /> <Route path="order-failed" element={<OrderFailed />} />
{/* Extra Features */} {/* Extra Features */}
<Route path="/my-cohort" element={<MyCohort />} /> <Route path="my-cohort" element={<MyCohort />} />
{/* Legal */} {/* Legal */}
<Route path="/faq" element={<FAQ />} /> <Route path="faq" element={<FAQ />} />
<Route path="/privacy" element={<Privacy />} /> <Route path="privacy" element={<Privacy />} />
<Route path="/terms" element={<Terms />} /> <Route path="terms" element={<Terms />} />
{/* Legacy Redirects */} {/* Legacy Redirects */}
<Route <Route
path="/corporate/dashboard" path="corporate/dashboard"
element={<Navigate to="/dashboard?view=corporate" replace />} element={<Navigate to="/dashboard?view=corporate" replace />}
/> />
<Route <Route
path="/corporate/library" path="corporate/library"
element={<Navigate to="/library?view=corporate" replace />} element={<Navigate to="/library?view=corporate" replace />}
/> />
<Route <Route
path="/corporate/course" path="corporate/course"
element={<Navigate to="/course?view=corporate" replace />} element={<Navigate to="/course?view=corporate" replace />}
/> />
<Route <Route
path="/corporate/settings" path="corporate/settings"
element={<Navigate to="/settings?view=corporate" replace />} element={<Navigate to="/settings?view=corporate" replace />}
/> />
<Route <Route
path="/corporate/surveys" path="corporate/surveys"
element={<Navigate to="/surveys?view=corporate" replace />} element={<Navigate to="/surveys?view=corporate" replace />}
/> />
<Route <Route
path="/corporate/webinars" path="corporate/webinars"
element={<Navigate to="/webinars?view=corporate" replace />} element={<Navigate to="/webinars?view=corporate" replace />}
/> />
<Route <Route
path="/corporate/leaderboard" path="corporate/leaderboard"
element={<Navigate to="/leaderboard?view=corporate" replace />} element={<Navigate to="/leaderboard?view=corporate" replace />}
/> />
{/* Catch-all */} {/* Catch-all under layout */}
<Route path="*" element={<NotFound />} /> <Route path="*" element={<NotFound />} />
</Route>
</Routes> </Routes>
</div> </div>
); );

View File

@@ -5,7 +5,8 @@ import { Badge } from '../ui/badge';
import { Sheet, SheetContent, SheetTrigger } from '../ui/sheet'; import { Sheet, SheetContent, SheetTrigger } from '../ui/sheet';
import { ScrollArea } from '../ui/scroll-area'; import { ScrollArea } from '../ui/scroll-area';
import { Separator } from '../ui/separator'; import { Separator } from '../ui/separator';
import logo from "../../assets/klc-logo.png" // import logo from "../../assets/klc-logo.png"
const logo = new URL("../../assets/klc-logo.png", import.meta.url).href
import { import {
Menu, Menu,
Search, Search,
@@ -261,7 +262,7 @@ export function LearnerLayout({ children, currentPage, userType = 'individual',
</div> </div>
{/* Navigation */} {/* Navigation */}
<ScrollArea className="flex-1 px-4 py-6"> <div className="flex-1 px-4 py-6" >
<nav className="space-y-2"> <nav className="space-y-2">
{navigationItems.map((item) => { {navigationItems.map((item) => {
const Icon = item.icon; const Icon = item.icon;
@@ -286,14 +287,14 @@ export function LearnerLayout({ children, currentPage, userType = 'individual',
</nav> </nav>
</ScrollArea> </div>
</div> </div >
); );
return ( return (
<div className="min-h-screen bg-background"> <div className="min-h-screen " style={{ backgroundColor: "green" }}>
{/* Mobile Header */} {/* Mobile Header */}
<header className="lg:hidden border-b border-border bg-card/95 backdrop-blur supports-[backdrop-filter]:bg-card/60"> <header className="lg:hidden fixed top-0 left-0 right-0 z-50 border-b border-border bg-card/95 backdrop-blur supports-[backdrop-filter]:bg-card/60">
<div className="flex items-center justify-between p-4"> <div className="flex items-center justify-between p-4">
<Sheet open={sidebarOpen} onOpenChange={setSidebarOpen}> <Sheet open={sidebarOpen} onOpenChange={setSidebarOpen}>
<SheetTrigger asChild> <SheetTrigger asChild>
@@ -359,9 +360,9 @@ export function LearnerLayout({ children, currentPage, userType = 'individual',
</div> </div>
{/* Main Content Area - Optimized for wider content */} {/* Main Content Area - Optimized for wider content */}
<div className="flex-1 lg:ml-0"> <div className="flex-1 lg:ml-0" style={{ backgroundColor: "green" }}>
{/* Desktop Header */} {/* Desktop Header */}
<header className="hidden lg:block border-b border-border bg-card/95 backdrop-blur supports-[backdrop-filter]:bg-card/60"> <header className="hidden lg:block fixed top-0 left-60 right-0 z-40 border-b border-border bg-card/95 backdrop-blur supports-[backdrop-filter]:bg-card/60">
<div className="flex items-center justify-end px-4 py-4"> <div className="flex items-center justify-end px-4 py-4">
{/* <div className="flex-1 max-w-sm"> {/* <div className="flex-1 max-w-sm">
<div className="relative"> <div className="relative">
@@ -431,8 +432,8 @@ export function LearnerLayout({ children, currentPage, userType = 'individual',
</AvatarFallback> </AvatarFallback>
</Avatar> </Avatar>
<div className="hidden xl:block"> <div className="hidden xl:block">
<p className="text-lg font-medium">{user?.name || 'Priya Sharma'}</p> <p className="text-lg font-medium">{user?.name || 'Parth Patel'}</p>
<p className="text-sm text-muted-foreground">{user?.email || 'priya.sharma@example.com'}</p> <p className="text-sm text-muted-foreground">{user?.email || 'parthPatel@example.com'}</p>
</div> </div>
<ChevronDown className="h-4 w-4 text-muted-foreground" /> <ChevronDown className="h-4 w-4 text-muted-foreground" />
</div> </div>
@@ -440,15 +441,15 @@ export function LearnerLayout({ children, currentPage, userType = 'individual',
</div> </div>
</header> </header>
{/* Page Content - Remove default padding, let pages control their own spacing */} {/* Page Content - Scrollable area under fixed headers */}
<main <main
className="flex-1 min-h-screen bg-background" className="flex-1 h-screen bg-background overflow-hidden"
role="main" role="main"
id="main-content" id="main-content"
tabIndex={-1} tabIndex={-1}
> >
{/* Content wrapper with consistent spacing and accessibility */} {/* Content wrapper with consistent spacing and accessibility */}
<div className="w-full min-h-full"> <div className="w-full h-full overflow-y-auto pt-[56px] lg:pt-[64px]">
{/* Skip to main content anchor for screen readers */} {/* Skip to main content anchor for screen readers */}
<a <a
href="#learner-content" href="#learner-content"
@@ -460,7 +461,7 @@ export function LearnerLayout({ children, currentPage, userType = 'individual',
{/* Main learner content area */} {/* Main learner content area */}
<div <div
id="learner-content" id="learner-content"
className="w-full" className="w-full h-full"
role="region" role="region"
aria-label="Learner portal content" aria-label="Learner portal content"
> >
@@ -528,7 +529,7 @@ export function LearnerLayout({ children, currentPage, userType = 'individual',
{/* Progress indicator for course content */} {/* Progress indicator for course content */}
<div <div
id="learner-progress-indicator" id="learner-progress-indicator"
className="fixed top-[70px] left-0 right-0 h-1 bg-gray-200 opacity-0 transition-opacity duration-200 z-40" className="fixed top-[56px] lg:top-[64px] left-0 right-0 h-1 bg-gray-200 opacity-0 transition-opacity duration-200 z-40"
role="progressbar" role="progressbar"
aria-label="Page loading progress" aria-label="Page loading progress"
aria-hidden="true" aria-hidden="true"

View File

@@ -1,14 +1,18 @@
import React from "react";
import { createRoot } from "react-dom/client"; import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom"; import { BrowserRouter } from "react-router-dom";
import App from "./App.tsx"; import App from "./App.tsx";
import "./styles/globals.css"; import "./styles/globals.css";
import { Provider } from "react-redux"; import { Provider } from "react-redux";
import { store } from "./Redux/Store.tsx"; import { store } from "./Redux/Store.tsx";
import { AuthProvider } from "./components/AuthContext.tsx";
createRoot(document.getElementById("root")!).render( createRoot(document.getElementById("root")!).render(
<Provider store={store}> <Provider store={store}>
<BrowserRouter> <AuthProvider>
<App /> <BrowserRouter>
</BrowserRouter> <App />
</BrowserRouter>
</AuthProvider>
</Provider> </Provider>
); );

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function AboutKLC() { export function AboutKLC() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function Articles() { export function Articles() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function BlogDetail() { export function BlogDetail() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function BlogListing() { export function BlogListing() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function Cart() { export function Cart() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function Checkout() { export function Checkout() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -3,7 +3,7 @@ import { Button } from '../components/ui/button';
import { Input } from '../components/ui/input'; import { Input } from '../components/ui/input';
import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card';
import { ArrowLeft, Mail, Phone, MapPin, Clock, Send } from 'lucide-react'; import { ArrowLeft, Mail, Phone, MapPin, Clock, Send } from 'lucide-react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function Contact() { export function Contact() {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
@@ -13,11 +13,12 @@ export function Contact() {
message: '' message: ''
}); });
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const navigate = useNavigate();
const handleSubmit = async (e: React.FormEvent) => { const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
setIsLoading(true); setIsLoading(true);
try { try {
// Simulate form submission // Simulate form submission
await new Promise(resolve => setTimeout(resolve, 1000)); await new Promise(resolve => setTimeout(resolve, 1000));
@@ -65,7 +66,7 @@ export function Contact() {
<div className="container mx-auto px-4 lg:px-8 -mt-8"> <div className="container mx-auto px-4 lg:px-8 -mt-8">
<div className="max-w-6xl mx-auto"> <div className="max-w-6xl mx-auto">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8"> <div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
{/* Contact Form */} {/* Contact Form */}
<div className="lg:col-span-2"> <div className="lg:col-span-2">
<Card className="bg-white shadow-xl border-0"> <Card className="bg-white shadow-xl border-0">
@@ -77,7 +78,7 @@ export function Contact() {
We'd love to hear from you. Fill out the form below and we'll get back to you as soon as possible. We'd love to hear from you. Fill out the form below and we'll get back to you as soon as possible.
</p> </p>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<form onSubmit={handleSubmit} className="space-y-6"> <form onSubmit={handleSubmit} className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 gap-6">

View File

@@ -2,9 +2,11 @@ import React from 'react';
import { Button } from '../components/ui/button'; import { Button } from '../components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card';
import { ArrowLeft, Building2, Users, Shield, BarChart3 } from 'lucide-react'; import { ArrowLeft, Building2, Users, Shield, BarChart3 } from 'lucide-react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function CorporateAuth() { export function CorporateAuth() {
const navigate = useNavigate();
const handleBackNavigation = () => { const handleBackNavigation = () => {
navigate('/auth'); navigate('/auth');
}; };
@@ -59,7 +61,7 @@ export function CorporateAuth() {
Sign in to your corporate learning account or request access from your administrator Sign in to your corporate learning account or request access from your administrator
</p> </p>
</CardHeader> </CardHeader>
<CardContent className="space-y-8"> <CardContent className="space-y-8">
{/* Features Overview */} {/* Features Overview */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 gap-6">

View File

@@ -40,7 +40,7 @@ import {
Sparkles Sparkles
} from 'lucide-react'; } from 'lucide-react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
const navigate = useNavigate(); // const navigate = useNavigate();
// Mock data for leaderboard // Mock data for leaderboard
const mockLeaderboard = [ const mockLeaderboard = [
@@ -165,7 +165,7 @@ const AnimatedNumber = ({ value, duration = 1000 }: { value: number; duration?:
const animate = (timestamp: number) => { const animate = (timestamp: number) => {
if (!startTime) startTime = timestamp; if (!startTime) startTime = timestamp;
const progress = Math.min((timestamp - startTime) / duration, 1); const progress = Math.min((timestamp - startTime) / duration, 1);
// Easing function for smooth animation // Easing function for smooth animation
const easeOut = 1 - Math.pow(1 - progress, 3); const easeOut = 1 - Math.pow(1 - progress, 3);
setDisplayValue(Math.floor(value * easeOut)); setDisplayValue(Math.floor(value * easeOut));
@@ -232,12 +232,12 @@ export function CorporateLeaderboard() {
// Filter leaderboard data // Filter leaderboard data
const filteredLeaderboard = mockLeaderboard.filter(user => { const filteredLeaderboard = mockLeaderboard.filter(user => {
const matchesSearch = user.name.toLowerCase().includes(searchQuery.toLowerCase()) || const matchesSearch = user.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
user.department.toLowerCase().includes(searchQuery.toLowerCase()) || user.department.toLowerCase().includes(searchQuery.toLowerCase()) ||
user.title.toLowerCase().includes(searchQuery.toLowerCase()); user.title.toLowerCase().includes(searchQuery.toLowerCase());
const matchesDepartment = selectedDepartment === 'all' || user.department === selectedDepartment; const matchesDepartment = selectedDepartment === 'all' || user.department === selectedDepartment;
const matchesLevel = selectedLevel === 'all' || user.level === selectedLevel; const matchesLevel = selectedLevel === 'all' || user.level === selectedLevel;
return matchesSearch && matchesDepartment && matchesLevel; return matchesSearch && matchesDepartment && matchesLevel;
}); });
@@ -299,7 +299,7 @@ export function CorporateLeaderboard() {
<h2 className="text-xl font-semibold mb-1 text-foreground">Performance Tracking</h2> <h2 className="text-xl font-semibold mb-1 text-foreground">Performance Tracking</h2>
<p className="text-base text-muted-foreground">View leaderboard data across different time periods</p> <p className="text-base text-muted-foreground">View leaderboard data across different time periods</p>
</div> </div>
<div className="flex gap-2"> <div className="flex gap-2">
<Button <Button
variant={timeFilter === 'week' ? 'default' : 'outline'} variant={timeFilter === 'week' ? 'default' : 'outline'}
@@ -353,64 +353,61 @@ export function CorporateLeaderboard() {
const isFirst = index === 0; const isFirst = index === 0;
const isSecond = index === 1; const isSecond = index === 1;
const isThird = index === 2; const isThird = index === 2;
return ( return (
<motion.div <motion.div
key={user.id} key={user.id}
initial={{ opacity: 0, y: 30, scale: 0.95 }} initial={{ opacity: 0, y: 30, scale: 0.95 }}
animate={{ opacity: 1, y: 0, scale: 1 }} animate={{ opacity: 1, y: 0, scale: 1 }}
transition={{ transition={{
duration: 0.6, duration: 0.6,
delay: index * 0.15, delay: index * 0.15,
ease: "easeOut" ease: "easeOut"
}} }}
whileHover={{ whileHover={{
scale: 1.02, scale: 1.02,
y: -5, y: -5,
transition: { duration: 0.2 } transition: { duration: 0.2 }
}} }}
className="w-full" className="w-full"
> >
<Card <Card
className={`relative overflow-hidden transition-all duration-300 hover:shadow-xl cursor-pointer group ${ className={`relative overflow-hidden transition-all duration-300 hover:shadow-xl cursor-pointer group ${isFirst ? 'border-2 border-[#F8C301] bg-gradient-to-br from-[#F8C301]/5 to-[#F8C301]/10' :
isFirst ? 'border-2 border-[#F8C301] bg-gradient-to-br from-[#F8C301]/5 to-[#F8C301]/10' : isSecond ? 'border-2 border-primary bg-gradient-to-br from-primary/5 to-primary/10' :
isSecond ? 'border-2 border-primary bg-gradient-to-br from-primary/5 to-primary/10' : 'border-2 border-[#26231A] bg-gradient-to-br from-[#26231A]/5 to-[#26231A]/10'
'border-2 border-[#26231A] bg-gradient-to-br from-[#26231A]/5 to-[#26231A]/10' } ${isFirst ? 'lg:scale-105 lg:-translate-y-2' : ''}`}
} ${isFirst ? 'lg:scale-105 lg:-translate-y-2' : ''}`}
> >
{/* Subtle Metallic Shimmer Effect for Top 3 */} {/* Subtle Metallic Shimmer Effect for Top 3 */}
<div <div
className={`absolute inset-0 opacity-0 group-hover:opacity-60 transition-opacity duration-1000 pointer-events-none shimmer-effect ${ className={`absolute inset-0 opacity-0 group-hover:opacity-60 transition-opacity duration-1000 pointer-events-none shimmer-effect ${isFirst ? 'shimmer-gold' : isSecond ? 'shimmer-silver' : 'shimmer-bronze'
isFirst ? 'shimmer-gold' : isSecond ? 'shimmer-silver' : 'shimmer-bronze' }`}
}`}
/> />
{/* Rank Ribbon with KLC Colors */} {/* Rank Ribbon with KLC Colors */}
<motion.div <motion.div
className={`absolute top-0 right-0 px-3 py-1 rounded-bl-lg text-white text-sm font-medium ${ className={`absolute top-0 right-0 px-3 py-1 rounded-bl-lg text-white text-sm font-medium ${isFirst ? 'bg-[#F8C301] text-[#26231A]' :
isFirst ? 'bg-[#F8C301] text-[#26231A]' : isSecond ? 'bg-primary text-white' :
isSecond ? 'bg-primary text-white' : 'bg-[#26231A] text-white'
'bg-[#26231A] text-white' }`}
}`}
initial={{ x: 20, opacity: 0 }} initial={{ x: 20, opacity: 0 }}
animate={{ x: 0, opacity: 1 }} animate={{ x: 0, opacity: 1 }}
transition={{ delay: index * 0.15 + 0.3 }} transition={{ delay: index * 0.15 + 0.3 }}
> >
#{user.rank} #{user.rank}
</motion.div> </motion.div>
{/* Winner Crown for First Place */} {/* Winner Crown for First Place */}
{isFirst && ( {isFirst && (
<motion.div <motion.div
className="absolute top-4 left-4" className="absolute top-4 left-4"
initial={{ rotate: -10, scale: 0 }} initial={{ rotate: -10, scale: 0 }}
animate={{ animate={{
rotate: 0, rotate: 0,
scale: 1, scale: 1,
y: [0, -2, 0], y: [0, -2, 0],
rotateZ: [0, 2, -2, 0] rotateZ: [0, 2, -2, 0]
}} }}
transition={{ transition={{
delay: 0.5, delay: 0.5,
type: "spring", type: "spring",
stiffness: 200, stiffness: 200,
@@ -433,29 +430,28 @@ export function CorporateLeaderboard() {
<CardContent className="p-8 text-center"> <CardContent className="p-8 text-center">
{/* Rank Icon */} {/* Rank Icon */}
<motion.div <motion.div
className="flex justify-center mb-6" className="flex justify-center mb-6"
initial={{ scale: 0, rotate: -180 }} initial={{ scale: 0, rotate: -180 }}
animate={{ scale: 1, rotate: 0 }} animate={{ scale: 1, rotate: 0 }}
transition={{ transition={{
delay: index * 0.15 + 0.2, delay: index * 0.15 + 0.2,
type: "spring", type: "spring",
stiffness: 150 stiffness: 150
}} }}
> >
<div className={`p-4 rounded-full ${ <div className={`p-4 rounded-full ${isFirst ? 'bg-[#F8C301]/10' : isSecond ? 'bg-primary/10' : 'bg-[#26231A]/10'
isFirst ? 'bg-[#F8C301]/10' : isSecond ? 'bg-primary/10' : 'bg-[#26231A]/10' }`}>
}`}>
{getRankIcon(user.rank)} {getRankIcon(user.rank)}
</div> </div>
</motion.div> </motion.div>
{/* User Avatar with Enhanced Styling */} {/* User Avatar with Enhanced Styling */}
<motion.div <motion.div
className="relative mb-6" className="relative mb-6"
initial={{ scale: 0 }} initial={{ scale: 0 }}
animate={{ scale: 1 }} animate={{ scale: 1 }}
transition={{ transition={{
delay: index * 0.15 + 0.4, delay: index * 0.15 + 0.4,
type: "spring", type: "spring",
stiffness: 200 stiffness: 200
@@ -469,7 +465,7 @@ export function CorporateLeaderboard() {
</AvatarFallback> </AvatarFallback>
</Avatar> </Avatar>
{/* Trend Indicator */} {/* Trend Indicator */}
<motion.div <motion.div
className="absolute -bottom-2 -right-2 p-1 bg-white rounded-full shadow-md" className="absolute -bottom-2 -right-2 p-1 bg-white rounded-full shadow-md"
initial={{ scale: 0 }} initial={{ scale: 0 }}
animate={{ animate={{
@@ -489,7 +485,7 @@ export function CorporateLeaderboard() {
</motion.div> </motion.div>
{/* User Information */} {/* User Information */}
<motion.div <motion.div
className="mb-6" className="mb-6"
initial={{ opacity: 0, y: 10 }} initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
@@ -501,7 +497,7 @@ export function CorporateLeaderboard() {
</motion.div> </motion.div>
{/* Performance Stats */} {/* Performance Stats */}
<motion.div <motion.div
className="grid grid-cols-3 gap-4 mb-6 p-4 bg-white/50 rounded-lg backdrop-blur-sm" className="grid grid-cols-3 gap-4 mb-6 p-4 bg-white/50 rounded-lg backdrop-blur-sm"
initial={{ opacity: 0, scale: 0.9 }} initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }} animate={{ opacity: 1, scale: 1 }}
@@ -528,7 +524,7 @@ export function CorporateLeaderboard() {
</motion.div> </motion.div>
{/* Level Progress */} {/* Level Progress */}
<motion.div <motion.div
className="mb-6" className="mb-6"
initial={{ opacity: 0, x: -20 }} initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }} animate={{ opacity: 1, x: 0 }}
@@ -545,7 +541,7 @@ export function CorporateLeaderboard() {
</motion.div> </motion.div>
{/* Achievement Badges */} {/* Achievement Badges */}
<motion.div <motion.div
className="space-y-3" className="space-y-3"
initial={{ opacity: 0, y: 10 }} initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
@@ -558,18 +554,17 @@ export function CorporateLeaderboard() {
key={badge} key={badge}
initial={{ opacity: 0, scale: 0.8 }} initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }} animate={{ opacity: 1, scale: 1 }}
transition={{ transition={{
delay: index * 0.15 + 1 + (badgeIndex * 0.1) delay: index * 0.15 + 1 + (badgeIndex * 0.1)
}} }}
whileHover={{ scale: 1.05 }} whileHover={{ scale: 1.05 }}
> >
<Badge <Badge
variant="outline" variant="outline"
className={`text-sm px-3 py-1 ${ className={`text-sm px-3 py-1 ${badgeIndex === 0 ? 'border-[#F8C301]/30 bg-[#F8C301]/5 text-[#26231A]' :
badgeIndex === 0 ? 'border-[#F8C301]/30 bg-[#F8C301]/5 text-[#26231A]' : badgeIndex === 1 ? 'border-primary/30 bg-primary/5 text-primary' :
badgeIndex === 1 ? 'border-primary/30 bg-primary/5 text-primary' : 'border-success/30 bg-success/5 text-success'
'border-success/30 bg-success/5 text-success' }`}
}`}
> >
{badge} {badge}
</Badge> </Badge>
@@ -579,7 +574,7 @@ export function CorporateLeaderboard() {
</motion.div> </motion.div>
{/* Monthly Performance Indicator */} {/* Monthly Performance Indicator */}
<motion.div <motion.div
className="mt-6 pt-4 border-t border-border/50" className="mt-6 pt-4 border-t border-border/50"
initial={{ opacity: 0, y: 10 }} initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
@@ -655,8 +650,8 @@ export function CorporateLeaderboard() {
</SelectContent> </SelectContent>
</Select> </Select>
<Button <Button
variant="outline" variant="outline"
className="text-base h-11" className="text-base h-11"
onClick={() => { onClick={() => {
setSearchQuery(''); setSearchQuery('');
@@ -720,7 +715,7 @@ export function CorporateLeaderboard() {
{user.name.split(' ').map(n => n[0]).join('')} {user.name.split(' ').map(n => n[0]).join('')}
</AvatarFallback> </AvatarFallback>
</Avatar> </Avatar>
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<p className="text-base font-medium text-foreground group-hover:text-primary transition-colors truncate"> <p className="text-base font-medium text-foreground group-hover:text-primary transition-colors truncate">

View File

@@ -2,7 +2,6 @@ import React, { useState, useEffect } from 'react';
import { Navigation } from '../components/Navigation'; import { Navigation } from '../components/Navigation';
import { Footer } from '../components/Footer'; import { Footer } from '../components/Footer';
import { AIChatbot } from '../components/AIChatbot'; import { AIChatbot } from '../components/AIChatbot';
const navigate = useNavigate();
import { Button } from '../components/ui/button'; import { Button } from '../components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../components/ui/card'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../components/ui/card';
import { Input } from '../components/ui/input'; import { Input } from '../components/ui/input';
@@ -33,6 +32,7 @@ import {
Target, Target,
Star Star
} from 'lucide-react'; } from 'lucide-react';
import { useNavigate } from 'react-router';
interface SignInFormData { interface SignInFormData {
workEmail: string; workEmail: string;
@@ -147,9 +147,10 @@ export default function CorporateLearnerLogin() {
const [showEmailVerification, setShowEmailVerification] = useState(false); const [showEmailVerification, setShowEmailVerification] = useState(false);
const [maskedEmail, setMaskedEmail] = useState(''); const [maskedEmail, setMaskedEmail] = useState('');
const [resendCooldown, setResendCooldown] = useState(0); const [resendCooldown, setResendCooldown] = useState(0);
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
document.title = isSignUp document.title = isSignUp
? 'Join Your Learning Journey - Corporate Learner | KLC' ? 'Join Your Learning Journey - Corporate Learner | KLC'
: 'Welcome Back, Learner - Corporate Access | KLC'; : 'Welcome Back, Learner - Corporate Access | KLC';
}, [isSignUp]); }, [isSignUp]);
@@ -171,10 +172,10 @@ export default function CorporateLearnerLogin() {
}; };
const score = Object.values(criteria).filter(Boolean).length; const score = Object.values(criteria).filter(Boolean).length;
let label = 'Very Weak'; let label = 'Very Weak';
let color = 'bg-destructive'; let color = 'bg-destructive';
if (score >= 4) { if (score >= 4) {
label = 'Strong'; label = 'Strong';
color = 'bg-success'; color = 'bg-success';
@@ -273,11 +274,11 @@ export default function CorporateLearnerLogin() {
const handleSignUpInputChange = (field: keyof SignUpFormData, value: string) => { const handleSignUpInputChange = (field: keyof SignUpFormData, value: string) => {
setSignUpData(prev => ({ ...prev, [field]: value })); setSignUpData(prev => ({ ...prev, [field]: value }));
if (errors[field]) { if (errors[field]) {
setErrors(prev => ({ ...prev, [field]: '' })); setErrors(prev => ({ ...prev, [field]: '' }));
} }
if (field === 'password') { if (field === 'password') {
setPasswordStrength(calculatePasswordStrength(value)); setPasswordStrength(calculatePasswordStrength(value));
} }
@@ -308,19 +309,19 @@ export default function CorporateLearnerLogin() {
try { try {
await new Promise(resolve => setTimeout(resolve, 1500)); await new Promise(resolve => setTimeout(resolve, 1500));
if (signInData.workEmail === 'suspended@company.com') { if (signInData.workEmail === 'suspended@company.com') {
setAccountSuspended(true); setAccountSuspended(true);
setIsSubmitting(false); setIsSubmitting(false);
return; return;
} }
if (signInData.workEmail === 'mfa@company.com' && signInData.password === 'learner123' && !requiresMFA) { if (signInData.workEmail === 'mfa@company.com' && signInData.password === 'learner123' && !requiresMFA) {
setRequiresMFA(true); setRequiresMFA(true);
setIsSubmitting(false); setIsSubmitting(false);
return; return;
} }
if (signInData.workEmail === 'learner@company.com' && signInData.password === 'learner123') { if (signInData.workEmail === 'learner@company.com' && signInData.password === 'learner123') {
const redirectUrl = sessionStorage.getItem('loginRedirect') || '/corporate/dashboard'; const redirectUrl = sessionStorage.getItem('loginRedirect') || '/corporate/dashboard';
sessionStorage.removeItem('loginRedirect'); sessionStorage.removeItem('loginRedirect');
@@ -372,7 +373,7 @@ export default function CorporateLearnerLogin() {
return ( return (
<div className="min-h-screen bg-background"> <div className="min-h-screen bg-background">
<Navigation currentPage="/signin/corporate-learner" /> <Navigation currentPage="/signin/corporate-learner" />
<main className="pt-40 pb-16"> <main className="pt-40 pb-16">
<div className="container mx-auto px-4 lg:px-8"> <div className="container mx-auto px-4 lg:px-8">
<div className="max-w-2xl mx-auto text-center"> <div className="max-w-2xl mx-auto text-center">
@@ -381,17 +382,17 @@ export default function CorporateLearnerLogin() {
<div className="w-16 h-16 bg-secondary/10 rounded-full flex items-center justify-center mx-auto mb-6"> <div className="w-16 h-16 bg-secondary/10 rounded-full flex items-center justify-center mx-auto mb-6">
<GraduationCap className="w-8 h-8 text-secondary" /> <GraduationCap className="w-8 h-8 text-secondary" />
</div> </div>
<h1 className="text-2xl mb-4">Check Your Inbox</h1> <h1 className="text-2xl mb-4">Check Your Inbox</h1>
<p className="text-base text-muted-foreground mb-6"> <p className="text-base text-muted-foreground mb-6">
We've sent a verification email to <strong>{maskedEmail}</strong> We've sent a verification email to <strong>{maskedEmail}</strong>
</p> </p>
<p className="text-base text-muted-foreground mb-8"> <p className="text-base text-muted-foreground mb-8">
Click the verification link to activate your learner account and start your development journey. Click the verification link to activate your learner account and start your development journey.
The link will expire in 30 minutes. The link will expire in 30 minutes.
</p> </p>
<div className="space-y-4"> <div className="space-y-4">
<Button <Button
onClick={handleResendEmail} onClick={handleResendEmail}
@@ -402,7 +403,7 @@ export default function CorporateLearnerLogin() {
<RefreshCw className="w-4 h-4 mr-2" /> <RefreshCw className="w-4 h-4 mr-2" />
{resendCooldown > 0 ? `Resend in ${resendCooldown}s` : 'Resend Email'} {resendCooldown > 0 ? `Resend in ${resendCooldown}s` : 'Resend Email'}
</Button> </Button>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Need help getting started? Contact your HR team or email us at{' '} Need help getting started? Contact your HR team or email us at{' '}
<a href="mailto:learners@klc.edu.in" className="text-primary hover:underline"> <a href="mailto:learners@klc.edu.in" className="text-primary hover:underline">
@@ -410,7 +411,7 @@ export default function CorporateLearnerLogin() {
</a> </a>
</p> </p>
</div> </div>
<div className="mt-8 p-4 bg-muted/50 rounded-lg"> <div className="mt-8 p-4 bg-muted/50 rounded-lg">
<p className="text-sm text-muted-foreground mb-2">Demo Mode:</p> <p className="text-sm text-muted-foreground mb-2">Demo Mode:</p>
<Button <Button
@@ -436,7 +437,7 @@ export default function CorporateLearnerLogin() {
return ( return (
<div className="min-h-screen bg-background"> <div className="min-h-screen bg-background">
<Navigation currentPage="/signin/corporate-learner" /> <Navigation currentPage="/signin/corporate-learner" />
<main className="pt-40 pb-16"> <main className="pt-40 pb-16">
<div className="container mx-auto px-4 lg:px-8"> <div className="container mx-auto px-4 lg:px-8">
<div className="max-w-6xl mx-auto"> <div className="max-w-6xl mx-auto">
@@ -452,7 +453,7 @@ export default function CorporateLearnerLogin() {
{isSignUp ? 'Start Your Learning Journey' : 'Welcome Back to Your Learning'} {isSignUp ? 'Start Your Learning Journey' : 'Welcome Back to Your Learning'}
</h1> </h1>
<p className="text-base text-muted-foreground leading-relaxed"> <p className="text-base text-muted-foreground leading-relaxed">
{isSignUp {isSignUp
? 'Join your organization\'s learning community and unlock your potential with personalized development programs, skill certifications, and peer collaboration.' ? 'Join your organization\'s learning community and unlock your potential with personalized development programs, skill certifications, and peer collaboration.'
: 'Continue your professional development journey with access to your learning dashboard, progress tracking, and new skill-building opportunities.' : 'Continue your professional development journey with access to your learning dashboard, progress tracking, and new skill-building opportunities.'
} }
@@ -481,7 +482,7 @@ export default function CorporateLearnerLogin() {
<h3 className="text-lg font-semibold text-foreground mb-2">Learning Excellence</h3> <h3 className="text-lg font-semibold text-foreground mb-2">Learning Excellence</h3>
<p className="text-base text-muted-foreground">Join thousands of successful learners</p> <p className="text-base text-muted-foreground">Join thousands of successful learners</p>
</div> </div>
<div className="grid grid-cols-2 gap-6"> <div className="grid grid-cols-2 gap-6">
{learnerStats.map((stat) => { {learnerStats.map((stat) => {
const Icon = stat.icon; const Icon = stat.icon;
@@ -511,15 +512,15 @@ export default function CorporateLearnerLogin() {
{isSignUp ? 'Join Your Learning Community' : 'Welcome Back, Learner'} {isSignUp ? 'Join Your Learning Community' : 'Welcome Back, Learner'}
</CardTitle> </CardTitle>
<CardDescription className="text-base min-h-[44px] flex items-center justify-center"> <CardDescription className="text-base min-h-[44px] flex items-center justify-center">
{isSignUp {isSignUp
? 'Get started with your personalized learning journey' ? 'Get started with your personalized learning journey'
: requiresMFA : requiresMFA
? 'Enter the verification code sent to your device' ? 'Enter the verification code sent to your device'
: 'Access your learning dashboard and continue growing' : 'Access your learning dashboard and continue growing'
} }
</CardDescription> </CardDescription>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<form onSubmit={isSignUp ? handleSignUpSubmit : handleSignInSubmit} className="space-y-6"> <form onSubmit={isSignUp ? handleSignUpSubmit : handleSignInSubmit} className="space-y-6">
{accountSuspended && ( {accountSuspended && (
@@ -617,7 +618,7 @@ export default function CorporateLearnerLogin() {
id="workEmail" id="workEmail"
type="email" type="email"
value={isSignUp ? signUpData.workEmail : signInData.workEmail} value={isSignUp ? signUpData.workEmail : signInData.workEmail}
onChange={(e) => isSignUp onChange={(e) => isSignUp
? handleSignUpInputChange('workEmail', e.target.value) ? handleSignUpInputChange('workEmail', e.target.value)
: handleSignInInputChange('workEmail', e.target.value) : handleSignInInputChange('workEmail', e.target.value)
} }
@@ -644,7 +645,7 @@ export default function CorporateLearnerLogin() {
id="password" id="password"
type={showPassword ? "text" : "password"} type={showPassword ? "text" : "password"}
value={isSignUp ? signUpData.password : signInData.password} value={isSignUp ? signUpData.password : signInData.password}
onChange={(e) => isSignUp onChange={(e) => isSignUp
? handleSignUpInputChange('password', e.target.value) ? handleSignUpInputChange('password', e.target.value)
: handleSignInInputChange('password', e.target.value) : handleSignInInputChange('password', e.target.value)
} }
@@ -677,16 +678,15 @@ export default function CorporateLearnerLogin() {
<div className="space-y-2"> <div className="space-y-2">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<span className="text-sm text-muted-foreground">Password strength:</span> <span className="text-sm text-muted-foreground">Password strength:</span>
<span className={`text-sm font-medium ${ <span className={`text-sm font-medium ${passwordStrength.score >= 4 ? 'text-success' :
passwordStrength.score >= 4 ? 'text-success' : passwordStrength.score >= 3 ? 'text-secondary' :
passwordStrength.score >= 3 ? 'text-secondary' : passwordStrength.score >= 2 ? 'text-orange-500' : 'text-destructive'
passwordStrength.score >= 2 ? 'text-orange-500' : 'text-destructive' }`}>
}`}>
{passwordStrength.label} {passwordStrength.label}
</span> </span>
</div> </div>
<Progress <Progress
value={(passwordStrength.score / 5) * 100} value={(passwordStrength.score / 5) * 100}
className="h-2" className="h-2"
/> />
<div className="grid grid-cols-2 gap-2 text-xs"> <div className="grid grid-cols-2 gap-2 text-xs">
@@ -695,9 +695,9 @@ export default function CorporateLearnerLogin() {
{met ? <Check className="w-3 h-3" /> : <X className="w-3 h-3" />} {met ? <Check className="w-3 h-3" /> : <X className="w-3 h-3" />}
<span> <span>
{key === 'length' ? '8+ chars' : {key === 'length' ? '8+ chars' :
key === 'lowercase' ? 'lowercase' : key === 'lowercase' ? 'lowercase' :
key === 'uppercase' ? 'uppercase' : key === 'uppercase' ? 'uppercase' :
key === 'number' ? 'number' : 'symbol'} key === 'number' ? 'number' : 'symbol'}
</span> </span>
</div> </div>
))} ))}

View File

@@ -3,8 +3,8 @@ import { Button } from '../components/ui/button';
import { Input } from '../components/ui/input'; import { Input } from '../components/ui/input';
import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card';
import { ArrowLeft, Eye, EyeOff, Mail, Lock, Building2 } from 'lucide-react'; import { ArrowLeft, Eye, EyeOff, Mail, Lock, Building2 } from 'lucide-react';
const navigate = useNavigate();
import { useAuth } from '../components/AuthContext'; import { useAuth } from '../components/AuthContext';
import { useNavigate } from 'react-router';
export function CorporateLogin() { export function CorporateLogin() {
const [email, setEmail] = useState(''); const [email, setEmail] = useState('');
@@ -12,11 +12,12 @@ export function CorporateLogin() {
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const { login } = useAuth(); const { login } = useAuth();
const navigate = useNavigate();
const handleSubmit = async (e: React.FormEvent) => { const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
setIsLoading(true); setIsLoading(true);
try { try {
// Simulate corporate login and go directly to corporate dashboard // Simulate corporate login and go directly to corporate dashboard
await login(email || 'corporate@klc.edu', password || 'demo'); await login(email || 'corporate@klc.edu', password || 'demo');
@@ -88,7 +89,7 @@ export function CorporateLogin() {
Sign in to your corporate learning account Sign in to your corporate learning account
</p> </p>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
{/* Quick Access Button */} {/* Quick Access Button */}
<div className="mb-6"> <div className="mb-6">

View File

@@ -3,7 +3,7 @@ import { Button } from '../components/ui/button';
import { Input } from '../components/ui/input'; import { Input } from '../components/ui/input';
import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card';
import { ArrowLeft, Mail, User, Building2, Phone, Users } from 'lucide-react'; import { ArrowLeft, Mail, User, Building2, Phone, Users } from 'lucide-react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function CorporateSignup() { export function CorporateSignup() {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
@@ -17,11 +17,12 @@ export function CorporateSignup() {
message: '' message: ''
}); });
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const navigate = useNavigate();
const handleSubmit = async (e: React.FormEvent) => { const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
setIsLoading(true); setIsLoading(true);
try { try {
// Simulate request submission // Simulate request submission
await new Promise(resolve => setTimeout(resolve, 1000)); await new Promise(resolve => setTimeout(resolve, 1000));
@@ -79,7 +80,7 @@ export function CorporateSignup() {
Fill out this form and our enterprise team will contact you within 24 hours Fill out this form and our enterprise team will contact you within 24 hours
</p> </p>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<form onSubmit={handleSubmit} className="space-y-6"> <form onSubmit={handleSubmit} className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 gap-6">

View File

@@ -47,10 +47,8 @@ import {
MoreHorizontal, MoreHorizontal,
Search Search
} from 'lucide-react'; } from 'lucide-react';
// const navigate = useNavigate();
import { ImageWithFallback } from '../components/figma/ImageWithFallback'; import { ImageWithFallback } from '../components/figma/ImageWithFallback';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
const navigate = useNavigate();
// Mock data for webinars // Mock data for webinars
const mockWebinars = [ const mockWebinars = [
{ {
@@ -185,7 +183,7 @@ const mockWebinars = [
// Enhanced badge components with KLC brand colors // Enhanced badge components with KLC brand colors
function RequiredBadge() { function RequiredBadge() {
return ( return (
<Badge <Badge
variant="outline" variant="outline"
className="text-sm font-medium px-3 py-1.5 h-auto flex items-center bg-destructive/5 text-destructive border-destructive/30 hover:bg-destructive/10 transition-colors" className="text-sm font-medium px-3 py-1.5 h-auto flex items-center bg-destructive/5 text-destructive border-destructive/30 hover:bg-destructive/10 transition-colors"
> >
@@ -197,7 +195,7 @@ function RequiredBadge() {
function CategoryBadge({ children }: { children: React.ReactNode }) { function CategoryBadge({ children }: { children: React.ReactNode }) {
return ( return (
<Badge <Badge
variant="outline" variant="outline"
className="text-sm font-medium px-2 py-1 bg-primary/5 text-primary border-primary/30" className="text-sm font-medium px-2 py-1 bg-primary/5 text-primary border-primary/30"
> >
@@ -209,7 +207,7 @@ function CategoryBadge({ children }: { children: React.ReactNode }) {
function TagBadge({ children }: { children: React.ReactNode }) { function TagBadge({ children }: { children: React.ReactNode }) {
return ( return (
<Badge <Badge
variant="outline" variant="outline"
className="text-sm px-2 py-1 bg-muted/50 text-muted-foreground border-border" className="text-sm px-2 py-1 bg-muted/50 text-muted-foreground border-border"
> >
@@ -234,9 +232,8 @@ function LevelBadge({ level }: { level: string }) {
return 'bg-muted/50 text-muted-foreground border-border'; return 'bg-muted/50 text-muted-foreground border-border';
} }
}; };
return ( return (
<Badge <Badge
variant="outline" variant="outline"
className={`text-sm font-medium px-2 py-1 ${getLevelStyle(level)}`} className={`text-sm font-medium px-2 py-1 ${getLevelStyle(level)}`}
> >
@@ -250,21 +247,22 @@ function truncateText(text: string, maxLength: number): { truncated: string; nee
if (text.length <= maxLength) { if (text.length <= maxLength) {
return { truncated: text, needsTruncation: false }; return { truncated: text, needsTruncation: false };
} }
// Find the last space before maxLength to avoid cutting words // Find the last space before maxLength to avoid cutting words
let truncatedText = text.substring(0, maxLength); let truncatedText = text.substring(0, maxLength);
const lastSpaceIndex = truncatedText.lastIndexOf(' '); const lastSpaceIndex = truncatedText.lastIndexOf(' ');
if (lastSpaceIndex > maxLength * 0.8) { // Only use word boundary if it's not too far back if (lastSpaceIndex > maxLength * 0.8) { // Only use word boundary if it's not too far back
truncatedText = text.substring(0, lastSpaceIndex); truncatedText = text.substring(0, lastSpaceIndex);
} }
return { truncated: truncatedText, needsTruncation: true }; return { truncated: truncatedText, needsTruncation: true };
} }
// Enhanced WebinarCard component with KLC branding and consistent design // Enhanced WebinarCard component with KLC branding and consistent design
function WebinarCard({ webinar }: { webinar: typeof mockWebinars[0] }) { function WebinarCard({ webinar }: { webinar: typeof mockWebinars[0] }) {
const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false); const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false);
const navigate = useNavigate();
const handleJoinWebinar = () => { const handleJoinWebinar = () => {
navigate(`/webinar-detail?id=${webinar.id}&view=corporate`); navigate(`/webinar-detail?id=${webinar.id}&view=corporate`);
@@ -289,10 +287,10 @@ function WebinarCard({ webinar }: { webinar: typeof mockWebinars[0] }) {
alt={webinar.title} alt={webinar.title}
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-200" className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-200"
/> />
{/* Brand Gradient Overlay */} {/* Brand Gradient Overlay */}
<div className="absolute inset-0 bg-gradient-to-br from-[#04045B]/80 via-[#04045B]/60 to-transparent" /> <div className="absolute inset-0 bg-gradient-to-br from-[#04045B]/80 via-[#04045B]/60 to-transparent" />
{/* Geometric Brand Elements */} {/* Geometric Brand Elements */}
<div className="absolute inset-0"> <div className="absolute inset-0">
<div className="absolute top-0 right-0 w-24 h-24 bg-[#F8C301]/20 transform rotate-45 translate-x-8 -translate-y-8" /> <div className="absolute top-0 right-0 w-24 h-24 bg-[#F8C301]/20 transform rotate-45 translate-x-8 -translate-y-8" />
@@ -301,7 +299,7 @@ function WebinarCard({ webinar }: { webinar: typeof mockWebinars[0] }) {
{/* Play Button with KLC Brand Colors */} {/* Play Button with KLC Brand Colors */}
<div className="absolute inset-0 flex items-center justify-center"> <div className="absolute inset-0 flex items-center justify-center">
<button <button
onClick={handleJoinWebinar} onClick={handleJoinWebinar}
className="w-16 h-16 bg-white rounded-full flex items-center justify-center shadow-lg hover:scale-105 transition-transform duration-200 group border-2 border-primary/20" className="w-16 h-16 bg-white rounded-full flex items-center justify-center shadow-lg hover:scale-105 transition-transform duration-200 group border-2 border-primary/20"
aria-label="Watch webinar" aria-label="Watch webinar"
@@ -317,7 +315,7 @@ function WebinarCard({ webinar }: { webinar: typeof mockWebinars[0] }) {
{/* Category Badge */} {/* Category Badge */}
<div className="absolute top-3 right-3"> <div className="absolute top-3 right-3">
<Badge <Badge
variant="outline" variant="outline"
className="bg-white/90 backdrop-blur-sm border-white/30 text-[#26231A] text-sm font-medium" className="bg-white/90 backdrop-blur-sm border-white/30 text-[#26231A] text-sm font-medium"
> >
@@ -404,7 +402,7 @@ function WebinarCard({ webinar }: { webinar: typeof mockWebinars[0] }) {
<span>{webinar.duration}min</span> <span>{webinar.duration}min</span>
</div> </div>
</div> </div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex items-center gap-2 text-base text-muted-foreground"> <div className="flex items-center gap-2 text-base text-muted-foreground">
<Users className="h-4 w-4" /> <Users className="h-4 w-4" />
@@ -433,7 +431,7 @@ function WebinarCard({ webinar }: { webinar: typeof mockWebinars[0] }) {
{/* CTA Button - Auto-positioned at bottom */} {/* CTA Button - Auto-positioned at bottom */}
<div className="mt-auto"> <div className="mt-auto">
<Button <Button
onClick={handleJoinWebinar} onClick={handleJoinWebinar}
className="w-full text-base font-medium h-11 group" className="w-full text-base font-medium h-11 group"
> >
@@ -447,6 +445,7 @@ function WebinarCard({ webinar }: { webinar: typeof mockWebinars[0] }) {
} }
export function CorporateWebinars() { export function CorporateWebinars() {
const navigate = useNavigate();
const [searchQuery, setSearchQuery] = useState(''); const [searchQuery, setSearchQuery] = useState('');
const [selectedCategory, setSelectedCategory] = useState('all'); const [selectedCategory, setSelectedCategory] = useState('all');
const [selectedStatus, setSelectedStatus] = useState('all'); const [selectedStatus, setSelectedStatus] = useState('all');
@@ -465,12 +464,12 @@ export function CorporateWebinars() {
// Filter webinars based on search and filters // Filter webinars based on search and filters
const filteredWebinars = mockWebinars.filter(webinar => { const filteredWebinars = mockWebinars.filter(webinar => {
const matchesSearch = webinar.title.toLowerCase().includes(searchQuery.toLowerCase()) || const matchesSearch = webinar.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
webinar.presenter.toLowerCase().includes(searchQuery.toLowerCase()) || webinar.presenter.toLowerCase().includes(searchQuery.toLowerCase()) ||
webinar.description.toLowerCase().includes(searchQuery.toLowerCase()); webinar.description.toLowerCase().includes(searchQuery.toLowerCase());
const matchesCategory = selectedCategory === 'all' || webinar.category === selectedCategory; const matchesCategory = selectedCategory === 'all' || webinar.category === selectedCategory;
const matchesStatus = selectedStatus === 'all' || webinar.status === selectedStatus; const matchesStatus = selectedStatus === 'all' || webinar.status === selectedStatus;
return matchesSearch && matchesCategory && matchesStatus; return matchesSearch && matchesCategory && matchesStatus;
}); });
@@ -539,8 +538,8 @@ export function CorporateWebinars() {
{/* Filters */} {/* Filters */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<select <select
value={selectedCategory} value={selectedCategory}
onChange={(e) => setSelectedCategory(e.target.value)} onChange={(e) => setSelectedCategory(e.target.value)}
className="px-3 py-2 border border-border rounded-md text-base min-h-[44px] bg-background" className="px-3 py-2 border border-border rounded-md text-base min-h-[44px] bg-background"
> >
@@ -552,8 +551,8 @@ export function CorporateWebinars() {
<option value="Sustainability">Sustainability</option> <option value="Sustainability">Sustainability</option>
</select> </select>
<select <select
value={selectedStatus} value={selectedStatus}
onChange={(e) => setSelectedStatus(e.target.value)} onChange={(e) => setSelectedStatus(e.target.value)}
className="px-3 py-2 border border-border rounded-md text-base min-h-[44px] bg-background" className="px-3 py-2 border border-border rounded-md text-base min-h-[44px] bg-background"
> >
@@ -563,8 +562,8 @@ export function CorporateWebinars() {
<option value="completed">Completed</option> <option value="completed">Completed</option>
</select> </select>
<Button <Button
variant="outline" variant="outline"
className="text-base min-h-[44px]" className="text-base min-h-[44px]"
onClick={() => { onClick={() => {
setSearchQuery(''); setSearchQuery('');
@@ -587,7 +586,7 @@ export function CorporateWebinars() {
{filteredWebinars.length} {filteredWebinars.length === 1 ? 'webinar' : 'webinars'} {filteredWebinars.length} {filteredWebinars.length === 1 ? 'webinar' : 'webinars'}
</Badge> </Badge>
</div> </div>
{filteredWebinars.length > 0 ? ( {filteredWebinars.length > 0 ? (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{filteredWebinars.map((webinar) => ( {filteredWebinars.map((webinar) => (
@@ -604,7 +603,7 @@ export function CorporateWebinars() {
<p className="text-base text-muted-foreground mb-6"> <p className="text-base text-muted-foreground mb-6">
Try adjusting your search terms or filters to find webinars. Try adjusting your search terms or filters to find webinars.
</p> </p>
<Button <Button
variant="outline" variant="outline"
onClick={() => { onClick={() => {
setSearchQuery(''); setSearchQuery('');
@@ -631,12 +630,12 @@ export function CorporateWebinars() {
Quick overview of your upcoming webinar commitments Quick overview of your upcoming webinar commitments
</p> </p>
</CardHeader> </CardHeader>
<CardContent className="flex-1"> <CardContent className="flex-1">
<div className="space-y-4"> <div className="space-y-4">
{mockWebinars.slice(0, 3).map((webinar) => ( {mockWebinars.slice(0, 3).map((webinar) => (
<div <div
key={webinar.id} key={webinar.id}
className="group cursor-pointer p-4 rounded-lg border border-border hover:border-primary/30 hover:bg-muted/30 transition-all duration-200" className="group cursor-pointer p-4 rounded-lg border border-border hover:border-primary/30 hover:bg-muted/30 transition-all duration-200"
onClick={() => navigate(`/webinar-detail?id=${webinar.id}&view=corporate`)} onClick={() => navigate(`/webinar-detail?id=${webinar.id}&view=corporate`)}
> >
@@ -667,9 +666,9 @@ export function CorporateWebinars() {
</div> </div>
))} ))}
</div> </div>
<div className="mt-6"> <div className="mt-6">
<Button <Button
variant="outline" variant="outline"
onClick={() => navigate('/webinars?view=corporate')} onClick={() => navigate('/webinars?view=corporate')}
className="w-full text-base h-11" className="w-full text-base h-11"

View File

@@ -2,13 +2,14 @@ import React from 'react';
import { Button } from '../components/ui/button'; import { Button } from '../components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card';
import { Mail, CheckCircle, RefreshCw } from 'lucide-react'; import { Mail, CheckCircle, RefreshCw } from 'lucide-react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function EmailVerification() { export function EmailVerification() {
const handleResendEmail = () => { const handleResendEmail = () => {
// Simulate resending verification email // Simulate resending verification email
console.log('Resending verification email...'); console.log('Resending verification email...');
}; };
const navigate = useNavigate();
return ( return (
<div className="min-h-screen bg-gradient-to-br from-gray-50 to-white flex items-center justify-center px-4"> <div className="min-h-screen bg-gradient-to-br from-gray-50 to-white flex items-center justify-center px-4">
@@ -24,7 +25,7 @@ export function EmailVerification() {
We've sent a verification link to your email address We've sent a verification link to your email address
</p> </p>
</CardHeader> </CardHeader>
<CardContent className="space-y-6"> <CardContent className="space-y-6">
<div className="bg-blue-50 rounded-lg p-4"> <div className="bg-blue-50 rounded-lg p-4">
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
@@ -44,7 +45,7 @@ export function EmailVerification() {
<p className="text-[16px] text-gray-600 text-center"> <p className="text-[16px] text-gray-600 text-center">
Don't see the email? Check your spam folder or request a new one. Don't see the email? Check your spam folder or request a new one.
</p> </p>
<Button <Button
onClick={handleResendEmail} onClick={handleResendEmail}
variant="outline" variant="outline"

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function ExecutiveLeadership() { export function ExecutiveLeadership() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -3,9 +3,11 @@ import { Button } from '../components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '../components/ui/collapsible'; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '../components/ui/collapsible';
import { ArrowLeft, ChevronDown, HelpCircle, Mail, Phone } from 'lucide-react'; import { ArrowLeft, ChevronDown, HelpCircle, Mail, Phone } from 'lucide-react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function FAQ() { export function FAQ() {
const navigate = useNavigate();
const handleBackNavigation = () => { const handleBackNavigation = () => {
navigate('/'); navigate('/');
}; };
@@ -99,7 +101,7 @@ export function FAQ() {
</div> </div>
</div> </div>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className="space-y-4"> <div className="space-y-4">
{faqData.map((faq, index) => ( {faqData.map((faq, index) => (

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function FacilityBooking() { export function FacilityBooking() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function FacilityDetail() { export function FacilityDetail() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function FacilityTour() { export function FacilityTour() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -3,17 +3,18 @@ import { Button } from '../components/ui/button';
import { Input } from '../components/ui/input'; import { Input } from '../components/ui/input';
import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card';
import { ArrowLeft, Mail, CheckCircle } from 'lucide-react'; import { ArrowLeft, Mail, CheckCircle } from 'lucide-react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function ForgotPassword() { export function ForgotPassword() {
const [email, setEmail] = useState(''); const [email, setEmail] = useState('');
const [isSubmitted, setIsSubmitted] = useState(false); const [isSubmitted, setIsSubmitted] = useState(false);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const navigate = useNavigate();
const handleSubmit = async (e: React.FormEvent) => { const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
setIsLoading(true); setIsLoading(true);
try { try {
// Simulate password reset request // Simulate password reset request
await new Promise(resolve => setTimeout(resolve, 1000)); await new Promise(resolve => setTimeout(resolve, 1000));
@@ -44,13 +45,13 @@ export function ForgotPassword() {
We've sent password reset instructions to {email} We've sent password reset instructions to {email}
</p> </p>
</CardHeader> </CardHeader>
<CardContent className="space-y-6"> <CardContent className="space-y-6">
<div className="text-center space-y-4"> <div className="text-center space-y-4">
<p className="text-[16px] text-gray-600"> <p className="text-[16px] text-gray-600">
Click the link in the email to reset your password. If you don't see it, check your spam folder. Click the link in the email to reset your password. If you don't see it, check your spam folder.
</p> </p>
<Button <Button
onClick={() => navigate('/auth')} onClick={() => navigate('/auth')}
className="w-full text-[16px] min-h-[48px] bg-primary hover:bg-primary/90" className="w-full text-[16px] min-h-[48px] bg-primary hover:bg-primary/90"
@@ -103,7 +104,7 @@ export function ForgotPassword() {
We'll help you get back into your account We'll help you get back into your account
</p> </p>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<form onSubmit={handleSubmit} className="space-y-6"> <form onSubmit={handleSubmit} className="space-y-6">
<div> <div>

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function InnovationLeadership() { export function InnovationLeadership() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -10,9 +10,9 @@ import { Skeleton } from '../components/ui/skeleton';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '../components/ui/tabs'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '../components/ui/tabs';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../components/ui/select'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../components/ui/select';
import { ImageWithFallback } from '../components/figma/ImageWithFallback'; import { ImageWithFallback } from '../components/figma/ImageWithFallback';
import { import {
ArrowLeft, ArrowLeft,
Trophy, Trophy,
Crown, Crown,
Medal, Medal,
Star, Star,
@@ -248,7 +248,7 @@ function AchievementBadge({ achievement, size = 'sm' }: { achievement: Achieveme
}; };
return ( return (
<div <div
className={`${sizeClasses[size]} ${rarityColors[achievement.rarity]} rounded-full border-2 flex items-center justify-center relative group cursor-pointer`} className={`${sizeClasses[size]} ${rarityColors[achievement.rarity]} rounded-full border-2 flex items-center justify-center relative group cursor-pointer`}
title={`${achievement.name}: ${achievement.description}`} title={`${achievement.name}: ${achievement.description}`}
> >
@@ -270,9 +270,8 @@ function RankChangeIndicator({ currentRank, previousRank }: { currentRank: numbe
if (change === 0) return null; if (change === 0) return null;
return ( return (
<div className={`flex items-center gap-1 text-sm font-medium ${ <div className={`flex items-center gap-1 text-sm font-medium ${change > 0 ? 'text-success' : 'text-destructive'
change > 0 ? 'text-success' : 'text-destructive' }`}>
}`}>
{change > 0 ? ( {change > 0 ? (
<ChevronUp className="h-4 w-4" /> <ChevronUp className="h-4 w-4" />
) : ( ) : (
@@ -303,14 +302,14 @@ function PersonalStatsOverview({ stats, achievements }: { stats: LearningStats;
out of {stats.totalParticipants.toLocaleString()} learners out of {stats.totalParticipants.toLocaleString()} learners
</div> </div>
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<div className="flex justify-between text-base"> <div className="flex justify-between text-base">
<span>Next milestone</span> <span>Next milestone</span>
<span className="font-semibold">#{stats.nextMilestone.rank}</span> <span className="font-semibold">#{stats.nextMilestone.rank}</span>
</div> </div>
<Progress <Progress
value={((stats.xpThisMonth / (stats.xpThisMonth + stats.nextMilestone.xpRequired)) * 100)} value={((stats.xpThisMonth / (stats.xpThisMonth + stats.nextMilestone.xpRequired)) * 100)}
className="h-3" className="h-3"
/> />
<div className="text-sm text-muted-foreground"> <div className="text-sm text-muted-foreground">
@@ -338,14 +337,14 @@ function PersonalStatsOverview({ stats, achievements }: { stats: LearningStats;
</div> </div>
<div className="text-sm text-muted-foreground">XP Earned</div> <div className="text-sm text-muted-foreground">XP Earned</div>
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<div className="flex justify-between text-base"> <div className="flex justify-between text-base">
<span className="text-muted-foreground">Target</span> <span className="text-muted-foreground">Target</span>
<span className="font-semibold">500 XP</span> <span className="font-semibold">500 XP</span>
</div> </div>
<Progress <Progress
value={(stats.xpThisWeek / 500) * 100} value={(stats.xpThisWeek / 500) * 100}
className="h-3" className="h-3"
/> />
<div className="text-sm text-muted-foreground text-center"> <div className="text-sm text-muted-foreground text-center">
@@ -370,12 +369,12 @@ function PersonalStatsOverview({ stats, achievements }: { stats: LearningStats;
<span className="text-base text-muted-foreground">XP Earned</span> <span className="text-base text-muted-foreground">XP Earned</span>
<span className="text-2xl font-bold text-primary">{stats.xpThisMonth}</span> <span className="text-2xl font-bold text-primary">{stats.xpThisMonth}</span>
</div> </div>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<span className="text-base text-muted-foreground">Courses</span> <span className="text-base text-muted-foreground">Courses</span>
<span className="text-2xl font-bold text-success">{stats.coursesThisMonth}</span> <span className="text-2xl font-bold text-success">{stats.coursesThisMonth}</span>
</div> </div>
<div className="text-center"> <div className="text-center">
<div className="text-sm text-muted-foreground">Monthly Goal</div> <div className="text-sm text-muted-foreground">Monthly Goal</div>
<div className="text-lg font-semibold">5 Courses</div> <div className="text-lg font-semibold">5 Courses</div>
@@ -401,12 +400,12 @@ function PersonalStatsOverview({ stats, achievements }: { stats: LearningStats;
<span className="text-2xl font-bold text-orange-600">{stats.currentStreak}</span> <span className="text-2xl font-bold text-orange-600">{stats.currentStreak}</span>
</div> </div>
</div> </div>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<span className="text-base text-muted-foreground">Best Streak</span> <span className="text-base text-muted-foreground">Best Streak</span>
<span className="text-lg font-bold">{stats.longestStreak} days</span> <span className="text-lg font-bold">{stats.longestStreak} days</span>
</div> </div>
<div> <div>
<div className="text-base text-muted-foreground mb-2">Achievements</div> <div className="text-base text-muted-foreground mb-2">Achievements</div>
<div className="flex gap-2 flex-wrap justify-center"> <div className="flex gap-2 flex-wrap justify-center">
@@ -423,11 +422,11 @@ function PersonalStatsOverview({ stats, achievements }: { stats: LearningStats;
} }
// Main leaderboard table component // Main leaderboard table component
function LeaderboardTable({ function LeaderboardTable({
data, data,
isLoading, isLoading,
currentUserRank currentUserRank
}: { }: {
data: LeaderboardEntry[]; data: LeaderboardEntry[];
isLoading: boolean; isLoading: boolean;
currentUserRank: number; currentUserRank: number;
@@ -472,7 +471,7 @@ function LeaderboardTable({
const formatLastActive = (date: Date) => { const formatLastActive = (date: Date) => {
const now = new Date(); const now = new Date();
const diffInMinutes = Math.floor((now.getTime() - date.getTime()) / (1000 * 60)); const diffInMinutes = Math.floor((now.getTime() - date.getTime()) / (1000 * 60));
if (diffInMinutes < 60) { if (diffInMinutes < 60) {
return `${diffInMinutes}m ago`; return `${diffInMinutes}m ago`;
} else if (diffInMinutes < 1440) { } else if (diffInMinutes < 1440) {
@@ -513,13 +512,12 @@ function LeaderboardTable({
{topPerformers.map((entry, index) => ( {topPerformers.map((entry, index) => (
<div <div
key={entry.id} key={entry.id}
className={`flex items-center gap-4 p-4 rounded-xl border transition-all duration-200 hover:shadow-md ${ className={`flex items-center gap-4 p-4 rounded-xl border transition-all duration-200 hover:shadow-md ${entry.rank <= 3
entry.rank <= 3 ? 'bg-gradient-to-r from-yellow-50 to-orange-50 border-yellow-200'
? 'bg-gradient-to-r from-yellow-50 to-orange-50 border-yellow-200'
: entry.isCurrentUser : entry.isCurrentUser
? 'bg-gradient-to-r from-primary/5 to-primary/10 border-primary/20 ring-2 ring-primary/20' ? 'bg-gradient-to-r from-primary/5 to-primary/10 border-primary/20 ring-2 ring-primary/20'
: 'bg-muted/30 border-border hover:bg-muted/50' : 'bg-muted/30 border-border hover:bg-muted/50'
}`} }`}
> >
{/* Rank */} {/* Rank */}
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
@@ -535,7 +533,7 @@ function LeaderboardTable({
{entry.name.split(' ').map(n => n[0]).join('')} {entry.name.split(' ').map(n => n[0]).join('')}
</AvatarFallback> </AvatarFallback>
</Avatar> </Avatar>
<div className="flex-1"> <div className="flex-1">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<h3 className="text-lg font-semibold">{entry.name}</h3> <h3 className="text-lg font-semibold">{entry.name}</h3>
@@ -544,7 +542,7 @@ function LeaderboardTable({
)} )}
<div className="text-sm text-muted-foreground">Level {entry.level}</div> <div className="text-sm text-muted-foreground">Level {entry.level}</div>
</div> </div>
<div className="flex items-center gap-4 text-sm text-muted-foreground"> <div className="flex items-center gap-4 text-sm text-muted-foreground">
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
<BookOpen className="h-3 w-3" /> <BookOpen className="h-3 w-3" />
@@ -590,7 +588,7 @@ function LeaderboardTable({
<span className="px-4 text-sm text-muted-foreground">Your Position</span> <span className="px-4 text-sm text-muted-foreground">Your Position</span>
<Separator className="flex-1" /> <Separator className="flex-1" />
</div> </div>
<div className="flex items-center gap-4 p-4 rounded-xl border bg-gradient-to-r from-primary/5 to-primary/10 border-primary/20 ring-2 ring-primary/20"> <div className="flex items-center gap-4 p-4 rounded-xl border bg-gradient-to-r from-primary/5 to-primary/10 border-primary/20 ring-2 ring-primary/20">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="text-lg font-bold text-muted-foreground">#{currentUser!.rank}</span> <span className="text-lg font-bold text-muted-foreground">#{currentUser!.rank}</span>
@@ -602,14 +600,14 @@ function LeaderboardTable({
<AvatarImage src={currentUser!.avatar} /> <AvatarImage src={currentUser!.avatar} />
<AvatarFallback className="text-base">You</AvatarFallback> <AvatarFallback className="text-base">You</AvatarFallback>
</Avatar> </Avatar>
<div className="flex-1"> <div className="flex-1">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<h3 className="text-lg font-semibold">{currentUser!.name}</h3> <h3 className="text-lg font-semibold">{currentUser!.name}</h3>
<Badge className="bg-primary text-primary-foreground text-sm">You</Badge> <Badge className="bg-primary text-primary-foreground text-sm">You</Badge>
<div className="text-sm text-muted-foreground">Level {currentUser!.level}</div> <div className="text-sm text-muted-foreground">Level {currentUser!.level}</div>
</div> </div>
<div className="flex items-center gap-4 text-sm text-muted-foreground"> <div className="flex items-center gap-4 text-sm text-muted-foreground">
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
<BookOpen className="h-3 w-3" /> <BookOpen className="h-3 w-3" />
@@ -652,7 +650,7 @@ export function Leaderboard() {
const [activeTab, setActiveTab] = useState('global'); const [activeTab, setActiveTab] = useState('global');
const [filterPeriod, setFilterPeriod] = useState('all-time'); const [filterPeriod, setFilterPeriod] = useState('all-time');
const [filterCategory, setFilterCategory] = useState('all'); const [filterCategory, setFilterCategory] = useState('all');
const navigate = useNavigate(); const navigate = useNavigate();
// Mock user data for LearnerLayout - matching Library page pattern // Mock user data for LearnerLayout - matching Library page pattern
@@ -686,101 +684,100 @@ export function Leaderboard() {
<div className="w-full max-w-none px-2 sm:px-4 lg:px-6 pb-8"> <div className="w-full max-w-none px-2 sm:px-4 lg:px-6 pb-8">
<div className="space-y-8"> <div className="space-y-8">
{/* Personal Stats Overview - Updated to 4 columns */} {/* Personal Stats Overview - Updated to 4 columns */}
<PersonalStatsOverview <PersonalStatsOverview
stats={mockCurrentUserStats} stats={mockCurrentUserStats}
achievements={mockAchievements} achievements={mockAchievements}
/> />
{/* Filters and Tabs */} {/* Filters and Tabs */}
<Card> <Card>
<CardContent className="p-6"> <CardContent className="p-6">
<div className="flex flex-col lg:flex-row gap-4 items-start lg:items-center justify-between"> <div className="flex flex-col lg:flex-row gap-4 items-start lg:items-center justify-between">
{/* Custom Segmented Control */} {/* Custom Segmented Control */}
<div className="w-full lg:w-auto bg-yellow-50/80 rounded-full p-1.5"> <div className="w-full lg:w-auto bg-yellow-50/80 rounded-full p-1.5">
<div className="flex items-center space-x-1"> <div className="flex items-center space-x-1">
{[ {[
{ value: 'global', label: 'Global' }, { value: 'global', label: 'Global' },
{ value: 'regional', label: 'Regional' }, { value: 'regional', label: 'Regional' },
{ value: 'friends', label: 'Friends' } { value: 'friends', label: 'Friends' }
].map((tab) => ( ].map((tab) => (
<button <button
key={tab.value} key={tab.value}
onClick={() => setActiveTab(tab.value)} onClick={() => setActiveTab(tab.value)}
className={`flex-1 px-4 py-2.5 text-base font-medium rounded-full transition-all duration-300 ease-in-out focus:outline-none focus:ring-0 active:outline-none ${ className={`flex-1 px-4 py-2.5 text-base font-medium rounded-full transition-all duration-300 ease-in-out focus:outline-none focus:ring-0 active:outline-none ${activeTab === tab.value
activeTab === tab.value ? 'bg-white text-gray-900 shadow-sm'
? 'bg-white text-gray-900 shadow-sm' : 'text-gray-700 hover:text-gray-900 hover:bg-white/60'
: 'text-gray-700 hover:text-gray-900 hover:bg-white/60' }`}
}`} >
> {tab.label}
{tab.label} </button>
</button> ))}
))} </div>
</div>
<div className="flex flex-col sm:flex-row gap-3 w-full lg:w-auto">
<Select value={filterPeriod} onValueChange={setFilterPeriod}>
<SelectTrigger className="w-full sm:w-40 text-base min-h-[44px]">
<SelectValue placeholder="Time Period" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all-time" className="text-base">All Time</SelectItem>
<SelectItem value="this-month" className="text-base">This Month</SelectItem>
<SelectItem value="this-week" className="text-base">This Week</SelectItem>
</SelectContent>
</Select>
<Select value={filterCategory} onValueChange={setFilterCategory}>
<SelectTrigger className="w-full sm:w-40 text-base min-h-[44px]">
<SelectValue placeholder="Category" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all" className="text-base">All Categories</SelectItem>
<SelectItem value="leadership" className="text-base">Leadership</SelectItem>
<SelectItem value="management" className="text-base">Management</SelectItem>
<SelectItem value="innovation" className="text-base">Innovation</SelectItem>
</SelectContent>
</Select>
</div> </div>
</div> </div>
</CardContent>
</Card>
<div className="flex flex-col sm:flex-row gap-3 w-full lg:w-auto"> {/* Tab Content */}
<Select value={filterPeriod} onValueChange={setFilterPeriod}> <Tabs value={activeTab} className="space-y-6">
<SelectTrigger className="w-full sm:w-40 text-base min-h-[44px]"> <TabsContent value="global" className="space-y-6">
<SelectValue placeholder="Time Period" /> <LeaderboardTable
</SelectTrigger> data={mockLeaderboardData}
<SelectContent> isLoading={isLoading}
<SelectItem value="all-time" className="text-base">All Time</SelectItem> currentUserRank={mockCurrentUserStats.currentRank}
<SelectItem value="this-month" className="text-base">This Month</SelectItem> />
<SelectItem value="this-week" className="text-base">This Week</SelectItem> </TabsContent>
</SelectContent>
</Select>
<Select value={filterCategory} onValueChange={setFilterCategory}> <TabsContent value="regional" className="space-y-6">
<SelectTrigger className="w-full sm:w-40 text-base min-h-[44px]"> <LeaderboardTable
<SelectValue placeholder="Category" /> data={mockLeaderboardData.filter(entry => entry.region === 'North America')}
</SelectTrigger> isLoading={isLoading}
<SelectContent> currentUserRank={mockCurrentUserStats.currentRank}
<SelectItem value="all" className="text-base">All Categories</SelectItem> />
<SelectItem value="leadership" className="text-base">Leadership</SelectItem> </TabsContent>
<SelectItem value="management" className="text-base">Management</SelectItem>
<SelectItem value="innovation" className="text-base">Innovation</SelectItem>
</SelectContent>
</Select>
</div>
</div>
</CardContent>
</Card>
{/* Tab Content */} <TabsContent value="friends" className="space-y-6">
<Tabs value={activeTab} className="space-y-6"> <Card>
<TabsContent value="global" className="space-y-6"> <CardContent className="p-8 text-center">
<LeaderboardTable <Users className="h-16 w-16 text-muted-foreground mx-auto mb-4" />
data={mockLeaderboardData} <h3 className="text-xl font-semibold mb-2">Connect with Friends</h3>
isLoading={isLoading} <p className="text-base text-muted-foreground mb-6">
currentUserRank={mockCurrentUserStats.currentRank} Add friends to see how you compare with your learning buddies
/> </p>
</TabsContent> <Button className="text-base min-h-[44px]">
<Users className="h-4 w-4 mr-2" />
<TabsContent value="regional" className="space-y-6"> Find Friends
<LeaderboardTable </Button>
data={mockLeaderboardData.filter(entry => entry.region === 'North America')} </CardContent>
isLoading={isLoading} </Card>
currentUserRank={mockCurrentUserStats.currentRank} </TabsContent>
/> </Tabs>
</TabsContent>
<TabsContent value="friends" className="space-y-6">
<Card>
<CardContent className="p-8 text-center">
<Users className="h-16 w-16 text-muted-foreground mx-auto mb-4" />
<h3 className="text-xl font-semibold mb-2">Connect with Friends</h3>
<p className="text-base text-muted-foreground mb-6">
Add friends to see how you compare with your learning buddies
</p>
<Button className="text-base min-h-[44px]">
<Users className="h-4 w-4 mr-2" />
Find Friends
</Button>
</CardContent>
</Card>
</TabsContent>
</Tabs>
</div> </div>
</div> </div>
</LearnerLayout> </LearnerLayout>

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function LeadershipOnline() { export function LeadershipOnline() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -3,7 +3,6 @@ import { Button } from '../components/ui/button';
import { Input } from '../components/ui/input'; import { Input } from '../components/ui/input';
import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card';
import { ArrowLeft, Eye, EyeOff, Mail, Lock } from 'lucide-react'; import { ArrowLeft, Eye, EyeOff, Mail, Lock } from 'lucide-react';
const navigate = useNavigate();
import { useAuth } from '../components/AuthContext'; import { useAuth } from '../components/AuthContext';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
@@ -13,11 +12,12 @@ export function Login() {
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const { login } = useAuth(); const { login } = useAuth();
const navigate = useNavigate();
const handleSubmit = async (e: React.FormEvent) => { const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
setIsLoading(true); setIsLoading(true);
try { try {
// Simulate login and go directly to individual dashboard // Simulate login and go directly to individual dashboard
await login(email || 'demo@klc.edu', password || 'demo'); await login(email || 'demo@klc.edu', password || 'demo');
@@ -86,7 +86,7 @@ export function Login() {
Sign in to your individual learning account Sign in to your individual learning account
</p> </p>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
{/* Quick Access Button */} {/* Quick Access Button */}
<div className="mb-6"> <div className="mb-6">

View File

@@ -6,9 +6,9 @@ import { ArrowLeft, Building2, User, ArrowRight, CheckCircle, Users, Target, Boo
// const navigate = useNavigate(); // const navigate = useNavigate();
import { useAuth } from '../components/AuthContext'; import { useAuth } from '../components/AuthContext';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
const navigate = useNavigate();
export function LoginSelection() { export function LoginSelection() {
const { login } = useAuth(); const { login } = useAuth();
const navigate = useNavigate();
const handleBackNavigation = () => { const handleBackNavigation = () => {
navigate('/'); navigate('/');
@@ -63,7 +63,7 @@ export function LoginSelection() {
<div className="container mx-auto px-4 lg:px-8 -mt-8"> <div className="container mx-auto px-4 lg:px-8 -mt-8">
<div className="max-w-6xl mx-auto"> <div className="max-w-6xl mx-auto">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
{/* Individual Learner Card */} {/* Individual Learner Card */}
<Card className="relative overflow-hidden hover:shadow-xl transition-all duration-300 border-2 hover:border-blue-200 bg-white"> <Card className="relative overflow-hidden hover:shadow-xl transition-all duration-300 border-2 hover:border-blue-200 bg-white">
<div className="absolute top-0 right-0 w-32 h-32 bg-gradient-to-br from-blue-500/10 to-transparent rounded-bl-full"></div> <div className="absolute top-0 right-0 w-32 h-32 bg-gradient-to-br from-blue-500/10 to-transparent rounded-bl-full"></div>
@@ -83,7 +83,7 @@ export function LoginSelection() {
Access your personalized learning journey with expert-led courses, assessments, and progress tracking tailored to your professional goals. Access your personalized learning journey with expert-led courses, assessments, and progress tracking tailored to your professional goals.
</p> </p>
</CardHeader> </CardHeader>
<CardContent className="space-y-6"> <CardContent className="space-y-6">
{/* Features List */} {/* Features List */}
<div className="space-y-4"> <div className="space-y-4">
@@ -134,7 +134,7 @@ export function LoginSelection() {
</div> </div>
</div> </div>
<Button <Button
onClick={handleIndividualLogin} onClick={handleIndividualLogin}
className="w-full text-[16px] min-h-[48px] bg-blue-600 hover:bg-blue-700 text-white group" className="w-full text-[16px] min-h-[48px] bg-blue-600 hover:bg-blue-700 text-white group"
> >
@@ -145,7 +145,7 @@ export function LoginSelection() {
<div className="text-center"> <div className="text-center">
<p className="text-[14px] text-gray-500"> <p className="text-[14px] text-gray-500">
Want to explore first?{' '} Want to explore first?{' '}
<button <button
onClick={() => navigate('/login')} onClick={() => navigate('/login')}
className="text-blue-600 hover:text-blue-700 font-medium hover:underline" className="text-blue-600 hover:text-blue-700 font-medium hover:underline"
> >
@@ -175,7 +175,7 @@ export function LoginSelection() {
Access your organization's learning programs with team collaboration, assigned courses, and comprehensive progress tracking for enterprise development. Access your organization's learning programs with team collaboration, assigned courses, and comprehensive progress tracking for enterprise development.
</p> </p>
</CardHeader> </CardHeader>
<CardContent className="space-y-6"> <CardContent className="space-y-6">
{/* Features List */} {/* Features List */}
<div className="space-y-4"> <div className="space-y-4">
@@ -226,7 +226,7 @@ export function LoginSelection() {
</div> </div>
</div> </div>
<Button <Button
onClick={handleCorporateLogin} onClick={handleCorporateLogin}
className="w-full text-[16px] min-h-[48px] bg-purple-600 hover:bg-purple-700 text-white group" className="w-full text-[16px] min-h-[48px] bg-purple-600 hover:bg-purple-700 text-white group"
> >
@@ -237,7 +237,7 @@ export function LoginSelection() {
<div className="text-center"> <div className="text-center">
<p className="text-[14px] text-gray-500"> <p className="text-[14px] text-gray-500">
Want to explore first?{' '} Want to explore first?{' '}
<button <button
onClick={() => navigate('/corporate/login')} onClick={() => navigate('/corporate/login')}
className="text-purple-600 hover:text-purple-700 font-medium hover:underline" className="text-purple-600 hover:text-purple-700 font-medium hover:underline"
> >
@@ -258,7 +258,7 @@ export function LoginSelection() {
<p className="text-[16px] text-gray-600 leading-relaxed mb-6 max-w-2xl mx-auto"> <p className="text-[16px] text-gray-600 leading-relaxed mb-6 max-w-2xl mx-auto">
Click the buttons above to instantly access either dashboard. No credentials required - designed for easy testing and exploration of the KLC learning platform. Click the buttons above to instantly access either dashboard. No credentials required - designed for easy testing and exploration of the KLC learning platform.
</p> </p>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8"> <div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
<div className="text-center"> <div className="text-center">
<div className="w-12 h-12 bg-[#F8C301] rounded-full flex items-center justify-center mx-auto mb-3"> <div className="w-12 h-12 bg-[#F8C301] rounded-full flex items-center justify-center mx-auto mb-3">
@@ -284,15 +284,15 @@ export function LoginSelection() {
</div> </div>
<div className="flex flex-col sm:flex-row gap-4 justify-center"> <div className="flex flex-col sm:flex-row gap-4 justify-center">
<Button <Button
variant="outline" variant="outline"
onClick={() => navigate('/contact')} onClick={() => navigate('/contact')}
className="text-[16px] min-h-[44px] border-[#04045B] text-[#04045B] hover:bg-[#04045B]/10" className="text-[16px] min-h-[44px] border-[#04045B] text-[#04045B] hover:bg-[#04045B]/10"
> >
Contact Support Contact Support
</Button> </Button>
<Button <Button
variant="outline" variant="outline"
onClick={() => navigate('/individual-webinars')} onClick={() => navigate('/individual-webinars')}
className="text-[16px] min-h-[44px] border-[#04045B] text-[#04045B] hover:bg-[#04045B]/10" className="text-[16px] min-h-[44px] border-[#04045B] text-[#04045B] hover:bg-[#04045B]/10"
> >
@@ -313,7 +313,7 @@ export function LoginSelection() {
Experience world-class leadership development with proven results Experience world-class leadership development with proven results
</p> </p>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-4 gap-8"> <div className="grid grid-cols-1 md:grid-cols-4 gap-8">
<div className="text-center"> <div className="text-center">
<p className="text-[32px] font-bold text-[#F8C301] mb-2">27,000+</p> <p className="text-[32px] font-bold text-[#F8C301] mb-2">27,000+</p>

View File

@@ -1,7 +1,10 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function MyCohort() { export function MyCohort() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -2,9 +2,11 @@ import React from 'react';
import { Button } from '../components/ui/button'; import { Button } from '../components/ui/button';
import { Card, CardContent } from '../components/ui/card'; import { Card, CardContent } from '../components/ui/card';
import { ArrowLeft, Home, Search, HelpCircle } from 'lucide-react'; import { ArrowLeft, Home, Search, HelpCircle } from 'lucide-react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function NotFound() { export function NotFound() {
const navigate = useNavigate();
const handleGoHome = () => { const handleGoHome = () => {
navigate('/'); navigate('/');
}; };
@@ -20,11 +22,11 @@ export function NotFound() {
<div className="w-32 h-32 bg-gradient-to-br from-[#04045B]/10 to-[#F8C301]/20 rounded-full flex items-center justify-center mx-auto mb-8 border-2 border-[#04045B]/20"> <div className="w-32 h-32 bg-gradient-to-br from-[#04045B]/10 to-[#F8C301]/20 rounded-full flex items-center justify-center mx-auto mb-8 border-2 border-[#04045B]/20">
<span className="text-[48px] font-bold text-[#04045B]">404</span> <span className="text-[48px] font-bold text-[#04045B]">404</span>
</div> </div>
<h1 className="text-[36px] font-bold text-[#04045B] mb-4"> <h1 className="text-[36px] font-bold text-[#04045B] mb-4">
Page Not Found Page Not Found
</h1> </h1>
<p className="text-[16px] text-gray-600 mb-8 leading-relaxed"> <p className="text-[16px] text-gray-600 mb-8 leading-relaxed">
Sorry, we couldn't find the page you're looking for. The page may have been moved, deleted, or you may have entered an incorrect URL. Sorry, we couldn't find the page you're looking for. The page may have been moved, deleted, or you may have entered an incorrect URL.
</p> </p>
@@ -37,7 +39,7 @@ export function NotFound() {
<Home className="w-4 w-4 mr-2" /> <Home className="w-4 w-4 mr-2" />
Return to Home Return to Home
</Button> </Button>
<Button <Button
variant="outline" variant="outline"
onClick={handleGoBack} onClick={handleGoBack}
@@ -62,7 +64,7 @@ export function NotFound() {
<Search className="h-4 w-4 text-gray-500 flex-shrink-0" /> <Search className="h-4 w-4 text-gray-500 flex-shrink-0" />
<span className="text-[16px] text-gray-700">Professional Webinars</span> <span className="text-[16px] text-gray-700">Professional Webinars</span>
</button> </button>
<button <button
onClick={() => navigate('/contact')} onClick={() => navigate('/contact')}
className="flex items-center gap-3 p-3 text-left rounded-lg hover:bg-gray-50 transition-colors" className="flex items-center gap-3 p-3 text-left rounded-lg hover:bg-gray-50 transition-colors"
@@ -70,7 +72,7 @@ export function NotFound() {
<HelpCircle className="h-4 w-4 text-gray-500 flex-shrink-0" /> <HelpCircle className="h-4 w-4 text-gray-500 flex-shrink-0" />
<span className="text-[16px] text-gray-700">Contact Support</span> <span className="text-[16px] text-gray-700">Contact Support</span>
</button> </button>
<button <button
onClick={() => navigate('/auth')} onClick={() => navigate('/auth')}
className="flex items-center gap-3 p-3 text-left rounded-lg hover:bg-gray-50 transition-colors" className="flex items-center gap-3 p-3 text-left rounded-lg hover:bg-gray-50 transition-colors"

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function OrderConfirmation() { export function OrderConfirmation() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function OrderFailed() { export function OrderFailed() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function OurExpertise() { export function OurExpertise() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function OurImpact() { export function OurImpact() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function OurTeam() { export function OurTeam() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function OurVision() { export function OurVision() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -2,9 +2,11 @@ import React from 'react';
import { Button } from '../components/ui/button'; import { Button } from '../components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card';
import { ArrowLeft, Shield, Eye, Lock, FileText } from 'lucide-react'; import { ArrowLeft, Shield, Eye, Lock, FileText } from 'lucide-react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function Privacy() { export function Privacy() {
const navigate = useNavigate();
const handleBackNavigation = () => { const handleBackNavigation = () => {
navigate('/'); navigate('/');
}; };
@@ -55,15 +57,15 @@ export function Privacy() {
</div> </div>
</div> </div>
</CardHeader> </CardHeader>
<CardContent className="prose prose-gray max-w-none"> <CardContent className="prose prose-gray max-w-none">
<div className="space-y-8"> <div className="space-y-8">
{/* Introduction */} {/* Introduction */}
<section> <section>
<h2 className="text-[24px] font-semibold text-gray-900 mb-4">Introduction</h2> <h2 className="text-[24px] font-semibold text-gray-900 mb-4">Introduction</h2>
<p className="text-[16px] text-gray-600 leading-relaxed mb-4"> <p className="text-[16px] text-gray-600 leading-relaxed mb-4">
At Kautilya Leadership Centre (KLC), we are committed to protecting your privacy and personal information. At Kautilya Leadership Centre (KLC), we are committed to protecting your privacy and personal information.
This Privacy Policy explains how we collect, use, disclose, and safeguard your information when you use our This Privacy Policy explains how we collect, use, disclose, and safeguard your information when you use our
learning platform and services. learning platform and services.
</p> </p>
</section> </section>
@@ -74,7 +76,7 @@ export function Privacy() {
<Eye className="h-5 w-5 text-primary" /> <Eye className="h-5 w-5 text-primary" />
<h2 className="text-[24px] font-semibold text-gray-900">Information We Collect</h2> <h2 className="text-[24px] font-semibold text-gray-900">Information We Collect</h2>
</div> </div>
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<h3 className="text-[18px] font-semibold text-gray-900 mb-2">Personal Information</h3> <h3 className="text-[18px] font-semibold text-gray-900 mb-2">Personal Information</h3>
@@ -110,7 +112,7 @@ export function Privacy() {
<FileText className="h-5 w-5 text-primary" /> <FileText className="h-5 w-5 text-primary" />
<h2 className="text-[24px] font-semibold text-gray-900">How We Use Your Information</h2> <h2 className="text-[24px] font-semibold text-gray-900">How We Use Your Information</h2>
</div> </div>
<ul className="list-disc pl-6 space-y-2 text-[16px] text-gray-600"> <ul className="list-disc pl-6 space-y-2 text-[16px] text-gray-600">
<li>Provide and improve our learning services</li> <li>Provide and improve our learning services</li>
<li>Personalize your learning experience</li> <li>Personalize your learning experience</li>
@@ -141,9 +143,9 @@ export function Privacy() {
<Lock className="h-5 w-5 text-primary" /> <Lock className="h-5 w-5 text-primary" />
<h2 className="text-[24px] font-semibold text-gray-900">Data Security</h2> <h2 className="text-[24px] font-semibold text-gray-900">Data Security</h2>
</div> </div>
<p className="text-[16px] text-gray-600 leading-relaxed mb-4"> <p className="text-[16px] text-gray-600 leading-relaxed mb-4">
We implement appropriate technical and organizational security measures to protect your personal information We implement appropriate technical and organizational security measures to protect your personal information
against unauthorized access, alteration, disclosure, or destruction. These measures include: against unauthorized access, alteration, disclosure, or destruction. These measures include:
</p> </p>
<ul className="list-disc pl-6 space-y-2 text-[16px] text-gray-600"> <ul className="list-disc pl-6 space-y-2 text-[16px] text-gray-600">
@@ -186,8 +188,8 @@ export function Privacy() {
<section> <section>
<h2 className="text-[24px] font-semibold text-gray-900 mb-4">Policy Updates</h2> <h2 className="text-[24px] font-semibold text-gray-900 mb-4">Policy Updates</h2>
<p className="text-[16px] text-gray-600 leading-relaxed"> <p className="text-[16px] text-gray-600 leading-relaxed">
We may update this Privacy Policy from time to time. We will notify you of any changes by posting the new We may update this Privacy Policy from time to time. We will notify you of any changes by posting the new
Privacy Policy on this page and updating the "Last updated" date. We encourage you to review this Privacy Privacy Policy on this page and updating the "Last updated" date. We encourage you to review this Privacy
Policy periodically for any changes. Policy periodically for any changes.
</p> </p>
</section> </section>

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function ProgrammeCatalogue() { export function ProgrammeCatalogue() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function ProgrammeDetail() { export function ProgrammeDetail() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function Resources() { export function Resources() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -3,7 +3,7 @@ import { Button } from '../components/ui/button';
import { Input } from '../components/ui/input'; import { Input } from '../components/ui/input';
import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card';
import { ArrowLeft, Eye, EyeOff, Mail, Lock, User } from 'lucide-react'; import { ArrowLeft, Eye, EyeOff, Mail, Lock, User } from 'lucide-react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function Signup() { export function Signup() {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
@@ -13,14 +13,16 @@ export function Signup() {
password: '', password: '',
confirmPassword: '' confirmPassword: ''
}); });
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false); const [showConfirmPassword, setShowConfirmPassword] = useState(false);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const navigate = useNavigate();
const handleSubmit = async (e: React.FormEvent) => { const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
setIsLoading(true); setIsLoading(true);
try { try {
// Simulate signup // Simulate signup
await new Promise(resolve => setTimeout(resolve, 1000)); await new Promise(resolve => setTimeout(resolve, 1000));
@@ -75,7 +77,7 @@ export function Signup() {
Create your individual learning account Create your individual learning account
</p> </p>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<form onSubmit={handleSubmit} className="space-y-6"> <form onSubmit={handleSubmit} className="space-y-6">
<div className="space-y-4"> <div className="space-y-4">

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function TeamLeadership() { export function TeamLeadership() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -2,9 +2,11 @@ import React from 'react';
import { Button } from '../components/ui/button'; import { Button } from '../components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card';
import { ArrowLeft, FileText, Scale, AlertCircle } from 'lucide-react'; import { ArrowLeft, FileText, Scale, AlertCircle } from 'lucide-react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function Terms() { export function Terms() {
const navigate = useNavigate();
const handleBackNavigation = () => { const handleBackNavigation = () => {
navigate('/'); navigate('/');
}; };
@@ -55,15 +57,15 @@ export function Terms() {
</div> </div>
</div> </div>
</CardHeader> </CardHeader>
<CardContent className="prose prose-gray max-w-none"> <CardContent className="prose prose-gray max-w-none">
<div className="space-y-8"> <div className="space-y-8">
{/* Introduction */} {/* Introduction */}
<section> <section>
<h2 className="text-[24px] font-semibold text-gray-900 mb-4">Agreement to Terms</h2> <h2 className="text-[24px] font-semibold text-gray-900 mb-4">Agreement to Terms</h2>
<p className="text-[16px] text-gray-600 leading-relaxed mb-4"> <p className="text-[16px] text-gray-600 leading-relaxed mb-4">
By accessing and using the Kautilya Leadership Centre (KLC) learning platform, you agree to be bound by these By accessing and using the Kautilya Leadership Centre (KLC) learning platform, you agree to be bound by these
Terms of Service and all applicable laws and regulations. If you do not agree with any of these terms, you are Terms of Service and all applicable laws and regulations. If you do not agree with any of these terms, you are
prohibited from using or accessing this site. prohibited from using or accessing this site.
</p> </p>
</section> </section>
@@ -74,9 +76,9 @@ export function Terms() {
<FileText className="h-5 w-5 text-primary" /> <FileText className="h-5 w-5 text-primary" />
<h2 className="text-[24px] font-semibold text-gray-900">Use License</h2> <h2 className="text-[24px] font-semibold text-gray-900">Use License</h2>
</div> </div>
<p className="text-[16px] text-gray-600 leading-relaxed mb-4"> <p className="text-[16px] text-gray-600 leading-relaxed mb-4">
Permission is granted to temporarily access the materials on KLC's learning platform for personal, Permission is granted to temporarily access the materials on KLC's learning platform for personal,
non-commercial transitory viewing only. This is the grant of a license, not a transfer of title, and under this license you may not: non-commercial transitory viewing only. This is the grant of a license, not a transfer of title, and under this license you may not:
</p> </p>
<ul className="list-disc pl-6 space-y-2 text-[16px] text-gray-600 mb-4"> <ul className="list-disc pl-6 space-y-2 text-[16px] text-gray-600 mb-4">
@@ -123,7 +125,7 @@ export function Terms() {
<section> <section>
<h2 className="text-[24px] font-semibold text-gray-900 mb-4">Course Content and Certificates</h2> <h2 className="text-[24px] font-semibold text-gray-900 mb-4">Course Content and Certificates</h2>
<p className="text-[16px] text-gray-600 leading-relaxed mb-4"> <p className="text-[16px] text-gray-600 leading-relaxed mb-4">
Our courses and learning materials are for educational purposes. Course completion certificates are issued Our courses and learning materials are for educational purposes. Course completion certificates are issued
upon successful completion of requirements. These certificates: upon successful completion of requirements. These certificates:
</p> </p>
<ul className="list-disc pl-6 space-y-2 text-[16px] text-gray-600"> <ul className="list-disc pl-6 space-y-2 text-[16px] text-gray-600">
@@ -152,8 +154,8 @@ export function Terms() {
<section> <section>
<h2 className="text-[24px] font-semibold text-gray-900 mb-4">Intellectual Property</h2> <h2 className="text-[24px] font-semibold text-gray-900 mb-4">Intellectual Property</h2>
<p className="text-[16px] text-gray-600 leading-relaxed"> <p className="text-[16px] text-gray-600 leading-relaxed">
All content, materials, and intellectual property on the KLC platform remain the exclusive property of All content, materials, and intellectual property on the KLC platform remain the exclusive property of
Kautilya Leadership Centre or its licensors. You may not reproduce, distribute, or create derivative works Kautilya Leadership Centre or its licensors. You may not reproduce, distribute, or create derivative works
without written permission. without written permission.
</p> </p>
</section> </section>
@@ -164,10 +166,10 @@ export function Terms() {
<AlertCircle className="h-5 w-5 text-amber-500 flex-shrink-0 mt-1" /> <AlertCircle className="h-5 w-5 text-amber-500 flex-shrink-0 mt-1" />
<h2 className="text-[24px] font-semibold text-gray-900">Disclaimer</h2> <h2 className="text-[24px] font-semibold text-gray-900">Disclaimer</h2>
</div> </div>
<p className="text-[16px] text-gray-600 leading-relaxed"> <p className="text-[16px] text-gray-600 leading-relaxed">
The materials on KLC's platform are provided on an 'as is' basis. KLC makes no warranties, expressed or implied, The materials on KLC's platform are provided on an 'as is' basis. KLC makes no warranties, expressed or implied,
and hereby disclaims all other warranties including, without limitation, implied warranties or conditions of and hereby disclaims all other warranties including, without limitation, implied warranties or conditions of
merchantability, fitness for a particular purpose, or non-infringement of intellectual property. merchantability, fitness for a particular purpose, or non-infringement of intellectual property.
</p> </p>
</section> </section>
@@ -176,8 +178,8 @@ export function Terms() {
<section> <section>
<h2 className="text-[24px] font-semibold text-gray-900 mb-4">Limitation of Liability</h2> <h2 className="text-[24px] font-semibold text-gray-900 mb-4">Limitation of Liability</h2>
<p className="text-[16px] text-gray-600 leading-relaxed"> <p className="text-[16px] text-gray-600 leading-relaxed">
In no event shall KLC or its suppliers be liable for any damages (including, without limitation, damages for In no event shall KLC or its suppliers be liable for any damages (including, without limitation, damages for
loss of data or profit, or due to business interruption) arising out of the use or inability to use the materials loss of data or profit, or due to business interruption) arising out of the use or inability to use the materials
on KLC's platform, even if KLC or an authorized representative has been notified of the possibility of such damage. on KLC's platform, even if KLC or an authorized representative has been notified of the possibility of such damage.
</p> </p>
</section> </section>

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function WebinarDetail() { export function WebinarDetail() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,7 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
const navigate = useNavigate(); import { useNavigate } from 'react-router';
export function WebinarListing() { export function WebinarListing() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -9,10 +9,10 @@ import { Separator } from '../../components/ui/separator';
import { Skeleton } from '../../components/ui/skeleton'; import { Skeleton } from '../../components/ui/skeleton';
import { Alert, AlertDescription } from '../../components/ui/alert'; import { Alert, AlertDescription } from '../../components/ui/alert';
import { PieChart, Pie, Cell, ResponsiveContainer, Legend, Tooltip } from 'recharts'; import { PieChart, Pie, Cell, ResponsiveContainer, Legend, Tooltip } from 'recharts';
import { import {
BookOpen, BookOpen,
Clock, Clock,
Trophy, Trophy,
Calendar, Calendar,
TrendingUp, TrendingUp,
Play, Play,
@@ -47,10 +47,10 @@ import {
MapPin MapPin
} from 'lucide-react'; } from 'lucide-react';
import { ImageWithFallback } from '../../components/figma/ImageWithFallback'; import { ImageWithFallback } from '../../components/figma/ImageWithFallback';
import globalMapImage from 'figma:asset/1b56e6afe31d5744d2e7a38d3e2f8c3ce78a90af.png'; // import globalMapImage from 'figma:asset/1b56e6afe31d5744d2e7a38d3e2f8c3ce78a90af.png';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
const navigate = useNavigate();
// Loading skeleton component for corporate dashboard // Loading skeleton component for corporate dashboard
const globalMapImage = 'https://images.unsplash.com/photo-1526778548025-fa2f459cd5c1?w=1600&auto=format&fit=crop&q=60'
function CorporateDashboardSkeleton() { function CorporateDashboardSkeleton() {
return ( return (
<div className="space-y-8"> <div className="space-y-8">
@@ -148,7 +148,7 @@ function ConnectionStatus() {
<WifiOff className="h-5 w-5 text-destructive" /> <WifiOff className="h-5 w-5 text-destructive" />
<AlertDescription className="flex items-center justify-between text-base"> <AlertDescription className="flex items-center justify-between text-base">
<span>You're currently offline. Some features may not be available.</span> <span>You're currently offline. Some features may not be available.</span>
<Button <Button
onClick={handleRetry} onClick={handleRetry}
disabled={isLoading} disabled={isLoading}
size="sm" size="sm"
@@ -170,36 +170,36 @@ function ConnectionStatus() {
// Corporate KPI Cards component // Corporate KPI Cards component
function CorporateKPICards() { function CorporateKPICards() {
const kpiData = [ const kpiData = [
{ {
id: 'team-members', id: 'team-members',
value: 24, value: 24,
label: "Team Members", label: "Team Members",
change: "+3 this quarter", change: "+3 this quarter",
icon: Users, icon: Users,
bgGradient: "bg-gradient-to-br from-brand-navy/70 to-brand-navy/80" bgGradient: "bg-gradient-to-br from-brand-navy/70 to-brand-navy/80"
}, },
{ {
id: 'completion-rate', id: 'completion-rate',
value: 87, value: 87,
label: "Completion Rate", label: "Completion Rate",
change: "+12% this month", change: "+12% this month",
icon: CheckCircle, icon: CheckCircle,
bgGradient: "bg-gradient-to-br from-success to-emerald-500" bgGradient: "bg-gradient-to-br from-success to-emerald-500"
}, },
{ {
id: 'team-ranking', id: 'team-ranking',
value: 3, value: 3,
label: "Division Ranking", label: "Division Ranking",
change: "↑2 positions", change: "↑2 positions",
icon: Trophy, icon: Trophy,
bgGradient: "bg-gradient-to-br from-brand-gold to-amber-500" bgGradient: "bg-gradient-to-br from-brand-gold to-amber-500"
}, },
{ {
id: 'upcoming-deadlines', id: 'upcoming-deadlines',
value: 8, value: 8,
label: "Upcoming Deadlines", label: "Upcoming Deadlines",
change: "Next: Today", change: "Next: Today",
icon: Calendar, icon: Calendar,
bgGradient: "bg-gradient-to-br from-brand-charcoal to-gray-800" bgGradient: "bg-gradient-to-br from-brand-charcoal to-gray-800"
} }
]; ];
@@ -240,65 +240,65 @@ function CorporateKPICards() {
// Team Performance Overview component // Team Performance Overview component
function TeamPerformanceOverview() { function TeamPerformanceOverview() {
const teamGoals = [ const teamGoals = [
{ {
id: '1', id: '1',
title: 'Q4 Leadership Development', title: 'Q4 Leadership Development',
description: 'Complete advanced leadership track', description: 'Complete advanced leadership track',
progress: 18, progress: 18,
total: 24, total: 24,
icon: Crown, icon: Crown,
bgGradient: 'bg-gradient-to-br from-brand-gold to-amber-500' bgGradient: 'bg-gradient-to-br from-brand-gold to-amber-500'
}, },
{ {
id: '2', id: '2',
title: 'Strategic Planning Mastery', title: 'Strategic Planning Mastery',
description: 'Team strategic thinking certification', description: 'Team strategic thinking certification',
progress: 15, progress: 15,
total: 20, total: 20,
icon: Brain, icon: Brain,
bgGradient: 'bg-gradient-to-br from-brand-charcoal to-gray-800' bgGradient: 'bg-gradient-to-br from-brand-charcoal to-gray-800'
}, },
{ {
id: '3', id: '3',
title: 'Innovation Workshop Series', title: 'Innovation Workshop Series',
description: 'Complete innovation methodology training', description: 'Complete innovation methodology training',
progress: 12, progress: 12,
total: 12, total: 12,
icon: Lightbulb, icon: Lightbulb,
bgGradient: 'bg-gradient-to-br from-success to-emerald-500' bgGradient: 'bg-gradient-to-br from-success to-emerald-500'
}, },
{ {
id: '4', id: '4',
title: 'Cross-Department Collaboration', title: 'Cross-Department Collaboration',
description: 'Inter-team project completion', description: 'Inter-team project completion',
progress: 8, progress: 8,
total: 16, total: 16,
icon: Network, icon: Network,
bgGradient: 'bg-gradient-to-br from-brand-navy/70 to-brand-navy/80' bgGradient: 'bg-gradient-to-br from-brand-navy/70 to-brand-navy/80'
}, },
{ {
id: '5', id: '5',
title: 'Digital Transformation Skills', title: 'Digital Transformation Skills',
description: 'Master digital leadership competencies', description: 'Master digital leadership competencies',
progress: 6, progress: 6,
total: 18, total: 18,
icon: Zap, icon: Zap,
bgGradient: 'bg-gradient-to-br from-purple-500 to-indigo-600' bgGradient: 'bg-gradient-to-br from-purple-500 to-indigo-600'
}, },
{ {
id: '6', id: '6',
title: 'Performance Management Excellence', title: 'Performance Management Excellence',
description: 'Advanced coaching and feedback techniques', description: 'Advanced coaching and feedback techniques',
progress: 14, progress: 14,
total: 22, total: 22,
icon: Star, icon: Star,
bgGradient: 'bg-gradient-to-br from-orange-400 to-pink-500' bgGradient: 'bg-gradient-to-br from-orange-400 to-pink-500'
} }
]; ];
const overallProgress = Math.round( const overallProgress = Math.round(
(teamGoals.reduce((acc, goal) => acc + goal.progress, 0) / (teamGoals.reduce((acc, goal) => acc + goal.progress, 0) /
teamGoals.reduce((acc, goal) => acc + goal.total, 0)) * 100 teamGoals.reduce((acc, goal) => acc + goal.total, 0)) * 100
); );
return ( return (
@@ -316,7 +316,7 @@ function TeamPerformanceOverview() {
</Badge> </Badge>
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
<CardContent className="flex-1 flex flex-col"> <CardContent className="flex-1 flex flex-col">
{/* Overall Progress */} {/* Overall Progress */}
<div className="space-y-2 mb-6"> <div className="space-y-2 mb-6">
@@ -334,13 +334,12 @@ function TeamPerformanceOverview() {
const Icon = goal.icon; const Icon = goal.icon;
const progressPercentage = Math.round((goal.progress / goal.total) * 100); const progressPercentage = Math.round((goal.progress / goal.total) * 100);
const isCompleted = goal.progress >= goal.total; const isCompleted = goal.progress >= goal.total;
return ( return (
<div <div
key={goal.id} key={goal.id}
className={`p-3 rounded-lg border transition-all duration-200 flex flex-col ${ className={`p-3 rounded-lg border transition-all duration-200 flex flex-col ${isCompleted ? 'bg-success/5 border-success/20' : 'bg-muted/30 hover:bg-muted/50'
isCompleted ? 'bg-success/5 border-success/20' : 'bg-muted/30 hover:bg-muted/50' }`}
}`}
> >
<div className="flex items-start gap-3 flex-1"> <div className="flex items-start gap-3 flex-1">
<div className={`w-10 h-10 rounded-full flex-shrink-0 flex items-center justify-center shadow-md border border-white/20 ${isCompleted ? 'bg-gradient-to-br from-success to-emerald-500' : goal.bgGradient}`}> <div className={`w-10 h-10 rounded-full flex-shrink-0 flex items-center justify-center shadow-md border border-white/20 ${isCompleted ? 'bg-gradient-to-br from-success to-emerald-500' : goal.bgGradient}`}>
@@ -381,6 +380,7 @@ function TeamPerformanceOverview() {
// Corporate Analytics component // Corporate Analytics component
function CorporateAnalytics() { function CorporateAnalytics() {
const navigate = useNavigate();
const analyticsData = [ const analyticsData = [
{ name: 'Completed', value: 68, color: '#21A36A' }, { name: 'Completed', value: 68, color: '#21A36A' },
{ name: 'In Progress', value: 25, color: '#F8C301' }, { name: 'In Progress', value: 25, color: '#F8C301' },
@@ -419,8 +419,8 @@ function CorporateAnalytics() {
</div> </div>
Team Analytics Team Analytics
</div> </div>
<Button <Button
variant="ghost" variant="ghost"
size="sm" size="sm"
onClick={() => navigate('/library?view=corporate')} onClick={() => navigate('/library?view=corporate')}
className="text-base h-auto p-0 text-primary hover:text-primary/80" className="text-base h-auto p-0 text-primary hover:text-primary/80"
@@ -429,7 +429,7 @@ function CorporateAnalytics() {
</Button> </Button>
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
<CardContent className="flex-1 flex flex-col"> <CardContent className="flex-1 flex flex-col">
{/* Top Statistics - 2x2 Grid */} {/* Top Statistics - 2x2 Grid */}
<div className="grid grid-cols-2 gap-4 text-center mb-6"> <div className="grid grid-cols-2 gap-4 text-center mb-6">
@@ -489,7 +489,7 @@ function CorporateAnalytics() {
<Tooltip content={<CustomTooltip />} /> <Tooltip content={<CustomTooltip />} />
</PieChart> </PieChart>
</ResponsiveContainer> </ResponsiveContainer>
{/* Center Text */} {/* Center Text */}
<div className="absolute inset-0 flex flex-col items-center justify-center"> <div className="absolute inset-0 flex flex-col items-center justify-center">
<div className="text-4xl font-bold text-primary"> <div className="text-4xl font-bold text-primary">
@@ -504,7 +504,7 @@ function CorporateAnalytics() {
{/* Bottom Button */} {/* Bottom Button */}
<div className="mt-6"> <div className="mt-6">
<Button <Button
variant="outline" variant="outline"
onClick={() => navigate('/library?view=corporate')} onClick={() => navigate('/library?view=corporate')}
className="w-full text-base h-11" className="w-full text-base h-11"
@@ -520,6 +520,7 @@ function CorporateAnalytics() {
// Corporate Assigned Training component // Corporate Assigned Training component
function AssignedTraining() { function AssignedTraining() {
const navigate = useNavigate();
const assignments = [ const assignments = [
{ {
id: '1', id: '1',
@@ -619,8 +620,8 @@ function AssignedTraining() {
</div> </div>
Assigned Training Assigned Training
</div> </div>
<Button <Button
variant="ghost" variant="ghost"
size="sm" size="sm"
onClick={() => navigate('/library?view=corporate')} onClick={() => navigate('/library?view=corporate')}
className="text-base h-10" className="text-base h-10"
@@ -629,16 +630,15 @@ function AssignedTraining() {
</Button> </Button>
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
<CardContent className="flex-1"> <CardContent className="flex-1">
{/* Assignments Grid */} {/* Assignments Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 h-full"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4 h-full">
{assignments.map((assignment) => ( {assignments.map((assignment) => (
<div <div
key={assignment.id} key={assignment.id}
className={`group cursor-pointer bg-white rounded-lg border transition-all duration-200 flex flex-col h-full overflow-hidden ${ className={`group cursor-pointer bg-white rounded-lg border transition-all duration-200 flex flex-col h-full overflow-hidden ${assignment.status === 'urgent' ? 'border-destructive/30 bg-destructive/5' : 'border-border hover:shadow-md'
assignment.status === 'urgent' ? 'border-destructive/30 bg-destructive/5' : 'border-border hover:shadow-md' }`}
}`}
onClick={() => navigate(`/library?view=corporate&courseId=${assignment.id}&tab=overview`)} onClick={() => navigate(`/library?view=corporate&courseId=${assignment.id}&tab=overview`)}
> >
{/* Course Image */} {/* Course Image */}
@@ -650,23 +650,21 @@ function AssignedTraining() {
/> />
{/* Category Badge Overlay */} {/* Category Badge Overlay */}
<div className="absolute top-3 left-3"> <div className="absolute top-3 left-3">
<Badge <Badge
variant="outline" variant="outline"
className={`text-sm font-normal border px-2 py-0.5 bg-white/90 backdrop-blur-sm ${ className={`text-sm font-normal border px-2 py-0.5 bg-white/90 backdrop-blur-sm ${assignment.categoryColor === 'bg-destructive' ? 'border-destructive/30 text-destructive' :
assignment.categoryColor === 'bg-destructive' ? 'border-destructive/30 text-destructive' :
assignment.categoryColor === 'bg-primary' ? 'border-primary/30 text-primary' : assignment.categoryColor === 'bg-primary' ? 'border-primary/30 text-primary' :
assignment.categoryColor === 'bg-success' ? 'border-success/30 text-success' : assignment.categoryColor === 'bg-success' ? 'border-success/30 text-success' :
'border-[#26231A]/30 text-[#26231A]' 'border-[#26231A]/30 text-[#26231A]'
}`} }`}
> >
{assignment.category} {assignment.category}
</Badge> </Badge>
</div> </div>
{/* Deadline Badge Overlay */} {/* Deadline Badge Overlay */}
<div className="absolute top-3 right-3"> <div className="absolute top-3 right-3">
<div className={`text-sm font-medium px-2 py-1 rounded bg-white/90 backdrop-blur-sm ${ <div className={`text-sm font-medium px-2 py-1 rounded bg-white/90 backdrop-blur-sm ${assignment.status === 'urgent' ? 'text-destructive' : 'text-muted-foreground'
assignment.status === 'urgent' ? 'text-destructive' : 'text-muted-foreground' }`}>
}`}>
Due: {assignment.deadline} Due: {assignment.deadline}
</div> </div>
</div> </div>
@@ -701,7 +699,7 @@ function AssignedTraining() {
<span className="font-medium">{new Date(assignment.dueDate).toLocaleDateString()}</span> <span className="font-medium">{new Date(assignment.dueDate).toLocaleDateString()}</span>
</div> </div>
</div> </div>
{/* Assignment Metadata and Action - Auto-positioned at bottom */} {/* Assignment Metadata and Action - Auto-positioned at bottom */}
<div className="mt-auto space-y-3"> <div className="mt-auto space-y-3">
<div className="flex items-center justify-between pt-3 border-t border-border"> <div className="flex items-center justify-between pt-3 border-t border-border">
@@ -709,16 +707,16 @@ function AssignedTraining() {
<Clock className="h-4 w-4" /> <Clock className="h-4 w-4" />
<span>{assignment.duration}</span> <span>{assignment.duration}</span>
</div> </div>
<Badge <Badge
variant={assignment.status === 'urgent' ? 'destructive' : 'outline'} variant={assignment.status === 'urgent' ? 'destructive' : 'outline'}
className="text-base" className="text-base"
> >
{assignment.status === 'urgent' ? 'Urgent' : 'Assigned'} {assignment.status === 'urgent' ? 'Urgent' : 'Assigned'}
</Badge> </Badge>
</div> </div>
{/* Action Button */} {/* Action Button */}
<Button <Button
size="sm" size="sm"
variant={assignment.status === 'urgent' ? 'destructive' : 'default'} variant={assignment.status === 'urgent' ? 'destructive' : 'default'}
className="w-full text-base h-10" className="w-full text-base h-10"
@@ -742,6 +740,7 @@ function AssignedTraining() {
// Team Leaderboard component // Team Leaderboard component
function TeamLeaderboard() { function TeamLeaderboard() {
const navigate = useNavigate();
const teamData = [ const teamData = [
{ id: '1', name: 'Sarah Johnson (You)', avatar: 'https://images.unsplash.com/photo-1494790108755-2616b612b786?w=100&h=100&fit=crop', points: 2156, rank: 1, completed: 12, isCurrentUser: true }, { id: '1', name: 'Sarah Johnson (You)', avatar: 'https://images.unsplash.com/photo-1494790108755-2616b612b786?w=100&h=100&fit=crop', points: 2156, rank: 1, completed: 12, isCurrentUser: true },
{ id: '2', name: 'Alex Chen', avatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=100&h=100&fit=crop', points: 2089, rank: 2, completed: 11 }, { id: '2', name: 'Alex Chen', avatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=100&h=100&fit=crop', points: 2089, rank: 2, completed: 11 },
@@ -761,8 +760,8 @@ function TeamLeaderboard() {
</div> </div>
<span className="bg-gradient-to-r from-gray-800 to-gray-600 bg-clip-text text-transparent">Team Leaderboard</span> <span className="bg-gradient-to-r from-gray-800 to-gray-600 bg-clip-text text-transparent">Team Leaderboard</span>
</div> </div>
<Button <Button
variant="outline" variant="outline"
size="sm" size="sm"
onClick={() => navigate('/leaderboard?view=corporate')} onClick={() => navigate('/leaderboard?view=corporate')}
className="text-base h-10 border-2 border-brand-navy/15 text-brand-navy/80 hover:bg-brand-navy/3 font-semibold" className="text-base h-10 border-2 border-brand-navy/15 text-brand-navy/80 hover:bg-brand-navy/3 font-semibold"
@@ -773,22 +772,20 @@ function TeamLeaderboard() {
</CardHeader> </CardHeader>
<CardContent className="space-y-4 p-6"> <CardContent className="space-y-4 p-6">
{teamData.map((entry) => ( {teamData.map((entry) => (
<div <div
key={entry.id} key={entry.id}
className={`flex items-center justify-between p-4 rounded-xl transition-all duration-200 hover:shadow-lg ${ className={`flex items-center justify-between p-4 rounded-xl transition-all duration-200 hover:shadow-lg ${entry.isCurrentUser
entry.isCurrentUser ? 'bg-gradient-to-r from-brand-navy/10 to-brand-navy/5 border-2 border-brand-navy/20 shadow-md'
? 'bg-gradient-to-r from-brand-navy/10 to-brand-navy/5 border-2 border-brand-navy/20 shadow-md' : 'hover:bg-gradient-to-r hover:from-gray-50 hover:to-white bg-white/50 border border-gray-200/50'
: 'hover:bg-gradient-to-r hover:from-gray-50 hover:to-white bg-white/50 border border-gray-200/50' }`}
}`}
> >
<div className="flex items-center gap-4 flex-1 min-w-0"> <div className="flex items-center gap-4 flex-1 min-w-0">
<div className={`flex items-center justify-center w-10 h-10 rounded-xl text-base font-bold flex-shrink-0 shadow-md ${ <div className={`flex items-center justify-center w-10 h-10 rounded-xl text-base font-bold flex-shrink-0 shadow-md ${entry.rank === 1 ? 'bg-gradient-to-br from-brand-gold to-amber-500 text-white' :
entry.rank === 1 ? 'bg-gradient-to-br from-brand-gold to-amber-500 text-white' :
entry.rank === 2 ? 'bg-gradient-to-br from-gray-400 to-gray-500 text-white' : entry.rank === 2 ? 'bg-gradient-to-br from-gray-400 to-gray-500 text-white' :
entry.rank === 3 ? 'bg-gradient-to-br from-amber-600 to-amber-700 text-white' : entry.rank === 3 ? 'bg-gradient-to-br from-amber-600 to-amber-700 text-white' :
entry.isCurrentUser ? 'bg-gradient-to-br from-brand-navy to-brand-navy/80 text-white' : entry.isCurrentUser ? 'bg-gradient-to-br from-brand-navy to-brand-navy/80 text-white' :
'bg-gradient-to-br from-gray-200 to-gray-300 text-gray-600' 'bg-gradient-to-br from-gray-200 to-gray-300 text-gray-600'
}`}> }`}>
{entry.rank} {entry.rank}
</div> </div>
<Avatar className="w-10 h-10 flex-shrink-0 shadow-md border-2 border-white"> <Avatar className="w-10 h-10 flex-shrink-0 shadow-md border-2 border-white">
@@ -811,10 +808,9 @@ function TeamLeaderboard() {
</div> </div>
</div> </div>
</div> </div>
<Badge variant={entry.isCurrentUser ? "default" : "outline"} className={`text-base px-3 py-1 font-semibold ${ <Badge variant={entry.isCurrentUser ? "default" : "outline"} className={`text-base px-3 py-1 font-semibold ${entry.isCurrentUser ? 'bg-gradient-to-r from-brand-navy to-brand-navy/80 text-white shadow-md' : 'border-gray-300 text-gray-600'
entry.isCurrentUser ? 'bg-gradient-to-r from-brand-navy to-brand-navy/80 text-white shadow-md' : 'border-gray-300 text-gray-600' }`}>
}`}>
#{entry.rank} #{entry.rank}
</Badge> </Badge>
</div> </div>
@@ -898,7 +894,7 @@ function RecentActivity() {
{activities.map((activity) => { {activities.map((activity) => {
const Icon = activity.icon; const Icon = activity.icon;
return ( return (
<div <div
key={activity.id} key={activity.id}
className={`group flex items-start gap-4 p-4 rounded-xl border-0 bg-gradient-to-r ${activity.bgColor} hover:shadow-lg transition-all duration-300 cursor-pointer hover:-translate-y-0.5`} className={`group flex items-start gap-4 p-4 rounded-xl border-0 bg-gradient-to-r ${activity.bgColor} hover:shadow-lg transition-all duration-300 cursor-pointer hover:-translate-y-0.5`}
> >
@@ -928,73 +924,73 @@ function RecentActivity() {
// Global Learner Map component - Full width heatmap // Global Learner Map component - Full width heatmap
function GlobalLearnerMap() { function GlobalLearnerMap() {
const learnersByCountry = [ const learnersByCountry = [
{ {
country: 'Romania', country: 'Romania',
learners: 55760, learners: 55760,
percentage: 21.2, percentage: 21.2,
color: '#04045B', color: '#04045B',
flag: '🇷🇴' flag: '🇷🇴'
}, },
{ {
country: 'Australia', country: 'Australia',
learners: 60374, learners: 60374,
percentage: 22.9, percentage: 22.9,
color: '#04045B', color: '#04045B',
flag: '🇦🇺' flag: '🇦🇺'
}, },
{ {
country: 'Russia', country: 'Russia',
learners: 37556, learners: 37556,
percentage: 17, percentage: 17,
color: '#04045B', color: '#04045B',
flag: '🇷🇺' flag: '🇷🇺'
}, },
{ {
country: 'Ireland', country: 'Ireland',
learners: 32123, learners: 32123,
percentage: 14, percentage: 14,
color: '#F8C301', color: '#F8C301',
flag: '🇮🇪' flag: '🇮🇪'
}, },
{ {
country: 'Ukraine', country: 'Ukraine',
learners: 30589, learners: 30589,
percentage: 13, percentage: 13,
color: '#F8C301', color: '#F8C301',
flag: '🇺🇦' flag: '🇺🇦'
}, },
{ {
country: 'USA', country: 'USA',
learners: 24544, learners: 24544,
percentage: 12.8, percentage: 12.8,
color: '#26231A', color: '#26231A',
flag: '🇺🇸' flag: '🇺🇸'
}, },
{ {
country: 'Germany', country: 'Germany',
learners: 23787, learners: 23787,
percentage: 12.8, percentage: 12.8,
color: '#26231A', color: '#26231A',
flag: '🇩🇪' flag: '🇩🇪'
}, },
{ {
country: 'Argentina', country: 'Argentina',
learners: 18245, learners: 18245,
percentage: 8.9, percentage: 8.9,
color: '#6B7280', color: '#6B7280',
flag: '🇦🇷' flag: '🇦🇷'
}, },
{ {
country: 'Spain', country: 'Spain',
learners: 12374, learners: 12374,
percentage: 3.7, percentage: 3.7,
color: '#6B7280', color: '#6B7280',
flag: '🇪🇸' flag: '🇪🇸'
}, },
{ {
country: 'Brazil', country: 'Brazil',
learners: 12374, learners: 12374,
percentage: 3.7, percentage: 3.7,
color: '#6B7280', color: '#6B7280',
flag: '🇧🇷' flag: '🇧🇷'
} }
@@ -1019,8 +1015,8 @@ function GlobalLearnerMap() {
</p> </p>
</div> </div>
</div> </div>
<Button <Button
variant="outline" variant="outline"
className="text-base h-11 px-6 border-brand-navy/20 text-brand-navy hover:bg-brand-navy/5" className="text-base h-11 px-6 border-brand-navy/20 text-brand-navy hover:bg-brand-navy/5"
> >
<MapPin className="h-4 w-4 mr-2" /> <MapPin className="h-4 w-4 mr-2" />
@@ -1031,7 +1027,7 @@ function GlobalLearnerMap() {
<CardContent className="p-8"> <CardContent className="p-8">
<div className="grid grid-cols-1 lg:grid-cols-5 gap-8 items-center"> <div className="grid grid-cols-1 lg:grid-cols-5 gap-8 items-center">
{/* Left Column - Country Statistics */} {/* Left Column - Country Statistics */}
<div className="lg:col-span-2 space-y-1"> <div className="lg:col-span-2 space-y-1">
<div className="mb-6"> <div className="mb-6">
@@ -1043,10 +1039,10 @@ function GlobalLearnerMap() {
Distribution of learners by country Distribution of learners by country
</p> </p>
</div> </div>
<div className="space-y-3 max-h-96 overflow-y-auto scrollbar-minimal"> <div className="space-y-3 max-h-96 overflow-y-auto scrollbar-minimal">
{learnersByCountry.map((country, index) => ( {learnersByCountry.map((country, index) => (
<div <div
key={country.country} key={country.country}
className="flex items-center justify-between py-3 px-4 rounded-lg hover:bg-gray-50/80 transition-colors duration-200 group cursor-pointer" className="flex items-center justify-between py-3 px-4 rounded-lg hover:bg-gray-50/80 transition-colors duration-200 group cursor-pointer"
style={{ style={{
@@ -1056,7 +1052,7 @@ function GlobalLearnerMap() {
<div className="flex items-center gap-3 flex-1"> <div className="flex items-center gap-3 flex-1">
<div className="flex items-center gap-3 min-w-0 flex-1"> <div className="flex items-center gap-3 min-w-0 flex-1">
<span className="text-xl flex-shrink-0">{country.flag}</span> <span className="text-xl flex-shrink-0">{country.flag}</span>
<div <div
className="w-4 h-4 rounded-full flex-shrink-0 shadow-sm border border-white/50" className="w-4 h-4 rounded-full flex-shrink-0 shadow-sm border border-white/50"
style={{ backgroundColor: country.color }} style={{ backgroundColor: country.color }}
></div> ></div>
@@ -1065,7 +1061,7 @@ function GlobalLearnerMap() {
</span> </span>
</div> </div>
</div> </div>
<div className="flex items-center gap-4 flex-shrink-0"> <div className="flex items-center gap-4 flex-shrink-0">
<div className="text-right"> <div className="text-right">
<div className="text-base font-semibold text-foreground"> <div className="text-base font-semibold text-foreground">
@@ -1076,9 +1072,9 @@ function GlobalLearnerMap() {
</div> </div>
</div> </div>
<div className="w-16 bg-gray-200 rounded-full h-2"> <div className="w-16 bg-gray-200 rounded-full h-2">
<div <div
className="h-2 rounded-full transition-all duration-500 shadow-sm" className="h-2 rounded-full transition-all duration-500 shadow-sm"
style={{ style={{
width: `${Math.min(country.percentage * 4, 100)}%`, width: `${Math.min(country.percentage * 4, 100)}%`,
backgroundColor: country.color backgroundColor: country.color
}} }}
@@ -1122,114 +1118,114 @@ function GlobalLearnerMap() {
alt="Global learner distribution map" alt="Global learner distribution map"
className="w-full h-auto opacity-90 drop-shadow-lg" className="w-full h-auto opacity-90 drop-shadow-lg"
/> />
{/* Overlay heatmap dots for major countries */} {/* Overlay heatmap dots for major countries */}
<div className="absolute inset-0"> <div className="absolute inset-0">
{/* Romania - Eastern Europe */} {/* Romania - Eastern Europe */}
<div <div
className="absolute w-3 h-3 rounded-full shadow-lg animate-pulse" className="absolute w-3 h-3 rounded-full shadow-lg animate-pulse"
style={{ style={{
backgroundColor: '#04045B', backgroundColor: '#04045B',
top: '25%', top: '25%',
left: '55%', left: '55%',
boxShadow: '0 0 20px rgba(4, 4, 91, 0.6)' boxShadow: '0 0 20px rgba(4, 4, 91, 0.6)'
}} }}
></div> ></div>
{/* Australia - Oceania */} {/* Australia - Oceania */}
<div <div
className="absolute w-4 h-4 rounded-full shadow-lg animate-pulse" className="absolute w-4 h-4 rounded-full shadow-lg animate-pulse"
style={{ style={{
backgroundColor: '#04045B', backgroundColor: '#04045B',
top: '75%', top: '75%',
right: '15%', right: '15%',
boxShadow: '0 0 25px rgba(4, 4, 91, 0.6)' boxShadow: '0 0 25px rgba(4, 4, 91, 0.6)'
}} }}
></div> ></div>
{/* Russia - Northern Asia */} {/* Russia - Northern Asia */}
<div <div
className="absolute w-3 h-3 rounded-full shadow-lg animate-pulse" className="absolute w-3 h-3 rounded-full shadow-lg animate-pulse"
style={{ style={{
backgroundColor: '#04045B', backgroundColor: '#04045B',
top: '20%', top: '20%',
left: '70%', left: '70%',
boxShadow: '0 0 20px rgba(4, 4, 91, 0.6)' boxShadow: '0 0 20px rgba(4, 4, 91, 0.6)'
}} }}
></div> ></div>
{/* Ireland - Western Europe */} {/* Ireland - Western Europe */}
<div <div
className="absolute w-3 h-3 rounded-full shadow-lg animate-pulse" className="absolute w-3 h-3 rounded-full shadow-lg animate-pulse"
style={{ style={{
backgroundColor: '#F8C301', backgroundColor: '#F8C301',
top: '28%', top: '28%',
left: '45%', left: '45%',
boxShadow: '0 0 20px rgba(248, 195, 1, 0.6)' boxShadow: '0 0 20px rgba(248, 195, 1, 0.6)'
}} }}
></div> ></div>
{/* Ukraine - Eastern Europe */} {/* Ukraine - Eastern Europe */}
<div <div
className="absolute w-3 h-3 rounded-full shadow-lg animate-pulse" className="absolute w-3 h-3 rounded-full shadow-lg animate-pulse"
style={{ style={{
backgroundColor: '#F8C301', backgroundColor: '#F8C301',
top: '30%', top: '30%',
left: '58%', left: '58%',
boxShadow: '0 0 20px rgba(248, 195, 1, 0.6)' boxShadow: '0 0 20px rgba(248, 195, 1, 0.6)'
}} }}
></div> ></div>
{/* USA - North America */} {/* USA - North America */}
<div <div
className="absolute w-3 h-3 rounded-full shadow-lg animate-pulse" className="absolute w-3 h-3 rounded-full shadow-lg animate-pulse"
style={{ style={{
backgroundColor: '#26231A', backgroundColor: '#26231A',
top: '35%', top: '35%',
left: '25%', left: '25%',
boxShadow: '0 0 20px rgba(38, 35, 26, 0.6)' boxShadow: '0 0 20px rgba(38, 35, 26, 0.6)'
}} }}
></div> ></div>
{/* Germany - Central Europe */} {/* Germany - Central Europe */}
<div <div
className="absolute w-3 h-3 rounded-full shadow-lg animate-pulse" className="absolute w-3 h-3 rounded-full shadow-lg animate-pulse"
style={{ style={{
backgroundColor: '#26231A', backgroundColor: '#26231A',
top: '32%', top: '32%',
left: '50%', left: '50%',
boxShadow: '0 0 20px rgba(38, 35, 26, 0.6)' boxShadow: '0 0 20px rgba(38, 35, 26, 0.6)'
}} }}
></div> ></div>
{/* Argentina - South America */} {/* Argentina - South America */}
<div <div
className="absolute w-2 h-2 rounded-full shadow-lg animate-pulse" className="absolute w-2 h-2 rounded-full shadow-lg animate-pulse"
style={{ style={{
backgroundColor: '#6B7280', backgroundColor: '#6B7280',
top: '80%', top: '80%',
left: '30%', left: '30%',
boxShadow: '0 0 15px rgba(107, 114, 128, 0.6)' boxShadow: '0 0 15px rgba(107, 114, 128, 0.6)'
}} }}
></div> ></div>
{/* Spain - Western Europe */} {/* Spain - Western Europe */}
<div <div
className="absolute w-2 h-2 rounded-full shadow-lg animate-pulse" className="absolute w-2 h-2 rounded-full shadow-lg animate-pulse"
style={{ style={{
backgroundColor: '#6B7280', backgroundColor: '#6B7280',
top: '38%', top: '38%',
left: '46%', left: '46%',
boxShadow: '0 0 15px rgba(107, 114, 128, 0.6)' boxShadow: '0 0 15px rgba(107, 114, 128, 0.6)'
}} }}
></div> ></div>
{/* Brazil - South America */} {/* Brazil - South America */}
<div <div
className="absolute w-2 h-2 rounded-full shadow-lg animate-pulse" className="absolute w-2 h-2 rounded-full shadow-lg animate-pulse"
style={{ style={{
backgroundColor: '#6B7280', backgroundColor: '#6B7280',
top: '70%', top: '70%',
left: '33%', left: '33%',
boxShadow: '0 0 15px rgba(107, 114, 128, 0.6)' boxShadow: '0 0 15px rgba(107, 114, 128, 0.6)'
}} }}
@@ -1320,7 +1316,7 @@ export function CorporateDashboard() {
<TeamPerformanceOverview /> <TeamPerformanceOverview />
<CorporateAnalytics /> <CorporateAnalytics />
</div> </div>
{/* Right Column - Assigned Training */} {/* Right Column - Assigned Training */}
<div className="lg:col-span-3"> <div className="lg:col-span-3">
<AssignedTraining /> <AssignedTraining />

View File

@@ -9,7 +9,7 @@ import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '..
import { Avatar, AvatarFallback, AvatarImage } from '../../components/ui/avatar'; import { Avatar, AvatarFallback, AvatarImage } from '../../components/ui/avatar';
import { Separator } from '../../components/ui/separator'; import { Separator } from '../../components/ui/separator';
import { Alert, AlertDescription } from '../../components/ui/alert'; import { Alert, AlertDescription } from '../../components/ui/alert';
import { import {
Play, Play,
Pause, Pause,
CheckCircle, CheckCircle,
@@ -385,12 +385,12 @@ function VideoPlayer({ course, isPlaying, onPlayPause }: {
return ( return (
<div className="relative bg-black rounded-lg overflow-hidden"> <div className="relative bg-black rounded-lg overflow-hidden">
<div className="aspect-video relative"> <div className="aspect-video relative">
<img <img
src={course.thumbnail} src={course.thumbnail}
alt={course.title} alt={course.title}
className="w-full h-full object-cover" className="w-full h-full object-cover"
/> />
{/* Play button overlay */} {/* Play button overlay */}
<div className="absolute inset-0 flex items-center justify-center"> <div className="absolute inset-0 flex items-center justify-center">
<Button <Button
@@ -417,18 +417,18 @@ function VideoPlayer({ course, isPlaying, onPlayPause }: {
> >
{isPlaying ? <Pause className="h-4 w-4" /> : <Play className="h-4 w-4" />} {isPlaying ? <Pause className="h-4 w-4" /> : <Play className="h-4 w-4" />}
</Button> </Button>
<div className="flex-1"> <div className="flex-1">
<Progress <Progress
value={(currentTime / duration) * 100} value={(currentTime / duration) * 100}
className="h-1 bg-white/20" className="h-1 bg-white/20"
/> />
</div> </div>
<span className="text-sm"> <span className="text-sm">
{formatTime(currentTime)} / {formatTime(duration)} {formatTime(currentTime)} / {formatTime(duration)}
</span> </span>
<Button <Button
variant="ghost" variant="ghost"
size="icon" size="icon"
@@ -437,7 +437,7 @@ function VideoPlayer({ course, isPlaying, onPlayPause }: {
> >
{isMuted ? <VolumeX className="h-4 w-4" /> : <Volume2 className="h-4 w-4" />} {isMuted ? <VolumeX className="h-4 w-4" /> : <Volume2 className="h-4 w-4" />}
</Button> </Button>
<Button <Button
variant="ghost" variant="ghost"
size="icon" size="icon"
@@ -454,11 +454,12 @@ function VideoPlayer({ course, isPlaying, onPlayPause }: {
// Course Header Component // Course Header Component
function CourseHeader({ course }: { course: Course }) { function CourseHeader({ course }: { course: Course }) {
const navigate = useNavigate()
return ( return (
<div className="space-y-4"> <div className="space-y-0">
{/* Breadcrumb Navigation */} {/* Breadcrumb Navigation */}
<nav className="flex items-center gap-2 text-base text-muted-foreground"> <nav className="flex items-center gap-2 text-base text-muted-foreground">
<button <button
onClick={() => navigate('/dashboard')} onClick={() => navigate('/dashboard')}
className="hover:text-foreground transition-colors active:bg-gray-100 focus:outline-none px-2 py-1 rounded" className="hover:text-foreground transition-colors active:bg-gray-100 focus:outline-none px-2 py-1 rounded"
style={{ outline: 'none' }} style={{ outline: 'none' }}
@@ -466,7 +467,7 @@ function CourseHeader({ course }: { course: Course }) {
Overview Overview
</button> </button>
<ChevronRight className="h-4 w-4" /> <ChevronRight className="h-4 w-4" />
<button <button
onClick={() => navigate('/library')} onClick={() => navigate('/library')}
className="hover:text-foreground transition-colors active:bg-gray-100 focus:outline-none px-2 py-1 rounded" className="hover:text-foreground transition-colors active:bg-gray-100 focus:outline-none px-2 py-1 rounded"
style={{ outline: 'none' }} style={{ outline: 'none' }}
@@ -531,12 +532,12 @@ function ActionButtons() {
<BookmarkPlus className="h-4 w-4 mr-2" /> <BookmarkPlus className="h-4 w-4 mr-2" />
Save Note Save Note
</Button> </Button>
<Button variant="outline" className="text-base min-h-[44px]"> <Button variant="outline" className="text-base min-h-[44px]">
<Download className="h-4 w-4 mr-2" /> <Download className="h-4 w-4 mr-2" />
Download Download
</Button> </Button>
<Button variant="outline" className="text-base min-h-[44px]"> <Button variant="outline" className="text-base min-h-[44px]">
<Share2 className="h-4 w-4 mr-2" /> <Share2 className="h-4 w-4 mr-2" />
Share Share
@@ -565,7 +566,7 @@ function FooterAwareSidebar({ children }: { children: React.ReactNode }) {
// Get footer position // Get footer position
const footerTop = footer.getBoundingClientRect().top + scrollTop; const footerTop = footer.getBoundingClientRect().top + scrollTop;
// Calculate when sidebar would start overlapping footer // Calculate when sidebar would start overlapping footer
// Account for sidebar height and sticky top offset (24 * 14px = 336px for top-24) // Account for sidebar height and sticky top offset (24 * 14px = 336px for top-24)
const sidebarHeight = sidebarRef.current.offsetHeight; const sidebarHeight = sidebarRef.current.offsetHeight;
@@ -607,11 +608,10 @@ function FooterAwareSidebar({ children }: { children: React.ReactNode }) {
return ( return (
<div <div
ref={sidebarRef} ref={sidebarRef}
className={`transition-all duration-200 ${ className={`transition-all duration-200 ${shouldStick
shouldStick ? 'sticky top-24 z-40'
? 'sticky top-24 z-40' : 'relative'
: 'relative' }`}
}`}
style={{ style={{
// Ensure sidebar doesn't exceed viewport height when sticky // Ensure sidebar doesn't exceed viewport height when sticky
maxHeight: shouldStick ? 'calc(100vh - 6rem)' : 'none' maxHeight: shouldStick ? 'calc(100vh - 6rem)' : 'none'
@@ -647,7 +647,7 @@ function CourseContentSidebar({ course }: { course: Course }) {
<ChevronDown className="h-5 w-5 text-muted-foreground" /> <ChevronDown className="h-5 w-5 text-muted-foreground" />
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
<CardContent className="p-0"> <CardContent className="p-0">
<div className="px-6 pb-4"> <div className="px-6 pb-4">
{/* Course Intro Progress */} {/* Course Intro Progress */}
@@ -663,19 +663,18 @@ function CourseContentSidebar({ course }: { course: Course }) {
<div className="space-y-3 max-h-[50vh] overflow-y-auto scrollbar-minimal"> <div className="space-y-3 max-h-[50vh] overflow-y-auto scrollbar-minimal">
{/* Current course sections from first module */} {/* Current course sections from first module */}
{course.modules[0]?.sections.map((section, index) => { {course.modules[0]?.sections.map((section, index) => {
const isCurrentSection = !section.completed && const isCurrentSection = !section.completed &&
course.modules[0].sections.slice(0, index).every(s => s.completed); course.modules[0].sections.slice(0, index).every(s => s.completed);
return ( return (
<div <div
key={section.id} key={section.id}
className={`flex items-center justify-between p-3 rounded-lg transition-colors cursor-pointer active:bg-gray-100 ${ className={`flex items-center justify-between p-3 rounded-lg transition-colors cursor-pointer active:bg-gray-100 ${section.completed
section.completed ? 'hover:bg-muted/50'
? 'hover:bg-muted/50' : isCurrentSection
: isCurrentSection ? 'bg-primary/5 border border-primary/20'
? 'bg-primary/5 border border-primary/20' : 'opacity-60 hover:bg-muted/30'
: 'opacity-60 hover:bg-muted/30' }`}
}`}
style={{ outline: 'none' }} style={{ outline: 'none' }}
> >
<div className="flex items-center gap-3 flex-1"> <div className="flex items-center gap-3 flex-1">
@@ -688,26 +687,23 @@ function CourseContentSidebar({ course }: { course: Course }) {
) : ( ) : (
<div className="w-5 h-5 rounded-full border-2 border-muted-foreground"></div> <div className="w-5 h-5 rounded-full border-2 border-muted-foreground"></div>
)} )}
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<p className={`font-medium text-base ${ <p className={`font-medium text-base ${section.completed ? 'text-foreground' :
section.completed ? 'text-foreground' : isCurrentSection ? 'text-primary' :
isCurrentSection ? 'text-primary' : 'text-muted-foreground'
'text-muted-foreground' }`}>
}`}>
{String(index + 1).padStart(2, '0')}: {section.title} {String(index + 1).padStart(2, '0')}: {section.title}
</p> </p>
<p className={`text-sm ${ <p className={`text-sm ${section.completed ? 'text-success' : 'text-muted-foreground'
section.completed ? 'text-success' : 'text-muted-foreground' }`}>
}`}>
{section.completed ? 'Completed' : section.duration} {section.completed ? 'Completed' : section.duration}
</p> </p>
</div> </div>
</div> </div>
<Play className={`h-5 w-5 ${ <Play className={`h-5 w-5 ${isCurrentSection ? 'text-primary' : 'text-muted-foreground'
isCurrentSection ? 'text-primary' : 'text-muted-foreground' }`} />
}`} />
</div> </div>
); );
})} })}
@@ -735,7 +731,7 @@ function CourseContentSidebar({ course }: { course: Course }) {
<ChevronDown className="h-4 w-4 text-muted-foreground" /> <ChevronDown className="h-4 w-4 text-muted-foreground" />
)} )}
</button> </button>
{expandedModules.has(module.id) && ( {expandedModules.has(module.id) && (
<div className="px-4 pb-4"> <div className="px-4 pb-4">
<div className="text-sm text-muted-foreground"> <div className="text-sm text-muted-foreground">
@@ -923,11 +919,10 @@ function ReviewsContent({ course }: { course: Course }) {
{[...Array(5)].map((_, i) => ( {[...Array(5)].map((_, i) => (
<Star <Star
key={i} key={i}
className={`h-4 w-4 ${ className={`h-4 w-4 ${i < review.rating
i < review.rating ? 'fill-yellow-400 text-yellow-400'
? 'fill-yellow-400 text-yellow-400' : 'text-muted-foreground'
: 'text-muted-foreground' }`}
}`}
/> />
))} ))}
</div> </div>
@@ -937,14 +932,14 @@ function ReviewsContent({ course }: { course: Course }) {
</div> </div>
</div> </div>
<div className="flex items-center gap-4 text-sm text-muted-foreground"> <div className="flex items-center gap-4 text-sm text-muted-foreground">
<button <button
className="flex items-center gap-1 hover:text-foreground active:bg-gray-100 focus:outline-none px-2 py-1 rounded" className="flex items-center gap-1 hover:text-foreground active:bg-gray-100 focus:outline-none px-2 py-1 rounded"
style={{ outline: 'none' }} style={{ outline: 'none' }}
> >
<ThumbsUp className="h-4 w-4" /> <ThumbsUp className="h-4 w-4" />
Helpful Helpful
</button> </button>
<button <button
className="hover:text-foreground active:bg-gray-100 focus:outline-none px-2 py-1 rounded" className="hover:text-foreground active:bg-gray-100 focus:outline-none px-2 py-1 rounded"
style={{ outline: 'none' }} style={{ outline: 'none' }}
> >
@@ -963,7 +958,7 @@ export function CourseTimeline({ userType = 'individual' }: CourseTimelineProps)
const [activeTab, setActiveTab] = useState('overview'); const [activeTab, setActiveTab] = useState('overview');
const [course, setCourse] = useState<Course | null>(null); const [course, setCourse] = useState<Course | null>(null);
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const navigate = useNavigate(); const navigate = useNavigate();
// Mock user data // Mock user data
@@ -977,14 +972,14 @@ export function CourseTimeline({ userType = 'individual' }: CourseTimelineProps)
useEffect(() => { useEffect(() => {
const courseId = getCourseId(); const courseId = getCourseId();
const selectedCourse = COURSE_DATABASE[courseId]; const selectedCourse = COURSE_DATABASE[courseId];
if (selectedCourse) { if (selectedCourse) {
setCourse(selectedCourse); setCourse(selectedCourse);
} else { } else {
// Fallback to Strategic Leadership Excellence // Fallback to Strategic Leadership Excellence
setCourse(COURSE_DATABASE['1']); setCourse(COURSE_DATABASE['1']);
} }
// Simulate loading time // Simulate loading time
setTimeout(() => { setTimeout(() => {
setIsLoading(false); setIsLoading(false);
@@ -998,7 +993,7 @@ export function CourseTimeline({ userType = 'individual' }: CourseTimelineProps)
if (isLoading || !course) { if (isLoading || !course) {
return ( return (
<LearnerLayout currentPage="/course-timeline" userType={userType} user={user}> <LearnerLayout currentPage="/course-timeline" userType={userType} user={user}>
<div className="space-y-6"> <div>
<div className="animate-pulse"> <div className="animate-pulse">
<div className="h-8 bg-muted rounded w-48 mb-4"></div> <div className="h-8 bg-muted rounded w-48 mb-4"></div>
<div className="h-12 bg-muted rounded w-3/4 mb-4"></div> <div className="h-12 bg-muted rounded w-3/4 mb-4"></div>
@@ -1012,9 +1007,9 @@ export function CourseTimeline({ userType = 'individual' }: CourseTimelineProps)
return ( return (
<LearnerLayout currentPage="/course-timeline" userType={userType} user={user}> <LearnerLayout currentPage="/course-timeline" userType={userType} user={user}>
{/* Main Container with proper spacing to account for footer */} {/* Main Container with proper spacing to account for footer */}
<div className="min-h-screen bg-gray-50"> <div className="min-h-screen bg-gray-50">
{/* Coursera-Style Header with Breadcrumb */} {/* Coursera-Style Header with Breadcrumb */}
<div className="bg-white border-b border-gray-200 sticky top-[70px] z-40"> <div className="bg-white border-b border-gray-200 sticky top-[0px] z-40">
<div className="w-full max-w-none px-4 lg:px-6"> <div className="w-full max-w-none px-4 lg:px-6">
<div className="py-4"> <div className="py-4">
{/* Breadcrumb Navigation */} {/* Breadcrumb Navigation */}
@@ -1035,7 +1030,7 @@ export function CourseTimeline({ userType = 'individual' }: CourseTimelineProps)
<ChevronRight className="h-4 w-4" /> <ChevronRight className="h-4 w-4" />
<span className="text-gray-900 font-medium">{course.title}</span> <span className="text-gray-900 font-medium">{course.title}</span>
</div> </div>
{/* Course Title and Progress */} {/* Course Title and Progress */}
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div> <div>
@@ -1063,11 +1058,11 @@ export function CourseTimeline({ userType = 'individual' }: CourseTimelineProps)
{/* Main Layout - 3 Column Coursera Style */} {/* Main Layout - 3 Column Coursera Style */}
<div className="flex min-h-screen"> <div className="flex min-h-screen">
{/* Left Sidebar - Course Navigation */} {/* Left Sidebar - Course Navigation */}
<div className="w-80 bg-white border-r border-gray-200 sticky top-[140px] h-[calc(100vh-140px)] overflow-y-auto"> <div className="w-80 bg-white border-r border-gray-200 sticky top-[104px] h-[calc(100vh-104px)] overflow-y-auto" >
<div className="p-6"> <div className="p-6">
<div className="mb-6"> <div className="mb-6">
<h3 className="text-lg font-semibold text-gray-900 mb-4">Course Material</h3> <h3 className="text-lg font-semibold text-gray-900 mb-4">Course Material</h3>
{/* Course Modules */} {/* Course Modules */}
<Accordion type="multiple" defaultValue={["module-1", "module-2"]} className="space-y-2"> <Accordion type="multiple" defaultValue={["module-1", "module-2"]} className="space-y-2">
{/* Module 1 */} {/* Module 1 */}
@@ -1095,7 +1090,7 @@ export function CourseTimeline({ userType = 'individual' }: CourseTimelineProps)
<CheckCircle className="h-3 w-3 text-green-600" /> <CheckCircle className="h-3 w-3 text-green-600" />
</div> </div>
</div> </div>
<div className="flex items-center gap-3 p-2 bg-blue-50 border border-blue-200 rounded-lg"> <div className="flex items-center gap-3 p-2 bg-blue-50 border border-blue-200 rounded-lg">
<Video className="h-4 w-4 text-blue-600" /> <Video className="h-4 w-4 text-blue-600" />
<div className="flex-1"> <div className="flex-1">
@@ -1106,7 +1101,7 @@ export function CourseTimeline({ userType = 'individual' }: CourseTimelineProps)
<Play className="h-2 w-2 text-white fill-white" /> <Play className="h-2 w-2 text-white fill-white" />
</div> </div>
</div> </div>
<div className="flex items-center gap-3 p-2 hover:bg-gray-50 rounded-lg cursor-pointer opacity-60"> <div className="flex items-center gap-3 p-2 hover:bg-gray-50 rounded-lg cursor-pointer opacity-60">
<FileText className="h-4 w-4 text-gray-400" /> <FileText className="h-4 w-4 text-gray-400" />
<div className="flex-1"> <div className="flex-1">
@@ -1142,7 +1137,7 @@ export function CourseTimeline({ userType = 'individual' }: CourseTimelineProps)
</div> </div>
<Lock className="h-4 w-4 text-gray-400" /> <Lock className="h-4 w-4 text-gray-400" />
</div> </div>
<div className="flex items-center gap-3 p-2 hover:bg-gray-50 rounded-lg cursor-pointer opacity-60"> <div className="flex items-center gap-3 p-2 hover:bg-gray-50 rounded-lg cursor-pointer opacity-60">
<FileText className="h-4 w-4 text-gray-400" /> <FileText className="h-4 w-4 text-gray-400" />
<div className="flex-1"> <div className="flex-1">
@@ -1171,7 +1166,7 @@ export function CourseTimeline({ userType = 'individual' }: CourseTimelineProps)
</AccordionItem> </AccordionItem>
</Accordion> </Accordion>
</div> </div>
{/* Course Info Section */} {/* Course Info Section */}
<div className="border-t border-gray-200 pt-6 space-y-4"> <div className="border-t border-gray-200 pt-6 space-y-4">
<div className="flex items-center gap-3 text-sm text-gray-600 hover:text-[#04045B] cursor-pointer"> <div className="flex items-center gap-3 text-sm text-gray-600 hover:text-[#04045B] cursor-pointer">
@@ -1201,12 +1196,12 @@ export function CourseTimeline({ userType = 'individual' }: CourseTimelineProps)
<span>Communication Styles</span> <span>Communication Styles</span>
</div> </div>
<h2 className="text-xl font-semibold text-gray-900 mb-4">Communication Styles</h2> <h2 className="text-xl font-semibold text-gray-900 mb-4">Communication Styles</h2>
{/* Video Player */} {/* Video Player */}
<VideoPlayer <VideoPlayer
course={course} course={course}
isPlaying={isPlaying} isPlaying={isPlaying}
onPlayPause={handlePlayPause} onPlayPause={handlePlayPause}
/> />
</div> </div>
@@ -1221,11 +1216,10 @@ export function CourseTimeline({ userType = 'individual' }: CourseTimelineProps)
<button <button
key={tab.value} key={tab.value}
onClick={() => setActiveTab(tab.value)} onClick={() => setActiveTab(tab.value)}
className={`py-3 px-1 border-b-2 font-medium text-sm transition-colors ${ className={`py-3 px-1 border-b-2 font-medium text-sm transition-colors ${activeTab === tab.value
activeTab === tab.value ? 'border-[#04045B] text-[#04045B]'
? 'border-[#04045B] text-[#04045B]' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300' }`}
}`}
> >
{tab.label} {tab.label}
</button> </button>
@@ -1285,16 +1279,16 @@ export function CourseTimeline({ userType = 'individual' }: CourseTimelineProps)
</div> </div>
{/* Right Sidebar - Learning Plan */} {/* Right Sidebar - Learning Plan */}
<div className="w-80 bg-white border-l border-gray-200 sticky top-[140px] h-[calc(100vh-140px)] overflow-y-auto"> <div className="w-80 bg-white border-l border-gray-200 sticky top-[104px] h-[calc(100vh-104px)] overflow-y-auto">
<div className="p-6"> <div className="p-6">
<div className="mb-6"> <div className="mb-6">
<h3 className="text-lg font-semibold text-gray-900 mb-4">Learning plan</h3> <h3 className="text-lg font-semibold text-gray-900 mb-4">Learning plan</h3>
<div className="space-y-4"> <div className="space-y-4">
<div className="text-sm text-gray-600"> <div className="text-sm text-gray-600">
I'm committed to learning 1 day a week on Coursera. I'm committed to learning 1 day a week on Coursera.
</div> </div>
{/* Current Week */} {/* Current Week */}
<div className="border border-gray-200 rounded-lg p-4"> <div className="border border-gray-200 rounded-lg p-4">
<div className="flex items-center justify-between mb-2"> <div className="flex items-center justify-between mb-2">
@@ -1320,7 +1314,7 @@ export function CourseTimeline({ userType = 'individual' }: CourseTimelineProps)
{/* Timeline */} {/* Timeline */}
<div className="space-y-3"> <div className="space-y-3">
<div className="text-sm font-medium text-gray-900">Course timeline</div> <div className="text-sm font-medium text-gray-900">Course timeline</div>
<div className="space-y-3"> <div className="space-y-3">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center text-xs font-semibold text-green-800"> <div className="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center text-xs font-semibold text-green-800">
@@ -1331,7 +1325,7 @@ export function CourseTimeline({ userType = 'individual' }: CourseTimelineProps)
<div className="text-xs text-gray-500">Your goal deadline</div> <div className="text-xs text-gray-500">Your goal deadline</div>
</div> </div>
</div> </div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="w-8 h-8 rounded-full bg-blue-100 flex items-center justify-center text-xs font-semibold text-blue-800"> <div className="w-8 h-8 rounded-full bg-blue-100 flex items-center justify-center text-xs font-semibold text-blue-800">
2 2
@@ -1341,7 +1335,7 @@ export function CourseTimeline({ userType = 'individual' }: CourseTimelineProps)
<div className="text-xs text-gray-500">Due in 3 days</div> <div className="text-xs text-gray-500">Due in 3 days</div>
</div> </div>
</div> </div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="w-8 h-8 rounded-full bg-gray-100 flex items-center justify-center text-xs font-semibold text-gray-400"> <div className="w-8 h-8 rounded-full bg-gray-100 flex items-center justify-center text-xs font-semibold text-gray-400">
📅 📅

View File

@@ -53,8 +53,8 @@ function LibrarySkeleton() {
export function Library({ userType = 'individual' }: LibraryProps) { export function Library({ userType = 'individual' }: LibraryProps) {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const [courses] = useState<Course[]>(getCoursesData(userType)); const [courses] = useState<Course[]>(getCoursesData(userType));
const navigate = useNavigate(); const navigate = useNavigate();
// Filter states // Filter states
const [searchQuery, setSearchQuery] = useState(''); const [searchQuery, setSearchQuery] = useState('');
const [selectedCategory, setSelectedCategory] = useState('All Categories'); const [selectedCategory, setSelectedCategory] = useState('All Categories');
@@ -89,9 +89,9 @@ export function Library({ userType = 'individual' }: LibraryProps) {
const filteredCourses = courses.filter(course => { const filteredCourses = courses.filter(course => {
// Search filter // Search filter
if (searchQuery && !course.title.toLowerCase().includes(searchQuery.toLowerCase()) && if (searchQuery && !course.title.toLowerCase().includes(searchQuery.toLowerCase()) &&
!course.description.toLowerCase().includes(searchQuery.toLowerCase()) && !course.description.toLowerCase().includes(searchQuery.toLowerCase()) &&
!course.instructor.name.toLowerCase().includes(searchQuery.toLowerCase()) && !course.instructor.name.toLowerCase().includes(searchQuery.toLowerCase()) &&
!course.tags.some(tag => tag.toLowerCase().includes(searchQuery.toLowerCase()))) { !course.tags.some(tag => tag.toLowerCase().includes(searchQuery.toLowerCase()))) {
return false; return false;
} }
@@ -192,7 +192,7 @@ export function Library({ userType = 'individual' }: LibraryProps) {
Leadership Development Library Leadership Development Library
</h1> </h1>
<p className="text-[16px] font-medium leading-[20px] text-[#6B7280]"> <p className="text-[16px] font-medium leading-[20px] text-[#6B7280]">
{userType === 'corporate' {userType === 'corporate'
? 'Access your assigned courses and explore additional leadership development opportunities' ? 'Access your assigned courses and explore additional leadership development opportunities'
: 'Discover and enroll in courses designed to advance your leadership journey' : 'Discover and enroll in courses designed to advance your leadership journey'
} }
@@ -251,11 +251,10 @@ export function Library({ userType = 'individual' }: LibraryProps) {
<button <button
key={tab.value} key={tab.value}
onClick={() => setActiveTab(tab.value)} onClick={() => setActiveTab(tab.value)}
className={`flex-1 px-4 py-2.5 text-[16px] font-semibold rounded-full transition-all duration-300 ease-in-out focus:outline-none focus:ring-0 active:outline-none ${ className={`flex-1 px-4 py-2.5 text-[16px] font-semibold rounded-full transition-all duration-300 ease-in-out focus:outline-none focus:ring-0 active:outline-none ${activeTab === tab.value
activeTab === tab.value
? 'bg-white text-[#111827] shadow-lg backdrop-blur-sm border border-white/50' ? 'bg-white text-[#111827] shadow-lg backdrop-blur-sm border border-white/50'
: 'text-[#6B7280] hover:text-[#111827] hover:bg-white/60 hover:shadow-md' : 'text-[#6B7280] hover:text-[#111827] hover:bg-white/60 hover:shadow-md'
}`} }`}
> >
{tab.label} {tab.label}
</button> </button>
@@ -278,7 +277,7 @@ export function Library({ userType = 'individual' }: LibraryProps) {
: 'No courses are available in this category.'} : 'No courses are available in this category.'}
</p> </p>
{(searchQuery || selectedCategory !== 'All Categories' || selectedLevel !== 'All Levels') && ( {(searchQuery || selectedCategory !== 'All Categories' || selectedLevel !== 'All Levels') && (
<Button <Button
variant="outline" variant="outline"
onClick={() => { onClick={() => {
setSearchQuery(''); setSearchQuery('');
@@ -300,11 +299,11 @@ export function Library({ userType = 'individual' }: LibraryProps) {
<CardHeader className="pb-6 bg-gradient-to-r from-white to-gray-50/50 border-b border-[#E5E7EB]/50"> <CardHeader className="pb-6 bg-gradient-to-r from-white to-gray-50/50 border-b border-[#E5E7EB]/50">
<CardTitle className="text-[20px] font-bold flex items-center justify-between"> <CardTitle className="text-[20px] font-bold flex items-center justify-between">
<span className="bg-gradient-to-r from-gray-800 to-gray-600 bg-clip-text text-transparent"> <span className="bg-gradient-to-r from-gray-800 to-gray-600 bg-clip-text text-transparent">
{activeTab === 'all' ? 'All Leadership Courses' : {activeTab === 'all' ? 'All Leadership Courses' :
activeTab === 'in-progress' ? 'In Progress' : activeTab === 'in-progress' ? 'In Progress' :
activeTab === 'completed' ? 'Completed Courses' : activeTab === 'completed' ? 'Completed Courses' :
activeTab === 'bookmarked' ? 'Bookmarked Courses' : activeTab === 'bookmarked' ? 'Bookmarked Courses' :
'Assigned Courses'} 'Assigned Courses'}
<span className="text-[#6B7280] ml-2 text-[16px] font-medium">({filteredCourses.length})</span> <span className="text-[#6B7280] ml-2 text-[16px] font-medium">({filteredCourses.length})</span>
</span> </span>
</CardTitle> </CardTitle>

View File

@@ -1,8 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
// import { navigate } from '../../components/Router'; // import { navigate } from '../../components/Router';
const navigate = useNavigate();
export function Consulting() { export function Consulting() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,9 +1,10 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
// import { navigate } from '../../components/Router'; // import { navigate } from '../../components/Router';
const navigate = useNavigate();
export function CultureCompetence() { export function CultureCompetence() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,9 +1,10 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
// import { navigate } from '../../components/Router'; // import { navigate } from '../../components/Router';
const navigate = useNavigate();
export function ExecutiveCoaching() { export function ExecutiveCoaching() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,8 +1,9 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
// import { navigate } from '../../components/Router'; // import { navigate } from '../../components/Router';
const navigate = useNavigate();
export function LeadershipDevelopment() { export function LeadershipDevelopment() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,9 +1,10 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
// import { navigate } from '../../components/Router'; // import { navigate } from '../../components/Router';
const navigate = useNavigate();
export function LearningFacility() { export function LearningFacility() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

View File

@@ -1,9 +1,10 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
// import { navigate } from '../../components/Router'; // import { navigate } from '../../components/Router';
const navigate = useNavigate();
export function ManagementDevelopment() { export function ManagementDevelopment() {
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
// This is a deprecated page, redirect to home // This is a deprecated page, redirect to home
navigate('/'); navigate('/');

21
src/types/images.d.ts vendored Normal file
View File

@@ -0,0 +1,21 @@
declare module '*.png' {
const src: string;
export default src;
}
declare module '*.jpg' {
const src: string;
export default src;
}
declare module '*.jpeg' {
const src: string;
export default src;
}
declare module '*.svg' {
const src: string;
export default src;
}