288 lines
16 KiB
TypeScript
288 lines
16 KiB
TypeScript
'use client';
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import Link from 'next/link';
|
|
import { Locale } from '../lib/i18n';
|
|
import { getTranslations } from '../lib/translations';
|
|
|
|
interface BlogShowcaseProps {
|
|
locale: Locale;
|
|
}
|
|
|
|
export default function BlogShowcase({ locale }: BlogShowcaseProps) {
|
|
const t = getTranslations(locale);
|
|
const [hoveredPost, setHoveredPost] = useState<string | null>(null);
|
|
|
|
// 获取博客文章数据
|
|
const blogPosts = [
|
|
{
|
|
id: 'featured',
|
|
...t.blog.posts.featured,
|
|
image: 'featured',
|
|
},
|
|
{
|
|
id: 'post1',
|
|
...t.blog.posts.post1,
|
|
image: 'post1',
|
|
},
|
|
{
|
|
id: 'post2',
|
|
...t.blog.posts.post2,
|
|
image: 'post2',
|
|
},
|
|
{
|
|
id: 'post3',
|
|
...t.blog.posts.post3,
|
|
image: 'post3',
|
|
},
|
|
];
|
|
|
|
const getCategoryColor = (category: string) => {
|
|
switch (category) {
|
|
case 'playerStories':
|
|
return 'bg-amber-500';
|
|
case 'development':
|
|
return 'bg-green-500';
|
|
case 'ecoFacts':
|
|
return 'bg-emerald-500';
|
|
default:
|
|
return 'bg-blue-500';
|
|
}
|
|
};
|
|
|
|
const getCategoryName = (category: string) => {
|
|
switch (category) {
|
|
case 'playerStories':
|
|
return t.blog.categories.playerStories;
|
|
case 'development':
|
|
return t.blog.categories.development;
|
|
case 'ecoFacts':
|
|
return t.blog.categories.ecoFacts;
|
|
default:
|
|
return category;
|
|
}
|
|
};
|
|
|
|
const getImageGradient = (imageId: string) => {
|
|
const gradients = {
|
|
featured: 'from-purple-500 via-blue-500 to-indigo-600',
|
|
post1: 'from-amber-500 via-orange-500 to-red-500',
|
|
post2: 'from-cyan-500 via-blue-500 to-indigo-500',
|
|
post3: 'from-green-500 via-emerald-500 to-teal-500',
|
|
};
|
|
return gradients[imageId as keyof typeof gradients] || 'from-gray-500 to-gray-600';
|
|
};
|
|
|
|
return (
|
|
<section className="relative z-10 py-20 bg-gradient-to-br from-slate-800 via-slate-900 to-black">
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
{/* Section Header */}
|
|
<div className="text-center mb-16">
|
|
<h2 className="text-4xl md:text-5xl font-bold text-white mb-4">
|
|
{t.blog.title}
|
|
</h2>
|
|
<p className="text-xl text-white/80 max-w-3xl mx-auto leading-relaxed">
|
|
{t.blog.subtitle}
|
|
</p>
|
|
<div className="mt-8">
|
|
<Link
|
|
href={`/${locale}/blog`}
|
|
className="inline-flex items-center bg-gradient-to-r from-green-500 to-emerald-600 hover:from-green-600 hover:to-emerald-700 text-white px-8 py-3 rounded-full font-semibold transition-all duration-200 transform hover:scale-105 shadow-lg"
|
|
>
|
|
{t.blog.categories.all}
|
|
<svg
|
|
className="w-5 h-5 ml-2"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
strokeWidth={2}
|
|
d="M17 8l4 4m0 0l-4 4m4-4H3"
|
|
/>
|
|
</svg>
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Blog Posts Grid */}
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
{/* Featured Post */}
|
|
<div className="lg:row-span-2">
|
|
<Link href={`/${locale}/blog/${blogPosts[0].id}`}>
|
|
<article
|
|
className="group cursor-pointer h-full"
|
|
onMouseEnter={() => setHoveredPost(blogPosts[0].id)}
|
|
onMouseLeave={() => setHoveredPost(null)}
|
|
>
|
|
<div className="bg-white/10 backdrop-blur-md rounded-3xl overflow-hidden border border-white/20 shadow-2xl hover:shadow-3xl transition-all duration-500 transform hover:scale-[1.02] h-full">
|
|
{/* Featured Post Image */}
|
|
<div className="relative h-80 overflow-hidden">
|
|
<div
|
|
className={`absolute inset-0 bg-gradient-to-br ${getImageGradient(blogPosts[0].image)} opacity-90`}
|
|
>
|
|
<div className="absolute inset-0 bg-black/20"></div>
|
|
{/* Animated particles for featured post */}
|
|
<div className="absolute inset-0">
|
|
{[...Array(6)].map((_, i) => (
|
|
<div
|
|
key={i}
|
|
className={`absolute w-2 h-2 bg-white/30 rounded-full animate-pulse ${
|
|
hoveredPost === blogPosts[0].id
|
|
? 'animate-bounce'
|
|
: ''
|
|
}`}
|
|
style={{
|
|
left: `${20 + i * 15}%`,
|
|
top: `${30 + (i % 2) * 20}%`,
|
|
animationDelay: `${i * 0.2}s`,
|
|
}}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div className="absolute top-6 left-6">
|
|
<span
|
|
className={`${getCategoryColor(blogPosts[0].category)} text-white px-4 py-2 rounded-full text-sm font-medium shadow-lg`}
|
|
>
|
|
{getCategoryName(blogPosts[0].category)}
|
|
</span>
|
|
</div>
|
|
<div className="absolute top-6 right-6">
|
|
<div className="bg-white/20 backdrop-blur-sm rounded-full px-3 py-1">
|
|
<span className="text-white text-sm font-medium">
|
|
{t.blog.featured}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div className="absolute bottom-6 left-6 right-6">
|
|
<div className="text-white/90 text-sm mb-2">
|
|
<div className="flex items-center space-x-4">
|
|
<span>{blogPosts[0].author}</span>
|
|
<span>•</span>
|
|
<span>{blogPosts[0].date}</span>
|
|
<span>•</span>
|
|
<span>{blogPosts[0].readTime}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Featured Post Content */}
|
|
<div className="p-8">
|
|
<h3 className="text-2xl font-bold text-white mb-4 group-hover:text-green-300 transition-colors duration-200 leading-tight">
|
|
{blogPosts[0].title}
|
|
</h3>
|
|
<p className="text-white/80 mb-6 leading-relaxed line-clamp-3">
|
|
{blogPosts[0].excerpt}
|
|
</p>
|
|
<div className="flex items-center justify-between">
|
|
<span className="text-green-300 font-medium group-hover:text-green-200 transition-colors duration-200">
|
|
{t.blog.readMore} →
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</article>
|
|
</Link>
|
|
</div>
|
|
|
|
{/* Other Posts */}
|
|
<div className="space-y-8">
|
|
{blogPosts.slice(1).map((post, index) => (
|
|
<Link key={post.id} href={`/${locale}/blog/${post.id}`}>
|
|
<article
|
|
className="group cursor-pointer"
|
|
onMouseEnter={() => setHoveredPost(post.id)}
|
|
onMouseLeave={() => setHoveredPost(null)}
|
|
>
|
|
<div className="bg-white/10 backdrop-blur-md rounded-2xl overflow-hidden border border-white/20 shadow-xl hover:shadow-2xl transition-all duration-300 transform hover:scale-[1.02]">
|
|
<div className="flex">
|
|
{/* Post Image */}
|
|
<div className="relative w-32 h-32 flex-shrink-0 overflow-hidden">
|
|
<div
|
|
className={`absolute inset-0 bg-gradient-to-br ${getImageGradient(post.image)} opacity-90`}
|
|
>
|
|
<div className="absolute inset-0 bg-black/20"></div>
|
|
{/* Mini particles */}
|
|
<div className="absolute inset-0">
|
|
{[...Array(3)].map((_, i) => (
|
|
<div
|
|
key={i}
|
|
className={`absolute w-1 h-1 bg-white/40 rounded-full ${
|
|
hoveredPost === post.id
|
|
? 'animate-ping'
|
|
: 'animate-pulse'
|
|
}`}
|
|
style={{
|
|
left: `${30 + i * 20}%`,
|
|
top: `${40 + i * 10}%`,
|
|
animationDelay: `${i * 0.3}s`,
|
|
}}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div className="absolute top-2 left-2">
|
|
<span
|
|
className={`${getCategoryColor(post.category)} text-white px-2 py-1 rounded-full text-xs font-medium`}
|
|
>
|
|
{getCategoryName(post.category)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Post Content */}
|
|
<div className="flex-1 p-6">
|
|
<h4 className="text-lg font-bold text-white mb-2 group-hover:text-green-300 transition-colors duration-200 line-clamp-2">
|
|
{post.title}
|
|
</h4>
|
|
<p className="text-white/70 text-sm mb-3 line-clamp-2">
|
|
{post.excerpt}
|
|
</p>
|
|
<div className="flex items-center justify-between">
|
|
<div className="text-white/60 text-xs">
|
|
<span>{post.author}</span>
|
|
<span className="mx-2">•</span>
|
|
<span>{post.readTime}</span>
|
|
</div>
|
|
<span className="text-green-300 text-sm font-medium group-hover:text-green-200 transition-colors duration-200">
|
|
→
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</article>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Bottom CTA */}
|
|
<div className="text-center mt-16">
|
|
<div className="bg-gradient-to-r from-green-500/20 to-emerald-500/20 backdrop-blur-md rounded-2xl p-8 border border-green-500/30">
|
|
<h3 className="text-2xl font-bold text-white mb-4">{t.blog.stayUpdated}</h3>
|
|
<p className="text-white/80 mb-6 max-w-2xl mx-auto">
|
|
{t.blog.stayUpdatedDesc}
|
|
</p>
|
|
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
|
<Link
|
|
href={`/${locale}/blog`}
|
|
className="bg-green-500 hover:bg-green-600 text-white px-8 py-3 rounded-full font-semibold transition-all duration-200 transform hover:scale-105"
|
|
>
|
|
{t.blog.exploreAll}
|
|
</Link>
|
|
<button className="border-2 border-green-500 text-green-400 hover:bg-green-500 hover:text-white px-8 py-3 rounded-full font-semibold transition-all duration-200">
|
|
{t.blog.subscribe}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|