This commit is contained in:
ct
2025-07-17 03:42:55 +08:00
parent 06675de71b
commit 85917e0cdf
46 changed files with 2426 additions and 121 deletions

View File

@@ -0,0 +1,89 @@
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';
import { KeywordBadge } from '@/components/ui/keyword-badge';
import { Link } from '@inertiajs/react';
import { Edit } from 'lucide-react';
import { route } from 'ziggy-js';
interface MemeMedia {
ids: string;
name: string;
description: string;
keywords: string[];
action_keywords: string[];
emotion_keywords: string[];
misc_keywords: string[];
mov_url: string;
webm_url: string;
gif_url: string;
webp_url: string;
slug: string;
}
interface MemeCardProps {
meme: MemeMedia;
showButton?: boolean;
showKeywords?: boolean;
className?: string;
}
export function MemeCard({ meme, showButton = true, showKeywords = true, className = '' }: MemeCardProps) {
return (
<Card className={`group flex flex-col overflow-hidden p-0 transition-shadow hover:shadow-lg ${className}`}>
<div
className="relative aspect-[9/16] overflow-hidden"
style={{
backgroundColor: '#ffffff',
backgroundImage: `
linear-gradient(45deg, #cccccc 25%, transparent 25%),
linear-gradient(-45deg, #cccccc 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, #cccccc 75%),
linear-gradient(-45deg, transparent 75%, #cccccc 75%)
`,
backgroundSize: '20px 20px',
backgroundPosition: '0 0, 0 10px, 10px -10px, -10px 0px'
}}
>
<img
src={meme.webp_url}
alt={meme.name}
className="h-full w-full object-cover transition-transform group-hover:scale-105"
/>
<Link
href={route('memes.show', meme.slug)}
className="bg-opacity-0 absolute inset-0 flex items-center justify-center transition-all group-hover:opacity-40 hover:bg-black"
>
<Edit className="h-8 w-8 text-white opacity-0 transition-opacity group-hover:opacity-100" />
</Link>
</div>
<div className="flex flex-grow flex-col px-4 pt-0 pb-4">
<h3 className="text-foreground mb-2 line-clamp-2 text-sm font-semibold">{meme.name}</h3>
{showKeywords && (
<div className="mb-3 flex flex-wrap gap-1">
{meme.keywords?.slice(0, 6).map((keyword, index) => (
<KeywordBadge key={index} keyword={keyword} />
))}
{meme.keywords && meme.keywords.length > 6 && (
<Badge variant="secondary" className="text-xs">
+{meme.keywords.length - 6} more
</Badge>
)}
</div>
)}
{showButton && (
<div className="mt-auto">
<Link href={route('memes.show', meme.slug)}>
<Button
size="sm"
className="w-full bg-gradient-to-r from-purple-600 to-pink-600 text-white hover:from-purple-700 hover:to-pink-700"
>
Use meme
</Button>
</Link>
</div>
)}
</div>
</Card>
);
}