Add dynamic pagination for blog posts #1

Merged
nakada0907 merged 1 commit from develop into main 2025-05-17 12:30:58 +00:00
2 changed files with 126 additions and 32 deletions

View file

@ -1,32 +0,0 @@
---
import { getCollection } from "astro:content";
import BaseLayout from "../layouts/BaseLayout.astro";
import BlogPost from "../components/BlogPost.astro";
const allPosts = await getCollection("blog");
const pageTitle = "Latest Posts";
---
<style>
.list-articles {
text-align: start;
margin-bottom: 2rem;
}
</style>
<BaseLayout pageTitle={pageTitle}>
<div class="list-articles">
{
allPosts.map((post: any) => (
<BlogPost
url={`/posts/${post.id}/`}
title={post.data.title}
datetime={post.data.pubDate.toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
})}
/>
))
}
</div>
</BaseLayout>

View file

@ -0,0 +1,126 @@
---
import { getCollection } from "astro:content";
import BaseLayout from "../../layouts/BaseLayout.astro";
import BlogPost from "../../components/BlogPost.astro";
type Page<T> = {
data: T[];
currentPage: number;
lastPage: number;
url: {
current: string;
first?: string;
prev?: string;
next?: string;
last?: string;
};
};
type BlogPostEntry = {
id: string;
data: {
title: string;
pubDate: Date;
};
};
interface Props {
page: Page<BlogPostEntry>;
}
export async function getStaticPaths({
paginate
} : {
paginate: (data: any[], options?: { pageSize?: number; params?: Record<string, string>; props?: Record<string, any> }) => any;
}) {
const allPosts = await getCollection("blog");
allPosts.sort(
(a, b) => new Date(b.data.pubDate).getTime() - new Date(a.data.pubDate).getTime()
);
return paginate(
allPosts,
{
pageSize: 6,
}
);
}
const { page } = Astro.props as Props;
const pageTitle = "Articles";
---
<style>
.list-articles {
text-align: start;
margin-bottom: 2rem;
}
nav.pagination {
display: flex;
justify-content: center;
align-items: center;
gap: 1rem;
margin-top: 2rem;
flex-wrap: wrap;
}
nav.pagination a,
nav.pagination span {
display: inline-block;
padding: 12px 24px;
background-color: #e0e0e0;
color: #333333;
font-size: 1rem;
font-weight: 600;
border-radius: 6px;
text-decoration: none;
transition: background-color 0.3s ease, transform 0.3s ease;
}
nav.pagination a:hover {
background-color: #cacaca;
transform: translateY(-2px);
}
nav.pagination a.active {
background-color: #cacaca;
font-weight: bold;
pointer-events: none;
}
@media (max-width: 600px) {
nav.pagination {
flex-direction: column;
gap: 8px;
}
nav.pagination a,
nav.pagination span {
padding: 10px 16px;
font-size: 0.9rem;
}
}
</style>
<BaseLayout pageTitle={ pageTitle }>
<div class="list-articles">
{
page.data.map((post) => (
<BlogPost
url={`/posts/${post.id}/`}
title={post.data.title}
datetime={post.data.pubDate.toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
})}
/>
))
}
</div>
<nav class="pagination">
{page.url.first && <a href={page.url.first}>&larr; First</a>}
{page.url.prev && <a href={page.url.prev}>&larr; Previous</a>}
<span>Page {page.currentPage} of {page.lastPage}</span>
{page.url.next && <a href={page.url.next}>Next &rarr;</a>}
{page.url.last && <a href={page.url.last}>Last</a>}
</nav>
</BaseLayout>