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
14
README.md
14
README.md
|
|
@ -11,13 +11,13 @@ npm run dev
|
|||
|
||||
## Commands
|
||||
|
||||
| Command | Action |
|
||||
| :---------------- | :------------------------------------------ |
|
||||
| `npm install` | Install dependencies |
|
||||
| `npm run dev` | Start dev server at `localhost:4321` |
|
||||
| `npm run build` | Build production site to `./dist/` |
|
||||
| `npm run preview` | Preview production build locally |
|
||||
| `npm run format` | Format code with Prettier |
|
||||
| Command | Action |
|
||||
| :---------------- | :----------------------------------- |
|
||||
| `npm install` | Install dependencies |
|
||||
| `npm run dev` | Start dev server at `localhost:4321` |
|
||||
| `npm run build` | Build production site to `./dist/` |
|
||||
| `npm run preview` | Preview production build locally |
|
||||
| `npm run format` | Format code with Prettier |
|
||||
|
||||
## Tech Stack
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@
|
|||
interface Props {
|
||||
href: string;
|
||||
ariaLabel?: string;
|
||||
class?: string;
|
||||
}
|
||||
|
||||
const { href, ariaLabel } = Astro.props;
|
||||
const { href, ariaLabel, class: className } = Astro.props;
|
||||
---
|
||||
|
||||
<a
|
||||
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}
|
||||
>
|
||||
<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