ai-chatbot/components/home/lovart/lovart-featured-gallery.tsx

101 lines
4.1 KiB
TypeScript

import { Heart, Loader2, Sparkles } from "lucide-react";
import type { Ref } from "react";
import type { FeaturedImage } from "./types";
import { MASONRY_HEIGHTS } from "./utils";
type LovartFeaturedGalleryProps = {
activeCategory: string;
categories: string[];
featuredItems: FeaturedImage[];
featuredLoadMoreRef: Ref<HTMLDivElement>;
featuredSectionRef: Ref<HTMLElement>;
isLoadingFeatured: boolean;
isLoadingMoreFeatured: boolean;
setActiveCategory: (category: string) => void;
};
export function LovartFeaturedGallery({
activeCategory,
categories,
featuredItems,
featuredLoadMoreRef,
featuredSectionRef,
isLoadingFeatured,
isLoadingMoreFeatured,
setActiveCategory,
}: LovartFeaturedGalleryProps) {
return (
<section ref={featuredSectionRef} className="mt-16">
<h2 className="text-[18px] font-semibold tracking-tight">灵感发现</h2>
<div className="mt-3 flex flex-wrap gap-1.5">
{categories.map((category) => (
<button
key={category}
type="button"
onClick={() => setActiveCategory(category)}
className={`rounded-xl px-3 py-1.5 text-[12px] ${
activeCategory === category
? "bg-[#ececec] text-black dark:bg-[#24242a] dark:text-white"
: "text-black/55 hover:bg-white dark:text-white/55 dark:hover:bg-[#17171b]"
}`}
>
{category}
</button>
))}
</div>
{featuredItems.length === 0 ? (
<div className="mt-5 rounded-xl border border-dashed border-black/15 bg-white p-10 text-center text-black/35 dark:border-white/12 dark:bg-[#141416] dark:text-white/35">
{isLoadingFeatured ? "灵感内容加载中..." : "当前没有可展示的灵感数据。"}
</div>
) : (
<div className="mt-5 columns-1 gap-4 md:columns-2 xl:columns-4">
{featuredItems.map((item, index) => (
<button
key={item.id}
type="button"
onClick={() => window.open(item.originalUrl || item.thumbnailUrl, "_blank")}
className="group mb-4 block w-full cursor-pointer break-inside-avoid rounded-2xl border border-black/8 bg-white text-left shadow-sm transition hover:-translate-y-0.5 dark:border-white/10 dark:bg-[#141416]"
>
<div
className="overflow-hidden rounded-t-2xl bg-[#e8e8e8] dark:bg-[#1b1c20]"
style={{ height: `${MASONRY_HEIGHTS[index % MASONRY_HEIGHTS.length]}px` }}
>
<img
src={item.thumbnailUrl || item.originalUrl}
alt={item.prompt || "灵感图"}
className="h-full w-full object-cover transition-transform duration-300 ease-out will-change-transform group-hover:scale-[1.04]"
/>
</div>
<div className="flex items-center justify-between px-3 py-2 text-[12px] text-black/60 dark:text-white/55">
<div className="line-clamp-1 font-medium text-black/85 dark:text-white/85">
{item.user?.name || "创作者"}
</div>
<div className="inline-flex items-center gap-2 text-[11px]">
<span className="inline-flex items-center gap-1">
<Sparkles className="h-2.5 w-2.5" />
{(1200 + index * 37).toLocaleString()}
</span>
<span className="inline-flex items-center gap-1">
<Heart className="h-2.5 w-2.5" />
{(20 + (index % 9) * 11).toLocaleString()}
</span>
</div>
</div>
</button>
))}
</div>
)}
<div ref={featuredLoadMoreRef} className="mt-3 flex h-10 items-center justify-center">
{isLoadingMoreFeatured ? (
<div className="inline-flex items-center gap-2 text-sm text-black/45 dark:text-white/45">
<Loader2 className="h-3.5 w-3.5 animate-spin" />
正在加载更多灵感...
</div>
) : null}
</div>
</section>
);
}