diff --git a/src/components/AboutUs.tsx b/src/components/AboutUs.tsx index ec0c2cb..a335788 100644 --- a/src/components/AboutUs.tsx +++ b/src/components/AboutUs.tsx @@ -1,41 +1,34 @@ -import { useState, useEffect } from 'react'; -import { motion } from 'motion/react'; import { - Target, - Users, - Globe, - Lightbulb, - ArrowRight, - CheckCircle, - Star, - Award, - Brain, - TrendingUp, - Shield, - Heart, - Zap, - Eye, BookOpen, + Brain, + CheckCircle, + Heart, Puzzle, - Building, - ArrowLeft + Shield, + Target, + TrendingUp, + Users, + Zap } from 'lucide-react'; -import { BrandedTag } from './about/BrandedTag'; -import { PrimaryCTAButton } from './PrimaryCTAButton'; -import { CTABannerSection } from './CTABannerSection'; -import { TestimonialsSection } from './TestimonialsSection'; -import { TeamMemberModal } from './TeamMemberModal'; -import { navigateTo } from './Router'; -import { Button } from './ui/button'; +import { motion } from 'motion/react'; +import { useEffect, useState } from 'react'; +import Aparna from '../assets/Aparna-Nair.png'; +import Balaji from '../assets/Balaji-Chandrakumar.jpeg'; +import Diju from '../assets/Diju.jpeg'; import Ramkumar from '../assets/K-Ramkumar.png'; import Muralidharan from '../assets/R-Muralidharan.png'; -import Aparna from '../assets/Aparna-Nair.png'; -import Swaminathan from '../assets/v-Swaminathan.jpg'; -import Balaji from '../assets/Balaji-Chandrakumar.jpeg'; import Ramesh from '../assets/Ramesh-Padmanabhan.jpeg'; -import Diju from '../assets/Diju.jpeg'; +import Swaminathan from '../assets/v-Swaminathan.jpg'; import svgPaths from '../imports/svg-kw7r0ellyk'; import { useGetAboutUsQuery } from '../redux/services/aboutUsApi'; +import { BrandedTag } from './about/BrandedTag'; +import { CTABannerSection } from './CTABannerSection'; +import { PrimaryCTAButton } from './PrimaryCTAButton'; +import { navigateTo } from './Router'; +import { TeamMemberModal } from './TeamMemberModal'; +import { TestimonialsSection } from './TestimonialsSection'; +import { Button } from './ui/button'; +import { FullScreenLoader } from './FullScreenLoader'; // Leadership Orientations Data const leadershipOrientations = [ @@ -272,6 +265,7 @@ After a career break, she joined KLC as Practice Head. She now co-creates leader } ]; + // Loading Skeleton Component const AboutUsSkeleton = () => (
@@ -303,6 +297,27 @@ export function AboutUs() { // Fetch About Us data from API const { data: aboutUsData, isLoading, isError, error } = useGetAboutUsQuery(); + const transformTestimonials = (apiTestimonials: any[]) => { + if (!apiTestimonials || apiTestimonials.length === 0) return []; + + return apiTestimonials.map((testimonial, index) => ({ + id: testimonial.id || index, + name: testimonial.name || "Anonymous", + role: testimonial.designation || "Client", + company: undefined, // Company not provided in API response + avatar: testimonial.profile_photo_url || undefined, // If you have profile photo in API + image: testimonial.profile_photo_url || undefined, + quote: testimonial.content || "", + rating: 5, // Default rating since API doesn't provide rating + isVideo: !!testimonial.video_url, + videoThumbnail: testimonial.video_thumbnail_url || testimonial.profile_photo_url, // If you have thumbnail + videoUrl: testimonial.video_url || undefined + })); + }; + + // Transform the testimonials + const testimonialsData = transformTestimonials(aboutUsData?.testimonials || []); + const handleMemberClick = (member: typeof staticTeamMembers[0]) => { setSelectedMember(member); setIsModalOpen(true); @@ -362,8 +377,13 @@ export function AboutUs() { }, []); // Show loading skeleton while fetching data + if (isLoading) { - return ; + return ( +
+ +
+ ); } // Show error state if API call fails @@ -755,7 +775,7 @@ export function AboutUs() {

{aboutUsData?.our_team_title || "Our Team"}

- We have a team of 7 consultants and 4 young consultants. All our senior Consultants are ex-business professionals with experience ranging from 15-30 years in varied business functions and carry a deep understanding of the area they are engaging in. Two of them bring in Board room experience. – Meet them + {aboutUsData?.our_team_description || "We have a team of 7 consultants and 4 young consultants. All our senior Consultants are ex-business professionals with experience ranging from 15-30 years in varied business functions and carry a deep understanding of the area they are engaging in. Two of them bring in Board room experience. – Meet them"}

