blog.hangerthem.com/app/(withRecent)/categories/page.tsx

76 lines
2.8 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 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 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>
)
}