83 lines
3 KiB
TypeScript
83 lines
3 KiB
TypeScript
import { getAllCategories } from '@/lib/categories'
|
|
import { getAllPostsMeta } from '@/lib/posts'
|
|
import { slugify } from '@/utils/slug'
|
|
import type { Metadata } from 'next'
|
|
import Link from 'next/link'
|
|
import { metadata } from '@/app/metadata'
|
|
import { dateFormatter } from '@/utils/time'
|
|
|
|
export async function generateStaticParams() {
|
|
const categories = getAllCategories()
|
|
return Object.keys(categories).map((category) => ({
|
|
categorySlug: category,
|
|
}))
|
|
}
|
|
|
|
export async function generateMetadata(): Promise<Metadata> {
|
|
return {
|
|
title: `Categories | ${metadata.title!.toString()}`,
|
|
description: 'List of categories',
|
|
openGraph: {
|
|
type: 'website',
|
|
title: `Categories | ${metadata.title!.toString()}`,
|
|
description: 'List of categories',
|
|
url: process.env.SITE_URL + '/categories',
|
|
siteName: metadata.title!.toString(),
|
|
},
|
|
}
|
|
}
|
|
|
|
export default function CategoriesPage() {
|
|
const categories = getAllCategories()
|
|
const posts = getAllPostsMeta()
|
|
const categoryNames = Object.keys(categories)
|
|
|
|
return (
|
|
<main className="max-w-3xl 2xl:max-w-4xl mx-auto px-4 py-8 lg:py-16 w-full">
|
|
<div className="text-sm text-fg-dim mb-2">~/categories</div>
|
|
|
|
<ul className="border-l border-neutral-800 ml-1">
|
|
{categoryNames.map((category) => {
|
|
const categoryPosts = posts.filter((post) => post.category === category)
|
|
|
|
return (
|
|
<li key={category} className="pl-5">
|
|
<Link
|
|
href={`/categories/${slugify(category)}`}
|
|
className="group flex items-baseline gap-2 py-2 px-2 -ml-2 hover:bg-accent/10 transition-colors"
|
|
>
|
|
<span className="font-bold group-hover:text-accent transition-colors">
|
|
{category}
|
|
</span>
|
|
<span className="font-mono text-xs text-neutral-600">({categoryPosts.length})</span>
|
|
</Link>
|
|
|
|
<ul className="border-l border-neutral-800 ml-3 mb-3">
|
|
{categoryPosts.map((post) => (
|
|
<li key={post.slug} className="pl-5">
|
|
<Link
|
|
href={`/posts/${post.slug}`}
|
|
className="group flex items-baseline justify-between gap-3 py-1.5 px-2 -ml-2 border-l-2 border-transparent hover:bg-accent/10 hover:border-accent transition-colors"
|
|
>
|
|
<span className="group-hover:text-accent transition-colors truncate">
|
|
{post.title}
|
|
</span>
|
|
{post.date && (
|
|
<time
|
|
dateTime={new Date(post.date).toISOString()}
|
|
className="text-sm whitespace-nowrap"
|
|
>
|
|
{dateFormatter.format(new Date(post.date))}
|
|
</time>
|
|
)}
|
|
</Link>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</li>
|
|
)
|
|
})}
|
|
</ul>
|
|
</main>
|
|
)
|
|
}
|