"use client" import { Badge } from "@/components/ui/badge"; import { Avatar, AvatarFallback } from "@/components/ui/avatar"; import { gql, useQuery } from "@apollo/client"; import Link from "next/link"; import { formatDistanceToNow } from "date-fns"; const BLOG = gql` query Blog { blogs(filter: { isActive: true status: "published" }, sort: { field: "createdAt" direction: "DESC" } ) { items { id title excerpt slug createdAt createdBy categoryId featuredImage } } } ` const INFO = gql` query Info($tagId: String!, $categoryId: String!, $authorId: String!) { blogTag(id: $tagId) { name slug color } blogCategory(id: $categoryId) { name slug } userWithGroups(id: $authorId) { user { username } } } ` export default function Blog() { const { data, loading, error } = useQuery(BLOG); const items = data?.blogs?.items || []; if (loading) { return (
Loading...
); } if (error) { return (
Error: {error.message}
); } return (

Latest articles

{items.length === 0 ? (
No articles found
) : (
{items.map((blog: any, index: number) => ( ))}
)}
); } interface BlogItemProps { blog: { id: string; title: string; excerpt: string; slug: string; createdAt: string; createdBy: string; categoryId: string; featuredImage?: string; }; featured?: boolean; } function BlogItem({ blog, featured = false }: BlogItemProps) { const timeAgo = formatDistanceToNow(new Date(blog.createdAt), { addSuffix: true }); // 使用 INFO 查询获取详细信息 const { data: infoData, loading: infoLoading } = useQuery(INFO, { variables: { tagId: blog.categoryId || "", categoryId: blog.categoryId, authorId: blog.createdBy }, skip: !blog.categoryId || !blog.createdBy, }); const category = infoData?.blogCategory; const author = infoData?.userWithGroups?.user; const tag = infoData?.blogTag; return (
{/* Featured Image */}
{blog.featuredImage ? ( {blog.title} ) : (
No image
)}
{/* Meta Information */}
{category?.name || tag?.name || 'Article'}
By {author?.username?.charAt(0)?.toUpperCase() || 'A'} {infoLoading ? 'Loading...' : (author?.username || 'Anonymous')} {timeAgo}
{/* Content */}

{blog.title}

{blog.excerpt || 'No excerpt available...'}

); }