Skip to content

Commit b59a7ea

Browse files
committed
feat: categories filter
1 parent 0445e96 commit b59a7ea

File tree

6 files changed

+87
-36
lines changed

6 files changed

+87
-36
lines changed

src/App.css

-3
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,6 @@ img.blog_image {
9090

9191
@media (min-width: 768px) {
9292
/* Main Image */
93-
img.blog_image{
94-
height: 600px;
95-
}
9693

9794
.block_content p {
9895
font-size: 20px;

src/Pages/Blog.jsx

+52-29
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,57 @@
22
import React, { useState, useEffect } from 'react';
33
import { Link } from 'react-router-dom';
44
import client from '../client';
5-
import { NavBarBlog } from '../components/Blog';
5+
import { Filter, NavBarBlog } from '../components/Blog';
66
import { motion } from 'framer-motion';
77
import Loader from '../components/Loader/Loader'; // Import the Loader component
88

99
const Blog = () => {
1010
const [posts, setPosts] = useState([]);
11+
const [categories, setCategories] = useState([])
1112
const [loading, setLoading] = useState(true); // Loading state
13+
const [activeFilter, setActiveFilter] = useState('All')
1214

1315
useEffect(() => {
14-
client.fetch(
15-
`*[_type == "post"] | order(publishedAt desc) {
16-
title,
17-
slug,
18-
body,
19-
publishedAt,
20-
mainImage {
21-
asset -> {
22-
_id,
23-
url
24-
},
25-
alt
26-
},
27-
categories[]->{
28-
_id,
29-
title
30-
}
31-
}`
32-
)
33-
.then((data) => {
34-
setPosts(data);
35-
setLoading(false); // Set loading to false once data is fetched
36-
})
37-
.catch((error) => {
38-
console.error(error);
39-
setLoading(false); // In case of error, also stop loading
40-
});
16+
const fetchData = async () => {
17+
try {
18+
const [postsData, categoriesData] = await Promise.all([
19+
client.fetch(`
20+
*[_type == "post"] | order(publishedAt desc) {
21+
title,
22+
slug,
23+
body,
24+
publishedAt,
25+
mainImage {
26+
asset -> {
27+
_id,
28+
url
29+
},
30+
alt
31+
},
32+
categories[]->{
33+
_id,
34+
title
35+
}
36+
}
37+
`),
38+
client.fetch(`
39+
*[_type == "category"] {
40+
_id,
41+
title
42+
}
43+
`)
44+
])
45+
46+
setPosts(postsData)
47+
setCategories([{ _id: 'all', title: 'All' }, ...categoriesData])
48+
setLoading(false)
49+
} catch (error) {
50+
console.error(error)
51+
setLoading(false)
52+
}
53+
}
54+
55+
fetchData();
4156
}, []);
4257

4358
const formatDate = (isoString) => {
@@ -49,9 +64,17 @@ const Blog = () => {
4964
});
5065
};
5166

67+
const filteredPosts = activeFilter === 'All'
68+
? posts
69+
: posts.filter(post => post.categories?.some(category => category?.title === activeFilter))
70+
71+
5272
return (
5373
<div className='bg-white'>
5474
<NavBarBlog/>
75+
76+
<Filter categories={categories} activeFilter={activeFilter} setActiveFilter={setActiveFilter} />
77+
5578
<section className='px-10'>
5679
<motion.div
5780
style={{ y: 30 }} animate={{ y: 0 }}
@@ -67,7 +90,7 @@ const Blog = () => {
6790
<Loader /> // Show loader when posts are being fetched
6891
) : (
6992
<div className='grid grid-cols-1 gap-5 md:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 lg:gap-24 mb-11'>
70-
{posts.map((post) => (
93+
{filteredPosts.map((post) => (
7194
<motion.div
7295
style={{ y: 30 }} animate={{ y: 0 }}
7396
transition={{duration: 0.55}}

src/Pages/SinglePost.jsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ const SinglePost = () => {
134134
{isLoading ? (
135135
<Loader />
136136
):
137-
<section className='px-5 xl:max-w-5xl xl:mx-auto pb-10'>
137+
<section className='px-5 md:max-w-4xl md:mx-auto pb-10'>
138138

139139
<motion.div
140140
style={{ y: 30 }} animate={{ y: 0 }}
@@ -144,7 +144,7 @@ const SinglePost = () => {
144144
style={{
145145
fontFamily: "'Sriracha', cursive"
146146
}}
147-
className="text-4xl md:text-6xl pt-5 mb-10 text-center "
147+
className="text-4xl md:text-5xl pt-5 mb-10 text-center "
148148
>
149149
{SinglePost.title}
150150
</h1>
@@ -157,7 +157,7 @@ const SinglePost = () => {
157157
style={{ x: -200 }} animate={{ x: 0 }}
158158
transition={{duration: 0.6}}
159159
>
160-
<img className='blog_image rounded-lg mx-auto' src={SinglePost.mainImage.asset.url} alt={SinglePost.title} title={SinglePost.title} />
160+
<img className='blog_image rounded-lg ' src={SinglePost.mainImage.asset.url} alt={SinglePost.title} title={SinglePost.title} />
161161
</motion.div>
162162

163163
<div className='flex justify-between items-center'>

src/components/Blog/Filter.jsx

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React from 'react';
2+
3+
export default function Filter({ categories, activeFilter, setActiveFilter }) {
4+
return (
5+
<div className="w-full overflow-x-auto py-3 px-10 sticky bg-white top-0 z-10">
6+
<div className="flex space-x-4">
7+
{categories?.map((category, index) => (
8+
// Check if category is not null or undefined before rendering
9+
category && (
10+
<button
11+
key={index}
12+
className={`whitespace-nowrap px-3 py-1 rounded-full text-sm font-medium ${
13+
activeFilter === category.title
14+
? 'bg-black text-white '
15+
: 'bg-neutral-200 hover:bg-neutral-300 text-black'
16+
}`}
17+
onClick={() => setActiveFilter(category.title)}
18+
>
19+
{category.title}
20+
</button>
21+
)
22+
))}
23+
</div>
24+
</div>
25+
);
26+
}

src/components/Blog/index.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import ClapButton from "./ClapButton";
22
import YouTubeEmbed from "./YouTubeEmbed";
33
import NavBarBlog from "./NavBarBlog/NavBarBlog";
44
import Comments from "./Comments/Comments";
5+
import Filter from './Filter'
56

67
export {
78
ClapButton,
89
YouTubeEmbed,
910
NavBarBlog,
10-
Comments
11+
Comments,
12+
Filter
1113
}

tailwind.config.js

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ module.exports = {
1010
borderRadius: '10px',
1111
},
1212
},
13+
backgroundImage: {
14+
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
15+
}
1316
},
1417
},
1518
plugins: [],

0 commit comments

Comments
 (0)