229 lines
7.8 KiB
JavaScript
229 lines
7.8 KiB
JavaScript
"use client";
|
|
import React, { useState, useEffect } from "react";
|
|
import { Card, CardHeader, CardContent } from "@/components/ui/card";
|
|
import { Button } from "@/components/ui/button";
|
|
import Link from "next/link";
|
|
import Image from "next/image";
|
|
import axios from "axios";
|
|
import { backendUrl } from "@/utils/axios";
|
|
import DOMPurify from 'dompurify';
|
|
|
|
const BlogPost = ({ title, author, date, excerpt, imageUrl, slug }) => {
|
|
const sanitizedExcerpt = DOMPurify.sanitize(excerpt);
|
|
|
|
const formattedImageUrl = imageUrl !== "NA"
|
|
? (imageUrl.startsWith('http') ? imageUrl : `${backendUrl}${imageUrl}`)
|
|
: "/api/placeholder/300/200";
|
|
|
|
return (
|
|
<div className="mb-6 flex sm:flex-row flex-col">
|
|
<div className=" h-full bg-purple-100 sm:w-1/2">
|
|
<Link href={`/blogs/blog/${slug}`}>
|
|
<Image
|
|
src={formattedImageUrl}
|
|
alt={title || "Image"}
|
|
className="object-cover rounded-md"
|
|
layout="responsive"
|
|
width={500}
|
|
height={300}
|
|
/>
|
|
</Link>
|
|
</div>
|
|
<div className="sm:w-2/3 p-4">
|
|
<Link href={`/blogs/blog/${slug}`}>
|
|
<h3 className="text-xl sm:text-2xl font-bold">{title}</h3>
|
|
</Link>
|
|
<p className="text-sm sm:text-lg text-gray-500 mb-2">
|
|
{author} | {date}
|
|
</p>
|
|
<div
|
|
className="text-sm blog-content"
|
|
dangerouslySetInnerHTML={{ __html: sanitizedExcerpt }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const PopularArticle = ({ title, author, date, slug }) => (
|
|
<div className="mb-4">
|
|
<Link href={`/blogs/blog/${slug}`}>
|
|
<h4 className="font-semibold">{title}</h4>
|
|
</Link>
|
|
<p className="text-sm text-gray-500">
|
|
{author} | {date}
|
|
</p>
|
|
</div>
|
|
);
|
|
|
|
const BlogHome = () => {
|
|
const [currentPage, setCurrentPage] = useState(1);
|
|
const [blogData, setBlogData] = useState({
|
|
recentBlogPosts: [],
|
|
popularArticles: []
|
|
});
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState(null);
|
|
const postsPerPage = 3;
|
|
|
|
useEffect(() => {
|
|
const fetchBlogData = async () => {
|
|
try {
|
|
setLoading(true);
|
|
const response = await axios.get(`${backendUrl}/blogs/`);
|
|
setBlogData(response.data);
|
|
setLoading(false);
|
|
} catch (err) {
|
|
console.error("Error fetching blog data:", err);
|
|
setError("Failed to load blog data. Please try again later.");
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
fetchBlogData();
|
|
}, []);
|
|
|
|
// Get featured blog (first blog from recent posts)
|
|
const featuredBlog = blogData.recentBlogPosts && blogData.recentBlogPosts.length > 0
|
|
? blogData.recentBlogPosts[0]
|
|
: null;
|
|
|
|
// Get remaining blogs for pagination
|
|
const remainingBlogs = blogData.recentBlogPosts && blogData.recentBlogPosts.length > 0
|
|
? blogData.recentBlogPosts.slice(1)
|
|
: [];
|
|
|
|
const indexOfLastPost = currentPage * postsPerPage;
|
|
const indexOfFirstPost = indexOfLastPost - postsPerPage;
|
|
const currentPosts = remainingBlogs.slice(indexOfFirstPost, indexOfLastPost);
|
|
|
|
const paginate = (pageNumber) => setCurrentPage(pageNumber);
|
|
|
|
const featuredImageUrl = featuredBlog && featuredBlog.imageUrl !== "NA"
|
|
? (featuredBlog.imageUrl.startsWith('http') ? featuredBlog.imageUrl : `${backendUrl}${featuredBlog.imageUrl}`)
|
|
: "/api/placeholder/300/200";
|
|
|
|
if (loading) {
|
|
return <div className="container mx-auto px-4 py-8">Loading blogs...</div>;
|
|
}
|
|
|
|
if (error) {
|
|
return <div className="container mx-auto px-4 py-8 text-red-500">{error}</div>;
|
|
}
|
|
|
|
// Check if there are no blogs at all
|
|
if (!blogData.recentBlogPosts || blogData.recentBlogPosts.length === 0) {
|
|
return (
|
|
<div className="container max-w-8xl mx-auto sm:px-20 px-3 py-20 text-center">
|
|
<h1 className="sm:text-5xl pt-3 text-3xl font-bold mb-8">
|
|
Insights from Gupta Rudraksha
|
|
</h1>
|
|
<div className="bg-gray-100 p-10 rounded-lg shadow-md">
|
|
<h2 className="text-2xl font-semibold text-gray-700 mb-4">No Blogs Found</h2>
|
|
<p className="text-gray-600">
|
|
We're currently working on creating insightful content for you. Please check back later.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="container max-w-8xl mx-auto sm:px-20 px-3 ">
|
|
<h1 className="sm:text-5xl pt-3 text-3xl font-bold mb-8">
|
|
Insights from Gupta Rudraksha
|
|
</h1>
|
|
<p className="sm:text-2xl text-lg ">
|
|
Explore our latest articles on the spiritual, cultural, and healing
|
|
aspects
|
|
</p>
|
|
|
|
{/* Featured blog section */}
|
|
{featuredBlog && (
|
|
<div className="min-h-[30vh] flex sm:flex-row flex-col-reverse">
|
|
<div className="mb-6 flex sm:flex-row flex-col">
|
|
<div className="h-full bg-purple-100">
|
|
<Link href={`/blogs/blog/${featuredBlog.slug}`}>
|
|
<Image
|
|
src={featuredImageUrl}
|
|
alt={featuredBlog.title}
|
|
layout="intrinsic"
|
|
width={600}
|
|
height={400}
|
|
className="object-cover rounded-md"
|
|
/>
|
|
</Link>
|
|
</div>
|
|
<div className="sm:w-2/3 p-4">
|
|
<Link href={`/blogs/blog/${featuredBlog.slug}`}>
|
|
<h3 className="text-xl sm:text-2xl font-bold">
|
|
{featuredBlog.title}
|
|
</h3>
|
|
</Link>
|
|
<p className="text-sm sm:text-lg text-gray-500 mb-2">
|
|
{featuredBlog.author} | {featuredBlog.date}
|
|
</p>
|
|
<div
|
|
className="text-sm py-4 line-clamp-2 blog-content"
|
|
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(featuredBlog.excerpt) }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className="w-full lg:w-1/3 px-4">
|
|
<h2 className="text-2xl font-bold mb-4">Popular Articles</h2>
|
|
{blogData.popularArticles && blogData.popularArticles.length > 0 ? (
|
|
blogData.popularArticles.map((article, index) => (
|
|
<PopularArticle key={index} {...article} />
|
|
))
|
|
) : (
|
|
<p className="text-gray-500">No popular articles available</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<div className="flex flex-wrap -mx-4">
|
|
<div className="w-full lg:w-2/3 px-4">
|
|
<h2 className="sm:text-4xl text-2xl font-bold mb-4">Recent Blogs</h2>
|
|
{currentPosts.length > 0 ? (
|
|
currentPosts.map((post, index) => (
|
|
<BlogPost key={post.id || index} {...post} />
|
|
))
|
|
) : (
|
|
<p className="text-gray-500 py-4">No recent blogs available</p>
|
|
)}
|
|
|
|
{remainingBlogs.length > postsPerPage && (
|
|
<div className="flex justify-center space-x-2 mb-8 items-center pt-6">
|
|
{[...Array(Math.ceil(remainingBlogs.length / postsPerPage))].map(
|
|
(_, index) => (
|
|
<Button
|
|
key={index}
|
|
onClick={() => paginate(index + 1)}
|
|
variant={currentPage === index + 1 ? "default" : "outline"}
|
|
>
|
|
{index + 1}
|
|
</Button>
|
|
)
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="w-full lg:w-1/3 px-4">
|
|
<h2 className="text-2xl font-bold mb-4">Popular Articles</h2>
|
|
{blogData.popularArticles && blogData.popularArticles.length > 0 ? (
|
|
blogData.popularArticles.map((article, index) => (
|
|
<PopularArticle key={index} {...article} />
|
|
))
|
|
) : (
|
|
<p className="text-gray-500">No popular articles available</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default BlogHome;
|