Skip to content

Commit e3e60f1

Browse files
committed
improve news prev/next buttons
1 parent 23f4ef6 commit e3e60f1

17 files changed

+1853
-244
lines changed

gatsby-node.ts

+10-11
Original file line numberDiff line numberDiff line change
@@ -660,23 +660,22 @@ export const createPages: GatsbyNode["createPages"] = async ({
660660

661661
const numPages = Math.ceil(posts.length / postsPerPage)
662662
Array.from({ length: numPages }).forEach((_, index) => {
663-
const currentPageNumber = index + 1
664-
const previousPageNumber =
665-
currentPageNumber === 1 ? null : currentPageNumber - 1
666-
const nextPageNumber =
667-
currentPageNumber === numPages ? null : currentPageNumber + 1
668-
663+
const currentPage = index + 1;
664+
const previousPageNumber = currentPage === 1 ? null : currentPage - 1;
665+
const nextPageNumber = currentPage === numPages ? null : currentPage + 1;
666+
669667
createPage({
670-
path: `/news/page/${index + 1}`,
668+
path: currentPage === 1 ? `/news` : `/news/page/${currentPage}`,
671669
component: path.resolve("./src/templates/newsPage.tsx"),
672670
context: {
673671
limit: postsPerPage,
674672
skip: index * postsPerPage,
675-
numPages,
676-
currentPageNumber,
673+
currentPage,
674+
totalPages: numPages,
677675
previousPageNumber,
678676
nextPageNumber,
677+
baseUrl: "/news",
679678
},
680-
})
681-
})
679+
});
680+
});
682681
}
+39-45
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,42 @@
1-
import React from "react"
2-
import { FaChevronLeft, FaChevronRight } from "react-icons/fa";
3-
import { Link } from "gatsby-plugin-react-i18next"
1+
import React from "react";
2+
import EventCard from "../../Events/EventCard";
3+
import Pagination from "../Pagination"; // adjust the import path as needed
44

