| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- import React, { useEffect } from 'react';
- import Navbar from '@/src/components/Navbar.tsx';
- import Sidebar from '@/src/components/Sidebar.tsx';
- import Footer from '@/src/components/Footer.tsx';
- import { CONTENT } from '../constants.ts';
- import { useLanguage } from '@/src/contexts/LanguageContext.tsx';
- import { useTheme } from '@/src/contexts/ThemeContext.tsx';
- import { useLocation, Link } from 'react-router-dom';
- import { ArrowRight, Anchor, Star, ChevronRight } from 'lucide-react';
- const CruiseSpace: React.FC = () => {
- const { language } = useLanguage();
- const { shipsPageImages } = useTheme();
- // We explicitly type 'any' here or assume CONTENT structure is updated because
- // TS might not immediately pick up the new keys added to constants without a full types reload in this context.
- // In a real app, types.ts should be updated, but here we access the object properties.
- const t = CONTENT[language].shipsPage as any;
- const location = useLocation();
- // Scroll to section on load or location change
- useEffect(() => {
- const SECTION_PREFIX = 'space-';
- const SCROLL_DELAY = 300; // ms - delay to ensure DOM is fully rendered
-
- const params = new URLSearchParams(location.search);
- const section = params.get('section');
-
- if (!section) {
- // Scroll to top when no section specified
- window.scrollTo({ top: 0, behavior: 'smooth' });
- return;
- }
-
- // Construct element ID and scroll to target section
- const elementId = `${SECTION_PREFIX}${section}`;
- const element = document.getElementById(elementId);
-
- if (element) {
- // Delay to ensure DOM is fully rendered before scrolling
- const timeoutId = setTimeout(() => {
- element.scrollIntoView({ behavior: 'smooth', block: 'start' });
- }, SCROLL_DELAY);
-
- // Cleanup timeout on unmount or search change
- return () => clearTimeout(timeoutId);
- }
- }, [location.search]);
- return (
- <div className="min-h-screen bg-white font-sans text-vista-darkblue overflow-x-hidden">
- <Navbar />
- <Sidebar />
- {/* Hero Section */}
- <div className="relative h-[70vh] w-full bg-vista-darkblue flex items-center justify-center overflow-hidden">
- <div className="absolute inset-0 bg-black/40 z-10"></div>
- <img
- src="https://images.unsplash.com/photo-1548291616-3c0f5f743538?q=80&w=1920&auto=format&fit=crop"
- alt="Ships Hero"
- className="absolute inset-0 w-full h-full object-cover animate-slow-zoom"
- />
- <div className="relative z-20 text-center text-white px-4 animate-fade-in-up">
- <span className="block text-sm md:text-base tracking-[0.3em] uppercase mb-4 text-vista-gold">{t.hero_sub}</span>
- <h1 className="text-5xl md:text-8xl font-serif italic mb-6">{CONTENT[language].nav.menu[1].title}</h1>
- <p className="max-w-xl mx-auto text-white/80 font-light text-lg">
- {t.hero_desc}
- </p>
- </div>
- </div>
- {/* Section 1: Facilities */}
- <section id="space-facilities" className="py-32 max-w-7xl mx-auto px-6">
- <div className="text-center mb-20">
- <h2 className="text-5xl md:text-7xl font-serif text-vista-darkblue mb-8">{t.spaces.facilities.title}</h2>
- <p className="text-vista-darkblue/70 text-lg md:text-xl leading-relaxed font-light max-w-3xl mx-auto">
- {t.spaces.facilities.desc}
- </p>
- </div>
- <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-12">
- {t.spaces.facilities.items.map((item: any, index: number) => (
- <div key={index} className="group bg-white p-8 rounded-lg shadow-lg hover:shadow-xl transition-all duration-300 hover:-translate-y-2">
- <div className="w-16 h-16 bg-vista-gold/10 rounded-full flex items-center justify-center mb-6 group-hover:bg-vista-gold transition-colors">
- <span className="text-vista-gold text-2xl">{index + 1}</span>
- </div>
- <h3 className="text-xl font-bold text-vista-darkblue mb-4">{item.title}</h3>
- <p className="text-vista-darkblue/70 leading-relaxed">{item.desc}</p>
- </div>
- ))}
- </div>
- </section>
- {/* Section 2: Room Types */}
- <section id="space-rooms" className="py-32 bg-vista-gray">
- <div className="max-w-7xl mx-auto px-6">
- <div className="text-center mb-20">
- <h2 className="text-5xl md:text-7xl font-serif text-vista-darkblue mb-8">{t.spaces.rooms.title}</h2>
- <p className="text-vista-darkblue/70 text-lg md:text-xl leading-relaxed font-light max-w-3xl mx-auto">
- {t.spaces.rooms.desc}
- </p>
- </div>
- <div className="grid grid-cols-1 md:grid-cols-2 gap-12">
- {t.spaces.rooms.types.map((room: any, index: number) => (
- <div key={index} className="bg-white rounded-lg overflow-hidden shadow-lg group">
- <div className="h-64 bg-vista-gold/20 relative overflow-hidden">
- <img
- src={`https://picsum.photos/600/400?random=${index + 10}`}
- alt={room.name}
- className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110"
- />
- <div className="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-end">
- <div className="p-6 text-white">
- <div className="flex gap-4 mb-4">
- <span className="text-xs uppercase tracking-widest font-bold bg-white/20 px-3 py-1 rounded-full">{room.area}</span>
- <span className="text-xs uppercase tracking-widest font-bold bg-white/20 px-3 py-1 rounded-full">{room.view}</span>
- </div>
- </div>
- </div>
- </div>
- <div className="p-8">
- <h3 className="text-2xl font-serif text-vista-darkblue mb-4">{room.name}</h3>
- <p className="text-vista-darkblue/70 leading-relaxed mb-6">{room.desc}</p>
- <div className="flex justify-between items-center">
- <div className="flex gap-4">
- <div className="text-center">
- <div className="text-vista-gold font-bold">{room.area}</div>
- <div className="text-xs text-vista-darkblue/70">面积</div>
- </div>
- <div className="text-center">
- <div className="text-vista-gold font-bold">{room.view}</div>
- <div className="text-xs text-vista-darkblue/70">景观</div>
- </div>
- </div>
- <Link to="#" className="inline-flex items-center gap-2 text-vista-darkblue hover:text-vista-gold transition-colors font-bold uppercase text-xs tracking-wider">
- {t.view_itineraries} <ChevronRight size={16} />
- </Link>
- </div>
- </div>
- </div>
- ))}
- </div>
- </div>
- </section>
- {/* Section 3: VIP Privileges */}
- <section id="space-vip" className="py-32 relative overflow-hidden">
- {/* Background */}
- <div className="absolute inset-0 opacity-10">
- <img
- src={shipsPageImages.lanyue[0]}
- alt="VIP"
- className="w-full h-full object-cover"
- />
- </div>
- <div className="max-w-7xl mx-auto px-6 relative z-10">
- <div className="text-center mb-20">
- <h2 className="text-5xl md:text-7xl font-serif text-vista-darkblue mb-8">{t.spaces.vip.title}</h2>
- <p className="text-vista-darkblue/70 text-lg md:text-xl leading-relaxed font-light max-w-3xl mx-auto">
- {t.spaces.vip.desc}
- </p>
- </div>
- <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 max-w-5xl mx-auto">
- {t.spaces.vip.benefits.map((benefit: string, index: number) => (
- <div key={index} className="bg-white p-6 rounded-lg shadow-md group hover:shadow-lg transition-all duration-300">
- <div className="w-12 h-12 bg-vista-gold/10 rounded-full flex items-center justify-center mb-4 group-hover:bg-vista-gold group-hover:text-white transition-colors">
- <Star size={20} className="text-vista-gold group-hover:text-white" />
- </div>
- <p className="text-center text-vista-darkblue font-medium">{benefit}</p>
- </div>
- ))}
- </div>
- <div className="mt-16 text-center">
- <Link to="/itineraries" className="inline-flex items-center gap-3 px-10 py-4 bg-vista-darkblue text-white uppercase tracking-widest text-xs font-bold hover:bg-vista-gold transition-colors duration-300">
- {t.view_itineraries} <ChevronRight size={16} />
- </Link>
- </div>
- </div>
- </section>
- <Footer />
- </div>
- );
- };
- export default CruiseSpace;
|