Files
b5c2d278-ac3e-4542-8f83-dd9…/src/pages/CategoryDetail.tsx
“dongming” ed40350aeb first commit
2025-12-28 22:43:26 +08:00

149 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'
import { Header } from '../components/Header'
import { Footer } from '../components/Footer'
import { PostCard } from '../components/PostCard'
import { PostCardSkeleton } from '../components/PostCardSkeleton'
import { Posts, Categories } from '../clientsdk/sdk.gen'
import { createClient } from '../clientsdk/client'
import { customQuerySerializer } from '../clientsdk/querySerializer'
import { TENANT_SLUG, TENANT_API_KEY, API_URL } from '../config'
const client = createClient({
baseUrl: API_URL,
querySerializer: customQuerySerializer,
headers: {
'X-Tenant-Slug': TENANT_SLUG,
'X-API-Key': TENANT_API_KEY,
},
})
export const CategoryDetail: React.FC = () => {
const { slug } = useParams<{ slug: string }>()
const [posts, setPosts] = useState<any[]>([])
const [category, setCategory] = useState<any>(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
useEffect(() => {
if (!slug) return
const fetchData = async () => {
try {
setLoading(true)
setError(null)
const [categoriesRes, postsRes] = await Promise.all([
// Use listCategories with where filter since findCategoryById doesn't support slug lookup
Categories.listCategories({
client,
query: {
where: {
slug: {
equals: slug,
},
},
limit: 1,
},
}),
Posts.listPosts({
client,
query: {
limit: 100,
sort: '-createdAt',
},
}),
])
const categoryDocs = (categoriesRes as any)?.data?.docs || []
if (categoryDocs[0]) {
setCategory(categoryDocs[0])
}
const allDocs = (postsRes as any)?.data?.docs || []
// categories is an array, check if any category in the array matches the slug
const categoryPosts = allDocs.filter((post: any) =>
post.categories?.some((cat: any) => cat.slug === slug)
)
setPosts(categoryPosts)
} catch (err) {
setError(err instanceof Error ? err.message : '加载失败')
console.error('获取数据失败:', err)
} finally {
setLoading(false)
}
}
fetchData()
}, [slug])
const stripHtml = (html: string): string => {
const tmp = document.createElement('div')
tmp.innerHTML = html
return tmp.textContent || tmp.innerText || ''
}
const formatDate = (dateString: string): string => {
const date = new Date(dateString)
return date.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric',
})
}
const getCategoryTitle = (post: any): string | undefined => {
// categories is an array, get the first one
return post.categories?.[0]?.title
}
const handlePostClick = (postSlug: string) => {
window.location.href = `/posts/${postSlug}`
}
return (
<div className="min-h-screen bg-gray-50">
<Header />
<main className="container mx-auto px-4 py-8">
<section className="mb-12">
<h2 className="text-3xl font-bold text-gray-900 mb-2">
📂 {category?.title || '分类'}
</h2>
<p className="text-gray-600"></p>
</section>
{error && (
<div className="bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded-lg mb-6">
<strong></strong> {error}
</div>
)}
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
{loading
? Array.from({ length: 6 }).map((_, i) => <PostCardSkeleton key={i} />)
: posts.map((post) => (
<PostCard
key={post.id}
title={post.title}
excerpt={stripHtml(post.content_html || post.content?.root?.children?.[0]?.children?.[0]?.text || post.title)}
category={getCategoryTitle(post)}
date={formatDate(post.createdAt)}
onClick={() => handlePostClick(post.slug)}
/>
))}
</div>
{!loading && posts.length === 0 && !error && (
<div className="text-center py-12">
<p className="text-gray-500 text-lg"></p>
</div>
)}
</main>
<Footer />
</div>
)
}