diff --git a/public/blog_cover_poster.png b/public/blog_cover_poster.png
new file mode 100644
index 0000000..85be596
Binary files /dev/null and b/public/blog_cover_poster.png differ
diff --git a/src/app/blogs/components/blogCard.jsx b/src/app/blogs/components/blogCard.jsx
new file mode 100644
index 0000000..936fcc4
--- /dev/null
+++ b/src/app/blogs/components/blogCard.jsx
@@ -0,0 +1,167 @@
+import React, { useState } from "react";
+import Image from "next/image";
+import Link from "next/link";
+
+import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"
+
+import { Montserrat } from "next/font/google";
+const montserratFont = Montserrat({ weight: ["100", "200", "400", "500", "600"], subsets: ["latin"] });
+
+export default function BlogCard(props) {
+ const [blog, setBlog] = useState(props.blog);
+ const [blogPosterUrl, setBlogPosterUrl] = useState(blog.posterUrl);
+ const [blogTitle, setBlogTitle] = useState(blog.title);
+ const [blogIntro, setBlogIntro] = useState(blog.intro);
+ const [creatorName, setCreatorName] = useState("Devesh Sawant")
+ const [createdAt, setCreatedAt] = useState(blog.created_at);
+ const [blogPoster, setblogPoster] = useState("/event_poster.avif");
+ const [blogLikes, setBlogLikes] = useState("10");
+ const [blogComments, setBlogComments] = useState("10");
+
+ console.log(trimString(blogTitle, 45));
+
+ return (
+
+
+
+
+
+
+
+
+
+
{formatDate(new Date(createdAt))}
+
+
+
+
+
+
+
+
{trimString(blogTitle, 45)}
+
+
{trimString(blogIntro, 200)}
+
+
+
+
+
+
+ )
+}
+
+
+function trimString(str, length) {
+ // Use Intl.Segmenter to handle grapheme clusters (e.g., emojis)
+ const segmenter = new Intl.Segmenter(undefined, { granularity: "grapheme" });
+ const segments = segmenter.segment(str);
+
+ // Convert segments iterator to an array of strings
+ const graphemes = Array.from(segments, segment => segment.segment);
+
+ // Check if truncation is needed
+ if (graphemes.length > length) {
+ return graphemes.slice(0, length).join('') + "...";
+ }
+
+ // Return the original string if no truncation is needed
+ return str;
+}
+
+
+function formatDate(date) {
+ // Array of month names
+ const monthNames = [
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"
+ ];
+
+ // Extract day, month, and year from the date
+ const day = date.getDate();
+ const month = monthNames[date.getMonth()];
+ const year = date.getFullYear();
+
+ // Format the date
+ return `${day} ${month}, ${year}`;
+}
+
+
+
+const ShareButton = (props) => {
+ const handleShare = async () => {
+ if (navigator.share) {
+ try {
+ await navigator.share({
+ title: 'Check this out!',
+ text: 'This is an awesome React app.',
+ url: window.location.origin + props.href
+ });
+
+ } catch (error) {
+ console.error('Error sharing:', error);
+ }
+ } else {
+ console.log('Web Share API not supported');
+ // Optionally handle fallback here
+ }
+ };
+
+ return (
+
+ );
+};
+
+const ShareIcon = () => (
+
+);
+
+
+const CommentIcon = () => (
+
+);
+
+
+const LikeIcon = () => (
+
+);
diff --git a/src/app/blogs/components/blogCoverPoster.jsx b/src/app/blogs/components/blogCoverPoster.jsx
new file mode 100644
index 0000000..1cf9ff8
--- /dev/null
+++ b/src/app/blogs/components/blogCoverPoster.jsx
@@ -0,0 +1,10 @@
+
+import Image from 'next/image';
+export default function Blogs() {
+ const blogCoverImage = "/blog_cover_poster.png";
+ return(
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/app/blogs/components/comment.jsx b/src/app/blogs/components/comment.jsx
new file mode 100644
index 0000000..4c7cf94
--- /dev/null
+++ b/src/app/blogs/components/comment.jsx
@@ -0,0 +1,11 @@
+const LikeIcon = () => (
+
+);
diff --git a/src/app/blogs/components/generateBlogCards.jsx b/src/app/blogs/components/generateBlogCards.jsx
new file mode 100644
index 0000000..d9203e3
--- /dev/null
+++ b/src/app/blogs/components/generateBlogCards.jsx
@@ -0,0 +1,23 @@
+import React, { useEffect } from "react";
+import BlogCard from "./blogCard";
+
+import "@/styles/blogs.css"
+
+import { Montserrat,Alata} from "next/font/google";
+const alataFont = Alata({weight: ["400"], subsets: ["latin"]});
+const montserratFont = Montserrat({weight: ["100","200","400","600"], subsets: ["latin"]});
+
+export default function GenerateBlogCards(props){
+ const blogs = props.blogs;
+
+ return(
+
+
+
Blogs
+
+ {blogs.map((blog)=>)}
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/app/blogs/components/heart.svg b/src/app/blogs/components/heart.svg
new file mode 100644
index 0000000..5dde482
--- /dev/null
+++ b/src/app/blogs/components/heart.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/app/blogs/fetchBlogs.jsx b/src/app/blogs/fetchBlogs.jsx
new file mode 100644
index 0000000..c501145
--- /dev/null
+++ b/src/app/blogs/fetchBlogs.jsx
@@ -0,0 +1,29 @@
+import { useState, useEffect } from 'react';
+import axios from 'axios';
+
+const useFetchBlog = (currentPage) => {
+ const [blogs, setBlogs] = useState({});
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ setLoading(true);
+ const fetchBlog = async () => {
+ try {
+ const response = await axios.get(`/api/v1/get/blogs?page=${currentPage}`);
+ const result = response.data;
+ setBlogs(result.blogs);
+ setLoading(false);
+ } catch (error) {
+ setError(error);
+ setLoading(false);
+ }
+ };
+
+ fetchBlog();
+ },[currentPage]);
+
+ return { blogs, loading, error };
+};
+
+export default useFetchBlog;
\ No newline at end of file
diff --git a/src/app/blogs/layout.tsx b/src/app/blogs/layout.tsx
new file mode 100644
index 0000000..1bcbaa6
--- /dev/null
+++ b/src/app/blogs/layout.tsx
@@ -0,0 +1,18 @@
+import React from 'react';
+import Navbar from "@/components/navbar"
+import Footer from "@/components/footer"
+
+
+interface RootLayoutProps {
+ children: React.ReactNode;
+}
+
+export default function RootLayout({ children } : RootLayoutProps) {
+ return (
+ <>
+
+ {children}
+
+ >
+ )
+}
\ No newline at end of file
diff --git a/src/app/blogs/page.jsx b/src/app/blogs/page.jsx
new file mode 100644
index 0000000..86b3906
--- /dev/null
+++ b/src/app/blogs/page.jsx
@@ -0,0 +1,123 @@
+'use client'
+import React, { useEffect, useState } from 'react';
+import { useRouter } from 'next/navigation';
+import useFetchBlog from './fetchBlogs';
+import Loader from '@/components/ui/loader';
+import Image from 'next/image';
+import Link from 'next/link';
+
+import BlogPosterCover from "./components/blogCoverPoster";
+import GenerateBlogCards from './components/generateBlogCards';
+
+import { Montserrat} from "next/font/google";
+const montserratFont = Montserrat({weight: ["100","200","400","600"], subsets: ["latin"]});
+
+
+export default function Blogs() {
+ const router = useRouter();
+
+ const [currentPage, setCurrentPage] = useState(1);
+ const [hasMore, setHasMore] = useState(true);
+ const [blogsArray, setBlogsArray] = useState([]);
+
+ const [searchInputValue , setSearchInputValue ] = useState("");
+ const { blogs, loading, error } = useFetchBlog(currentPage);
+
+ useEffect(() => {
+ if (!loading && blogs) {
+ setBlogsArray(prevBlogs => {
+ // Create a new array by filtering out blogs that already exist in the array based on a unique identifier
+ const newBlogs = blogs.filter(blog => !prevBlogs.some(prevBlog => prevBlog.id === blog.id));
+ return [...prevBlogs, ...newBlogs];
+ });
+
+ if (blogs.length < 5) {
+ setHasMore(false);
+ }
+ }
+ }, [blogs, loading]);
+
+ if (error) {
+ console.error(error);
+ router.push('/');
+ return null;
+ }
+
+ const handlePageChange = () => {
+ if (hasMore) {
+ setCurrentPage(prevPage => prevPage + 1);
+ }
+ };
+
+
+
+ // const blogsArray =[
+ // {
+ // "id": 24,
+ // "title": "Seventh Blog",
+ // "intro": "This is the seventh blog",
+ // "writer": "b4e05b86-df08-49d8-a118-51c205216401",
+ // "created_at": "2024-07-26T07:33:28.697994+00:00",
+ // "posterUrl": "undefined/web_data/images/24/poster",
+ // "blogFileUrl": "undefined/web_data/blogs/24/blog",
+ // "images": []
+ // },
+ // {
+ // "id": 25,
+ // "title": "ReactJS Tic-Tac-Toe (💥Passed Job Interview 😂 ) (💥Passed Job Interview💥)",
+ // "intro": "From bugs to brilliance: the journey of a coder. From bugs to brilliance: the journey of a coder. From bugs to brilliance: the journey of a coder. From bugs to brilliance: the journey of a coder. From bugs to brilliance: the journey of a coder. From bugs to brilliance: the journey of a coder",
+ // "writer": "b4e05b86-df08-49d8-a118-51c205216401",
+ // "created_at": "2024-06-14T07:33:28.697994+00:00",
+ // "posterUrl": "undefined/web_data/images/24/poster",
+ // "blogFileUrl": "undefined/web_data/blogs/24/blog",
+ // "images": ["https://i.ibb.co/3RWZ6rF/image.png",
+ // "https://cdn.pixabay.com/photo/2024/05/16/20/20/digital-8766937_1280.png",
+ // "https://cdn.pixabay.com/photo/2024/05/20/13/28/ai-generated-8775234_1280.png"
+ // ]
+ // }
+ // ]
+ const handleSearchInputChange = (event) => {
+ setSearchInputValue(event.target.value);
+ };
+
+ return (
+ <>
+
+
+
+ {loading?:
+ hasMore?
+
+
+
+ :null
+ }
+ >
+ )
+}
+
+const SearchIcon = () => (
+
+);
diff --git a/src/styles/blogs.css b/src/styles/blogs.css
new file mode 100644
index 0000000..7a560be
--- /dev/null
+++ b/src/styles/blogs.css
@@ -0,0 +1,152 @@
+
+.blogs-div{
+ width: 100%;
+ display: flex;
+ justify-content: center;
+}
+
+.blogs-container{
+ width: 95%;
+}
+
+.blogs-search-div{
+ position: relative;
+ width: max-content;
+ height: 50px;
+ bottom: 25px;
+ border-radius: 20px;
+ background-color : color-mix(in srgb, var(--primary) 20%, transparent);
+ display: flex;
+ justify-content: space-evenly;
+ gap: 10px;
+ align-items: center;
+ padding: 10px 25px;
+
+}
+.blogs-search-input {
+ width: 95px;
+ background: none;
+ transition: 0.5s;
+ font-size: 20px;
+ opacity: 50%;
+}
+.blogs-search-input:focus {
+ width: 175px;
+ outline: none;
+ transition: 0.5s;
+ opacity: 100%;
+}
+.blogs-heading-title{
+ text-decoration:underline;
+ font-size: 30px;
+ margin-left: 15px;
+}
+.blogs-card{
+ flex-wrap: wrap;
+ margin-bottom: 25px;
+ gap: 20px;
+}
+
+
+.blogs-poster-div{
+ overflow: hidden;
+ height: 250px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+.blogs-poster{
+ object-fit: cover;
+ width: 100%;
+ height: 100%;
+}
+.blogs-details-container-1{
+ color: var(--muted-foreground);
+}
+
+.blogs-date{
+ font-weight: 400;
+ font-size: 15px;
+ width: fit-content;
+ margin-left: 15px;
+}
+
+.blogs-details-container-2{
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ justify-content: space-between;
+}
+.blogs-title{
+ font-weight: 500;
+ font-size: 24px;
+ line-height: 110%;
+ text-transform: uppercase;
+ color: var(--primary);
+}
+
+.blogs-title-div{
+ display: flex;
+ flex-direction: row;
+ gap: 10px;
+ max-height: 52px;
+ margin-bottom: 10px;
+ overflow: hidden;
+}
+.blogs-title-div>div{
+ background-color: var(--primary);
+ width: 2px;
+}
+
+.blogs-details-div{
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+}
+.blogs-intro{
+ margin-left: 15px;
+}
+.blogs-data{
+ font-weight: 400;
+ font-size: 16px;
+ color: var(--muted-foreground);
+}
+
+.comments-container{
+ margin-right: 10px;
+}
+
+.show-more-button{
+
+ box-sizing: border-box;
+ width: 400px;
+ height: 60px;
+
+ background-color : color-mix(in srgb, var(--primary) 10%, transparent);
+ box-shadow: #291f24 1px 1px 15px;
+ border-radius: 43px;
+
+ transition: 0.5s;
+}
+.show-more-button:hover{
+ background-color : color-mix(in srgb, var(--muted-foreground) 40%, transparent);
+}
+.show-more-button>p{
+ font-weight: 700;
+ font-size: 18px;
+
+ color: var(--primary);
+}
+
+
+@media screen and (max-width : 1024px){
+ .blogs-container{
+ width: 95%;
+ }
+ .show-more-button{
+
+ box-sizing: border-box;
+ width: 200px;
+ height: 50px;
+ }
+}
\ No newline at end of file
diff --git a/src/styles/navbar.css b/src/styles/navbar.css
index 7be95e8..b91a94b 100644
--- a/src/styles/navbar.css
+++ b/src/styles/navbar.css
@@ -58,6 +58,7 @@
.logo-subtitle{
font-size: 14px;
margin-left: 3px;
+ margin-bottom: 7px;
}
.menu-container{