Skip to content

Commit f881d1a

Browse files
committed
Blogs Page Added
1 parent be19943 commit f881d1a

File tree

8 files changed

+710
-106
lines changed

8 files changed

+710
-106
lines changed

Frontend/src/App.jsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ import ManageFaqs from "./pages/ADMIN/ManageFaqs";
5858
import { AdminAuthProvider } from "./context/ADMIN/AdminAuthContext";
5959
import { AdminOrdersProvider } from "./context/ADMIN/AdminOrdersContext";
6060
import { AdminUsersProvider } from "./context/ADMIN/AdminUsersContext";
61+
import BlogDetail from "./components/CLIENT/Blog/BlogDetail";
6162

6263
const router = createBrowserRouter([
6364
{
@@ -100,6 +101,10 @@ const router = createBrowserRouter([
100101
path: "/blog",
101102
element: <BlogPage />,
102103
},
104+
{
105+
path: "/blog/:id",
106+
element: <BlogDetail />,
107+
},
103108
{
104109
path: "/plant/description/:plantId",
105110
element: <DescriptionLayout />,
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React from "react";
2+
import { Link } from "react-router-dom";
3+
4+
const BlogCard = ({ id, imageUrl, title, description }) => {
5+
return (
6+
<div className="bg-white rounded-lg shadow-md overflow-hidden hover:shadow-lg transition">
7+
<img
8+
src={imageUrl}
9+
alt={title}
10+
className="w-full h-48 md:h-64 object-cover"
11+
/>
12+
<div className="p-4">
13+
<h3 className="text-lg font-semibold mb-2">{title}</h3>
14+
<p className="text-sm text-gray-600 mb-4">{description}</p>
15+
<Link
16+
to={`/blog/${id}`}
17+
className="bg-green-600 text-white px-4 py-2 rounded-full text-xs hover:bg-green-700 transition"
18+
>
19+
Read More
20+
</Link>
21+
</div>
22+
</div>
23+
);
24+
};
25+
26+
export default BlogCard;
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import React from "react";
2+
import { useParams, Link } from "react-router-dom";
3+
import blogData from "./blogData";
4+
5+
const BlogDetail = () => {
6+
const { id } = useParams();
7+
const blog = blogData.find((b) => b.id === Number(id));
8+
9+
if (!blog) {
10+
return (
11+
<div className="text-center py-20">
12+
<h1 className="text-3xl font-bold text-red-600">Blog Not Found</h1>
13+
<p className="text-gray-600 mt-2">Sorry, we couldn't find this blog.</p>
14+
<Link
15+
to="/blog"
16+
className="mt-4 inline-block text-green-600 underline hover:text-green-800"
17+
>
18+
← Go back to Blog Page
19+
</Link>
20+
</div>
21+
);
22+
}
23+
24+
return (
25+
<>
26+
{/* Back link */}
27+
<div className="mt-8 ">
28+
<Link
29+
to="/blog"
30+
className="text-green-600 underline hover:text-green-800 ml-5 flex justify-start"
31+
>
32+
← Back to all blogs
33+
</Link>
34+
<div className="px-4 md:px-12 py-10 max-w-4xl mx-auto">
35+
{/* Image */}
36+
<div className="mb-6">
37+
<div className="max-w-md mx-auto rounded-md overflow-hidden">
38+
<img
39+
src={blog.imageUrl}
40+
alt={blog.title}
41+
className="w-full h-auto object-cover rounded-lg shadow"
42+
/>
43+
</div>
44+
</div>
45+
46+
{/* Title and Content */}
47+
<h1 className="text-xl md:text-2xl lg:text-3xl font-bold text-green-700 mb-4 text-center">
48+
{blog.title}
49+
</h1>
50+
<div className="text-gray-800 leading-relaxed">
51+
{/* Iterate over the fullContent array to render each block */}
52+
{blog.fullContent.map((block, index) => {
53+
if (block.type === "paragraph") {
54+
// Render a paragraph, using dangerouslySetInnerHTML for potential HTML like strong tags
55+
return (
56+
<p
57+
key={index}
58+
className="mb-4"
59+
dangerouslySetInnerHTML={{ __html: block.content }}
60+
/>
61+
);
62+
} else if (block.type === "heading") {
63+
// Dynamically render h2, h3, etc., for headings
64+
const HeadingTag = `h${block.level || 3}`; // Default to h3 if level is not specified
65+
return (
66+
<HeadingTag
67+
key={index}
68+
className="text-lg md:text-xl font-bold text-green-600 mt-6 mb-3"
69+
dangerouslySetInnerHTML={{ __html: block.content }}
70+
/>
71+
);
72+
} else if (block.type === "list") {
73+
// Render an unordered list
74+
return (
75+
<ul key={index} className="list-disc pl-5 mb-4">
76+
{block.items.map((item, itemIndex) => (
77+
<li
78+
key={itemIndex}
79+
className="mb-2"
80+
dangerouslySetInnerHTML={{ __html: item }}
81+
/>
82+
))}
83+
</ul>
84+
);
85+
} else if (block.type === "separator") {
86+
// Render a horizontal rule for separators
87+
return <hr key={index} className="my-8 border-gray-300" />;
88+
}
89+
return null; // Return null for any unhandled block types
90+
})}
91+
</div>
92+
</div>
93+
</div>
94+
</>
95+
);
96+
};
97+
98+
export default BlogDetail;
File renamed without changes.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import React, { useEffect, useState } from "react";
2+
import BlogCard from "./BlogCard";
3+
import blogData from "./blogData";
4+
5+
const BlogSection = () => {
6+
const [blogs, setBlogs] = useState([]);
7+
8+
useEffect(() => {
9+
setBlogs(blogData);
10+
}, []);
11+
12+
return (
13+
<div className="px-4 md:px-8 lg:px-16 py-8 bg-gray-50">
14+
<div className="max-w-7xl mx-auto">
15+
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
16+
{blogs.map((blog) => (
17+
<BlogCard
18+
key={blog.id}
19+
id={blog.id}
20+
imageUrl={blog.imageUrl}
21+
title={blog.title}
22+
description={blog.description}
23+
/>
24+
))}
25+
</div>
26+
</div>
27+
</div>
28+
);
29+
};
30+
31+
export default BlogSection;

0 commit comments

Comments
 (0)