mirror of
https://github.com/10h30/blog-balodeplao.git
synced 2026-05-12 15:21:15 +09:00
102 lines
3.1 KiB
Plaintext
102 lines
3.1 KiB
Plaintext
---
|
|
import BaseLayout from "@/layouts/BaseLayout.astro";
|
|
import { getCollection } from "astro:content";
|
|
import Headline from "@/components/ui/Headline.astro";
|
|
import PostItem from "@/components/blog/PostItem.astro";
|
|
import Pagination from "@/components/ui/Pagination.astro";
|
|
import type { Page } from "astro";
|
|
import type { CollectionEntry } from "astro:content";
|
|
import {
|
|
categoryMap,
|
|
getCategoryPath,
|
|
type TaxonomyItem,
|
|
} from "@/utils/taxonomy";
|
|
|
|
export async function getStaticPaths() {
|
|
const PAGE_SIZE = 6;
|
|
const allPosts = await getCollection("blog");
|
|
const posts = allPosts.filter((post) => post.data && post.data.pubDate);
|
|
|
|
const catSlugs = new Set<string>();
|
|
posts.forEach((post) =>
|
|
post.data.categories?.forEach((c) => catSlugs.add(c)),
|
|
);
|
|
|
|
return Array.from(catSlugs).flatMap((slug) => {
|
|
const catPosts = posts
|
|
.filter((post) => post.data.categories?.includes(slug))
|
|
.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
|
|
|
|
const fullPath = getCategoryPath(slug);
|
|
const cat = categoryMap.get(slug) ?? ({ slug, name: slug } as TaxonomyItem);
|
|
const totalPages = Math.max(1, Math.ceil(catPosts.length / PAGE_SIZE));
|
|
|
|
return Array.from({ length: totalPages }, (_, i) => {
|
|
const pageNum = i + 1;
|
|
return {
|
|
params: { rest: pageNum === 1 ? fullPath : `${fullPath}/${pageNum}` },
|
|
props: {
|
|
cat,
|
|
fullPath,
|
|
posts: catPosts.slice(i * PAGE_SIZE, (i + 1) * PAGE_SIZE),
|
|
currentPage: pageNum,
|
|
lastPage: totalPages,
|
|
total: catPosts.length,
|
|
prevUrl:
|
|
pageNum === 1
|
|
? undefined
|
|
: pageNum === 2
|
|
? `/category/${fullPath}`
|
|
: `/category/${fullPath}/${pageNum - 1}`,
|
|
nextUrl:
|
|
pageNum === totalPages
|
|
? undefined
|
|
: `/category/${fullPath}/${pageNum + 1}`,
|
|
},
|
|
};
|
|
});
|
|
});
|
|
}
|
|
|
|
const { cat, posts, currentPage, lastPage, total, prevUrl, nextUrl } =
|
|
Astro.props;
|
|
|
|
const page = {
|
|
currentPage,
|
|
lastPage,
|
|
url: { prev: prevUrl, next: nextUrl },
|
|
} as unknown as Page<CollectionEntry<"blog">>;
|
|
|
|
const metadata = {
|
|
title: cat.name,
|
|
description: cat.description ?? `Các bài viết trong danh mục ${cat.name}.`,
|
|
};
|
|
---
|
|
|
|
<BaseLayout metadata={metadata}>
|
|
<section class="relative px-4 py-8 sm:px-6 lg:px-8 md:py-12">
|
|
<div class="relative mx-auto max-w-5xl">
|
|
<Headline
|
|
tagline="Category"
|
|
title={cat.name}
|
|
subtitle={cat.description ?? `Hiển thị ${total} bài viết.`}
|
|
classes={{
|
|
container: "mb-12 text-center",
|
|
title:
|
|
"font-heading mb-4 text-4xl font-bold tracking-tight text-foreground md:text-6xl capitalized",
|
|
subtitle: "mx-auto max-w-3xl text-xl text-muted-foreground",
|
|
}}
|
|
/>
|
|
|
|
<div class="mb-8 text-center">
|
|
<a href="/blog" class="text-primary hover:underline">← Quay lại blog</a>
|
|
</div>
|
|
|
|
<div class="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
|
|
{posts.map((post) => <PostItem post={post} />)}
|
|
</div>
|
|
<Pagination page={page} />
|
|
</div>
|
|
</section>
|
|
</BaseLayout>
|