@@ -3,47 +3,36 @@ import { ImageWithFallback } from "./figma/ImageWithFallback";
|
|||||||
import { BrandedTag } from "./about/BrandedTag";
|
import { BrandedTag } from "./about/BrandedTag";
|
||||||
import { StandardCTAButton } from "./StandardCTAButton";
|
import { StandardCTAButton } from "./StandardCTAButton";
|
||||||
import { navigateTo } from "./Router";
|
import { navigateTo } from "./Router";
|
||||||
|
import { useGetFeaturedBlogsQuery } from "../redux/services/homepageApi";
|
||||||
|
import { FullScreenLoader } from "./FullScreenLoader";
|
||||||
|
import { getSlugWithId } from "../utils/urlHelpers";
|
||||||
|
|
||||||
interface InsightCard {
|
// Interface for featured blog items from API
|
||||||
id: number;
|
interface FeaturedBlog {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
short_description: string | null;
|
||||||
|
slug_name: string;
|
||||||
|
banner_img: string | null;
|
||||||
|
updated_at: string;
|
||||||
|
content_category: string;
|
||||||
|
content_type: string;
|
||||||
|
tags: string[];
|
||||||
|
featured: boolean;
|
||||||
|
featured_order: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insight Card Component Interface
|
||||||
|
interface InsightCardData {
|
||||||
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
date: string;
|
date: string;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
image: string;
|
image: string;
|
||||||
slug?: string;
|
slug: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const insightCards: InsightCard[] = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
title: "A New Lens on Leadership",
|
|
||||||
description: "Your leadership calls, and how you interpret opportunities and threats, are influenced by your lenses, which are unique and personal to you.",
|
|
||||||
date: "16-08-2016",
|
|
||||||
tags: ["Leadership Lens", "Perspective"],
|
|
||||||
image: "https://images.unsplash.com/photo-1560550900-5c10828c40aa?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxsZWFkZXJzaGlwJTIwbGVucyUyMHBlcnNwZWN0aXZlfGVufDF8fHx8MTc1OTk5NTg0N3ww&ixlib=rb-4.1.0&q=80&w=1080",
|
|
||||||
slug: "new-lens-on-leadership"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
title: "Putting Psychometry in perspective",
|
|
||||||
description: "An in-depth exploration of the limitations and appropriate use of psychometric tools in leadership assessment and talent selection.",
|
|
||||||
date: "17-12-2016",
|
|
||||||
tags: ["Psychometry", "Assessment"],
|
|
||||||
image: "https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=600&h=400&fit=crop",
|
|
||||||
slug: "putting-psychometry-in-perspective"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
title: "The Busby Way to Talent Management: The Making of \"Busby's Babes\" – Part 1",
|
|
||||||
description: "How Matt Busby transformed Manchester United through visionary talent management and youth development, creating a legacy that shaped modern football leadership.",
|
|
||||||
date: "05-12-2013",
|
|
||||||
tags: ["Talent Management", "Youth Development"],
|
|
||||||
image: "https://images.unsplash.com/photo-1574629810360-7efbbe195018?w=600&h=400&fit=crop",
|
|
||||||
slug: "busby-way-talent-management-part-1"
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
// Insight Tag Component
|
// Insight Tag Component
|
||||||
function InsightTag({ text }: { text: string }) {
|
function InsightTag({ text }: { text: string }) {
|
||||||
return (
|
return (
|
||||||
@@ -78,7 +67,7 @@ function CalendarIcon() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explore All Button Component - Updated to redirect to articles page
|
// Explore All Button Component
|
||||||
function ExploreAllButton() {
|
function ExploreAllButton() {
|
||||||
return (
|
return (
|
||||||
<StandardCTAButton
|
<StandardCTAButton
|
||||||
@@ -90,14 +79,15 @@ function ExploreAllButton() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Large Insight Card Component
|
// Large Insight Card Component
|
||||||
function LargeInsightCard({ card }: { card: InsightCard }) {
|
function LargeInsightCard({ card }: { card: InsightCardData }) {
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
if (card.slug) {
|
if (card.slug && card.id) {
|
||||||
navigateTo(`/learning/articles/${card.slug}`);
|
const url = getSlugWithId(card.slug, card.id);
|
||||||
|
navigateTo(`/learning/articles/${url}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const hasLink = !!card.slug;
|
const hasLink = !!(card.slug && card.id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -125,8 +115,8 @@ function LargeInsightCard({ card }: { card: InsightCard }) {
|
|||||||
<div className="insight-card-white-box absolute bottom-6 left-6 right-6 bg-white rounded-xl p-6 shadow-lg transition-all duration-300 group-hover:shadow-xl">
|
<div className="insight-card-white-box absolute bottom-6 left-6 right-6 bg-white rounded-xl p-6 shadow-lg transition-all duration-300 group-hover:shadow-xl">
|
||||||
{/* Top section with tags and arrow */}
|
{/* Top section with tags and arrow */}
|
||||||
<div className="insight-card-header flex items-start justify-between mb-4">
|
<div className="insight-card-header flex items-start justify-between mb-4">
|
||||||
<div className="insight-card-tags flex gap-2">
|
<div className="insight-card-tags flex gap-2 flex-wrap">
|
||||||
{card.tags.map((tag, index) => (
|
{card.tags.slice(0, 2).map((tag, index) => (
|
||||||
<InsightTag key={index} text={tag} />
|
<InsightTag key={index} text={tag} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -158,14 +148,15 @@ function LargeInsightCard({ card }: { card: InsightCard }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Small Insight Card Component
|
// Small Insight Card Component
|
||||||
function SmallInsightCard({ card }: { card: InsightCard }) {
|
function SmallInsightCard({ card }: { card: InsightCardData }) {
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
if (card.slug) {
|
if (card.slug && card.id) {
|
||||||
navigateTo(`/learning/articles/${card.slug}`);
|
const url = getSlugWithId(card.slug, card.id);
|
||||||
|
navigateTo(`/learning/articles/${url}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const hasLink = !!card.slug;
|
const hasLink = !!(card.slug && card.id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -193,8 +184,8 @@ function SmallInsightCard({ card }: { card: InsightCard }) {
|
|||||||
<div className="insight-card-white-box absolute bottom-4 left-4 right-4 bg-white rounded-xl p-4 shadow-lg transition-all duration-300 group-hover:shadow-xl">
|
<div className="insight-card-white-box absolute bottom-4 left-4 right-4 bg-white rounded-xl p-4 shadow-lg transition-all duration-300 group-hover:shadow-xl">
|
||||||
{/* Top section with tags and arrow */}
|
{/* Top section with tags and arrow */}
|
||||||
<div className="insight-card-header flex items-start justify-between mb-3">
|
<div className="insight-card-header flex items-start justify-between mb-3">
|
||||||
<div className="insight-card-tags flex gap-2">
|
<div className="insight-card-tags flex gap-2 flex-wrap">
|
||||||
{card.tags.map((tag, index) => (
|
{card.tags.slice(0, 2).map((tag, index) => (
|
||||||
<span
|
<span
|
||||||
key={index}
|
key={index}
|
||||||
className="px-2.5 py-1 text-xs font-medium rounded-full"
|
className="px-2.5 py-1 text-xs font-medium rounded-full"
|
||||||
@@ -232,7 +223,97 @@ function SmallInsightCard({ card }: { card: InsightCard }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Format date function
|
||||||
|
const formatDate = (dateString: string) => {
|
||||||
|
return new Date(dateString).toLocaleDateString('en-US', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
day: 'numeric'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export function InsightsSection() {
|
export function InsightsSection() {
|
||||||
|
// Fetch featured blogs from API
|
||||||
|
const { data: featuredBlogs, isLoading, isError } = useGetFeaturedBlogsQuery({ limit: 3 });
|
||||||
|
|
||||||
|
// Transform API data to match InsightCardData format
|
||||||
|
const transformToInsightCard = (blog: FeaturedBlog): InsightCardData => ({
|
||||||
|
id: blog.id,
|
||||||
|
title: blog.title,
|
||||||
|
description: blog.short_description || undefined,
|
||||||
|
date: formatDate(blog.updated_at),
|
||||||
|
tags: blog.tags || [],
|
||||||
|
image: blog.banner_img || 'https://images.unsplash.com/photo-1481627834876-b7833e8f5570?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&w=1080',
|
||||||
|
slug: blog.slug_name,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle loading state
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
className="py-24"
|
||||||
|
style={{
|
||||||
|
backgroundColor: '#F7F7FD',
|
||||||
|
paddingTop: '8.75rem',
|
||||||
|
paddingBottom: '8.75rem'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="max-w-7xl mx-auto section-margin-x">
|
||||||
|
<div className="flex items-center justify-center min-h-[400px]">
|
||||||
|
<FullScreenLoader text="Loading insights..." />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle error or no data state
|
||||||
|
if (isError || !featuredBlogs || featuredBlogs.length === 0) {
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
className="py-24"
|
||||||
|
style={{
|
||||||
|
backgroundColor: '#F7F7FD',
|
||||||
|
paddingTop: '8.75rem',
|
||||||
|
paddingBottom: '8.75rem'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="max-w-7xl mx-auto section-margin-x">
|
||||||
|
<BrandedTag text="Leadership Insights" />
|
||||||
|
|
||||||
|
<div className="insights-container">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="insights-header flex flex-col lg:flex-row lg:items-center lg:justify-between mb-16 gap-8 text-center lg:text-left">
|
||||||
|
<h2
|
||||||
|
className="insights-title text-3xl md:text-4xl lg:text-5xl font-bold leading-tight"
|
||||||
|
style={{ color: 'var(--color-brand-black)' }}
|
||||||
|
>
|
||||||
|
Leadership Insights & Ideas
|
||||||
|
</h2>
|
||||||
|
<ExploreAllButton />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Show message when no featured blogs available */}
|
||||||
|
<div className="text-center py-12">
|
||||||
|
<p className="text-gray-600">No featured insights available at the moment. Check back soon!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure we have at least 3 blogs for the layout (use placeholders if needed)
|
||||||
|
const cards = featuredBlogs.map(transformToInsightCard);
|
||||||
|
|
||||||
|
// The layout expects: first card (large) + two small cards
|
||||||
|
const largeCard = cards[0];
|
||||||
|
const smallCards = cards.slice(1, 3);
|
||||||
|
|
||||||
|
// If we don't have enough cards, we can still render with what we have
|
||||||
|
const hasLargeCard = !!largeCard;
|
||||||
|
const hasSmallCards = smallCards.length > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
className="py-24"
|
className="py-24"
|
||||||
@@ -243,7 +324,6 @@ export function InsightsSection() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="max-w-7xl mx-auto section-margin-x">
|
<div className="max-w-7xl mx-auto section-margin-x">
|
||||||
{/* Branded Tag */}
|
|
||||||
<BrandedTag text="Leadership Insights" />
|
<BrandedTag text="Leadership Insights" />
|
||||||
|
|
||||||
<div className="insights-container">
|
<div className="insights-container">
|
||||||
@@ -261,15 +341,20 @@ export function InsightsSection() {
|
|||||||
{/* Main Grid Layout */}
|
{/* Main Grid Layout */}
|
||||||
<div className="insights-grid grid grid-cols-1 lg:grid-cols-2 gap-4 md:gap-6 lg:gap-8">
|
<div className="insights-grid grid grid-cols-1 lg:grid-cols-2 gap-4 md:gap-6 lg:gap-8">
|
||||||
{/* Large Card - Takes full height on left */}
|
{/* Large Card - Takes full height on left */}
|
||||||
|
{hasLargeCard && (
|
||||||
<div className="lg:row-span-2">
|
<div className="lg:row-span-2">
|
||||||
<LargeInsightCard card={insightCards[0]} />
|
<LargeInsightCard card={largeCard} />
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Small Cards - Stack on right */}
|
{/* Small Cards - Stack on right */}
|
||||||
|
{hasSmallCards && (
|
||||||
<div className="flex flex-col gap-4 md:gap-6 lg:gap-8">
|
<div className="flex flex-col gap-4 md:gap-6 lg:gap-8">
|
||||||
<SmallInsightCard card={insightCards[1]} />
|
{smallCards.map((card:any, index:any) => (
|
||||||
<SmallInsightCard card={insightCards[2]} />
|
<SmallInsightCard key={card.id || index} card={card} />
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export function LearningOnline() {
|
|||||||
const [selectedPriceRange, setSelectedPriceRange] = useState('All Prices');
|
const [selectedPriceRange, setSelectedPriceRange] = useState('All Prices');
|
||||||
const [selectedDuration, setSelectedDuration] = useState('All Durations');
|
const [selectedDuration, setSelectedDuration] = useState('All Durations');
|
||||||
const [selectedRating, setSelectedRating] = useState('All Ratings');
|
const [selectedRating, setSelectedRating] = useState('All Ratings');
|
||||||
const [sortBy, setSortBy] = useState('Most Popular');
|
const [sortBy, setSortBy] = useState('most_popular'); // ✅ Changed to match API value
|
||||||
const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid');
|
const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid');
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
const coursesPerPage = 9;
|
const coursesPerPage = 9;
|
||||||
@@ -68,14 +68,15 @@ export function LearningOnline() {
|
|||||||
offset: 0
|
offset: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ✅ Updated sort options to match backend API values
|
||||||
const sortOptions = [
|
const sortOptions = [
|
||||||
{ value: 'most_popular', label: 'Most Popular' },
|
{ value: 'most_popular', label: 'Most Popular' },
|
||||||
{ value: 'newest', label: 'Newest First' },
|
{ value: 'newest', label: 'Newest First' },
|
||||||
{ value: 'title_asc', label: 'Title A-Z' },
|
{ value: 'title_asc', label: 'Title A-Z' },
|
||||||
{ value: 'price_asc', label: 'Price: Low to High' },
|
{ value: 'price_low', label: 'Price: Low to High' },
|
||||||
{ value: 'price_desc', label: 'Price: High to Low' },
|
{ value: 'price_high', label: 'Price: High to Low' },
|
||||||
{ value: 'rating_desc', label: 'Highest Rated' },
|
{ value: 'highest_rated', label: 'Highest Rated' },
|
||||||
{ value: 'duration_asc', label: 'Duration' }
|
{ value: 'duration', label: 'Duration' }
|
||||||
];
|
];
|
||||||
|
|
||||||
const priceRanges = [
|
const priceRanges = [
|
||||||
@@ -112,33 +113,33 @@ export function LearningOnline() {
|
|||||||
return cats;
|
return cats;
|
||||||
}, [categoriesData]);
|
}, [categoriesData]);
|
||||||
|
|
||||||
// Helper function to convert UI price range to API format
|
// ✅ Helper function to convert UI price range to API format
|
||||||
const getPriceRangeForApi = useCallback((priceRange: string): string | undefined => {
|
const getPriceRangeForApi = useCallback((priceRange: string): string | undefined => {
|
||||||
switch (priceRange) {
|
switch (priceRange) {
|
||||||
case 'Under ₹20,000':
|
case 'Under ₹20,000':
|
||||||
return '0-20000';
|
return 'under_20000';
|
||||||
case '₹20,000 - ₹35,000':
|
case '₹20,000 - ₹35,000':
|
||||||
return '20000-35000';
|
return '20000_35000';
|
||||||
case '₹35,000 - ₹50,000':
|
case '₹35,000 - ₹50,000':
|
||||||
return '35000-50000';
|
return '35000_50000';
|
||||||
case 'Over ₹50,000':
|
case 'Over ₹50,000':
|
||||||
return '50000-999999';
|
return 'above_50000';
|
||||||
default:
|
default:
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Helper function to convert UI duration to API format
|
// ✅ Helper function to convert UI duration to API format
|
||||||
const getDurationForApi = useCallback((duration: string): string | undefined => {
|
const getDurationForApi = useCallback((duration: string): string | undefined => {
|
||||||
switch (duration) {
|
switch (duration) {
|
||||||
case 'Under 6 hours':
|
case 'Under 6 hours':
|
||||||
return '0-6';
|
return 'under_6';
|
||||||
case '6-10 hours':
|
case '6-10 hours':
|
||||||
return '6-10';
|
return '6_10';
|
||||||
case '10-15 hours':
|
case '10-15 hours':
|
||||||
return '10-15';
|
return '10_15';
|
||||||
case 'Over 15 hours':
|
case 'Over 15 hours':
|
||||||
return '15-999';
|
return 'above_15';
|
||||||
default:
|
default:
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@@ -158,26 +159,11 @@ export function LearningOnline() {
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Helper function to convert sort option to API format
|
// ✅ Helper function to convert sort option to API format
|
||||||
const getSortByForApi = useCallback((sort: string): string | undefined => {
|
const getSortByForApi = useCallback((sort: string): string | undefined => {
|
||||||
switch (sort) {
|
// sort is already in API format (most_popular, newest, title_asc, etc.)
|
||||||
case 'Most Popular':
|
// Just return it as is
|
||||||
return 'popular';
|
return sort;
|
||||||
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
|
// Build API filters based on current UI state
|
||||||
@@ -304,7 +290,7 @@ export function LearningOnline() {
|
|||||||
setSelectedPriceRange('All Prices');
|
setSelectedPriceRange('All Prices');
|
||||||
setSelectedDuration('All Durations');
|
setSelectedDuration('All Durations');
|
||||||
setSelectedRating('All Ratings');
|
setSelectedRating('All Ratings');
|
||||||
setSortBy('Most Popular');
|
setSortBy('most_popular'); // ✅ Updated to match API value
|
||||||
};
|
};
|
||||||
|
|
||||||
const hasActiveFilters = searchTerm ||
|
const hasActiveFilters = searchTerm ||
|
||||||
@@ -361,7 +347,7 @@ export function LearningOnline() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ backgroundColor: '#FFFFFF' }}>
|
<div style={{ backgroundColor: '#FFFFFF' }}>
|
||||||
{/* Hero Banner (keep as is) */}
|
{/* Hero Banner */}
|
||||||
<section className="relative py-16 overflow-hidden">
|
<section className="relative py-16 overflow-hidden">
|
||||||
<div
|
<div
|
||||||
className="absolute inset-0"
|
className="absolute inset-0"
|
||||||
@@ -398,7 +384,7 @@ export function LearningOnline() {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Search and Controls Section (keep as is) */}
|
{/* Search and Controls Section */}
|
||||||
<section className="py-8" style={{ backgroundColor: '#FFFFFF' }}>
|
<section className="py-8" style={{ backgroundColor: '#FFFFFF' }}>
|
||||||
<div className="section-margin-x">
|
<div className="section-margin-x">
|
||||||
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-6">
|
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-6">
|
||||||
@@ -453,7 +439,7 @@ export function LearningOnline() {
|
|||||||
<SelectValue placeholder="Sort by" />
|
<SelectValue placeholder="Sort by" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{sortOptions.map((option: any) => (
|
{sortOptions.map((option) => (
|
||||||
<SelectItem key={option.value} value={option.value}>
|
<SelectItem key={option.value} value={option.value}>
|
||||||
{option.label}
|
{option.label}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
@@ -597,6 +583,15 @@ export function LearningOnline() {
|
|||||||
<p className="text-body-lg text-muted">
|
<p className="text-body-lg text-muted">
|
||||||
No courses found matching your criteria.
|
No courses found matching your criteria.
|
||||||
</p>
|
</p>
|
||||||
|
{hasActiveFilters && (
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={clearAllFilters}
|
||||||
|
className="mt-4"
|
||||||
|
>
|
||||||
|
Clear Filters
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
@@ -693,18 +688,17 @@ export function LearningOnline() {
|
|||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={(e: any) => {
|
onClick={(e: React.MouseEvent) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
handleAddToCart({
|
handleAddToCart({
|
||||||
id: course.id,
|
id: course.id,
|
||||||
title: course.title,
|
title: course.title,
|
||||||
price: course.price,
|
price: course.price,
|
||||||
originalPrice: course.originalPrice,
|
originalPrice: course.originalPrice,
|
||||||
thumbnail: course.thumbnail,
|
thumbnail: course.thumbnail,
|
||||||
category: course.category, // ✅ FIX
|
category: course.category,
|
||||||
level: course.level, // ✅ FIX
|
level: course.level,
|
||||||
type: 'course' // optional (if you added in interface)
|
type: 'course'
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
className="flex items-center gap-2 hover:bg-blue-50 hover:border-blue-300"
|
className="flex items-center gap-2 hover:bg-blue-50 hover:border-blue-300"
|
||||||
|
|||||||
@@ -321,8 +321,8 @@ export const courseApi = createApi({
|
|||||||
const queryString = searchParams.toString();
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
return queryString
|
return queryString
|
||||||
? `admin/course/list?${queryString}`
|
? `admin/course/public/list?${queryString}`
|
||||||
: `admin/course/list`;
|
: `admin/course/public/list`;
|
||||||
},
|
},
|
||||||
|
|
||||||
providesTags: (result) =>
|
providesTags: (result) =>
|
||||||
|
|||||||
@@ -112,9 +112,22 @@ export const homepageApi = createApi({
|
|||||||
providesTags: [{ type: "Homepage", id: "LIST" }],
|
providesTags: [{ type: "Homepage", id: "LIST" }],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
getFeaturedBlogs: builder.query({
|
||||||
|
query: ({ limit = 3 }) => ({
|
||||||
|
url: `/admin/blogs/featured?limit=${limit}`,
|
||||||
|
method: 'GET',
|
||||||
|
}),
|
||||||
|
transformResponse: (response: any) => {
|
||||||
|
if (response?.success && response?.data) {
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
/* ================= HOOKS ================= */
|
/* ================= HOOKS ================= */
|
||||||
|
|
||||||
export const { useGetHomepageQuery } = homepageApi;
|
export const { useGetHomepageQuery, useGetFeaturedBlogsQuery } = homepageApi;
|
||||||
Reference in New Issue
Block a user