ai-chatbot/components/home/lovart/lovart-projects-section.tsx

123 lines
4.9 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 { ArrowRight, Loader2, Trash2 } from "lucide-react";
import type { Ref } from "react";
import type { CanvasProject } from "./types";
import { formatRelativeTime } from "./utils";
type LovartProjectsSectionProps = {
deletingProjectId: string | null;
hasMoreProjects: boolean;
isProjectsOnlyView: boolean;
onCreateProject: () => void;
onDeleteProject: (projectId: string, projectTitle?: string) => void;
onOpenProject: (projectId: string) => void;
projects: CanvasProject[];
projectSectionRef: Ref<HTMLElement>;
setShowAllProjects: (updater: (value: boolean) => boolean) => void;
showAllProjects: boolean;
};
export function LovartProjectsSection({
deletingProjectId,
hasMoreProjects,
isProjectsOnlyView,
onCreateProject,
onDeleteProject,
onOpenProject,
projects,
projectSectionRef,
setShowAllProjects,
showAllProjects,
}: LovartProjectsSectionProps) {
return (
<section
ref={projectSectionRef}
className={isProjectsOnlyView ? "mt-6" : "mt-20"}
>
<div className="mb-4 flex items-center justify-between">
<h2 className="text-[18px] font-semibold tracking-tight">
{isProjectsOnlyView ? "所有项目" : "最近项目"}
</h2>
{!isProjectsOnlyView && hasMoreProjects ? (
<button
type="button"
className="inline-flex items-center gap-1 text-[13px] text-black/45 hover:text-black dark:text-white/45 dark:hover:text-white"
onClick={() => setShowAllProjects((value) => !value)}
>
{showAllProjects ? "收起" : "查看更多"}
<ArrowRight
className={`h-3.5 w-3.5 transition-transform ${showAllProjects ? "rotate-90" : ""}`}
/>
</button>
) : null}
</div>
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-4">
<button
type="button"
onClick={onCreateProject}
className="cursor-pointer rounded-[22px] border border-black/8 bg-white p-3 text-left shadow-sm transition hover:-translate-y-0.5 dark:border-white/10 dark:bg-[#141416]"
>
<div className="flex aspect-[4/3] items-center justify-center rounded-2xl bg-[#efefef] dark:bg-[#1b1c20]">
<div className="text-center">
<div className="mb-2 text-3xl">+</div>
<div className="text-[14px]">新建项目</div>
</div>
</div>
</button>
{projects.map((item) => (
<div
key={item.id}
className="group relative rounded-[22px] border border-black/8 bg-white p-3 text-left shadow-sm transition hover:-translate-y-0.5 dark:border-white/10 dark:bg-[#141416]"
>
<button
type="button"
onClick={() => onOpenProject(item.id)}
className="block w-full cursor-pointer text-left"
>
<div className="aspect-[4/3] overflow-hidden rounded-2xl bg-[#efefef] dark:bg-[#1b1c20]">
{item.thumbnail ? (
<img
src={item.thumbnail}
alt={item.title}
className="h-full w-full object-cover transition-transform duration-300 ease-out will-change-transform group-hover:scale-[1.045]"
/>
) : (
<div className="flex h-full w-full items-center justify-center text-black/35 dark:text-white/35">
Untitled
</div>
)}
</div>
<div className="mt-3 text-[14px] font-medium">
{item.title || "Untitled"}
</div>
<div className="mt-1 text-xs text-black/35 dark:text-white/35">
{formatRelativeTime(item.updatedAt || item.createdAt)}
</div>
</button>
<button
type="button"
onClick={() => onDeleteProject(item.id, item.title)}
disabled={deletingProjectId === item.id}
className="absolute right-5 top-5 z-20 inline-flex h-7 w-7 items-center justify-center rounded-full border border-black/10 bg-white/90 text-black/45 shadow-sm transition hover:border-[#ffb4b4] hover:text-[#ef4444] disabled:cursor-not-allowed disabled:opacity-80 dark:border-white/10 dark:bg-[#18181c]/90 dark:text-white/45"
aria-label={`删除${item.title || "未命名画布"}`}
>
{deletingProjectId === item.id ? (
<Loader2 className="h-3.5 w-3.5 animate-spin" />
) : (
<Trash2 className="h-3.5 w-3.5" />
)}
</button>
</div>
))}
{projects.length === 0 && (
<div className="rounded-[22px] border border-dashed border-black/15 bg-white p-6 text-center text-black/40 md:col-span-3 dark:border-white/12 dark:bg-[#141416] dark:text-white/40">
还没有项目,点击“新建项目”开始。
</div>
)}
</div>
</section>
);
}