2026-03-18 16:42:18 +05:30

244 lines
10 KiB
TypeScript

"use client";
import React, { useState, useEffect, useMemo } from "react";
import { BlogData } from "@/utils/constant.utils";
import Link from "next/link";
import Slider from "react-slick";
const allBlogs = [...BlogData].sort(
(a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()
);
interface BlogSectionProps {
hideHeader?: boolean;
isPaginated?: boolean;
searchTerm?: string;
selectedCategory?: string;
blogsPerPage?: number;
columns?: string; // e.g., "col-xxl-4 col-xl-4 col-lg-6"
}
const BlogSection = ({
hideHeader = false,
isPaginated = false,
searchTerm = "",
selectedCategory = "",
blogsPerPage = 12,
columns = "col-xxl-4 col-xl-4 col-lg-6"
}: BlogSectionProps) => {
const [currentPage, setCurrentPage] = useState(1);
const [isSlider, setIsSlider] = useState(false);
const [isMounted, setIsMounted] = useState(false);
// Reset to first page when filtering changes
useEffect(() => {
setCurrentPage(1);
}, [searchTerm, selectedCategory]);
// Handle mount and resize
useEffect(() => {
setIsMounted(true);
if (isPaginated) {
setIsSlider(false);
return;
}
const handleResize = () => {
setIsSlider(window.innerWidth <= 1024);
};
handleResize();
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, [isPaginated]);
// Filter blogs based on search and category
const filteredBlogs = useMemo(() => {
let list = [...allBlogs];
if (selectedCategory) {
list = list.filter(blog => blog.category === selectedCategory);
}
if (searchTerm) {
const lowerTerm = searchTerm.toLowerCase();
list = list.filter(blog =>
blog.title.toLowerCase().includes(lowerTerm) ||
blog.category.toLowerCase().includes(lowerTerm)
);
}
return list;
}, [searchTerm, selectedCategory]);
if (!isMounted) {
return null; // Avoid hydration mismatch
}
// Total pages
const totalPages = Math.ceil(filteredBlogs.length / blogsPerPage);
// Get current blogs
const indexOfLastBlog = currentPage * blogsPerPage;
const indexOfFirstBlog = indexOfLastBlog - blogsPerPage;
const currentBlogs = isPaginated ? filteredBlogs.slice(indexOfFirstBlog, indexOfLastBlog) : filteredBlogs.slice(0, 3);
const paginate = (pageNumber: number) => {
if (pageNumber >= 1 && pageNumber <= totalPages) {
setCurrentPage(pageNumber);
window.scrollTo({ top: 0, behavior: 'smooth' });
}
};
// Pagination display logic: show up to 5 numbers then arrows
const renderPageNumbers = () => {
const pages = [];
let startPage = Math.max(1, currentPage - 2);
let endPage = Math.min(totalPages, startPage + 4);
if (endPage - startPage < 4) {
startPage = Math.max(1, endPage - 4);
}
for (let i = startPage; i <= endPage; i++) {
pages.push(
<button
key={i}
onClick={() => paginate(i)}
className={`pagination-btn ${currentPage === i ? 'active' : ''}`}
suppressHydrationWarning
>
{i}
</button>
);
}
return pages;
};
const sliderSettings = {
dots: false,
infinite: true,
speed: 500,
slidesToShow: 2,
slidesToScroll: 1,
arrows: false,
autoplay: true,
responsive: [
{
breakpoint: 767, // Below 768px show 1 card
settings: {
slidesToShow: 1,
slidesToScroll: 1,
},
},
],
};
return (
<section className={`blog-section-one section-space ${isPaginated ? "pb-0 pt-0" : ""}`}>
<div className={`small-container ${isSlider ? "blog-slider-active" : ""}`}>
{!hideHeader && (
<div className="row justify-content-center mb-30 text-center">
<div className="col-lg-8">
<div className="sec-title text-center">
<div className="sec-title__shape"></div>
<h6 className="sec-title__tagline">OUR BLOGS</h6>
<h3 className="sec-title__title">Latest Blogs Post</h3>
</div>
</div>
</div>
)}
{isSlider ? (
<Slider {...sliderSettings} className="blog-slider-inner">
{currentBlogs.map((blog) => (
<div key={blog.id} className="blog-slider-item px-3">
<div className="blog-style-one relative overflow-hidden">
<Link className="blog-image w-img block relative" href={`/${blog.slug}`}>
<img loading="lazy" src={blog.image} alt={blog.title} />
<span className="blog-category-tag">{blog.category}</span>
</Link>
<div className="blog-content">
<div className="post-meta">
<span className="p-relative"><i className="fa-solid fa-user"></i> By Admin</span>
<span className="p-relative"><i className="fa-solid fa-calendar-days"></i> {blog.date}</span>
</div>
<h5 className="blog-title mb-20 mt-15">
<Link href={`/${blog.slug}`}>{blog.title}</Link>
</h5>
<div className="blog-footer">
<div className="blog-link-learn">
<Link href={`/${blog.slug}`} className="learn-more-link">
Learn More <span>+</span>
</Link>
</div>
</div>
</div>
</div>
</div>
))}
</Slider>
) : (
<div className="row g-4">
{currentBlogs.map((blog) => (
<div key={blog.id} className={columns}>
<div className="blog-style-one relative overflow-hidden">
<Link className="blog-image w-img block relative" href={`/${blog.slug}`}>
<img loading="lazy" src={blog.image} alt={blog.title} />
<span className="blog-category-tag">{blog.category}</span>
</Link>
<div className="blog-content">
<div className="post-meta">
<span className="p-relative"><i className="fa-solid fa-user"></i> By Admin</span>
<span className="p-relative"><i className="fa-solid fa-calendar-days"></i> {blog.date}</span>
</div>
<h5 className="blog-title mb-20 mt-15">
<Link href={`/${blog.slug}`}>{blog.title}</Link>
</h5>
<div className="blog-footer">
<div className="blog-link-learn">
<Link href={`/${blog.slug}`} className="learn-more-link">
Learn More <span>+</span>
</Link>
</div>
</div>
</div>
</div>
</div>
))}
{currentBlogs.length === 0 && (
<div className="col-12 text-center py-5">
<h3 className="no-blog-found">No blogs found matching your criteria.</h3>
</div>
)}
</div>
)}
{isPaginated && totalPages > 1 && (
<div className="pagination-wrapper text-center">
<div className="pagination-items d-flex justify-content-center align-items-center gap-2">
<button
onClick={() => paginate(currentPage - 1)}
disabled={currentPage === 1}
className={`pagination-arrow ${currentPage === 1 ? 'disabled' : ''}`}
suppressHydrationWarning
>
<i className="fa-solid fa-angles-left"></i>
</button>
{renderPageNumbers()}
<button
onClick={() => paginate(currentPage + 1)}
disabled={currentPage === totalPages}
className={`pagination-arrow ${currentPage === totalPages ? 'disabled' : ''}`}
suppressHydrationWarning
>
<i className="fa-solid fa-angles-right"></i>
</button>
</div>
</div>
)}
</div>
</section>
);
};
export default BlogSection;