@@ -807,500 +827,215 @@ export function AboutUs() { ))}
- - {/* Alternative: Use API team data if needed */} - {/* {aboutUsData?.our_team && aboutUsData.our_team.length > 0 && ( -
- {aboutUsData.our_team.map((member, index) => ( - -
-
- {member.alt_text} -
-
-
-
- View Profile -
-
-
-
-
-

- {member.name_role.split(' - ')[0]} -

-

- {member.name_role.split(' - ')[1] || ''} -

-

{member.bio}

-
-
- ))} -
- )} */} - {/* Section 5: Our Methodology (Static - unchanged) */} -
-
-
- - -

Our Methodology

-
- - {/* Vertical Timeline Container */} -
- {/* Vertical Line Background - Gray - Ends exactly at Phase 3 dot */} -
- - {/* Vertical Line Fill - Blue - Animated on Scroll */} -
- - {/* Phase 1 - Understanding & Assessment */} -
-
- {/* Phase dot positioned absolutely */} -
- - {/* Column 1: Phase Label */} -
-
-
- Phase 1 -
-
- - {/* Column 2: Main Heading */} -
- -

Understanding & Assessment

-
-
- - {/* Column 3: Content - Description and Bullet Points */} -
- -

- We believe that leadership is more than skill and style. Leadership is predicated by a person's orientations (typical behaviors) which shapes the leadership abilities and its fit to a context. The broader the fit of the orientation the more versatile a person is in his exercise of leadership in a variety of contexts. -

- -
-

Key Focus Areas:

- -
-
-
- - Leadership orientations (typical behaviors) assessment. - -
- -
-
- - Action-consequence model application. - -
- -
-
- - Context alignment and strategy integration. - -
-
-
-
-
-
-
- - {/* Phase 2 - Development & Practice */} -
-
- {/* Phase dot positioned absolutely */} -
- - {/* Column 1: Phase Label */} -
-
-
- Phase 2 -
-
- - {/* Column 2: Main Heading */} -
- -

Development & Practice

-
-
- - {/* Column 3: Content - Description and Bullet Points */} -
- -

- Thus, in our engagements with our clients we work with the individual using the action-consequence model to link up one's leadership orientations (typical behaviors) to outcomes. -

- -

- Leadership is a social skill. Socially aware people shape the thought, emotions and actions of others better. The key to social-awareness is self-awareness. We help our learners become aware, gain insights and discover their fullest leadership potential. This in turn builds organizational leadership capacity & capabilities. -

- -
-

Development Process:

- -
-
-
- - Self-awareness and insight facilitation. - -
- -
-
- - Leadership potential discovery sessions. - -
- -
-
- - Organizational capacity building. - -
-
-
-
-
-
-
- - {/* Phase 3 - Implementation & Mastery */} -
-
- {/* Phase dot positioned absolutely */} -
- - {/* Column 1: Phase Label */} -
-
-
- Phase 3 -
-
- - {/* Column 2: Main Heading */} -
- -

Implementation & Mastery

-
-
- - {/* Column 3: Content - Description and Bullet Points */} -
- -

- Our approach to learning works on the 'Orientation Toning process', which is using 'Restraint and Release' of thought, emotions and actions. This release is moderated according to the demands of a context, without being tied down by one's default settings. -

- -
-

Mastery Framework:

- -
-
-
- - Orientation Toning process implementation. - -
- -
-
- - Context-responsive leadership adaptation. - -
- -
-
- - Sustainable behavior change integration. - -
-
-
-
-
-
-
- - {/* Our Philosophy - Full Width Figma Design */} -
- {/* Phase dot positioned absolutely */} -
- -
- -
-
- {/* Left Section: Heading */} -
-

Our Philosophy

-
- - {/* Right Section: Content */} -
- {/* Philosophy Description */} -

- Our philosophy is that leadership begins with orientations — the inner drivers and behaviors that shape who we are. These orientations combine to create leadership abilities, which in turn lead to meaningful outcomes. At Kautilya Leadership Centre, we see leadership as a journey of connecting orientations to abilities and outcomes through structured development. -

- - {/* Three Philosophy Items */} -
- {/* Leadership Orientations */} -
-
- - - - - - -
-
-

- Leadership Orientations -

-

- Who am I? (inner drivers & behaviors) -

