Skip to content

Commit 08b1676

Browse files
authored
refactor: replace pagination logic with Astro built-in pagination (satnaing#376)
1 parent 70b2486 commit 08b1676

12 files changed

+102
-195
lines changed

src/components/Pagination.astro

+14-20
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,43 @@
11
---
2+
import type { Page } from "astro";
23
import LinkButton from "./LinkButton.astro";
4+
import type { CollectionEntry } from "astro:content";
35
46
export interface Props {
5-
currentPage: number;
6-
totalPages: number;
7-
prevUrl: string;
8-
nextUrl: string;
7+
page: Page<CollectionEntry<"blog">>;
98
}
109
11-
const { currentPage, totalPages, prevUrl, nextUrl } = Astro.props;
12-
13-
const prev = currentPage > 1 ? "" : "disabled";
14-
const next = currentPage < totalPages ? "" : "disabled";
15-
const isPrevDisabled = prev === "disabled";
16-
const isNextDisabled = next === "disabled";
10+
const { page } = Astro.props;
1711
---
1812

1913
{
20-
totalPages > 1 && (
14+
page.lastPage > 1 && (
2115
<nav class="pagination-wrapper" aria-label="Pagination">
2216
<LinkButton
23-
disabled={isPrevDisabled}
24-
href={prevUrl}
25-
className={`mr-4 select-none ${prev}`}
17+
disabled={!page.url.prev}
18+
href={page.url.prev as string}
19+
className={`mr-4 select-none ${page.url.prev ? "" : "disabled"}`}
2620
ariaLabel="Previous"
2721
>
2822
<svg
2923
xmlns="http://www.w3.org/2000/svg"
30-
class:list={[{ "disabled-svg": isPrevDisabled }]}
24+
class:list={[{ "disabled-svg": !page.url.prev }]}
3125
>
3226
<path d="M12.707 17.293 8.414 13H18v-2H8.414l4.293-4.293-1.414-1.414L4.586 12l6.707 6.707z" />
3327
</svg>
3428
Prev
3529
</LinkButton>
36-
{currentPage} / {totalPages}
30+
{page.currentPage} / {page.lastPage}
3731
<LinkButton
38-
disabled={isNextDisabled}
39-
href={nextUrl}
40-
className={`ml-4 select-none ${next}`}
32+
disabled={!page.url.next}
33+
href={page.url.next as string}
34+
className={`mx-4 select-none ${page.url.next ? "" : "disabled"}`}
4135
ariaLabel="Next"
4236
>
4337
Next
4438
<svg
4539
xmlns="http://www.w3.org/2000/svg"
46-
class:list={[{ "disabled-svg": isNextDisabled }]}
40+
class:list={[{ "disabled-svg": !page.url.next }]}
4741
>
4842
<path d="m11.293 17.293 1.414 1.414L19.414 12l-6.707-6.707-1.414 1.414L15.586 11H6v2h9.586z" />
4943
</svg>

src/layouts/Posts.astro

+7-13
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,34 @@
11
---
2-
import type { CollectionEntry } from "astro:content";
32
import Layout from "@layouts/Layout.astro";
43
import Main from "@layouts/Main.astro";
54
import Header from "@components/Header.astro";
65
import Footer from "@components/Footer.astro";
76
import Pagination from "@components/Pagination.astro";
87
import Card from "@components/Card";
98
import { SITE } from "@config";
9+
import type { Page } from "astro";
10+
import type { CollectionEntry } from "astro:content";
1011
1112
export interface Props {
12-
currentPage: number;
13-
totalPages: number;
14-
paginatedPosts: CollectionEntry<"blog">[];
13+
page: Page<CollectionEntry<"blog">>;
1514
}
1615
17-
const { currentPage, totalPages, paginatedPosts } = Astro.props;
16+
const { page } = Astro.props;
1817
---
1918

2019
<Layout title={`Posts | ${SITE.title}`}>
2120
<Header activeNav="posts" />
2221
<Main pageTitle="Posts" pageDesc="All the articles I've posted.">
2322
<ul>
2423
{
25-
paginatedPosts.map(({ data, slug }) => (
24+
page.data.map(({ data, slug }) => (
2625
<Card href={`/posts/${slug}/`} frontmatter={data} />
2726
))
2827
}
2928
</ul>
3029
</Main>
3130

32-
<Pagination
33-
{currentPage}
34-
{totalPages}
35-
prevUrl={`/posts${currentPage - 1 !== 1 ? "/" + (currentPage - 1) : ""}/`}
36-
nextUrl={`/posts/${currentPage + 1}/`}
37-
/>
31+
<Pagination {page} />
3832

39-
<Footer noMarginTop={totalPages > 1} />
33+
<Footer noMarginTop={page.lastPage > 1} />
4034
</Layout>

src/layouts/TagPosts.astro

+7-15
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
---
2-
import { type CollectionEntry } from "astro:content";
32
import Layout from "@layouts/Layout.astro";
43
import Main from "@layouts/Main.astro";
54
import Header from "@components/Header.astro";
65
import Footer from "@components/Footer.astro";
76
import Card from "@components/Card";
87
import Pagination from "@components/Pagination.astro";
98
import { SITE } from "@config";
9+
import type { Page } from "astro";
10+
import type { CollectionEntry } from "astro:content";
1011
1112
export interface Props {
12-
currentPage: number;
13-
totalPages: number;
14-
paginatedPosts: CollectionEntry<"blog">[];
13+
page: Page<CollectionEntry<"blog">>;
1514
tag: string;
1615
tagName: string;
1716
}
1817
19-
const { currentPage, totalPages, paginatedPosts, tag, tagName } = Astro.props;
18+
const { page, tag, tagName } = Astro.props;
2019
---
2120

2221
<Layout title={`Tag: ${tagName} | ${SITE.title}`}>
@@ -29,21 +28,14 @@ const { currentPage, totalPages, paginatedPosts, tag, tagName } = Astro.props;
2928
<h1 slot="title" transition:name={tag}>{`Tag:${tag}`}</h1>
3029
<ul>
3130
{
32-
paginatedPosts.map(({ data, slug }) => (
31+
page.data.map(({ data, slug }) => (
3332
<Card href={`/posts/${slug}/`} frontmatter={data} />
3433
))
3534
}
3635
</ul>
3736
</Main>
3837

39-
<Pagination
40-
{currentPage}
41-
{totalPages}
42-
prevUrl={`/tags/${tag}${
43-
currentPage - 1 !== 1 ? "/" + (currentPage - 1) : ""
44-
}/`}
45-
nextUrl={`/tags/${tag}/${currentPage + 1}/`}
46-
/>
38+
<Pagination {page} />
4739

48-
<Footer noMarginTop={totalPages > 1} />
40+
<Footer noMarginTop={page.lastPage > 1} />
4941
</Layout>

src/pages/posts/[...page].astro

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
import { SITE } from "@config";
3+
import Posts from "@layouts/Posts.astro";
4+
import type { GetStaticPaths } from "astro";
5+
import { getCollection } from "astro:content";
6+
7+
export const getStaticPaths = (async ({ paginate }) => {
8+
const posts = await getCollection("blog", ({ data }) => !data.draft);
9+
return paginate(posts, { pageSize: SITE.postPerPage });
10+
}) satisfies GetStaticPaths;
11+
12+
const { page } = Astro.props;
13+
---
14+
15+
<Posts {page} />

src/pages/posts/[page].astro

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
import { SITE } from "@config";
3+
import Posts from "@layouts/Posts.astro";
4+
import type { GetStaticPaths } from "astro";
5+
import { getCollection } from "astro:content";
6+
7+
export const getStaticPaths = (async ({ paginate }) => {
8+
const posts = await getCollection("blog", ({ data }) => !data.draft);
9+
return paginate(posts, { pageSize: SITE.postPerPage });
10+
}) satisfies GetStaticPaths;
11+
12+
const { page } = Astro.props;
13+
---
14+
15+
<Posts {page} />

src/pages/posts/[slug]/index.astro

+2-20
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
---
22
import { type CollectionEntry, getCollection } from "astro:content";
3-
import Posts from "@layouts/Posts.astro";
43
import PostDetails from "@layouts/PostDetails.astro";
5-
import getSortedPosts from "@utils/getSortedPosts";
6-
import getPageNumbers from "@utils/getPageNumbers";
7-
import getPagination from "@utils/getPagination";
84
95
export interface Props {
106
post: CollectionEntry<"blog">;
@@ -18,24 +14,10 @@ export async function getStaticPaths() {
1814
props: { post },
1915
}));
2016
21-
const pagePaths = getPageNumbers(posts.length).map(pageNum => ({
22-
params: { slug: String(pageNum) },
23-
}));
24-
25-
return [...postResult, ...pagePaths];
17+
return postResult;
2618
}
2719
28-
const { slug } = Astro.params;
2920
const { post } = Astro.props;
30-
31-
const posts = await getCollection("blog");
32-
33-
const sortedPosts = getSortedPosts(posts);
34-
35-
const pagination = getPagination({
36-
posts: sortedPosts,
37-
page: slug,
38-
});
3921
---
4022

41-
{post ? <PostDetails post={post} /> : <Posts {...pagination} />}
23+
<PostDetails post={post} />

src/pages/posts/index.astro

-18
This file was deleted.

src/pages/tags/[tag]/[...page].astro

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
import { getCollection } from "astro:content";
3+
import TagPosts from "@layouts/TagPosts.astro";
4+
import getUniqueTags from "@utils/getUniqueTags";
5+
import getPostsByTag from "@utils/getPostsByTag";
6+
import type { GetStaticPathsOptions } from "astro";
7+
import { SITE } from "@config";
8+
9+
export async function getStaticPaths({ paginate }: GetStaticPathsOptions) {
10+
const posts = await getCollection("blog");
11+
const tags = getUniqueTags(posts);
12+
13+
return tags.flatMap(({ tag, tagName }) => {
14+
const tagPosts = getPostsByTag(posts, tag);
15+
16+
return paginate(tagPosts, {
17+
params: { tag },
18+
props: { tagName },
19+
pageSize: SITE.postPerPage,
20+
});
21+
});
22+
}
23+
24+
const params = Astro.params;
25+
const { tag } = params;
26+
const { page, tagName } = Astro.props;
27+
---
28+
29+
<TagPosts {page} {tag} {tagName} />

src/pages/tags/[tag]/[page].astro

+13-28
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,29 @@
11
---
2-
import { type CollectionEntry, getCollection } from "astro:content";
2+
import { getCollection } from "astro:content";
33
import TagPosts from "@layouts/TagPosts.astro";
44
import getUniqueTags from "@utils/getUniqueTags";
55
import getPostsByTag from "@utils/getPostsByTag";
6-
import getPageNumbers from "@utils/getPageNumbers";
7-
import getPagination from "@utils/getPagination";
6+
import type { GetStaticPathsOptions } from "astro";
7+
import { SITE } from "@config";
88
9-
export interface Props {
10-
post: CollectionEntry<"blog">;
11-
tag: string;
12-
tagName: string;
13-
}
14-
15-
export async function getStaticPaths() {
9+
export async function getStaticPaths({ paginate }: GetStaticPathsOptions) {
1610
const posts = await getCollection("blog");
17-
1811
const tags = getUniqueTags(posts);
1912
2013
return tags.flatMap(({ tag, tagName }) => {
2114
const tagPosts = getPostsByTag(posts, tag);
22-
const totalPages = getPageNumbers(tagPosts.length);
2315
24-
return totalPages.map(page => ({
25-
params: { tag, page },
26-
props: { tag, tagName },
27-
}));
16+
return paginate(tagPosts, {
17+
params: { tag },
18+
props: { tagName },
19+
pageSize: SITE.postPerPage,
20+
});
2821
});
2922
}
3023
31-
const { page } = Astro.params;
32-
const { tag, tagName } = Astro.props;
33-
34-
const posts = await getCollection("blog", ({ data }) => !data.draft);
35-
36-
const postsByTag = getPostsByTag(posts, tag);
37-
38-
const pagination = getPagination({
39-
posts: postsByTag,
40-
page,
41-
});
24+
const params = Astro.params;
25+
const { tag } = params;
26+
const { page, tagName } = Astro.props;
4227
---
4328

44-
<TagPosts {...pagination} {tag} {tagName} />
29+
<TagPosts {page} {tag} {tagName} />

src/pages/tags/[tag]/index.astro

-32
This file was deleted.

src/utils/getPageNumbers.ts

-14
This file was deleted.

0 commit comments

Comments
 (0)