5-
import EventCard from "../../Events/EventCard"
5+
const NewsCardList = ({
6+
posts,
7+
previousPageNumber,
8+
previousPageLink,
9+
nextPage,
10+
currentPage,
11+
totalPages,
12+
baseUrl,
13+
}) => {
14+
const data1 = posts.slice(0, 3);
15+
const data2 = posts.slice(3, 6);
616

7-
const NewsCardList = ({ posts, previousPageNumber, previousPageLink, nextPage }) => {
8-
const data1 = posts.slice(0, 3)
9-
const data2 = posts.slice(3, 6)
10-
return (
11-
<div className="max-w-[1264px] mx-auto px-6 py-8 md:pt-12">
12-
<div className="flex justify-center gap-6 items-center flex-wrap pt-8 md:pt-12">
13-
{data1.map((post, index) => (
14-
<EventCard key={index} post={post} />
15-
))}
16-
</div>
17-
<div className="flex justify-center gap-6 items-center flex-wrap py-8 md:py-12">
18-
{data2.map((post, index) => (
19-
<EventCard key={index} post={post} />
20-
))}
21-
</div>
22-
<div className="flex justify-center items-center gap-8 md:gap-14">
23-
{previousPageNumber && (
24-
<Link to={previousPageLink} rel="prev">
25-
<div className="flex items-center gap-3">
26-
<span className="cursor-pointer">
27-
<FaChevronLeft />
28-
</span>
29-
<p className="tab-button-text mb-0 hidden md:block">Previous Page</p>
30-
</div>
31-
</Link>
32-
)}
33-
{nextPage && (
34-
<Link to={nextPage}>
35-
<div className="flex items-center gap-3">
36-
<p className="tab-button-text mb-0 hidden md:block">Next Page</p>
37-
<span className="cursor-pointer">
38-
<FaChevronRight />
39-
</span>
40-
</div>
41-
</Link>
42-
)}
43-
</div>
44-
</div>
45-
)
46-
}
17+
return (
18+
<div className="max-w-[1264px] mx-auto px-6 py-8 md:pt-12">
19+
<div className="flex justify-center gap-6 items-center flex-wrap pt-8 md:pt-12">
20+
{data1.map((post, index) => (
21+
<EventCard key={index} post={post} />
22+
))}
23+
</div>
24+
<div className="flex justify-center gap-6 items-center flex-wrap py-8 md:py-12">
25+
{data2.map((post, index) => (
26+
<EventCard key={index} post={post} />
27+
))}
28+
</div>
4729

48-
export default NewsCardList
30+
<Pagination
31+
previousPageNumber={previousPageNumber}
32+
previousPageLink={previousPageLink}
33+
nextPage={nextPage}
34+
currentPage={currentPage}
35+
totalPages={totalPages}
36+
baseUrl={baseUrl}
37+
/>
38+
</div>
39+
);
40+
};
41+
42+
export default NewsCardList;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import React from "react";
2+
import { render, screen } from "@testing-library/react";
3+
import { describe, it, expect } from "vitest";
4+
import Pagination from "../";
5+
6+
describe("Pagination component", () => {
7+
it("renders correctly when totalPages <= 7", () => {
8+
render(
9+
<Pagination
10+
previousPageNumber={2}
11+
previousPageLink="/test/page/2"
12+
nextPage="/test/page/4"
13+
currentPage={3}
14+
totalPages={5}
15+
baseUrl="/test"
16+
/>
17+
);
18+
19+
// Expect pages 1 through 5 to be rendered with no ellipsis.
20+
for (let i = 1; i <= 5; i++) {
21+
expect(screen.getByText(String(i))).toBeInTheDocument();
22+
}
23+
expect(screen.queryByText("...")).toBeNull();
24+
25+
// Check that both "Previous" and "Next" buttons are rendered.
26+
expect(screen.getByText("Previous")).toBeInTheDocument();
27+
expect(screen.getByText("Next")).toBeInTheDocument();
28+
});
29+
30+
it("renders correctly for currentPage=1 when totalPages > 7", () => {
31+
render(
32+
<Pagination
33+
previousPageNumber={null}
34+
previousPageLink={null}
35+
nextPage="/test/page/2"
36+
currentPage={1}
37+
totalPages={8}
38+
baseUrl="/test"
39+
/>
40+
);
41+
42+
// Expected pages for page 1: 1, 2, 3, 4, 5, ... , 8
43+
expect(screen.getByText("1")).toBeInTheDocument();
44+
expect(screen.getByText("2")).toBeInTheDocument();
45+
expect(screen.getByText("3")).toBeInTheDocument();
46+
expect(screen.getByText("4")).toBeInTheDocument();
47+
expect(screen.getByText("5")).toBeInTheDocument();
48+
expect(screen.getByText("8")).toBeInTheDocument();
49+
50+
// There should be one ellipsis.
51+
expect(screen.getAllByText("...")).toHaveLength(1);
52+
53+
// "Previous" button should not render when previousPageNumber is null.
54+
expect(screen.queryByText("Previous")).toBeNull();
55+
expect(screen.getByText("Next")).toBeInTheDocument();
56+
});
57+
58+
it("renders correctly for a middle page when totalPages > 7", () => {
59+
render(
60+
<Pagination
61+
previousPageNumber={4}
62+
previousPageLink="/test/page/4"
63+
nextPage="/test/page/6"
64+
currentPage={5}
65+
totalPages={10}
66+
baseUrl="/test"
67+
/>
68+
);
69+
70+
// Expected pages for currentPage 5: 1, ... , 3, 4, 5, 6, 7, ... , 10
71+
expect(screen.getByText("1")).toBeInTheDocument();
72+
expect(screen.getByText("3")).toBeInTheDocument();
73+
expect(screen.getByText("4")).toBeInTheDocument();
74+
expect(screen.getByText("5")).toBeInTheDocument();
75+
expect(screen.getByText("6")).toBeInTheDocument();
76+
expect(screen.getByText("7")).toBeInTheDocument();
77+
expect(screen.getByText("10")).toBeInTheDocument();
78+
79+
// There should be two ellipses.
80+
expect(screen.getAllByText("...")).toHaveLength(2);
81+
82+
// Both arrow links should be rendered.
83+
expect(screen.getByText("Previous")).toBeInTheDocument();
84+
expect(screen.getByText("Next")).toBeInTheDocument();
85+
});
86+
87+
it("renders correctly for a near-end page", () => {
88+
render(
89+
<Pagination
90+
previousPageNumber={6}
91+
previousPageLink="/test/page/6"
92+
nextPage="/test/page/8"
93+
currentPage={7}
94+
totalPages={8}
95+
baseUrl="/test"
96+
/>
97+
);
98+
99+
// Expected pages for currentPage 7: 1, ... , 4, 5, 6, 7, 8
100+
expect(screen.getByText("1")).toBeInTheDocument();
101+
expect(screen.getByText("4")).toBeInTheDocument();
102+
expect(screen.getByText("5")).toBeInTheDocument();
103+
expect(screen.getByText("6")).toBeInTheDocument();
104+
expect(screen.getByText("7")).toBeInTheDocument();
105+
expect(screen.getByText("8")).toBeInTheDocument();
106+
107+
// There should be one ellipsis.
108+
expect(screen.getAllByText("...")).toHaveLength(1);
109+
110+
// Both arrow links should be rendered.
111+
expect(screen.getByText("Previous")).toBeInTheDocument();
112+
expect(screen.getByText("Next")).toBeInTheDocument();
113+
});
114+
});
+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import React from "react";
2+
import { Link } from "gatsby-plugin-react-i18next";
3+
import { FaChevronLeft, FaChevronRight } from "react-icons/fa";
4+
5+
interface PaginationProps {
6+
previousPageNumber?: number | null;
7+
previousPageLink?: string | null;
8+
nextPage?: string | null;
9+
currentPage: number;
10+
totalPages: number;
11+
baseUrl: string;
12+
}
13+
14+
const Pagination: React.FC<PaginationProps> = ({
15+
previousPageNumber,
16+
previousPageLink,
17+
nextPage,
18+
currentPage,
19+
totalPages,
20+
baseUrl,
21+
}) => {
22+
// Helper to build a link for a given page number.
23+
// If page 1, return the baseUrl; otherwise append "/page/{page}".
24+
const createPageLink = (page: number): string =>
25+
page === 1 ? `${baseUrl}` : `${baseUrl}/page/${page}`;
26+
27+
// Build an array of page numbers and ellipses.
28+
const pages: (number | string)[] = [];
29+
if (totalPages <= 7) {
30+
// If few pages, show them all.
31+
for (let i = 1; i <= totalPages; i++) {
32+
pages.push(i);
33+
}
34+
} else {
35+
// Always show the first page.
36+
pages.push(1);
37+
38+
// Determine the range around the current page.
39+
let start = Math.max(2, currentPage - 2);
40+
let end = Math.min(totalPages - 1, currentPage + 2);
41+
42+
// Adjust range if near the beginning.
43+
if (currentPage <= 3) {
44+
start = 2;
45+
end = 5;
46+
}
47+
// Adjust range if near the end.
48+
if (currentPage >= totalPages - 2) {
49+
start = totalPages - 4;
50+
end = totalPages - 1;
51+
}
52+
53+
// Add ellipsis if there's a gap between 1 and the start.
54+
if (start > 2) {
55+
pages.push("...");
56+
}
57+
58+
// Add the page numbers in the range.
59+
for (let i = start; i <= end; i++) {
60+
pages.push(i);
61+
}
62+
63+
// Add ellipsis if there's a gap between end and the last page.
64+
if (end < totalPages - 1) {
65+
pages.push("...");
66+
}
67+
68+
// Always show the last page.
69+
pages.push(totalPages);
70+
}
71+
72+
return (
73+
<div className="flex justify-center items-center gap-8 md:gap-14 my-8">
74+
{/* Previous arrow using your passed parameters */}
75+
{previousPageNumber && previousPageLink && (
76+
<Link to={previousPageLink} rel="prev" className="flex items-center gap-3">
77+
<span className="cursor-pointer">
78+
<FaChevronLeft />
79+
</span>
80+
<p className="tab-button-text mb-0 hidden md:block">Previous</p>
81+
</Link>
82+
)}
83+
84+
{/* Numbered pagination */}
85+
<div className="flex items-center gap-5">
86+
<div className="flex items-center justify-between gap-6 border border-[#3E3355] rounded-[80px] px-6 py-3">
87+
{pages.map((page, index) =>
88+
page === "..." ? (
89+
<p key={index} className="tab-button-text mb-0">
90+
...
91+
</p>
92+
) : (
93+
<Link key={index} to={createPageLink(page as number)}>
94+
<p
95+
className={`tab-button-text mb-0 cursor-pointer ${
96+
page === currentPage ? "font-bold text-pink" : ""
97+
}`}
98+
>
99+
{page}
100+
</p>
101+
</Link>
102+
)
103+
)}
104+
</div>
105+
</div>
106+
107+
{/* Next arrow using your passed parameters */}
108+
{nextPage && (
109+
<Link to={nextPage} className="flex items-center gap-3">
110+
<p className="tab-button-text mb-0 hidden md:block">Next</p>
111+
<span className="cursor-pointer">
112+
<FaChevronRight />
113+
</span>
114+
</Link>
115+
)}
116+
</div>
117+
);
118+
};
119+
120+
export default Pagination;