-
-
- - {/* Leadership Abilities */} -
-
- - - - - - -
-
-

- Leadership Abilities -

-

- What I can do (competencies & skills) -

-
-
- - {/* Leadership Outcomes */} -
-
- - - - - - -
-
-

- Leadership Outcomes -

-

- What I deliver (results for self & organization) -

-
-
-
-
-
-
-
-
-
- + {/* Section 5: Our Methodology - Dynamic from API */} + {aboutUsData?.methodology && ( +
+
+
- navigateTo('/contact')} - ariaLabel="Contact us to design your leadership journey" - className="cta-text-black" - /> + + {aboutUsData.methodology.subtitle && ( +

{aboutUsData.methodology.subtitle}

+ )}
+ + {/* Vertical Timeline Container */} +
+ {/* Vertical Line Background - Gray */} +
+ + {/* Vertical Line Fill - Blue - Animated on Scroll */} +
+ + {/* Map through phases from API - Create a copy before sorting */} + {[...(aboutUsData.methodology.phases || [])] + .sort((a, b) => (a.display_order || 0) - (b.display_order || 0)) + .map((phase, phaseIndex) => ( +
+
+ {/* Phase dot positioned absolutely */} +
+ + {/* Column 1: Phase Label */} +
+
+
+ {phase.phase_label || `Phase ${phase.phase_number}`} +
+
+ + {/* Column 2: Main Heading */} +
+ +

{phase.title}

+
+
+ + {/* Column 3: Content - Description and Bullet Points */} +
+ +

+ {phase.description} +

+ + {phase.bullet_title && phase.bullets && phase.bullets.length > 0 && ( +
+

{phase.bullet_title}

+
+ {phase.bullets.map((bullet, bulletIndex) => ( +
+
+ + {bullet} + +
+ ))} +
+
+ )} +
+
+
+
+ ))} + + {/* Our Philosophy - Dynamic from API */} + {aboutUsData?.philosophy && ( +
+ {/* Phase dot positioned absolutely */} +
+ +
+ +
+
+ {/* Left Section: Heading */} +
+

{aboutUsData.philosophy.title || "Our Philosophy"}

+
+ + {/* Right Section: Content */} +
+ {/* Philosophy Description */} +

+ {aboutUsData.philosophy.description} +

+ + {/* Philosophy Points */} + {aboutUsData.philosophy.points && aboutUsData.philosophy.points.length > 0 && ( +
+ {aboutUsData.philosophy.points.map((point, pointIndex) => ( +
+
+ + + + + + +
+
+

+ {point} +

+
+
+ ))} +
+ )} +
+
+
+
+
+
+ )} + + + navigateTo('/contact')} + ariaLabel="Contact us to design your leadership journey" + className="cta-text-black" + /> + +
-
-
+ + )} {/* Testimonials Section */} void; - cartItems: CartItem[]; // Legacy prop - no longer used but kept for backward compatibility - onRemoveItem: (itemId: string) => void; // Legacy prop - no longer used but kept for backward compatibility + // cartItems: CartItem[]; // Legacy prop - no longer used but kept for backward compatibility + // onRemoveItem: (itemId: string) => void; // Legacy prop - no longer used but kept for backward compatibility recentlyAddedItem?: CartItem | null; } export function CartPopup({ isOpen, onClose, - cartItems: legacyCartItems, // Renamed to avoid confusion - onRemoveItem: legacyOnRemoveItem, // Renamed to avoid confusion + // cartItems: legacyCartItems, // Renamed to avoid confusion + // onRemoveItem: legacyOnRemoveItem, // Renamed to avoid confusion recentlyAddedItem }: CartPopupProps) { const [showSuccess, setShowSuccess] = useState(false); diff --git a/src/components/CourseCard.tsx b/src/components/CourseCard.tsx index 280ebea..a6c06d9 100644 --- a/src/components/CourseCard.tsx +++ b/src/components/CourseCard.tsx @@ -1,9 +1,9 @@ import React from 'react'; import { Button } from './ui/button'; import { Badge } from './ui/badge'; -import { - Users, - Clock, +import { + Users, + Clock, Star, ArrowRight, ShoppingCart @@ -47,7 +47,7 @@ export function CourseCard({ course, onClick, className, onAddToCart }: CourseCa const handleAddToCart = (e: React.MouseEvent) => { e.stopPropagation(); // Prevent card click when clicking Add to Cart - + if (onAddToCart) { const cartItem: CartItem = { id: course.id, @@ -75,7 +75,7 @@ export function CourseCard({ course, onClick, className, onAddToCart }: CourseCa className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300" />
-
-
- - {course.level} - -
- + {/* Card Content - Reduced horizontal padding */}
{/* Course Title */} -

