Skip to content

Commit 959f67a

Browse files
authored
Merge pull request #46 from 1chooo/dev/enhancement
Extract common filtering logic and add page button in Blog (#44, #45)
2 parents 99296f5 + 7bc12c5 commit 959f67a

File tree

4 files changed

+84
-38
lines changed

4 files changed

+84
-38
lines changed

src/App.css

+32-10
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,37 @@
9595

9696
}
9797

98+
/*-----------------------------------*\
99+
#PAGINATION
100+
\*-----------------------------------*/
101+
102+
.pagination {
103+
display: flex;
104+
justify-content: center;
105+
margin-top: 20px;
106+
}
107+
108+
.pagination-btn {
109+
background: var(--border-gradient-onyx);
110+
border: none;
111+
padding: 10px 15px;
112+
margin: 0 5px;
113+
width: 40px;
114+
height: 40px;
115+
cursor: pointer;
116+
font-size: 16px;
117+
color: hsl(0, 0%, 98%);
118+
transition: background-color 0.3s ease;
119+
border-radius: 14px;
120+
}
121+
122+
.pagination-btn.active {
123+
color: hsl(45, 100%, 71%);
124+
}
98125

126+
.pagination-btn:hover {
127+
background-color: hsl(45, 100%, 71%);
128+
}
99129

100130

101131

@@ -275,10 +305,10 @@ article.active {
275305
}
276306

277307
.has-scrollbar::-webkit-scrollbar {
278-
width: 5px;
279308
/* for vertical scrollbar */
280-
height: 5px;
309+
width: 5px;
281310
/* for horizontal scrollbar */
311+
height: 5px;
282312
}
283313

