feat: implement pagination for blog posts and enhance NavLink component with class support
This commit is contained in:
parent
ca2c54de0e
commit
6b831e7100
5 changed files with 87 additions and 39 deletions
|
|
@ -12,7 +12,7 @@ npm run dev
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
| Command | Action |
|
| Command | Action |
|
||||||
| :---------------- | :------------------------------------------ |
|
| :---------------- | :----------------------------------- |
|
||||||
| `npm install` | Install dependencies |
|
| `npm install` | Install dependencies |
|
||||||
| `npm run dev` | Start dev server at `localhost:4321` |
|
| `npm run dev` | Start dev server at `localhost:4321` |
|
||||||
| `npm run build` | Build production site to `./dist/` |
|
| `npm run build` | Build production site to `./dist/` |
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,15 @@
|
||||||
interface Props {
|
interface Props {
|
||||||
href: string;
|
href: string;
|
||||||
ariaLabel?: string;
|
ariaLabel?: string;
|
||||||
|
class?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { href, ariaLabel } = Astro.props;
|
const { href, ariaLabel, class: className } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<a
|
<a
|
||||||
href={href}
|
href={href}
|
||||||
class="hover:underline underline-offset-4 decoration-transparent hover:decoration-current transition-colors duration-300 aria-[current]:underline aria-[current]:decoration-current aria-[current]:font-semibold"
|
class={`hover:underline underline-offset-4 decoration-transparent hover:decoration-current transition-colors duration-300 aria-[current]:underline aria-[current]:decoration-current aria-[current]:font-semibold ${className ?? ""}`}
|
||||||
aria-label={ariaLabel}
|
aria-label={ariaLabel}
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
|
|
|
||||||
26
src/components/Pagination.astro
Normal file
26
src/components/Pagination.astro
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
---
|
||||||
|
import NavLink from "./NavLink.astro";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
currentPage: number;
|
||||||
|
lastPage: number;
|
||||||
|
getPageUrl: (page: number) => string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { currentPage, lastPage, getPageUrl } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<nav aria-label="Pagination Navigation" class="flex py-6">
|
||||||
|
{
|
||||||
|
currentPage > 1 && (
|
||||||
|
<NavLink href={getPageUrl(currentPage - 1)}>« Previous</NavLink>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
currentPage < lastPage && (
|
||||||
|
<NavLink href={getPageUrl(currentPage + 1)} class="ml-auto">
|
||||||
|
Next »
|
||||||
|
</NavLink>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</nav>
|
||||||
51
src/pages/posts/[...page].astro
Normal file
51
src/pages/posts/[...page].astro
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
---
|
||||||
|
import type { PaginateFunction, Page } from "astro";
|
||||||
|
import { getCollection } from "astro:content";
|
||||||
|
import Layout from "@/layouts/Layout.astro";
|
||||||
|
import BlogPostCard from "@/components/BlogPostCard.astro";
|
||||||
|
import PageTitle from "@/components/PageTitle.astro";
|
||||||
|
import type { CollectionEntry } from "astro:content";
|
||||||
|
import Pagination from "@/components/Pagination.astro";
|
||||||
|
|
||||||
|
export async function getStaticPaths({
|
||||||
|
paginate,
|
||||||
|
}: {
|
||||||
|
paginate: PaginateFunction;
|
||||||
|
}) {
|
||||||
|
const posts = await getCollection("blog");
|
||||||
|
posts.sort((a, b) => b.data.date.getTime() - a.data.date.getTime());
|
||||||
|
return paginate(posts, { pageSize: 5 });
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
page: Page<CollectionEntry<"blog">>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { page } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout
|
||||||
|
title="Posts - Dhemas Nurjaya"
|
||||||
|
description="Read the latest blog posts by Dhemas Nurjaya"
|
||||||
|
>
|
||||||
|
<PageTitle title="Posts" />
|
||||||
|
<ul class="space-y-4">
|
||||||
|
{
|
||||||
|
page.data.map((post) => (
|
||||||
|
<li>
|
||||||
|
<BlogPostCard
|
||||||
|
id={post.id}
|
||||||
|
title={post.data.title}
|
||||||
|
date={post.data.date}
|
||||||
|
description={post.data.description}
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
<Pagination
|
||||||
|
currentPage={page.currentPage}
|
||||||
|
lastPage={page.lastPage}
|
||||||
|
getPageUrl={(page) => (page === 1 ? `/posts/` : `/posts/${page}/`)}
|
||||||
|
/>
|
||||||
|
</Layout>
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
---
|
|
||||||
import { getCollection } from "astro:content";
|
|
||||||
import Layout from "@/layouts/Layout.astro";
|
|
||||||
import BlogPostCard from "@/components/BlogPostCard.astro";
|
|
||||||
import PageTitle from "@/components/PageTitle.astro";
|
|
||||||
|
|
||||||
const posts = await getCollection("blog");
|
|
||||||
posts.sort((a, b) => b.data.date.getTime() - a.data.date.getTime());
|
|
||||||
---
|
|
||||||
|
|
||||||
<Layout
|
|
||||||
title="Posts - Dhemas Nurjaya"
|
|
||||||
description="Read the latest blog posts by Dhemas Nurjaya"
|
|
||||||
>
|
|
||||||
<PageTitle title="Posts" />
|
|
||||||
<ul class="space-y-4">
|
|
||||||
{
|
|
||||||
posts.map((post) => (
|
|
||||||
<li>
|
|
||||||
<BlogPostCard
|
|
||||||
id={post.id}
|
|
||||||
title={post.data.title}
|
|
||||||
date={post.data.date}
|
|
||||||
description={post.data.description}
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
</Layout>
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue