CloudPro/components/Banner/HeroBanner_fixed.tsx
2025-09-16 16:15:57 +08:00

460 lines
21 KiB
TypeScript
Raw Permalink 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.

'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>
);
}