Files
kazoottt-blog/src/pages/blog/[...page].astro
2024-10-11 20:41:13 +08:00

170 lines
4.8 KiB
Plaintext

---
export const prerender = true
import type { GetStaticPaths, Page } from 'astro'
import type { CollectionEntry } from 'astro:content'
import Button from '@/components/Button.astro'
import Pagination from '@/components/Paginator.astro'
import PostPreview from '@/components/blog/PostPreview.astro'
import PageLayout from '@/layouts/BaseLayout.astro'
import { getAllPosts, getUniqueCategories, getUniqueTags, sortMDByDate } from '@/utils'
export const getStaticPaths = (async ({ paginate }) => {
const allPosts = await getAllPosts()
const allPostsByDate = sortMDByDate(allPosts)
const uniqueTags = getUniqueTags(allPosts)
const uniqueCategories = getUniqueCategories(allPosts)
return paginate(allPostsByDate, { pageSize: 50, props: { uniqueTags, uniqueCategories } })
}) satisfies GetStaticPaths
interface Props {
page: Page<CollectionEntry<'post'>>
uniqueTags: string[]
uniqueCategories: string[]
}
const { page, uniqueTags, uniqueCategories } = Astro.props
const meta = {
description: 'Posts',
title: 'Blog'
}
const paginationProps = {
...(page.url.prev && {
prevUrl: {
text: `← Previous Posts`,
url: page.url.prev
}
}),
...(page.url.next && {
nextUrl: {
text: `Next Posts →`,
url: page.url.next
}
})
}
---
<PageLayout meta={meta}>
<div class='w-full'>
<Button title='Back' href='/' style='button'>
<svg
xmlns='http://www.w3.org/2000/svg'
width='14'
height='14'
viewBox='0 0 24 24'
slot='icon-before'
>
<path
fill='currentColor'
d='m6.921 12.5l5.792 5.792L12 19l-7-7l7-7l.713.708L6.921 11.5H19v1z'
>
</path>
</svg>
</Button>
<h1 class='mb-6 mt-5 text-2xl font-bold'>Blog</h1>
{page.data.length === 0 && <p>No posts yet.</p>}
{
page.data.length > 0 && (
<div class='grid gap-y-16 sm:grid-cols-[3fr_1fr] sm:gap-x-8'>
<section aria-label='Blog posts list'>
<ul class='flex flex-col gap-y-4 text-start'>
{page.data.map((p) => (
<PostPreview post={p} />
))}
</ul>
<Pagination {...paginationProps} />
</section>
<div>
{!!uniqueCategories.length && (
<aside>
<h2 class='mb-4 flex items-center text-lg font-semibold'>
<svg
aria-hidden='true'
class='h-6 w-6'
fill='none'
stroke='currentColor'
stroke-linecap='round'
stroke-linejoin='round'
stroke-width='1.5'
viewBox='0 0 24 24'
xmlns='http://www.w3.org/2000/svg'
>
<path d='M0 0h24v24H0z' fill='none' stroke='none' />
<path d='M7.859 6h-2.834a2.025 2.025 0 0 0 -2.025 2.025v2.834c0 .537 .213 1.052 .593 1.432l6.116 6.116a2.025 2.025 0 0 0 2.864 0l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-6.117 -6.116a2.025 2.025 0 0 0 -1.431 -.593z' />
<path d='M17.573 18.407l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-7.117 -7.116' />
<path d='M6 9h-.01' />
</svg>
Categories
</h2>
<ul class='text-bgColor flex flex-wrap gap-2'>
{uniqueCategories.slice(0, 6).map((category) => (
<li>
<Button title={category} href={`/categories/${category}/`} style='pill' />
</li>
))}
</ul>
<span class='mt-4 block sm:text-end'>
<a
aria-label='View all blog categories'
class=''
href='/categories/'
data-astro-prefetch
>
View all →
</a>
</span>
</aside>
)}
{!!uniqueTags.length && (
<aside>
<h2 class='mb-4 flex items-center text-lg font-semibold'>
<svg
aria-hidden='true'
class='h-6 w-6'
fill='none'
stroke='currentColor'
stroke-linecap='round'
stroke-linejoin='round'
stroke-width='1.5'
viewBox='0 0 24 24'
xmlns='http://www.w3.org/2000/svg'
>
<path d='M0 0h24v24H0z' fill='none' stroke='none' />
<path d='M7.859 6h-2.834a2.025 2.025 0 0 0 -2.025 2.025v2.834c0 .537 .213 1.052 .593 1.432l6.116 6.116a2.025 2.025 0 0 0 2.864 0l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-6.117 -6.116a2.025 2.025 0 0 0 -1.431 -.593z' />
<path d='M17.573 18.407l2.834 -2.834a2.025 2.025 0 0 0 0 -2.864l-7.117 -7.116' />
<path d='M6 9h-.01' />
</svg>
Tags
</h2>
<ul class='text-bgColor flex flex-wrap gap-2'>
{uniqueTags.slice(0, 6).map((tag) => (
<li>
<Button title={tag} href={`/tags/${tag}/`} style='pill' />
</li>
))}
</ul>
<span class='mt-4 block sm:text-end'>
<a
aria-label='View all blog categories'
class=''
href='/tags/'
data-astro-prefetch
>
View all →
</a>
</span>
</aside>
)}
</div>
</div>
)
}
</div>
</PageLayout>