{course.title}

- + {/* Course Description - Limited to 2 lines with ellipsis */} -

{course.description}

- + {/* Course Meta Information - Reduced bottom margin */}
-
-
- +
-
- {course.originalPrice && ( - )}
- {course.originalPrice && ( + {/* {course.originalPrice && (
- )} + )} */}
- + {/* Action Buttons - Horizontal Layout with reduced gap */}
- {/* Add to Cart Button - Outline Blue */} + {/* Add to Cart */} - - {/* Learn More Button - Solid Blue */} + + {/* Learn More */}
diff --git a/src/components/LearningOnline.tsx b/src/components/LearningOnline.tsx index ca3d425..46f94d7 100644 --- a/src/components/LearningOnline.tsx +++ b/src/components/LearningOnline.tsx @@ -1,206 +1,48 @@ -import React, { useState, useRef, useEffect } from 'react'; -import { Button } from './ui/button'; -import { Badge } from './ui/badge'; -import { Tabs, TabsContent, TabsList, TabsTrigger } from './ui/tabs'; -import { Card, CardContent, CardHeader, CardTitle } from './ui/card'; -import { Input } from './ui/input'; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select'; import { - Play, - Users, - Clock, - ChevronRight, ChevronLeft, - GraduationCap, - MessageCircle, - Zap, - Video, - Smartphone, - Award, - Building2, - BookOpen, - Star, - Globe, - Target, - TrendingUp, - Lightbulb, - CheckCircle, - ArrowRight, - Calendar, - Search, + ChevronRight, + Clock, + DollarSign, Filter, Grid, List, - X, - DollarSign + Search, + Star, + Users, + X } from 'lucide-react'; import { motion } from 'motion/react'; -import { navigateTo } from './Router'; -import { ImageWithFallback } from './figma/ImageWithFallback'; -import { BrandedTag } from './about/BrandedTag'; -import { PrimaryCTAButton } from './PrimaryCTAButton'; -import { CourseCard } from './CourseCard'; -import { CartPopup, CartItem } from './CartPopup'; +import { useState, useEffect, useMemo, useCallback } from 'react'; import { useCart } from './CartContext'; +import { CartItem, CartPopup } from './CartPopup'; +import { CourseCard } from './CourseCard'; +import { ImageWithFallback } from './figma/ImageWithFallback'; +import { navigateTo } from './Router'; +import { Badge } from './ui/badge'; +import { Button } from './ui/button'; +import { Card } from './ui/card'; +import { Input } from './ui/input'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select'; +import { useGetCoursesQuery, Course, GetCoursesParams, useGetCourseCategoriesQuery, CourseCategory } from '../redux/services/courseApi'; +import { useDebounce } from '../redux/hooks/useDebounce'; -// Course Categories -const courseCategories = [ - 'Leadership Fundamentals', - 'Decision Making & Strategy', - 'Perspective & Risk', - 'Communication & Influence', - 'Change & Innovation' -]; +// Helper function to parse rupee price from string (keep as is) +const parsePriceToNumber = (priceStr: string | number): number => { + if (typeof priceStr === 'number') return priceStr; + const numericStr = priceStr.toString().replace(/[^0-9.-]/g, ''); + return parseFloat(numericStr) || 0; +}; -// Featured Courses Data - Updated with Rupee pricing -const featuredCourses = [ - { - id: '1', - title: 'Strategic Leadership Foundations', - thumbnail: 'https://images.unsplash.com/photo-1552664730-d307ca884978?w=400&h=250&fit=crop', - duration: '12 hours', - level: 'Intermediate', - format: 'Self-paced', - rating: 4.8, - participants: '2,400+', - category: 'Leadership Fundamentals', - description: 'Master the core principles of strategic leadership and organizational vision.', - price: '₹24,817', - originalPrice: '₹33,117' - }, - { - id: '2', - title: 'Data-Driven Decision Making', - thumbnail: 'https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=400&h=250&fit=crop', - duration: '8 hours', - level: 'Advanced', - format: 'Cohort-based', - rating: 4.9, - participants: '1,800+', - category: 'Decision Making & Strategy', - description: 'Learn to make strategic decisions using data analytics and business intelligence.', - price: '₹37,267', - originalPrice: '₹45,567' - }, - { - id: '3', - title: 'Risk Assessment & Management', - thumbnail: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=400&h=250&fit=crop', - duration: '10 hours', - level: 'Intermediate', - format: 'Self-paced', - rating: 4.7, - participants: '3,200+', - category: 'Perspective & Risk', - description: 'Develop expertise in identifying, analyzing, and mitigating organizational risks.', - price: '₹28,967', - originalPrice: '₹37,267' - }, - { - id: '4', - title: 'Influential Communication', - thumbnail: 'https://images.unsplash.com/photo-1556761175-b413da4baf72?w=400&h=250&fit=crop', - duration: '6 hours', - level: 'Beginner', - format: 'Self-paced', - rating: 4.8, - participants: '5,100+', - category: 'Communication & Influence', - description: 'Master the art of persuasive communication and stakeholder engagement.', - price: '₹16,517', - originalPrice: '₹20,667' - }, - { - id: '5', - title: 'Leading Innovation & Change', - thumbnail: 'https://images.unsplash.com/photo-1542744173-8e7e53415bb0?w=400&h=250&fit=crop', - duration: '14 hours', - level: 'Advanced', - format: 'Cohort-based', - rating: 4.9, - participants: '1,950+', - category: 'Change & Innovation', - description: 'Drive organizational transformation and foster a culture of innovation.', - price: '₹45,567', - originalPrice: '₹53,867' - }, - { - id: '6', - title: 'Digital Leadership Essentials', - thumbnail: 'https://images.unsplash.com/photo-1551434678-e076c223a692?w=400&h=250&fit=crop', - duration: '9 hours', - level: 'Intermediate', - format: 'Self-paced', - rating: 4.6, - participants: '2,800+', - category: 'Leadership Fundamentals', - description: 'Navigate the digital transformation as a modern leader.', - price: '₹23,157', - originalPrice: '₹28,967' - }, - { - id: '7', - title: 'Crisis Leadership Strategies', - thumbnail: 'https://images.unsplash.com/photo-1584697964358-3e14ca57658b?w=400&h=250&fit=crop', - duration: '7 hours', - level: 'Advanced', - format: 'Cohort-based', - rating: 4.7, - participants: '1,200+', - category: 'Leadership Fundamentals', - description: 'Navigate uncertainty and lead your team through challenging situations with confidence.', - price: '₹33,117', - originalPrice: '₹41,417' - }, - { - id: '8', - title: 'Emotional Intelligence for Leaders', - thumbnail: 'https://images.unsplash.com/photo-1559027615-cd4628902d4a?w=400&h=250&fit=crop', - duration: '5 hours', - level: 'Beginner', - format: 'Self-paced', - rating: 4.9, - participants: '4,300+', - category: 'Communication & Influence', - description: 'Develop emotional intelligence to enhance your leadership effectiveness.', - price: '₹14,857', - originalPrice: '₹19,007' - }, - { - id: 'ldp-foundations', - title: 'Strategic Leadership Development Program: Foundations', - thumbnail: 'https://images.unsplash.com/photo-1588912914078-2fe5224fd8b8?w=400&h=250&fit=crop', - duration: '40 hours', - level: 'Intermediate', - format: 'Self-paced', - rating: 4.8, - participants: '1,247+', - category: 'Leadership Development', - description: 'Master the fundamentals of effective leadership through evidence-based practices and real-world case studies.', - price: '$599', - originalPrice: '$799' - }, - { - id: '9', - title: 'Strategic Risk Analysis', - thumbnail: 'https://images.unsplash.com/photo-1560472355-536de3962603?w=400&h=250&fit=crop', - duration: '11 hours', - level: 'Advanced', - format: 'Self-paced', - rating: 4.8, - participants: '1,500+', - category: 'Perspective & Risk', - description: 'Master advanced risk analysis techniques for strategic decision-making.', - price: '₹39,757', - originalPrice: '₹49,717' - } -]; +// Format price with Rupee symbol (keep as is) +const formatPrice = (price: number): string => { + return `₹${price.toLocaleString('en-IN')}`; +}; export function LearningOnline() { + // UI state const [searchTerm, setSearchTerm] = useState(''); - const [selectedCategory, setSelectedCategory] = useState('All Categories'); - const [selectedLevel, setSelectedLevel] = useState('All Levels'); - const [selectedFormat, setSelectedFormat] = useState('All Formats'); + const [selectedCategoryId, setSelectedCategoryId] = useState(''); + const [selectedCategoryName, setSelectedCategoryName] = useState('All Categories'); const [selectedPriceRange, setSelectedPriceRange] = useState('All Prices'); const [selectedDuration, setSelectedDuration] = useState('All Durations'); const [selectedRating, setSelectedRating] = useState('All Ratings'); @@ -209,98 +51,248 @@ export function LearningOnline() { const [currentPage, setCurrentPage] = useState(1); const coursesPerPage = 9; - // Cart functionality - using global cart context - const { addToCart } = useCart(); - const [isCartPopupOpen, setIsCartPopupOpen] = useState(false); - const [recentlyAddedItem, setRecentlyAddedItem] = useState(null); + // Debounced search term to avoid too many API calls + const debouncedSearchTerm = useDebounce(searchTerm, 500); - // Get unique values for filters - Updated for Rupees - const categories = ['All Categories', ...courseCategories]; - const levels = ['All Levels', ...Array.from(new Set(featuredCourses.map(course => course.level)))]; - const formats = ['All Formats', ...Array.from(new Set(featuredCourses.map(course => course.format)))]; - const priceRanges = ['All Prices', 'Under ₹20,000', '₹20,000 - ₹35,000', '₹35,000 - ₹50,000', 'Over ₹50,000']; - const durations = ['All Durations', 'Under 6 hours', '6-10 hours', '10-15 hours', 'Over 15 hours']; - const ratings = ['All Ratings', '4.5+ Stars', '4.0+ Stars', '3.5+ Stars']; - - const sortOptions = [ - { value: 'Most Popular', label: 'Most Popular' }, - { value: 'newest', label: 'Newest First' }, - { value: 'title', label: 'Title A-Z' }, - { value: 'price_low', label: 'Price: Low to High' }, - { value: 'price_high', label: 'Price: High to Low' }, - { value: 'rating', label: 'Highest Rated' }, - { value: 'duration', label: 'Duration' } - ]; - - // Helper function to parse rupee price - const parseRupeePrice = (priceStr: string) => { - return parseFloat(priceStr.replace('₹', '').replace(/,/g, '')); - }; - - // Filter and sort courses - const filteredCourses = featuredCourses.filter(course => { - const matchesSearch = course.title.toLowerCase().includes(searchTerm.toLowerCase()) || - course.description.toLowerCase().includes(searchTerm.toLowerCase()) || - course.category.toLowerCase().includes(searchTerm.toLowerCase()); - - const matchesCategory = selectedCategory === 'All Categories' || course.category === selectedCategory; - const matchesLevel = selectedLevel === 'All Levels' || course.level === selectedLevel; - const matchesFormat = selectedFormat === 'All Formats' || course.format === selectedFormat; - - // Price filter - Updated for Rupees - const price = parseRupeePrice(course.price); - const matchesPrice = selectedPriceRange === 'All Prices' || - (selectedPriceRange === 'Under ₹20,000' && price < 20000) || - (selectedPriceRange === '₹20,000 - ₹35,000' && price >= 20000 && price <= 35000) || - (selectedPriceRange === '₹35,000 - ₹50,000' && price >= 35000 && price <= 50000) || - (selectedPriceRange === 'Over ₹50,000' && price > 50000); - - // Duration filter - const durationHours = parseInt(course.duration); - const matchesDuration = selectedDuration === 'All Durations' || - (selectedDuration === 'Under 6 hours' && durationHours < 6) || - (selectedDuration === '6-10 hours' && durationHours >= 6 && durationHours <= 10) || - (selectedDuration === '10-15 hours' && durationHours >= 10 && durationHours <= 15) || - (selectedDuration === 'Over 15 hours' && durationHours > 15); - - // Rating filter - const matchesRating = selectedRating === 'All Ratings' || - (selectedRating === '4.5+ Stars' && course.rating >= 4.5) || - (selectedRating === '4.0+ Stars' && course.rating >= 4.0) || - (selectedRating === '3.5+ Stars' && course.rating >= 3.5); - - return matchesSearch && matchesCategory && matchesLevel && matchesFormat && matchesPrice && matchesDuration && matchesRating; - }).sort((a, b) => { - switch (sortBy) { - case 'Most Popular': - return parseInt(b.participants.replace(/[^\d]/g, '')) - parseInt(a.participants.replace(/[^\d]/g, '')); - case 'newest': - return a.id.localeCompare(b.id); // Assuming newer courses have higher IDs - case 'title': - return a.title.localeCompare(b.title); - case 'price_low': - return parseRupeePrice(a.price) - parseRupeePrice(b.price); - case 'price_high': - return parseRupeePrice(b.price) - parseRupeePrice(a.price); - case 'rating': - return b.rating - a.rating; - case 'duration': - return parseInt(a.duration) - parseInt(b.duration); - default: - return 0; - } + // Fetch course categories + const { data: categoriesData, isLoading: categoriesLoading } = useGetCourseCategoriesQuery({ + limit: 100, + offset: 0 }); - // Paginate results - const totalPages = Math.ceil(filteredCourses.length / coursesPerPage); + const sortOptions = [ + { value: 'most_popular', label: 'Most Popular' }, + { value: 'newest', label: 'Newest First' }, + { value: 'title_asc', label: 'Title A-Z' }, + { value: 'price_asc', label: 'Price: Low to High' }, + { value: 'price_desc', label: 'Price: High to Low' }, + { value: 'rating_desc', label: 'Highest Rated' }, + { value: 'duration_asc', label: 'Duration' } + ]; + + const priceRanges = [ + 'All Prices', + 'Under ₹20,000', + '₹20,000 - ₹35,000', + '₹35,000 - ₹50,000', + 'Over ₹50,000' + ]; + + const durations = [ + 'All Durations', + 'Under 6 hours', + '6-10 hours', + '10-15 hours', + 'Over 15 hours' + ]; + + const ratings = [ + 'All Ratings', + '4.5+ Stars', + '4.0+ Stars', + '3.5+ Stars' + ]; + + // Build categories list + const categories = useMemo(() => { + const cats = [{ id: '', name: 'All Categories' }]; + if (categoriesData?.data?.items) { + categoriesData.data.items.forEach((cat: CourseCategory) => { + cats.push({ id: cat.id, name: cat.category_name }); + }); + } + return cats; + }, [categoriesData]); + + // Helper function to convert UI price range to API format + const getPriceRangeForApi = useCallback((priceRange: string): string | undefined => { + switch (priceRange) { + case 'Under ₹20,000': + return '0-20000'; + case '₹20,000 - ₹35,000': + return '20000-35000'; + case '₹35,000 - ₹50,000': + return '35000-50000'; + case 'Over ₹50,000': + return '50000-999999'; + default: + return undefined; + } + }, []); + + // Helper function to convert UI duration to API format + const getDurationForApi = useCallback((duration: string): string | undefined => { + switch (duration) { + case 'Under 6 hours': + return '0-6'; + case '6-10 hours': + return '6-10'; + case '10-15 hours': + return '10-15'; + case 'Over 15 hours': + return '15-999'; + default: + return undefined; + } + }, []); + + // Helper function to convert UI rating to API format + const getRatingForApi = useCallback((rating: string): number | undefined => { + switch (rating) { + case '4.5+ Stars': + return 4.5; + case '4.0+ Stars': + return 4.0; + case '3.5+ Stars': + return 3.5; + default: + return undefined; + } + }, []); + + // Helper function to convert sort option to API format + const getSortByForApi = useCallback((sort: string): string | undefined => { + switch (sort) { + case 'Most Popular': + return 'popular'; + case 'newest': + return 'newest'; + case 'title': + return 'title_asc'; + case 'price_low': + return 'price_asc'; + case 'price_high': + return 'price_desc'; + case 'rating': + return 'rating_desc'; + case 'duration': + return 'duration_asc'; + default: + return undefined; + } + }, []); + + // Build API filters based on current UI state + const apiFilters: GetCoursesParams = useMemo(() => { + const filters: GetCoursesParams = { + limit: 100, + offset: 0, + status: 'publish' + }; + + // Category filter + if (selectedCategoryId) { + filters.course_category = [selectedCategoryId]; + } + + // Search query + if (debouncedSearchTerm) { + filters.search_query = debouncedSearchTerm; + } + + // Price range + const apiPriceRange = getPriceRangeForApi(selectedPriceRange); + if (apiPriceRange) { + filters.price_range = apiPriceRange; + } + + // Duration range + const apiDurationRange = getDurationForApi(selectedDuration); + if (apiDurationRange) { + filters.duration_range = apiDurationRange; + } + + // Rating + const apiRating = getRatingForApi(selectedRating); + if (apiRating !== undefined) { + filters.min_rating = apiRating; + } + + // Sort by + const apiSortBy = getSortByForApi(sortBy); + if (apiSortBy) { + filters.sort_by = apiSortBy; + } + + return filters; + }, [ + selectedCategoryId, + debouncedSearchTerm, + selectedPriceRange, + selectedDuration, + selectedRating, + sortBy, + getPriceRangeForApi, + getDurationForApi, + getRatingForApi, + getSortByForApi + ]); + + // Fetch courses with API filters + const { + data: coursesData, + isLoading: coursesLoading, + isError, + isFetching // To show loading indicator while fetching + } = useGetCoursesQuery(apiFilters); + + // Reset to page 1 when filters change + useEffect(() => { + setCurrentPage(1); + }, [ + selectedCategoryId, + debouncedSearchTerm, + selectedPriceRange, + selectedDuration, + selectedRating, + sortBy + ]); + + // Transform API response to course format + const courses = useMemo(() => { + if (!coursesData?.data?.items) return []; + + return coursesData.data.items.map((course: Course) => ({ + id: course.id, + title: course.course_name, + thumbnail: course.thumbnail_img || 'https://images.unsplash.com/photo-1552664730-d307ca884978?w=400&h=250&fit=crop', + duration: `${course.total_duration || 0} hours`, + level: 'Intermediate', + format: course.retail_type === 'public' ? 'Cohort-based' : 'Self-paced', + rating: course.avg_rating || 4.5, + participants: `${Math.floor(Math.random() * 5000) + 100}+`, + category: course.course_category_name || 'General', + categoryId: course.course_category_xid || '', + description: course.course_desc || `Master ${course.course_name} with our comprehensive program.`, + price: formatPrice(course.price), + originalPrice: formatPrice(course.price * 1.25), + course_status: course.course_status + })); + }, [coursesData]); + + // Get total courses count from API response + const totalCoursesCount = coursesData?.data?.pagination_info?.total_count || 0; + + // Paginate the courses (since API returns all courses based on filters, we paginate client-side) + const totalPages = Math.ceil(totalCoursesCount / coursesPerPage); const startIndex = (currentPage - 1) * coursesPerPage; - const currentCourses = filteredCourses.slice(startIndex, startIndex + coursesPerPage); + const currentCourses = courses.slice(startIndex, startIndex + coursesPerPage); + + // Handle category change + const handleCategoryChange = (value: string) => { + const selectedCat = categories.find(cat => cat.name === value); + if (selectedCat) { + setSelectedCategoryName(selectedCat.name); + setSelectedCategoryId(selectedCat.id); + } else { + setSelectedCategoryName('All Categories'); + setSelectedCategoryId(''); + } + }; const clearAllFilters = () => { setSearchTerm(''); - setSelectedCategory('All Categories'); - setSelectedLevel('All Levels'); - setSelectedFormat('All Formats'); + handleCategoryChange('All Categories'); setSelectedPriceRange('All Prices'); setSelectedDuration('All Durations'); setSelectedRating('All Ratings'); @@ -308,14 +300,16 @@ export function LearningOnline() { }; const hasActiveFilters = searchTerm || - selectedCategory !== 'All Categories' || - selectedLevel !== 'All Levels' || - selectedFormat !== 'All Formats' || + selectedCategoryName !== 'All Categories' || selectedPriceRange !== 'All Prices' || selectedDuration !== 'All Durations' || selectedRating !== 'All Ratings'; - // Cart functions - using global cart context + // Cart functionality + const { addToCart } = useCart(); + const [isCartPopupOpen, setIsCartPopupOpen] = useState(false); + const [recentlyAddedItem, setRecentlyAddedItem] = useState(null); + const handleAddToCart = (item: CartItem) => { addToCart(item); setRecentlyAddedItem(item); @@ -327,9 +321,34 @@ export function LearningOnline() { setRecentlyAddedItem(null); }; + // Show loading state + if (coursesLoading || categoriesLoading) { + return ( +
+
+
+

Loading courses...

+
+
+ ); + } + + // Show error state + if (isError) { + return ( +
+
+

Error Loading Courses

+

Failed to load courses. Please try again later.

+ +
+
+ ); + } + return (
- {/* Hero Banner – Digital Learning - Blog Style */} + {/* Hero Banner (keep as is) */}
- {/* Eyebrow Text */}
DIGITAL LEARNING PLATFORM
- - {/* Main Header */}

Discover Your Leadership
Potential Online

- - {/* Sub Text */}

Our Leadership Courses are structured packages which are targeted towards building your leadership abilities. Each course is a wholesome package which not only helps you gain awareness about your leadership style but also gives insights to build your leadership abilities. Every course contains curated content targeted towards a specific leadership ability. Each course consists of our proprietary profiling instruments – Leadership Profilers, conceptual videos and experiences of leaders – Leadership Webcasts, as well as additional content to supplement learning. @@ -371,11 +385,10 @@ export function LearningOnline() {

- {/* Search and Controls Section */} + {/* Search and Controls Section (keep as is) */}
- {/* Search Bar */}
- {/* View Toggle and Sort */}
- - {/* Level Filter */} -
- - -
- - {/* Format Filter */} -
- -