mirror of
https://github.com/basketikun/infinite-canvas.git
synced 2026-07-24 06:54:06 +08:00
60 lines
2.4 KiB
TypeScript
60 lines
2.4 KiB
TypeScript
import { Copy, FileText } from "lucide-react";
|
|
import type { ReactNode } from "react";
|
|
import { Button, Card, Tag } from "antd";
|
|
|
|
import { formatPromptDate, type Prompt } from "@/services/api/prompts";
|
|
|
|
export function PromptCard({
|
|
item,
|
|
onOpen,
|
|
onCopy,
|
|
actionLabel = "复制",
|
|
actionIcon = <Copy className="size-3.5" />,
|
|
actionType = "text",
|
|
extraAction,
|
|
}: {
|
|
item: Prompt;
|
|
onOpen: () => void;
|
|
onCopy: () => void;
|
|
actionLabel?: string;
|
|
actionIcon?: ReactNode;
|
|
actionType?: "text" | "primary";
|
|
extraAction?: ReactNode;
|
|
}) {
|
|
return (
|
|
<Card
|
|
hoverable
|
|
className="overflow-hidden"
|
|
styles={{ body: { padding: 0 } }}
|
|
cover={
|
|
<button type="button" className="block w-full text-left" onClick={onOpen}>
|
|
{item.coverUrl ? <img src={item.coverUrl} alt={item.title} className="aspect-[4/3] w-full object-cover" loading="lazy" /> : <span className="grid aspect-[4/3] w-full place-items-center bg-stone-100 text-stone-400 dark:bg-stone-900 dark:text-stone-600"><FileText className="size-8" /></span>}
|
|
</button>
|
|
}
|
|
>
|
|
<button type="button" className="block w-full text-left" onClick={onOpen}>
|
|
<div className="p-4">
|
|
<div className="flex items-start justify-between gap-3">
|
|
<h2 className="line-clamp-1 text-sm font-semibold text-stone-950 dark:text-stone-100">{item.title}</h2>
|
|
<span className="shrink-0 text-xs text-stone-400 dark:text-stone-500">{formatPromptDate(item.updatedAt)}</span>
|
|
</div>
|
|
<p className="mt-2 line-clamp-3 text-xs leading-5 text-stone-600 dark:text-stone-400">{item.description || item.prompt}</p>
|
|
<div className="mt-3 flex flex-wrap gap-1.5">
|
|
{item.tags.map((tag) => (
|
|
<Tag key={tag} className="m-0 text-[11px]">
|
|
{tag}
|
|
</Tag>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</button>
|
|
<div className="flex items-center gap-2 px-4 pb-4">
|
|
<Button block={actionType === "primary"} type={actionType} size="small" icon={actionIcon} onClick={onCopy}>
|
|
{actionLabel}
|
|
</Button>
|
|
{extraAction}
|
|
</div>
|
|
</Card>
|
|
);
|
|
}
|