feat: make blog data dynamic
This commit is contained in:
16
app/api/blogs/route.js
Normal file
16
app/api/blogs/route.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import axios from "axios";
|
||||||
|
import { backendUrl } from "@/utils/axios";
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`${backendUrl}/blogs/`);
|
||||||
|
return NextResponse.json(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching blogs:", error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Failed to fetch blog data" },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
app/api/blogs[slug]/route.js
Normal file
19
app/api/blogs[slug]/route.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import axios from "axios";
|
||||||
|
import { backendUrl } from "@/utils/axios";
|
||||||
|
|
||||||
|
export async function GET(request, { params }) {
|
||||||
|
const { slug } = params;
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log(`API route fetching blog with slug: ${slug}`);
|
||||||
|
const response = await axios.get(`${backendUrl}/blogs/${slug}/`);
|
||||||
|
return NextResponse.json(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error fetching blog with slug ${slug}:`, error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: `Failed to fetch blog: ${error.message}` },
|
||||||
|
{ status: error.response?.status || 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
app/blogs/blog[slug]/page.jsx
Normal file
14
app/blogs/blog[slug]/page.jsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
"use client";
|
||||||
|
import React from "react";
|
||||||
|
import SingleBlog from "@/components/blog/SingleBlog";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
|
||||||
|
export default function BlogPage() {
|
||||||
|
const params = useParams();
|
||||||
|
const slug = params?.["blog-id"];
|
||||||
|
|
||||||
|
console.log("BlogPage params:", params);
|
||||||
|
console.log("BlogPage slug:", slug);
|
||||||
|
|
||||||
|
return <SingleBlog slug={slug} />;
|
||||||
|
}
|
||||||
@@ -2,11 +2,11 @@ export const DASHBOARD = {
|
|||||||
"images": [
|
"images": [
|
||||||
{
|
{
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 2,
|
"id": 2,
|
||||||
"path": "page_images/2.jpg",
|
"path": "/page_images/2.jpg",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"heading1": "Explore Gupta Rudraksha",
|
"heading1": "Explore Gupta Rudraksha",
|
||||||
@@ -19,35 +19,35 @@ export const DASHBOARD = {
|
|||||||
"title": "Since 1973",
|
"title": "Since 1973",
|
||||||
"image": {
|
"image": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Vedic Energization",
|
"title": "Vedic Energization",
|
||||||
"image": {
|
"image": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Lab Certification",
|
"title": "Lab Certification",
|
||||||
"image": {
|
"image": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "ISO 9001:2015 certified",
|
"title": "ISO 9001:2015 certified",
|
||||||
"image": {
|
"image": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Secure Payment",
|
"title": "Secure Payment",
|
||||||
"image": {
|
"image": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -58,21 +58,21 @@ export const DASHBOARD = {
|
|||||||
{
|
{
|
||||||
"image": {
|
"image": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
"title": "Spirituality",
|
"title": "Spirituality",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"image": {
|
"image": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
"title": "Meditation",
|
"title": "Meditation",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"image": {
|
"image": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
"title": "Wellness",
|
"title": "Wellness",
|
||||||
},
|
},
|
||||||
@@ -84,11 +84,11 @@ export const DASHBOARD = {
|
|||||||
"heading8": "Gupta Rudraksha - The Only Vendor in the World To 100% Lifetime Money Back Authenticity Guarantee.",
|
"heading8": "Gupta Rudraksha - The Only Vendor in the World To 100% Lifetime Money Back Authenticity Guarantee.",
|
||||||
"footer_image1": {
|
"footer_image1": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
"footer_image2": {
|
"footer_image2": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ export const CONSULTATION = {
|
|||||||
"description": "Enhance personal growth, gain clarity, and overcome obstacles.",
|
"description": "Enhance personal growth, gain clarity, and overcome obstacles.",
|
||||||
"image": {
|
"image": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -120,7 +120,7 @@ export const CONSULTATION = {
|
|||||||
"description": "Scale your business, improve operations, and navigate challenges.",
|
"description": "Scale your business, improve operations, and navigate challenges.",
|
||||||
"image": {
|
"image": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -128,7 +128,7 @@ export const CONSULTATION = {
|
|||||||
"description": "Plan your career, enhance job search strategies, and build professional skills.",
|
"description": "Plan your career, enhance job search strategies, and build professional skills.",
|
||||||
"image": {
|
"image": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -136,7 +136,7 @@ export const CONSULTATION = {
|
|||||||
"description": "Navigate significant life changes and find new directions for personal fulfillment.",
|
"description": "Navigate significant life changes and find new directions for personal fulfillment.",
|
||||||
"image": {
|
"image": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -144,7 +144,7 @@ export const CONSULTATION = {
|
|||||||
"description": "Optimize health, wellness, and live a balanced lifestyle.",
|
"description": "Optimize health, wellness, and live a balanced lifestyle.",
|
||||||
"image": {
|
"image": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -152,7 +152,7 @@ export const CONSULTATION = {
|
|||||||
"description": "Resolve conflicts, improve communication, and build healthier relationships.",
|
"description": "Resolve conflicts, improve communication, and build healthier relationships.",
|
||||||
"image": {
|
"image": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -160,7 +160,7 @@ export const CONSULTATION = {
|
|||||||
"description": "Optimize finances, plan for retirement, and grow wealth.",
|
"description": "Optimize finances, plan for retirement, and grow wealth.",
|
||||||
"image": {
|
"image": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -168,7 +168,7 @@ export const CONSULTATION = {
|
|||||||
"description": "Overcome feeling stuck, gain perspective, and find purpose.",
|
"description": "Overcome feeling stuck, gain perspective, and find purpose.",
|
||||||
"image": {
|
"image": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -179,11 +179,11 @@ export const CONSULTATION = {
|
|||||||
"description": "Consultation provides access to expert advice and guidance from professionals who have in-depth knowledge and experience in their respective fields. We can offer valuable insights, strategies, and solutions tailored to your specific needs.",
|
"description": "Consultation provides access to expert advice and guidance from professionals who have in-depth knowledge and experience in their respective fields. We can offer valuable insights, strategies, and solutions tailored to your specific needs.",
|
||||||
"image1": {
|
"image1": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
"image2": {
|
"image2": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -191,11 +191,11 @@ export const CONSULTATION = {
|
|||||||
"description": "Rudraksha experts can recommend specific mantras that align with your spiritual goals and intentions. Mantras are considered powerful tools for spiritual growth, and the right mantra can enhance the effectiveness of your Rudraksha.",
|
"description": "Rudraksha experts can recommend specific mantras that align with your spiritual goals and intentions. Mantras are considered powerful tools for spiritual growth, and the right mantra can enhance the effectiveness of your Rudraksha.",
|
||||||
"image1": {
|
"image1": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
"image2": {
|
"image2": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -203,11 +203,11 @@ export const CONSULTATION = {
|
|||||||
"description": "Rudraksha experts may also have knowledge of Vedic astrology. By analyzing your birth chart, they can provide insights into the planetary influences on your life and suggest Rudraksha combinations that may help balance and harmonize these influences.",
|
"description": "Rudraksha experts may also have knowledge of Vedic astrology. By analyzing your birth chart, they can provide insights into the planetary influences on your life and suggest Rudraksha combinations that may help balance and harmonize these influences.",
|
||||||
"image1": {
|
"image1": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
"image2": {
|
"image2": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -215,11 +215,11 @@ export const CONSULTATION = {
|
|||||||
"description": "Understanding the birth charts of family members can offer a holistic view of the energy dynamics within the family. Rudraksha experts can provide guidance on selecting Rudraksha beads that complement the energy of the entire family, fostering a harmonious environment.",
|
"description": "Understanding the birth charts of family members can offer a holistic view of the energy dynamics within the family. Rudraksha experts can provide guidance on selecting Rudraksha beads that complement the energy of the entire family, fostering a harmonious environment.",
|
||||||
"image1": {
|
"image1": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
"image2": {
|
"image2": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -227,11 +227,11 @@ export const CONSULTATION = {
|
|||||||
"description": "Understanding the birth charts of family members can offer a holistic view of the energy dynamics within the family. Rudraksha experts can provide guidance on selecting Rudraksha beads that complement the energy of the entire family, fostering a harmonious environment.",
|
"description": "Understanding the birth charts of family members can offer a holistic view of the energy dynamics within the family. Rudraksha experts can provide guidance on selecting Rudraksha beads that complement the energy of the entire family, fostering a harmonious environment.",
|
||||||
"image1": {
|
"image1": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
"image2": {
|
"image2": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -239,11 +239,11 @@ export const CONSULTATION = {
|
|||||||
"description": "Understanding the birth charts of family members can offer a holistic view of the energy dynamics within the family. Rudraksha experts can provide guidance on selecting Rudraksha beads that complement the energy of the entire family, fostering a harmonious environment.",
|
"description": "Understanding the birth charts of family members can offer a holistic view of the energy dynamics within the family. Rudraksha experts can provide guidance on selecting Rudraksha beads that complement the energy of the entire family, fostering a harmonious environment.",
|
||||||
"image1": {
|
"image1": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
"image2": {
|
"image2": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"path": "page_images/1.jpg",
|
"path": "/page_images/1.jpg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,39 +1,55 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import React, { useState } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Card, CardHeader, CardContent } from "@/components/ui/card";
|
import { Card, CardHeader, CardContent } from "@/components/ui/card";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Image from "next/image";
|
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 }) => (
|
const BlogPost = ({ title, author, date, excerpt, imageUrl, slug }) => {
|
||||||
<div className="mb-6 flex sm:flex-row flex-col">
|
const sanitizedExcerpt = DOMPurify.sanitize(excerpt);
|
||||||
<div className=" h-full bg-purple-100 sm:w-1/2">
|
|
||||||
<Link href={`/blogs/blog/${title}`}>
|
const formattedImageUrl = imageUrl !== "NA"
|
||||||
<Image
|
? (imageUrl.startsWith('http') ? imageUrl : `${backendUrl}${imageUrl}`)
|
||||||
src={imageUrl}
|
: "/api/placeholder/300/200";
|
||||||
alt={title || "Image"}
|
|
||||||
className="object-cover rounded-md"
|
return (
|
||||||
layout="responsive"
|
<div className="mb-6 flex sm:flex-row flex-col">
|
||||||
width={500}
|
<div className=" h-full bg-purple-100 sm:w-1/2">
|
||||||
height={300}
|
<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 }}
|
||||||
/>
|
/>
|
||||||
</Link>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="sm:w-2/3 p-4">
|
);
|
||||||
<Link href={`/blogs/blog/${title}`}>
|
};
|
||||||
<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>
|
|
||||||
<p className="text-sm">{excerpt}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const PopularArticle = ({ title, author, date }) => (
|
const PopularArticle = ({ title, author, date, slug }) => (
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<h4 className="font-semibold">{title}</h4>
|
<Link href={`/blogs/blog/${slug}`}>
|
||||||
|
<h4 className="font-semibold">{title}</h4>
|
||||||
|
</Link>
|
||||||
<p className="text-sm text-gray-500">
|
<p className="text-sm text-gray-500">
|
||||||
{author} | {date}
|
{author} | {date}
|
||||||
</p>
|
</p>
|
||||||
@@ -42,63 +58,77 @@ const PopularArticle = ({ title, author, date }) => (
|
|||||||
|
|
||||||
const BlogHome = () => {
|
const BlogHome = () => {
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
|
const [blogData, setBlogData] = useState({
|
||||||
|
recentBlogPosts: [],
|
||||||
|
popularArticles: []
|
||||||
|
});
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState(null);
|
||||||
const postsPerPage = 3;
|
const postsPerPage = 3;
|
||||||
|
|
||||||
const recentBlogPosts = [
|
useEffect(() => {
|
||||||
{
|
const fetchBlogData = async () => {
|
||||||
title: "Benefits of Wearing Rudraksha Mala",
|
try {
|
||||||
author: "Gupta Rudraksha",
|
setLoading(true);
|
||||||
date: "29 August, 2024",
|
const response = await axios.get(`${backendUrl}/blogs/`);
|
||||||
excerpt:
|
setBlogData(response.data);
|
||||||
"Rudraksha are sacred beads of great significance in Hinduism and various spiritual practices. The term Rudraksha combines two Sanskrit words: 'Rudra,' another name for Lord Sh...",
|
setLoading(false);
|
||||||
imageUrl: "/blogs/significance-of-dhanteras.webp",
|
} catch (err) {
|
||||||
},
|
console.error("Error fetching blog data:", err);
|
||||||
{
|
setError("Failed to load blog data. Please try again later.");
|
||||||
title: "Shravan Maas for Spiritual Growth and Divine Connection",
|
setLoading(false);
|
||||||
author: "Gupta Rudraksha",
|
}
|
||||||
date: "04 September, 2024",
|
};
|
||||||
excerpt:
|
|
||||||
"Shrawan Mass, a sacred month in the Hindu calendar, holds deep spiritual significance for millions of devotees. But what exactly is Shravan Maas, and why is it so important? Let...",
|
|
||||||
imageUrl: "/blogs/navaratri-siginificance.webp",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "The Complete Guide to Rudraksha Energization",
|
|
||||||
author: "Gupta Rudraksha",
|
|
||||||
date: "28 August, 2024",
|
|
||||||
excerpt:
|
|
||||||
"For centuries, Rudraksha beads have been valued not only for their aesthetic beauty, but also for their powerful spiritual and healing properties. Whether you're a seasoned prac...",
|
|
||||||
imageUrl: "/blogs/rudraksha-pran-pratishtha-pooja.webp",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Strengthening Planetary Forces with Rudraksha",
|
|
||||||
author: "Gupta Rudraksha",
|
|
||||||
date: "26 April, 2024",
|
|
||||||
excerpt:
|
|
||||||
"In the vast universe, planets hold immense power over our lives, influencing everything from our moods to our destinies. However, Rudraksha beads, ancient treasures from the ear...",
|
|
||||||
imageUrl: "/api/placeholder/300/200",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const popularArticles = [
|
fetchBlogData();
|
||||||
{
|
}, []);
|
||||||
title: "Dhanteras Significance and How Rudraksha Brings Prosperity",
|
|
||||||
author: "Gupta Rudraksha",
|
// Get featured blog (first blog from recent posts)
|
||||||
date: "30 September, 2024",
|
const featuredBlog = blogData.recentBlogPosts && blogData.recentBlogPosts.length > 0
|
||||||
},
|
? blogData.recentBlogPosts[0]
|
||||||
{
|
: null;
|
||||||
title:
|
|
||||||
"Certified Rudraksha: Nepal's 1st ISO 9001:2015 Certified Organization",
|
// Get remaining blogs for pagination
|
||||||
author: "Gupta Admin",
|
const remainingBlogs = blogData.recentBlogPosts && blogData.recentBlogPosts.length > 0
|
||||||
date: "30 September, 2024",
|
? blogData.recentBlogPosts.slice(1)
|
||||||
},
|
: [];
|
||||||
];
|
|
||||||
|
|
||||||
const indexOfLastPost = currentPage * postsPerPage;
|
const indexOfLastPost = currentPage * postsPerPage;
|
||||||
const indexOfFirstPost = indexOfLastPost - postsPerPage;
|
const indexOfFirstPost = indexOfLastPost - postsPerPage;
|
||||||
const currentPosts = recentBlogPosts.slice(indexOfFirstPost, indexOfLastPost);
|
const currentPosts = remainingBlogs.slice(indexOfFirstPost, indexOfLastPost);
|
||||||
|
|
||||||
const paginate = (pageNumber) => setCurrentPage(pageNumber);
|
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 for updates on Rudraksha and spiritual practices.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container max-w-8xl mx-auto sm:px-20 px-3 ">
|
<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">
|
<h1 className="sm:text-5xl pt-3 text-3xl font-bold mb-8">
|
||||||
@@ -108,73 +138,88 @@ const BlogHome = () => {
|
|||||||
Explore our latest articles on the spiritual, cultural, and healing
|
Explore our latest articles on the spiritual, cultural, and healing
|
||||||
aspects
|
aspects
|
||||||
</p>
|
</p>
|
||||||
{/* top container for one blog card */}
|
|
||||||
<dir 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/`}>
|
|
||||||
<Image
|
|
||||||
src="/blogs/significance-of-dhanteras.webp"
|
|
||||||
alt="images blog"
|
|
||||||
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/`}>
|
|
||||||
<h3 className="text-xl sm:text-2xl font-bold">
|
|
||||||
Dhanteras Significance and How Rudraksha Brings Prosperity and
|
|
||||||
Protection
|
|
||||||
</h3>
|
|
||||||
</Link>
|
|
||||||
<p className="text-sm sm:text-lg text-gray-500 mb-2">
|
|
||||||
Gupta Rudraksha | 30 September, 2024
|
|
||||||
</p>
|
|
||||||
<p className="text-sm py-4 line-clamp-2">
|
|
||||||
Dhanteras, the first day of Diwali festival, marks a unique
|
|
||||||
celebration of wealth and prosperity in Hindu tradition. As the
|
|
||||||
name suggests - 'Dhan' meaning wealth and
|
|
||||||
'Teras' ref
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="w-full lg:w-1/3 px-4">
|
|
||||||
<h2 className="text-2xl font-bold mb-4">Popular Articles</h2>
|
|
||||||
{popularArticles.map((article, index) => (
|
|
||||||
<PopularArticle key={index} {...article} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</dir>
|
|
||||||
|
|
||||||
<div className="flex flex-wrap -mx-4">
|
{/* Featured blog section */}
|
||||||
<div className="w-full lg:w-2/3 px-4">
|
{featuredBlog && (
|
||||||
<h2 className="sm:text-4xl text-2xl font-bold mb-4">Recent Blogs</h2>
|
<div className="min-h-[30vh] flex sm:flex-row flex-col-reverse">
|
||||||
{currentPosts.map((post, index) => (
|
<div className="mb-6 flex sm:flex-row flex-col">
|
||||||
<BlogPost key={index} {...post} />
|
<div className="h-full bg-purple-100">
|
||||||
))}
|
<Link href={`/blogs/blog/${featuredBlog.slug}`}>
|
||||||
<div className="flex justify-center space-x-2 mb-8 items-center pt-6">
|
<Image
|
||||||
{[...Array(Math.ceil(recentBlogPosts.length / postsPerPage))].map(
|
src={featuredImageUrl}
|
||||||
(_, index) => (
|
alt={featuredBlog.title}
|
||||||
<Button
|
layout="intrinsic"
|
||||||
key={index}
|
width={600}
|
||||||
onClick={() => paginate(index + 1)}
|
height={400}
|
||||||
variant={currentPage === index + 1 ? "default" : "outline"}
|
className="object-cover rounded-md"
|
||||||
>
|
/>
|
||||||
{index + 1}
|
</Link>
|
||||||
</Button>
|
</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>
|
</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">
|
<div className="w-full lg:w-1/3 px-4">
|
||||||
<h2 className="text-2xl font-bold mb-4">Popular Articles</h2>
|
<h2 className="text-2xl font-bold mb-4">Popular Articles</h2>
|
||||||
{popularArticles.map((article, index) => (
|
{blogData.popularArticles && blogData.popularArticles.length > 0 ? (
|
||||||
<PopularArticle key={index} {...article} />
|
blogData.popularArticles.map((article, index) => (
|
||||||
))}
|
<PopularArticle key={index} {...article} />
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<p className="text-gray-500">No popular articles available</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,43 +2,120 @@
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import "./blog.css";
|
import "./blog.css";
|
||||||
|
import axios from "axios";
|
||||||
|
import { backendUrl } from "@/utils/axios";
|
||||||
|
import DOMPurify from 'dompurify';
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const SingleBlog = () => {
|
const SingleBlog = () => {
|
||||||
const [blogResData, setResData] = useState(null);
|
const [blog, setBlog] = useState(null);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState(null);
|
||||||
|
|
||||||
|
// Debug log to check if slug is received
|
||||||
|
const params = useParams();
|
||||||
|
|
||||||
|
console.log("BlogPage params:", params);
|
||||||
|
console.log("SingleBlog received slug:", params?.["blog-id"]);
|
||||||
|
const slug = params?.["blog-id"]
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
const fetchBlogData = async () => {
|
||||||
|
if (!slug) {
|
||||||
|
console.error("No slug provided");
|
||||||
|
setError("Blog not found. Missing identifier.");
|
||||||
|
setLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch("/api/blog");
|
console.log(`Fetching blog with slug: ${slug}`);
|
||||||
const blog = await response.json();
|
setLoading(true);
|
||||||
setResData(blog.blogdata);
|
|
||||||
} catch (error) {
|
// Log the full URL being called for debugging
|
||||||
console.error("Error fetching blog data:", error);
|
const url = `${backendUrl}/blogs/${slug}/`;
|
||||||
|
console.log(`Making API call to: ${url}`);
|
||||||
|
|
||||||
|
const response = await axios.get(url);
|
||||||
|
console.log("API response:", response.data);
|
||||||
|
|
||||||
|
if (response.data) {
|
||||||
|
setBlog(response.data);
|
||||||
|
} else {
|
||||||
|
setError("No blog data received from server");
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error fetching blog data:", err);
|
||||||
|
setError(`Failed to load blog content: ${err.message || "Unknown error"}`);
|
||||||
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
fetchData();
|
|
||||||
}, []);
|
fetchBlogData();
|
||||||
|
}, [slug]);
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return (
|
||||||
|
<div className="max-w-4xl mx-auto p-5 text-center">
|
||||||
|
<p className="text-gray-500">Loading blog content for slug: {slug}...</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<div className="max-w-4xl mx-auto p-5 text-center">
|
||||||
|
<p className="text-red-500">Error: {error}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!blog) {
|
||||||
|
return (
|
||||||
|
<div className="max-w-4xl mx-auto p-5 text-center">
|
||||||
|
<p className="text-gray-500">Blog not found for slug: {slug}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format the image URL
|
||||||
|
const imageUrl = blog.imageUrl !== "NA"
|
||||||
|
? (blog.imageUrl.startsWith('http') ? blog.imageUrl : `${backendUrl}${blog.imageUrl}`)
|
||||||
|
: "/api/placeholder/800/500";
|
||||||
|
|
||||||
|
// Sanitize the blog description
|
||||||
|
const sanitizedDescription = DOMPurify.sanitize(blog.description);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-4xl mx-auto p-5 space-y-6 bg-white shadow-lg rounded-lg">
|
<div className="max-w-4xl mx-auto p-5 space-y-6 bg-white shadow-lg rounded-lg">
|
||||||
|
{/* Blog Title */}
|
||||||
|
<h1 className="text-3xl font-bold text-center mb-6">{blog.title}</h1>
|
||||||
|
|
||||||
|
{/* Blog Meta Information */}
|
||||||
|
<div className="text-center text-gray-600 mb-6">
|
||||||
|
<p>{blog.author} | {blog.date}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Blog Image */}
|
{/* Blog Image */}
|
||||||
<div className="w-full flex justify-center">
|
<div className="w-full flex justify-center">
|
||||||
<Image
|
<Image
|
||||||
src={"/blogs/significance-of-dhanteras.webp"}
|
src={imageUrl}
|
||||||
height={500}
|
height={500}
|
||||||
width={800}
|
width={800}
|
||||||
alt="Blog Cover Image"
|
alt={blog.title || "Blog Cover Image"}
|
||||||
className="rounded-lg object-cover"
|
className="rounded-lg object-cover"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Blog Content */}
|
{/* Blog Content */}
|
||||||
<div className="prose lg:prose-xl mx-auto text-gray-800 leading-relaxed">
|
<div className="prose lg:prose-xl mx-auto text-gray-800 leading-relaxed">
|
||||||
{blogResData ? (
|
<div
|
||||||
<div dangerouslySetInnerHTML={{ __html: blogResData }} />
|
className="blog-content"
|
||||||
) : (
|
dangerouslySetInnerHTML={{ __html: sanitizedDescription }}
|
||||||
<p className="text-center text-gray-500">Loading blog content...</p>
|
/>
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
17
package-lock.json
generated
17
package-lock.json
generated
@@ -19,6 +19,7 @@
|
|||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"dompurify": "^3.2.5",
|
||||||
"embla-carousel-autoplay": "^8.3.0",
|
"embla-carousel-autoplay": "^8.3.0",
|
||||||
"embla-carousel-react": "^8.3.0",
|
"embla-carousel-react": "^8.3.0",
|
||||||
"framer-motion": "^12.0.6",
|
"framer-motion": "^12.0.6",
|
||||||
@@ -1807,6 +1808,13 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/trusted-types": {
|
||||||
|
"version": "2.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
|
||||||
|
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.6.0",
|
"version": "8.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.6.0.tgz",
|
||||||
@@ -2833,6 +2841,15 @@
|
|||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dompurify": {
|
||||||
|
"version": "3.2.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.5.tgz",
|
||||||
|
"integrity": "sha512-mLPd29uoRe9HpvwP2TxClGQBzGXeEC/we/q+bFlmPPmj2p2Ugl3r6ATu/UU1v77DXNcehiBg9zsr1dREyA/dJQ==",
|
||||||
|
"license": "(MPL-2.0 OR Apache-2.0)",
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@types/trusted-types": "^2.0.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eastasianwidth": {
|
"node_modules/eastasianwidth": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"dompurify": "^3.2.5",
|
||||||
"embla-carousel-autoplay": "^8.3.0",
|
"embla-carousel-autoplay": "^8.3.0",
|
||||||
"embla-carousel-react": "^8.3.0",
|
"embla-carousel-react": "^8.3.0",
|
||||||
"framer-motion": "^12.0.6",
|
"framer-motion": "^12.0.6",
|
||||||
|
|||||||
Reference in New Issue
Block a user