pagination added in artical and other changes
This commit is contained in:
@@ -134,7 +134,25 @@ const articles = [
|
||||
featured: false,
|
||||
views: '1.5k',
|
||||
likes: 28
|
||||
}
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
slug: 'strategic-thinking-frameworks',
|
||||
title: 'Strategic Thinking Frameworks for Modern Leaders',
|
||||
excerpt: 'Master strategic thinking with proven frameworks that help leaders anticipate challenges and seize opportunities.',
|
||||
content: 'Strategic thinking is a critical skill for leaders navigating complex business environments...',
|
||||
author: 'Dr. Amanda Foster',
|
||||
authorTitle: 'Strategic Leadership Coach',
|
||||
authorAvatar: 'https://images.unsplash.com/photo-1544725176-7c40e5a71c5e?w=150&h=150&fit=crop&crop=face',
|
||||
date: '2024-02-05',
|
||||
readTime: '11 min read',
|
||||
category: 'Strategy',
|
||||
tags: ['Strategic Thinking', 'Frameworks', 'Decision Making', 'Planning'],
|
||||
thumbnail: 'https://images.unsplash.com/photo-1552664730-d307ca884978?w=600&h=400&fit=crop',
|
||||
featured: false,
|
||||
views: '2.1k',
|
||||
likes: 39
|
||||
},
|
||||
];
|
||||
|
||||
export function Articles() {
|
||||
@@ -147,7 +165,9 @@ export function Articles() {
|
||||
const [sortBy, setSortBy] = useState('Most Recent');
|
||||
const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid');
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const articlesPerPage = 6;
|
||||
const articlesPerPage = 4;
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
|
||||
// Get unique values for filters
|
||||
const categories = ['All Categories', ...Array.from(new Set(articles.map(article => article.category)))];
|
||||
@@ -166,31 +186,31 @@ export function Articles() {
|
||||
// Filter and sort articles
|
||||
const filteredArticles = articles.filter(article => {
|
||||
const matchesSearch = article.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
article.excerpt.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
article.author.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
article.tags.some(tag => tag.toLowerCase().includes(searchTerm.toLowerCase()));
|
||||
article.excerpt.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
article.author.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
article.tags.some(tag => tag.toLowerCase().includes(searchTerm.toLowerCase()));
|
||||
const matchesCategory = selectedCategory === 'All Categories' || article.category === selectedCategory;
|
||||
const matchesAuthor = selectedAuthor === 'All Authors' || article.author === selectedAuthor;
|
||||
|
||||
// Read time filter
|
||||
const readTimeMinutes = parseInt(article.readTime);
|
||||
|
||||
// FIXED: Read time filter - properly parse the read time
|
||||
const readTimeMinutes = parseInt(article.readTime.replace(' min read', '')) || 0;
|
||||
const matchesReadTime = selectedReadTime === 'All Read Times' ||
|
||||
(selectedReadTime === 'Under 5 min' && readTimeMinutes < 5) ||
|
||||
(selectedReadTime === '5-10 min' && readTimeMinutes >= 5 && readTimeMinutes <= 10) ||
|
||||
(selectedReadTime === 'Over 10 min' && readTimeMinutes > 10);
|
||||
|
||||
(selectedReadTime === 'Under 5 min' && readTimeMinutes < 5) ||
|
||||
(selectedReadTime === '5-10 min' && readTimeMinutes >= 5 && readTimeMinutes <= 10) ||
|
||||
(selectedReadTime === 'Over 10 min' && readTimeMinutes > 10);
|
||||
|
||||
// Date range filter
|
||||
const articleDate = new Date(article.date);
|
||||
const now = new Date();
|
||||
const matchesDateRange = selectedDateRange === 'All Time' ||
|
||||
(selectedDateRange === 'Last 7 days' && (now.getTime() - articleDate.getTime()) <= 7 * 24 * 60 * 60 * 1000) ||
|
||||
(selectedDateRange === 'Last 30 days' && (now.getTime() - articleDate.getTime()) <= 30 * 24 * 60 * 60 * 1000) ||
|
||||
(selectedDateRange === 'Last 3 months' && (now.getTime() - articleDate.getTime()) <= 90 * 24 * 60 * 60 * 1000);
|
||||
|
||||
(selectedDateRange === 'Last 7 days' && (now.getTime() - articleDate.getTime()) <= 7 * 24 * 60 * 60 * 1000) ||
|
||||
(selectedDateRange === 'Last 30 days' && (now.getTime() - articleDate.getTime()) <= 30 * 24 * 60 * 60 * 1000) ||
|
||||
(selectedDateRange === 'Last 3 months' && (now.getTime() - articleDate.getTime()) <= 90 * 24 * 60 * 60 * 1000);
|
||||
|
||||
// Topic filter
|
||||
const matchesTopic = selectedTopic === 'All Topics' ||
|
||||
article.tags.includes(selectedTopic);
|
||||
|
||||
const matchesTopic = selectedTopic === 'All Topics' ||
|
||||
article.tags.includes(selectedTopic);
|
||||
|
||||
return matchesSearch && matchesCategory && matchesAuthor && matchesReadTime && matchesDateRange && matchesTopic;
|
||||
}).sort((a, b) => {
|
||||
switch (sortBy) {
|
||||
@@ -201,7 +221,8 @@ export function Articles() {
|
||||
case 'title':
|
||||
return a.title.localeCompare(b.title);
|
||||
case 'readTime':
|
||||
return parseInt(a.readTime) - parseInt(b.readTime);
|
||||
// FIXED: Sort by read time - properly parse the values
|
||||
return (parseInt(a.readTime.replace(' min read', '')) || 0) - (parseInt(b.readTime.replace(' min read', '')) || 0);
|
||||
case 'popular':
|
||||
return parseInt(b.views) - parseInt(a.views);
|
||||
default:
|
||||
@@ -234,12 +255,12 @@ export function Articles() {
|
||||
|
||||
|
||||
|
||||
const hasActiveFilters = searchTerm ||
|
||||
selectedCategory !== 'All Categories' ||
|
||||
selectedAuthor !== 'All Authors' ||
|
||||
selectedReadTime !== 'All Read Times' ||
|
||||
selectedDateRange !== 'All Time' ||
|
||||
selectedTopic !== 'All Topics';
|
||||
const hasActiveFilters = searchTerm ||
|
||||
selectedCategory !== 'All Categories' ||
|
||||
selectedAuthor !== 'All Authors' ||
|
||||
selectedReadTime !== 'All Read Times' ||
|
||||
selectedDateRange !== 'All Time' ||
|
||||
selectedTopic !== 'All Topics';
|
||||
|
||||
return (
|
||||
<div style={{ backgroundColor: '#FFFFFF' }}>
|
||||
@@ -260,11 +281,11 @@ export function Articles() {
|
||||
<div className="dot"></div>
|
||||
<span className="text">INSIGHTS & KNOWLEDGE</span>
|
||||
</div>
|
||||
|
||||
|
||||
<h1 className="text-h1-white mb-6">
|
||||
Articles & Research
|
||||
</h1>
|
||||
|
||||
|
||||
<p className="text-body-lg-white mb-8 max-w-2xl mx-auto">
|
||||
Discover cutting-edge insights, research findings, and expert perspectives on leadership development, management strategies, and organizational excellence.
|
||||
</p>
|
||||
@@ -320,11 +341,10 @@ export function Articles() {
|
||||
<div className="flex items-center border border-gray-300 rounded-lg overflow-hidden">
|
||||
<button
|
||||
onClick={() => setViewMode('grid')}
|
||||
className={`p-2 transition-colors ${
|
||||
viewMode === 'grid'
|
||||
? 'text-white'
|
||||
className={`p-2 transition-colors ${viewMode === 'grid'
|
||||
? 'text-white'
|
||||
: 'bg-white text-gray-600 hover:bg-gray-50'
|
||||
}`}
|
||||
}`}
|
||||
style={{
|
||||
backgroundColor: viewMode === 'grid' ? 'var(--color-primary)' : undefined
|
||||
}}
|
||||
@@ -334,11 +354,10 @@ export function Articles() {
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setViewMode('list')}
|
||||
className={`p-2 transition-colors ${
|
||||
viewMode === 'list'
|
||||
? 'text-white'
|
||||
className={`p-2 transition-colors ${viewMode === 'list'
|
||||
? 'text-white'
|
||||
: 'bg-white text-gray-600 hover:bg-gray-50'
|
||||
}`}
|
||||
}`}
|
||||
style={{
|
||||
backgroundColor: viewMode === 'list' ? 'var(--color-primary)' : undefined
|
||||
}}
|
||||
@@ -521,9 +540,9 @@ export function Articles() {
|
||||
<>
|
||||
{/* Grid View */}
|
||||
{viewMode === 'grid' && (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
|
||||
{currentArticles.map((article) => (
|
||||
<Card
|
||||
<Card
|
||||
key={article.id}
|
||||
className="overflow-hidden hover:shadow-lg transition-all duration-300 cursor-pointer group"
|
||||
onClick={() => navigateTo(`/learning/articles/${article.slug}`)}
|
||||
@@ -536,7 +555,7 @@ export function Articles() {
|
||||
/>
|
||||
{article.featured && (
|
||||
<div className="absolute top-4 right-4">
|
||||
<Badge
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="bg-yellow-100 text-yellow-800 border-yellow-200"
|
||||
>
|
||||
@@ -552,11 +571,11 @@ export function Articles() {
|
||||
</Badge>
|
||||
<span className="text-small text-muted">{article.readTime}</span>
|
||||
</div>
|
||||
|
||||
|
||||
<h3 className="text-h4 mb-3 group-hover:text-blue-600 transition-colors line-clamp-2">
|
||||
{article.title}
|
||||
</h3>
|
||||
|
||||
|
||||
<p className="text-small text-muted mb-4 line-clamp-3">
|
||||
{article.excerpt}
|
||||
</p>
|
||||
@@ -584,7 +603,7 @@ export function Articles() {
|
||||
{viewMode === 'list' && (
|
||||
<div className="space-y-6">
|
||||
{currentArticles.map((article) => (
|
||||
<Card
|
||||
<Card
|
||||
key={article.id}
|
||||
className="overflow-hidden hover:shadow-lg transition-all duration-300 cursor-pointer group"
|
||||
onClick={() => navigateTo(`/learning/articles/${article.slug}`)}
|
||||
@@ -598,7 +617,7 @@ export function Articles() {
|
||||
/>
|
||||
{article.featured && (
|
||||
<div className="absolute top-2 right-2">
|
||||
<Badge
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="bg-yellow-100 text-yellow-800 border-yellow-200 text-xs"
|
||||
>
|
||||
@@ -621,11 +640,11 @@ export function Articles() {
|
||||
<span>{article.views}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h3 className="text-h4 mb-2 group-hover:text-blue-600 transition-colors">
|
||||
{article.title}
|
||||
</h3>
|
||||
|
||||
|
||||
<p className="text-body text-muted mb-3">
|
||||
{article.excerpt}
|
||||
</p>
|
||||
@@ -657,29 +676,71 @@ export function Articles() {
|
||||
|
||||
{/* Pagination */}
|
||||
{totalPages > 1 && (
|
||||
<div className="flex items-center justify-center gap-4 mt-12">
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setCurrentPage(prev => Math.max(prev - 1, 1))}
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setCurrentPage(prev => Math.max(1, prev - 1));
|
||||
containerRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}}
|
||||
disabled={currentPage === 1}
|
||||
className="text-body"
|
||||
className="flex items-center gap-1 border-gray-300 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4 mr-2" />
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
Previous
|
||||
</Button>
|
||||
|
||||
<span className="text-body">
|
||||
Page {currentPage} of {totalPages}
|
||||
</span>
|
||||
|
||||
|
||||
<div className="flex items-center gap-1">
|
||||
{Array.from({ length: totalPages }, (_, i) => {
|
||||
const page = i + 1;
|
||||
// Show limited pages for better UX
|
||||
if (totalPages > 7) {
|
||||
const showPage =
|
||||
page === 1 ||
|
||||
page === totalPages ||
|
||||
(page >= currentPage - 1 && page <= currentPage + 1);
|
||||
|
||||
if (!showPage) {
|
||||
if (page === currentPage - 2 || page === currentPage + 2) {
|
||||
return <span key={page} className="px-2">...</span>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
key={page}
|
||||
variant={currentPage === page ? "default" : "outline"}
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setCurrentPage(page);
|
||||
containerRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}}
|
||||
className={`min-w-10 ${currentPage === page
|
||||
? 'bg-blue-600 text-white hover:bg-blue-700'
|
||||
: 'border-gray-300 text-gray-700 hover:bg-gray-50'
|
||||
}`}
|
||||
>
|
||||
{page}
|
||||
</Button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setCurrentPage(prev => Math.min(prev + 1, totalPages))}
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setCurrentPage(prev => Math.min(totalPages, prev + 1));
|
||||
containerRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}}
|
||||
disabled={currentPage === totalPages}
|
||||
className="text-body"
|
||||
className="flex items-center gap-1 border-gray-300 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
Next
|
||||
<ChevronRight className="w-4 h-4 ml-2" />
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
@@ -703,9 +764,9 @@ export function Articles() {
|
||||
</div>
|
||||
|
||||
<div className="relative h-full flex items-center justify-end section-margin-x">
|
||||
<div
|
||||
<div
|
||||
className="bg-opacity-95 backdrop-blur-sm rounded-lg p-16 max-w-2xl"
|
||||
style={{
|
||||
style={{
|
||||
backgroundColor: 'var(--color-brand-primary)'
|
||||
}}
|
||||
>
|
||||
@@ -715,8 +776,8 @@ export function Articles() {
|
||||
</div>
|
||||
|
||||
<h2 className="text-h2-white mb-8">
|
||||
Ready to explore more insights?
|
||||
<span
|
||||
Ready to explore more insights?
|
||||
<span
|
||||
className="italic"
|
||||
style={{ color: 'var(--color-brand-accent)' }}
|
||||
>
|
||||
@@ -725,7 +786,7 @@ export function Articles() {
|
||||
our complete library of leadership resources.
|
||||
</h2>
|
||||
|
||||
<PrimaryCTAButton
|
||||
<PrimaryCTAButton
|
||||
text="Browse All Resources"
|
||||
onClick={() => navigateTo('/learning/articles')}
|
||||
ariaLabel="Browse all leadership articles and resources"
|
||||
|
||||
Reference in New Issue
Block a user