mirror of
https://github.com/zenlm/zen-blog.git
synced 2026-10-30 15:05:49 +00:00
The home now says who makes Zen LM, Zoo Labs Foundation, a 501(c)(3) non-profit, the two jobs it is chosen for, that Zen 6 and Zen 6 Flash are available now, and that Zen 7 is a research preview with a link to request access. The footer names the foundation, and "Qwen" leaves the site keywords. Posts marked "upstream: true" carry data-upstream on their page, card and read-more link, and scripts/check-zen.mjs fails the build when a name from zen.upstream shows anywhere else. The build stops measuring remote images: fumadocs fetched every one to read its size, and a single host answering 403 failed the build.
77 lines
2.1 KiB
TypeScript
77 lines
2.1 KiB
TypeScript
"use client";
|
|
|
|
import { useSearchParams } from "next/navigation";
|
|
import { BlogCard } from "@/components/blog-card";
|
|
import { TagSearch } from "@/components/tag-search";
|
|
|
|
interface BlogItem {
|
|
url: string;
|
|
title: string;
|
|
description: string;
|
|
date: string;
|
|
tags: string[];
|
|
thumbnail: string | null;
|
|
upstream: boolean;
|
|
formattedDate: string;
|
|
}
|
|
|
|
interface BlogListProps {
|
|
blogs: BlogItem[];
|
|
allTags: string[];
|
|
tagCounts: Record<string, number>;
|
|
}
|
|
|
|
export function BlogList({ blogs, allTags, tagCounts }: BlogListProps) {
|
|
const searchParams = useSearchParams();
|
|
const selectedTag = searchParams.get("tag") || "All";
|
|
|
|
const filteredBlogs =
|
|
selectedTag === "All"
|
|
? blogs
|
|
: blogs.filter((b) => b.tags.includes(selectedTag));
|
|
|
|
return (
|
|
<>
|
|
{/* Tag filter bar */}
|
|
<div className="max-w-5xl mx-auto w-full px-6 py-4 flex items-center justify-between gap-4">
|
|
<p className="text-sm text-muted-foreground">
|
|
{selectedTag === "All" ? (
|
|
<span>{blogs.length} posts</span>
|
|
) : (
|
|
<span>
|
|
<span className="text-foreground font-medium">{selectedTag}</span>
|
|
{" ยท "}
|
|
{filteredBlogs.length} post{filteredBlogs.length !== 1 ? "s" : ""}
|
|
</span>
|
|
)}
|
|
</p>
|
|
{allTags.length > 0 && (
|
|
<TagSearch
|
|
tags={allTags}
|
|
selectedTag={selectedTag}
|
|
tagCounts={tagCounts}
|
|
/>
|
|
)}
|
|
</div>
|
|
|
|
{/* Blog grid */}
|
|
<div className="max-w-5xl mx-auto w-full px-6">
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
{filteredBlogs.map((blog) => (
|
|
<BlogCard
|
|
key={blog.url}
|
|
url={blog.url}
|
|
title={blog.title}
|
|
description={blog.description}
|
|
date={blog.formattedDate}
|
|
thumbnail={blog.thumbnail ?? undefined}
|
|
upstream={blog.upstream}
|
|
showRightBorder={false}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|