TechCorp/components/HomePage.tsx
2025-09-16 17:40:37 +08:00

525 lines
25 KiB
TypeScript

'use client';
import { useState, useEffect, useCallback } from 'react';
import { languages } from '../lib/i18n/config';
import { useTranslation } from '../lib/i18n/useTranslation';
const bannerImages = [
'https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=1920&h=1080&fit=crop',
'https://images.unsplash.com/photo-1504384308090-c894fdcc538d?w=1920&h=1080&fit=crop',
'https://images.unsplash.com/photo-1519389950473-47ba0277781c?w=1920&h=1080&fit=crop',
];
export default function HomePage({ initialLanguage }: { initialLanguage?: string }) {
const { language, t, changeLanguage, getLocalizedPath, isInitialized } =
useTranslation(initialLanguage);
const [currentSlide, setCurrentSlide] = useState(0);
const [isMenuOpen, setIsMenuOpen] = useState(false);
// Auto-advance carousel
useEffect(() => {
const timer = setInterval(() => {
setCurrentSlide((prev) => (prev + 1) % t.banner.slides.length);
}, 5000);
return () => clearInterval(timer);
}, [t.banner.slides.length]);
// 防抖的语言切换处理
const handleLanguageChange = useCallback(
(newLanguage: string) => {
changeLanguage(newLanguage as any);
},
[changeLanguage],
);
// Navigation items
const navItems = [
{ key: 'home', label: t.nav.home, href: getLocalizedPath('/') },
{ key: 'products', label: t.nav.products, href: getLocalizedPath('/products') },
{ key: 'news', label: t.nav.news, href: getLocalizedPath('/news') },
{ key: 'support', label: t.nav.support, href: getLocalizedPath('/support') },
{ key: 'about', label: t.nav.about, href: getLocalizedPath('/about') },
];
if (!isInitialized) {
return (
<div
className="min-h-screen bg-gradient-to-br from-blue-50 via-indigo-50 to-purple-50 flex items-center justify-center"
data-oid="oapni0f"
>
<div className="text-center" data-oid="dt7:7lh">
<div
className="w-12 h-12 border-4 border-blue-600 border-t-transparent rounded-full animate-spin mx-auto mb-4"
data-oid="p3:w.cy"
></div>
<p className="text-gray-600" data-oid=".qjvo16">
Loading...
</p>
</div>
</div>
);
}
return (
<div
className="min-h-screen bg-gradient-to-br from-blue-50 via-indigo-50 to-purple-50"
data-oid="kdmy.k-"
>
{/* Navigation */}
<nav
className="fixed top-0 left-0 w-full z-50 bg-white/80 backdrop-blur-md border-b border-white/20 shadow-sm"
data-oid="2145_w8"
>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8" data-oid="p.qa9un">
<div className="flex justify-between items-center h-16" data-oid="svakdep">
{/* Logo */}
<div className="flex items-center" data-oid="leblynm">
<div className="flex-shrink-0" data-oid="e2mc7xv">
<div
className="w-10 h-10 bg-gradient-to-r from-blue-600 to-purple-600 rounded-lg flex items-center justify-center"
data-oid="y43tpc4"
>
<span
className="text-white font-bold text-lg"
data-oid="tbe-k8q"
>
T
</span>
</div>
</div>
<div className="ml-3" data-oid="g4jhxrf">
<span
className="text-xl font-semibold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent"
data-oid="0sgze_e"
>
TechCorp
</span>
</div>
</div>
{/* Desktop Navigation */}
<div className="hidden md:block" data-oid="umt6j0n">
<div className="ml-10 flex items-baseline space-x-8" data-oid="r2bawsb">
{navItems.map((item) => (
<a
key={item.key}
href={item.href}
className="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium transition-colors duration-200 hover:bg-blue-50 rounded-md"
data-oid="usc29ud"
>
{item.label}
</a>
))}
</div>
</div>
{/* Language Selector & Mobile Menu */}
<div className="flex items-center space-x-4" data-oid="7:cj.hr">
{/* Language Selector */}
<div className="relative" data-oid="ecc0ugm">
<select
value={language}
onChange={(e) => handleLanguageChange(e.target.value)}
className="appearance-none bg-white/80 border border-gray-200 rounded-md px-3 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
data-oid="c8yzx8s"
>
{languages.map((lang) => (
<option
key={lang.code}
value={lang.code}
data-oid="0wqfdk_"
>
{lang.flag} {lang.label}
</option>
))}
</select>
</div>
{/* Mobile menu button */}
<div className="md:hidden" data-oid="_6uyhfa">
<button
onClick={() => setIsMenuOpen(!isMenuOpen)}
className="text-gray-700 hover:text-blue-600 p-2"
data-oid="bk0-sc_"
>
<svg
className="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
data-oid=":zv7-8-"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 6h16M4 12h16M4 18h16"
data-oid="l9-fwrm"
/>
</svg>
</button>
</div>
</div>
</div>
{/* Mobile Navigation */}
{isMenuOpen && (
<div className="md:hidden" data-oid="dltgnv4">
<div
className="px-2 pt-2 pb-3 space-y-1 bg-white/90 backdrop-blur-md rounded-lg mt-2"
data-oid="e9nd4qt"
>
{navItems.map((item) => (
<a
key={item.key}
href={item.href}
className="text-gray-700 hover:text-blue-600 block px-3 py-2 text-base font-medium transition-colors duration-200"
data-oid="o:e-:da"
>
{item.label}
</a>
))}
</div>
</div>
)}
</div>
</nav>
{/* Banner Carousel */}
<section className="relative min-h-screen" data-oid="tjo4goy">
<div className="pt-16" data-oid="zx.628s">
<div className="absolute inset-0" data-oid="j3300l3">
{t.banner.slides.map((slide, index) => (
<div
key={index}
className={`absolute inset-0 transition-opacity duration-1000 ${
index === currentSlide ? 'opacity-100' : 'opacity-0'
}`}
data-oid="01ekuuk"
>
<div
className="w-full h-full bg-cover bg-center relative"
style={{ backgroundImage: `url(${bannerImages[index]})` }}
data-oid="fc96k-h"
>
<div
className="absolute inset-0 bg-gradient-to-r from-black/60 to-black/30"
data-oid="_:7czli"
></div>
<div
className="relative z-10 flex items-center justify-center h-full text-center text-white px-4"
data-oid="my37fw0"
>
<div className="max-w-4xl" data-oid="bf69mr-">
<h1
className="text-4xl md:text-6xl font-bold mb-4 animate-fade-in-up"
data-oid="u8::6-a"
>
{slide.title}
</h1>
<p
className="text-xl md:text-2xl mb-8 animate-fade-in-up animation-delay-200"
data-oid="it2j9h6"
>
{slide.subtitle}
</p>
<button
className="bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 text-white px-8 py-3 rounded-full text-lg font-semibold transition-all duration-300 transform hover:scale-105 animate-fade-in-up animation-delay-400"
data-oid="lwjte.q"
>
{slide.cta}
</button>
</div>
</div>
</div>
</div>
))}
</div>
{/* Carousel Indicators */}
<div
className="absolute bottom-4 left-1/2 transform -translate-x-1/2 flex space-x-2"
data-oid="m3sdak1"
>
{t.banner.slides.map((_, index) => (
<button
key={index}
onClick={() => setCurrentSlide(index)}
className={`w-3 h-3 rounded-full transition-all duration-300 ${
index === currentSlide ? 'bg-white' : 'bg-white/50'
}`}
data-oid="rha.867"
/>
))}
</div>
{/* Carousel Navigation */}
<button
onClick={() =>
setCurrentSlide(
(prev) =>
(prev - 1 + t.banner.slides.length) % t.banner.slides.length,
)
}
className="absolute left-4 top-1/2 transform -translate-y-1/2 bg-white/20 hover:bg-white/30 text-white p-2 rounded-full transition-all duration-300"
data-oid="2j3q4ly"
>
<svg
className="w-6 h-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
data-oid="rob:qv1"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M15 19l-7-7 7-7"
data-oid="05m8kfe"
/>
</svg>
</button>
<button
onClick={() =>
setCurrentSlide((prev) => (prev + 1) % t.banner.slides.length)
}
className="absolute right-4 top-1/2 transform -translate-y-1/2 bg-white/20 hover:bg-white/30 text-white p-2 rounded-full transition-all duration-300"
data-oid="erli9o6"
>
<svg
className="w-6 h-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
data-oid="s-y9c2e"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 5l7 7-7 7"
data-oid="iq32:kc"
/>
</svg>
</button>
</div>
</section>
{/* Features Section */}
<section className="py-20 px-4 sm:px-6 lg:px-8" data-oid="mujfnk2">
<div className="max-w-7xl mx-auto" data-oid="389x5r.">
<div className="text-center mb-16" data-oid="-2y286k">
<h2
className="text-3xl md:text-4xl font-bold text-gray-900 mb-4"
data-oid="15bp_6x"
>
{t.features.title}
</h2>
<p className="text-xl text-gray-600 max-w-3xl mx-auto" data-oid="uk3vhjw">
{t.features.subtitle}
</p>
</div>
<div
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8"
data-oid="-vpsmcc"
>
{t.features.items.map((feature, index) => (
<div
key={index}
className="bg-white/60 backdrop-blur-sm rounded-xl p-6 text-center hover:bg-white/80 transition-all duration-300 transform hover:-translate-y-2 hover:shadow-xl border border-white/20"
data-oid="i89e7vc"
>
<div className="text-4xl mb-4" data-oid="7l0o8m:">
{feature.icon}
</div>
<h3
className="text-xl font-semibold text-gray-900 mb-3"
data-oid="dekqh_y"
>
{feature.title}
</h3>
<p className="text-gray-600" data-oid="q5hh.fn">
{feature.description}
</p>
</div>
))}
</div>
</div>
</section>
{/* CTA Section */}
<section
className="py-20 px-4 sm:px-6 lg:px-8 bg-gradient-to-r from-blue-600 to-purple-600"
data-oid="cic0dnw"
>
<div className="max-w-4xl mx-auto text-center text-white" data-oid="rz6-1jd">
<h2 className="text-3xl md:text-4xl font-bold mb-6" data-oid="9yq2-y.">
{t.cta.title}
</h2>
<p className="text-xl mb-8 opacity-90" data-oid="knn1269">
{t.cta.subtitle}
</p>
<div
className="flex flex-col sm:flex-row gap-4 justify-center"
data-oid=".hh3g7b"
>
<button
className="bg-white text-blue-600 px-8 py-3 rounded-full font-semibold hover:bg-gray-100 transition-all duration-300 transform hover:scale-105"
data-oid="cwhn47p"
>
{t.cta.primaryButton}
</button>
<button
className="border-2 border-white text-white px-8 py-3 rounded-full font-semibold hover:bg-white hover:text-blue-600 transition-all duration-300 transform hover:scale-105"
data-oid="h49zy3d"
>
{t.cta.secondaryButton}
</button>
</div>
</div>
</section>
{/* Footer */}
<footer
className="bg-gray-900 text-white py-12 px-4 sm:px-6 lg:px-8"
data-oid="jjefhwi"
>
<div className="max-w-7xl mx-auto" data-oid="16lwyf1">
<div className="grid grid-cols-1 md:grid-cols-4 gap-8" data-oid="68g0ztx">
<div data-oid="7azoht:">
<div className="flex items-center mb-4" data-oid="jj1osko">
<div
className="w-8 h-8 bg-gradient-to-r from-blue-600 to-purple-600 rounded-lg flex items-center justify-center mr-3"
data-oid="f1aryiu"
>
<span className="text-white font-bold" data-oid="beg519q">
T
</span>
</div>
<span className="text-xl font-semibold" data-oid="i55qean">
TechCorp
</span>
</div>
<p className="text-gray-400" data-oid="0ihfh.y">
{t.footer.description}
</p>
</div>
<div data-oid="j7:4_ux">
<h3 className="text-lg font-semibold mb-4" data-oid="2up_jf-">
{t.footer.sections.products.title}
</h3>
<ul className="space-y-2 text-gray-400" data-oid="n1o3z54">
{t.footer.sections.products.items.map((item, index) => (
<li key={index} data-oid="7mkp03q">
<a
href={getLocalizedPath(item.href)}
className="hover:text-white transition-colors"
data-oid="u6laexv"
>
{item.label}
</a>
</li>
))}
</ul>
</div>
<div data-oid="gjz7b5p">
<h3 className="text-lg font-semibold mb-4" data-oid="35ue2a5">
{t.footer.sections.support.title}
</h3>
<ul className="space-y-2 text-gray-400" data-oid="9klm-d8">
{t.footer.sections.support.items.map((item, index) => (
<li key={index} data-oid=".nlrc2t">
<a
href={getLocalizedPath(item.href)}
className="hover:text-white transition-colors"
data-oid="k5.xeeh"
>
{item.label}
</a>
</li>
))}
</ul>
</div>
<div data-oid="i3emobr">
<h3 className="text-lg font-semibold mb-4" data-oid="m8sylzh">
{t.footer.sections.social.title}
</h3>
<div className="flex space-x-4" data-oid="6aov0kj">
<a
href="#"
className="text-gray-400 hover:text-white transition-colors"
data-oid="oc_6.hw"
>
<span className="sr-only" data-oid="2t1m41k">
</span>
💬
</a>
<a
href="#"
className="text-gray-400 hover:text-white transition-colors"
data-oid="jxjb8z2"
>
<span className="sr-only" data-oid="-ng0r68">
</span>
📱
</a>
<a
href="#"
className="text-gray-400 hover:text-white transition-colors"
data-oid="_jnybdz"
>
<span className="sr-only" data-oid="5qm_goh">
</span>
📧
</a>
</div>
</div>
</div>
<div
className="border-t border-gray-800 mt-8 pt-8 text-center text-gray-400"
data-oid="k951feh"
>
<p data-oid="6mm3mnm">&copy; 2024 TechCorp. {t.footer.copyright}</p>
</div>
</div>
</footer>
<style jsx data-oid="fj9q-8j">{`
@keyframes fade-in-up {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animate-fade-in-up {
animation: fade-in-up 0.8s ease-out forwards;
}
.animation-delay-200 {
animation-delay: 0.2s;
opacity: 0;
}
.animation-delay-400 {
animation-delay: 0.4s;
opacity: 0;
}
`}</style>
</div>
);
}