CloudPro/components/Banner/HeroBanner_fixed.tsx

460 lines
21 KiB
TypeScript
Raw Normal View History

2025-09-16 16:15:57 +08:00
'use client';
import { useState, useEffect, useRef } from 'react';
import { ChevronLeft, ChevronRight, Play, Pause, Star, Clock, Gift, Zap } from 'lucide-react';
interface BannerSlide {
id: string;
type: 'hero' | 'product' | 'promotion';
title: string;
subtitle?: string;
description: string;
image?: string;
gradient: string;
cta: {
primary: { text: string; href: string };
secondary?: { text: string; href: string };
};
badge?: {
text: string;
type: 'new' | 'hot' | 'discount' | 'limited';
};
features?: string[];
price?: {
original?: string;
current: string;
discount?: string;
};
}
interface HeroBannerProps {
currentLang: string;
translations: any;
}
export function HeroBanner({ currentLang, translations }: HeroBannerProps) {
const [currentSlide, setCurrentSlide] = useState(0);
const [isPlaying, setIsPlaying] = useState(true);
const [isHovered, setIsHovered] = useState(false);
const intervalRef = useRef<NodeJS.Timeout | null>(null);
const t = translations[currentLang];
// Banner slides data
const slides: BannerSlide[] = [
{
id: 'hero-main',
type: 'hero',
title:
currentLang === 'zh'
? '专业云服务器解决方案'
: 'Professional Cloud Server Solutions',
subtitle:
currentLang === 'zh'
? '为您的业务提供稳定、高效、安全的云计算服务'
: 'Stable, Efficient, and Secure Cloud Computing Services',
description:
currentLang === 'zh'
? '我们是领先的云服务器代理商,提供全球顶级云服务商的产品与服务,助力企业数字化转型'
: 'Leading cloud server reseller providing top-tier global cloud services to accelerate your digital transformation',
gradient: 'from-amber-900 via-yellow-800 to-orange-700',
cta: {
primary: { text: t.hero.cta, href: '/contact' },
secondary: { text: t.hero.demo, href: '/demo' },
},
features: [
currentLang === 'zh' ? '99.9% 可用性保证' : '99.9% Uptime Guarantee',
currentLang === 'zh' ? '24/7 技术支持' : '24/7 Technical Support',
currentLang === 'zh' ? '全球数据中心' : 'Global Data Centers',
],
},
{
id: 'product-ecs',
type: 'product',
title:
currentLang === 'zh'
? '云服务器 ECS - 弹性计算'
: 'Cloud Server ECS - Elastic Computing',
description:
currentLang === 'zh'
? '高性能云服务器,支持弹性扩展,按需付费,助力业务快速发展'
: 'High-performance cloud servers with elastic scaling and pay-as-you-go pricing',
gradient: 'from-blue-900 via-indigo-800 to-purple-700',
badge: { text: currentLang === 'zh' ? '热销' : 'Hot', type: 'hot' },
cta: {
primary: {
text: currentLang === 'zh' ? '立即购买' : 'Buy Now',
href: '/products/ecs',
},
secondary: {
text: currentLang === 'zh' ? '免费试用' : 'Free Trial',
href: '/trial/ecs',
},
},
price: {
original: currentLang === 'zh' ? '¥199/月' : '$29/month',
current: currentLang === 'zh' ? '¥99/月' : '$15/month',
discount: '50%',
},
features: [
currentLang === 'zh' ? '2-64核 CPU' : '2-64 Core CPU',
currentLang === 'zh' ? '1GB-256GB 内存' : '1GB-256GB RAM',
currentLang === 'zh' ? 'SSD 高速存储' : 'SSD High-Speed Storage',
],
},
{
id: 'promotion-new-year',
type: 'promotion',
title:
currentLang === 'zh'
? '新年特惠 - 云服务大促销'
: 'New Year Special - Cloud Services Sale',
description:
currentLang === 'zh'
? '限时优惠!所有云产品享受超低折扣,新用户更有专属礼包'
: 'Limited time offer! All cloud products at super low prices, exclusive packages for new users',
gradient: 'from-red-900 via-pink-800 to-rose-700',
badge: { text: currentLang === 'zh' ? '限时' : 'Limited', type: 'limited' },
cta: {
primary: {
text: currentLang === 'zh' ? '抢购优惠' : 'Grab Deal',
href: '/promotions/new-year',
},
secondary: {
text: currentLang === 'zh' ? '查看详情' : 'View Details',
href: '/promotions',
},
},
features: [
currentLang === 'zh' ? '最高7折优惠' : 'Up to 30% Off',
currentLang === 'zh' ? '免费迁移服务' : 'Free Migration Service',
currentLang === 'zh' ? '专属技术支持' : 'Dedicated Support',
],
},
{
id: 'product-database',
type: 'product',
title:
currentLang === 'zh'
? '云数据库 RDS - 高可用数据库'
: 'Cloud Database RDS - High Availability',
description:
currentLang === 'zh'
? '企业级云数据库服务支持MySQL、PostgreSQL等多种数据库引擎'
: 'Enterprise-grade cloud database service supporting MySQL, PostgreSQL and more',
gradient: 'from-green-900 via-emerald-800 to-teal-700',
badge: { text: currentLang === 'zh' ? '新品' : 'New', type: 'new' },
cta: {
primary: {
text: currentLang === 'zh' ? '立即体验' : 'Try Now',
href: '/products/rds',
},
secondary: {
text: currentLang === 'zh' ? '技术咨询' : 'Consultation',
href: '/support',
},
},
price: {
current: currentLang === 'zh' ? '¥199/月起' : 'From $29/month',
},
features: [
currentLang === 'zh' ? '自动备份恢复' : 'Auto Backup & Recovery',
currentLang === 'zh' ? '读写分离' : 'Read-Write Splitting',
currentLang === 'zh' ? '监控告警' : 'Monitoring & Alerts',
],
},
];
// Auto-play functionality
useEffect(() => {
if (isPlaying && !isHovered) {
intervalRef.current = setInterval(() => {
setCurrentSlide((prev) => (prev + 1) % slides.length);
}, 5000);
} else {
if (intervalRef.current) {
clearInterval(intervalRef.current);
}
}
return () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
}
};
}, [isPlaying, isHovered, slides.length]);
const goToSlide = (index: number) => {
setCurrentSlide(index);
};
const nextSlide = () => {
setCurrentSlide((prev) => (prev + 1) % slides.length);
};
const prevSlide = () => {
setCurrentSlide((prev) => (prev - 1 + slides.length) % slides.length);
};
const togglePlayPause = () => {
setIsPlaying(!isPlaying);
};
const getBadgeIcon = (type: string) => {
switch (type) {
case 'new':
return <Star className="w-3 h-3" />;
case 'hot':
return <Zap className="w-3 h-3" />;
case 'discount':
return <Gift className="w-3 h-3" />;
case 'limited':
return <Clock className="w-3 h-3" />;
default:
return null;
}
};
const getBadgeColor = (type: string) => {
switch (type) {
case 'new':
return 'bg-green-500 text-white';
case 'hot':
return 'bg-red-500 text-white';
case 'discount':
return 'bg-purple-500 text-white';
case 'limited':
return 'bg-orange-500 text-white';
default:
return 'bg-gray-500 text-white';
}
};
const currentSlideData = slides[currentSlide];
return (
<section
className="relative h-[600px] md:h-[700px] overflow-hidden"
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
role="banner"
aria-label="Hero banner carousel"
>
{/* Background with gradient */}
<div
className={`absolute inset-0 bg-gradient-to-br ${currentSlideData.gradient} transition-all duration-1000`}
/>
{/* Background pattern */}
<div className="absolute inset-0 opacity-10">
<div className="absolute inset-0 bg-[url('data:image/svg+xml,%3Csvg width=%2260%22 height=%2260%22 viewBox=%220 0 60 60%22 xmlns=%22http://www.w3.org/2000/svg%22%3E%3Cg fill=%22none%22 fill-rule=%22evenodd%22%3E%3Cg fill=%22%23ffffff%22 fill-opacity=%220.1%22%3E%3Ccircle cx=%2230%22 cy=%2230%22 r=%222%22/%3E%3C/g%3E%3C/g%3E%3C/svg%3E')] bg-repeat" />
</div>
{/* Content */}
<div className="relative h-full flex items-center">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 w-full">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
{/* Left Content */}
<div className="text-white space-y-6">
{/* Badge */}
{currentSlideData.badge && (
<div className="inline-flex items-center space-x-2">
<span
className={`inline-flex items-center space-x-1 px-3 py-1 rounded-full text-xs font-semibold ${getBadgeColor(currentSlideData.badge.type)}`}
>
{getBadgeIcon(currentSlideData.badge.type)}
<span>{currentSlideData.badge.text}</span>
</span>
</div>
)}
{/* Title */}
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold leading-tight">
{currentSlideData.title}
</h1>
{/* Subtitle */}
{currentSlideData.subtitle && (
<p className="text-xl md:text-2xl text-white/90 leading-relaxed">
{currentSlideData.subtitle}
</p>
)}
{/* Description */}
<p className="text-lg text-white/80 leading-relaxed max-w-2xl">
{currentSlideData.description}
</p>
{/* Features */}
{currentSlideData.features && (
<div className="flex flex-wrap gap-4">
{currentSlideData.features.map((feature, index) => (
<div
key={index}
className="flex items-center space-x-2 bg-white/10 backdrop-blur-sm rounded-full px-4 py-2"
>
<div className="w-2 h-2 bg-yellow-400 rounded-full" />
<span className="text-sm font-medium">{feature}</span>
</div>
))}
</div>
)}
{/* Price */}
{currentSlideData.price && (
<div className="flex items-center space-x-4">
<div className="text-3xl font-bold text-yellow-300">
{currentSlideData.price.current}
</div>
{currentSlideData.price.original && (
<div className="flex items-center space-x-2">
<span className="text-lg text-white/60 line-through">
{currentSlideData.price.original}
</span>
{currentSlideData.price.discount && (
<span className="bg-red-500 text-white px-2 py-1 rounded text-sm font-semibold">
-{currentSlideData.price.discount}
</span>
)}
</div>
)}
</div>
)}
{/* CTA Buttons */}
<div className="flex flex-col sm:flex-row gap-4 pt-4">
<a
href={currentSlideData.cta.primary.href}
className="inline-flex items-center justify-center px-8 py-4 bg-yellow-500 hover:bg-yellow-600 text-white font-semibold rounded-lg transition-all duration-200 transform hover:scale-105 shadow-lg hover:shadow-xl"
>
{currentSlideData.cta.primary.text}
</a>
{currentSlideData.cta.secondary && (
<a
href={currentSlideData.cta.secondary.href}
className="inline-flex items-center justify-center px-8 py-4 border-2 border-white/30 text-white hover:bg-white/10 font-semibold rounded-lg transition-all duration-200 backdrop-blur-sm"
>
{currentSlideData.cta.secondary.text}
</a>
)}
</div>
</div>
{/* Right Content - Visual Element */}
<div className="hidden lg:block">
<div className="relative">
{/* Floating Cards */}
<div className="space-y-4">
<div className="bg-white/10 backdrop-blur-md rounded-xl p-6 transform rotate-3 hover:rotate-0 transition-transform duration-300">
<div className="flex items-center space-x-3 mb-3">
<div className="w-3 h-3 bg-green-400 rounded-full" />
<span className="text-white font-medium">
{currentLang === 'zh'
? '服务状态:正常'
: 'Service Status: Normal'}
</span>
</div>
<div className="text-2xl font-bold text-white">99.9%</div>
<div className="text-white/70 text-sm">
{currentLang === 'zh'
? '可用性保证'
: 'Uptime Guarantee'}
</div>
</div>
<div className="bg-white/10 backdrop-blur-md rounded-xl p-6 transform -rotate-2 hover:rotate-0 transition-transform duration-300 ml-8">
<div className="flex items-center space-x-3 mb-3">
<div className="w-3 h-3 bg-blue-400 rounded-full" />
<span className="text-white font-medium">
{currentLang === 'zh' ? '全球节点' : 'Global Nodes'}
</span>
</div>
<div className="text-2xl font-bold text-white">50+</div>
<div className="text-white/70 text-sm">
{currentLang === 'zh' ? '数据中心' : 'Data Centers'}
</div>
</div>
<div className="bg-white/10 backdrop-blur-md rounded-xl p-6 transform rotate-1 hover:rotate-0 transition-transform duration-300">
<div className="flex items-center space-x-3 mb-3">
<div className="w-3 h-3 bg-yellow-400 rounded-full" />
<span className="text-white font-medium">
{currentLang === 'zh'
? '客户满意度'
: 'Customer Satisfaction'}
</span>
</div>
<div className="text-2xl font-bold text-white">4.9/5</div>
<div className="text-white/70 text-sm">
{currentLang === 'zh' ? '用户评分' : 'User Rating'}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{/* Navigation Controls */}
<div className="absolute bottom-6 left-1/2 transform -translate-x-1/2 flex items-center space-x-4">
{/* Slide Indicators */}
<div className="flex space-x-2">
{slides.map((_, index) => (
<button
key={index}
onClick={() => goToSlide(index)}
className={`w-3 h-3 rounded-full transition-all duration-200 ${
index === currentSlide
? 'bg-yellow-400 w-8'
: 'bg-white/30 hover:bg-white/50'
}`}
aria-label={`Go to slide ${index + 1}`}
/>
))}
</div>
{/* Play/Pause Button */}
<button
onClick={togglePlayPause}
className="p-2 bg-white/10 backdrop-blur-sm rounded-full hover:bg-white/20 transition-colors duration-200"
aria-label={isPlaying ? 'Pause slideshow' : 'Play slideshow'}
>
{isPlaying ? (
<Pause className="w-4 h-4 text-white" />
) : (
<Play className="w-4 h-4 text-white" />
)}
</button>
</div>
{/* Navigation Arrows */}
<button
onClick={prevSlide}
className="absolute left-4 top-1/2 transform -translate-y-1/2 p-3 bg-white/10 backdrop-blur-sm rounded-full hover:bg-white/20 transition-colors duration-200 group"
aria-label="Previous slide"
>
<ChevronLeft className="w-6 h-6 text-white group-hover:scale-110 transition-transform" />
</button>
<button
onClick={nextSlide}
className="absolute right-4 top-1/2 transform -translate-y-1/2 p-3 bg-white/10 backdrop-blur-sm rounded-full hover:bg-white/20 transition-colors duration-200 group"
aria-label="Next slide"
>
<ChevronRight className="w-6 h-6 text-white group-hover:scale-110 transition-transform" />
</button>
{/* Progress Bar */}
<div className="absolute bottom-0 left-0 w-full h-1 bg-white/20">
<div
className="h-full bg-yellow-400 transition-all duration-300 ease-linear"
style={{
width: `${((currentSlide + 1) / slides.length) * 100}%`,
}}
/>
</div>
</section>
);
}