284314
.has-scrollbar::-webkit-scrollbar-track {
@@ -315,10 +345,6 @@ article.active {
315345
z-index: -1;
316346
}
317347

318-
319-
320-
321-
322348
/*-----------------------------------*\
323349
#MAIN
324350
\*-----------------------------------*/
@@ -329,10 +355,6 @@ main {
329355
min-width: 259px;
330356
}
331357

332-
333-
334-
335-
336358
/*-----------------------------------*\
337359
#SIDEBAR
338360
\*-----------------------------------*/

src/components/blog/blogPosts.tsx

+35-13
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
11
import React, { useState, useEffect } from 'react';
22
import { MdExpandMore } from 'react-icons/md';
33
import { blogTags, postsData, Post } from '../../Config/BlogData';
4+
import { filterFunc, handleItemClick } from '../../utils/filterUtils';
45

56
const BlogPosts: React.FC = () => {
67
const [selectedValue, setSelectedValue] = useState('All');
78
const [isSelectActive, setIsSelectActive] = useState(false);
9+
const [currentPage, setCurrentPage] = useState(1);
10+
const postsPerPage = 6;
811

912
useEffect(() => {
10-
handleItemClick('All');
13+
handleItemClick('All', setSelectedValue);
1114
}, []);
1215

13-
const handleItemClick = (value: string) => {
14-
setSelectedValue(value);
15-
};
16+
const filteredPosts = filterFunc(selectedValue, postsData);
1617

17-
const filterFunc = (selectedValue: string) => {
18-
return selectedValue === 'All'
19-
? postsData
20-
: postsData.filter((post) => post.category.toLowerCase() === selectedValue.toLowerCase());
21-
};
18+
// Calculate the current posts to display
19+
const indexOfLastPost = currentPage * postsPerPage;
20+
const indexOfFirstPost = indexOfLastPost - postsPerPage;
21+
const currentPosts = filteredPosts.slice(indexOfFirstPost, indexOfLastPost);
2222

23-
const filteredPosts = filterFunc(selectedValue);
23+
// Calculate total pages
24+
const totalPages = Math.ceil(filteredPosts.length / postsPerPage);
25+
26+
const handlePageChange = (pageNumber: number) => {
27+
setCurrentPage(pageNumber);
28+
};
2429

2530
return (
2631
<section className="blog-posts">
@@ -29,7 +34,10 @@ const BlogPosts: React.FC = () => {
2934
<li className="filter-item" key={index}>
3035
<button
3136
className={`filter-btn ${selectedValue === tag ? 'active' : ''}`}
32-
onClick={() => handleItemClick(tag)}
37+
onClick={() => {
38+
handleItemClick(tag, setSelectedValue);
39+
setCurrentPage(1); // Reset to first page on filter change
40+
}}
3341
>
3442
{tag}
3543
</button>
@@ -54,8 +62,9 @@ const BlogPosts: React.FC = () => {
5462
{blogTags.map((tag, index) => (
5563
<li className="select-item" key={index}>
5664
<button onClick={() => {
57-
handleItemClick(tag);
65+
handleItemClick(tag, setSelectedValue);
5866
setIsSelectActive(false);
67+
setCurrentPage(1); // Reset to first page on filter change
5968
}}>
6069
{tag}
6170
</button>
@@ -66,7 +75,7 @@ const BlogPosts: React.FC = () => {
6675
</div>
6776

6877
<ul className="blog-posts-list">
69-
{filteredPosts.map((post: Post, index: number) => (
78+
{currentPosts.map((post: Post, index: number) => (
7079
<li
7180
key={index}
7281
className="blog-post-item active"
@@ -97,6 +106,19 @@ const BlogPosts: React.FC = () => {
97106
</li>
98107
))}
99108
</ul>
109+
110+
{/* Pagination */}
111+
<div className="pagination">
112+
{[...Array(totalPages)].map((_, index) => (
113+
<button
114+
key={index}
115+
className={`pagination-btn ${currentPage === index + 1 ? 'active' : ''}`}
116+
onClick={() => handlePageChange(index + 1)}
117+
>
118+
{index + 1}
119+
</button>
120+
))}
121+
</div>
100122
</section>
101123
);
102124
};

src/components/portfolio/projects.tsx

+5-15
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,18 @@ import React, { useState, useEffect } from 'react';
22
import { MdExpandMore } from "react-icons/md";
33
import { LuEye } from "react-icons/lu";
44
import { projectTags, projectsData, Project } from '../../Config/PortfolioData';
5-
5+
import { filterFunc, handleItemClick } from '../../utils/filterUtils';
66

77
const Projects: React.FC = () => {
88

99
const [selectedValue, setSelectedValue] = useState('All');
1010
const [isSelectActive, setIsSelectActive] = useState(false);
1111

1212
useEffect(() => {
13-
handleItemClick('All');
13+
handleItemClick('All', setSelectedValue);
1414
}, []);
1515

16-
const handleItemClick = (value: string) => {
17-
setSelectedValue(value);
18-
};
19-
20-
const filterFunc = (selectedValue: string) => {
21-
return selectedValue === 'All'
22-
? projectsData
23-
: projectsData.filter((post) => post.category.toLowerCase() === selectedValue.toLowerCase());
24-
};
25-
26-
const filteredProjects = filterFunc(selectedValue);
16+
const filteredProjects = filterFunc(selectedValue, projectsData);
2717

2818
return (
2919
<section className="projects">
@@ -34,7 +24,7 @@ const Projects: React.FC = () => {
3424
<button
3525
className={`filter-btn ${selectedValue === tag ? 'active' : ''}`}
3626
data-filter-btn
37-
onClick={() => handleItemClick(tag)}
27+
onClick={() => handleItemClick(tag, setSelectedValue)}
3828
>
3929
{tag}
4030
</button>
@@ -59,7 +49,7 @@ const Projects: React.FC = () => {
5949
{projectTags.map((tag, index) => (
6050
<li className="select-item" key={index}>
6151
<button onClick={() => {
62-
handleItemClick(tag);
52+
handleItemClick(tag, setSelectedValue);
6353
setIsSelectActive(false);
6454
}}>
6555
{tag}

src/utils/filterUtils.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
export const handleItemClick = (
3+
value: string,
4+
setSelectedValue: React.Dispatch<React.SetStateAction<string>>) => {
5+
setSelectedValue(value);
6+
};
7+
8+
export const filterFunc = (selectedValue: string, data: any[]) => {
9+
return selectedValue === 'All'
10+
? data
11+
: data.filter((item) => item.category.toLowerCase() === selectedValue.toLowerCase());
12+
};

0 commit comments

Comments
 (0)