src/pages/__tests__/__snapshots__/blog.test.tsx.snap

+21-3
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ exports[`News page > renders correctly 1`] = `
7777
</div>
7878
</div>
7979
<div
80-
class="max-w-[1264px] mx-auto px-6 py-8 md:pt-12"
80+
class="max-w-[1264px] mx-auto px-6 py-8 md:pt-12"
8181
>
8282
<div
8383
class="flex justify-center gap-6 items-center flex-wrap pt-8 md:pt-12"
@@ -127,8 +127,26 @@ exports[`News page > renders correctly 1`] = `
127127
class="flex justify-center gap-6 items-center flex-wrap py-8 md:py-12"
128128
/>
129129
<div
130-
class="flex justify-center items-center gap-8 md:gap-14"
131-
/>
130+
class="flex justify-center items-center gap-8 md:gap-14 my-8"
131+
>
132+
<div
133+
class="flex items-center gap-5"
134+
>
135+
<div
136+
class="flex items-center justify-between gap-6 border border-[#3E3355] rounded-[80px] px-6 py-3"
137+
>
138+
<a
139+
href="/news"
140+
>
141+
<p
142+
class="tab-button-text mb-0 cursor-pointer font-bold text-pink"
143+
>
144+
1
145+
</p>
146+
</a>
147+
</div>
148+
</div>
149+
</div>
132150
</div>
133151
</main>
134152
`;

0 commit comments

Comments
 (0)