Merge pull request 'main' (#22) from main into testing
All checks were successful
CityCards-Website / Build-CityCards-Website (push) Successful in 24s
All checks were successful
CityCards-Website / Build-CityCards-Website (push) Successful in 24s
Reviewed-on: #22
This commit is contained in:
@@ -20,11 +20,11 @@ interface Testimonial {
|
||||
company: string;
|
||||
signature: string;
|
||||
}
|
||||
|
||||
const cityName = localStorage.getItem('cityName') || 'the city';
|
||||
const testimonials: Testimonial[] = [
|
||||
{
|
||||
id: 1,
|
||||
quote: "CityCards transformed our Melbourne trip into an unforgettable adventure. The seamless access to attractions and insider recommendations made every moment magical.",
|
||||
quote: `CityCards transformed our ${cityName} trip into an unforgettable adventure. The seamless access to attractions and insider recommendations made every moment magical.`,
|
||||
name: "Sarah Chen",
|
||||
company: "Travel Blogger",
|
||||
signature: "Sarah"
|
||||
|
||||
@@ -45,10 +45,10 @@ export function Footer({
|
||||
/>
|
||||
|
||||
{/* Enhanced White Gradient Overlay at Top */}
|
||||
<div className="absolute top-0 left-0 right-0 h-48 bg-gradient-to-b from-white via-white/95 via-white/80 via-white/60 via-white/40 to-transparent z-10" />
|
||||
<div className="absolute top-0 left-0 right-0 h-24 bg-gradient-to-b from-white via-white/95 via-white/80 via-white/60 via-white/40 to-transparent z-10" />
|
||||
|
||||
{/* Additional Smooth Transition Layer */}
|
||||
<div className="absolute top-0 left-0 right-0 h-24 bg-gradient-to-b from-white via-white/90 to-white/70 z-10" />
|
||||
<div className="absolute top-0 left-0 right-0 h-4 bg-gradient-to-b from-white via-white/90 to-white/70 z-10" />
|
||||
|
||||
{/* Dark overlay for text readability */}
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-black/30 to-black/70 z-20" />
|
||||
@@ -61,7 +61,7 @@ export function Footer({
|
||||
</div>
|
||||
|
||||
{/* Content Overlay */}
|
||||
<div className="relative z-30 py-24">
|
||||
<div className="relative z-30 py-4">
|
||||
<div className="container mx-auto px-4">
|
||||
{/* Footer Content Grid */}
|
||||
<div className="w-full mt-48 bg-primary/10 backdrop-blur-lg rounded-[10px] border border-white/10 p-12">
|
||||
|
||||
@@ -19,13 +19,15 @@ export function HeroBannerCarousel({
|
||||
const [currentSlide, setCurrentSlide] = useState(0);
|
||||
const [isPaused, setIsPaused] = useState(false);
|
||||
|
||||
const cityName = localStorage.getItem("cityName")
|
||||
|
||||
const slides = [
|
||||
{
|
||||
id: 1,
|
||||
title: "Discover",
|
||||
highlight: "Melbourne",
|
||||
highlight: cityName,
|
||||
subtitle: "Ultimate Guide to Iconic City",
|
||||
description: "From Flinders Street to St Kilda Beach: explore the best of Melbourne's landmarks, culture, food and more!",
|
||||
description: cityName === "Melbourne" ? "From Flinders Street to St Kilda Beach: explore the best of Melbourne's landmarks, culture, food and more!" : "From the Sydney Opera House to Bondi Beach: explore the best of Sydney’s landmarks, culture, food and more!",
|
||||
image: "https://images.unsplash.com/photo-1757470238279-0e9f331d02c9?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxNZWxib3VybmUlMjBza3lsaW5lJTIwc3Vuc2V0fGVufDF8fHx8MTc2MDUwOTIyMHww&ixlib=rb-4.1.0&q=80&w=1080",
|
||||
cta: "Get Started",
|
||||
onClick: onCheckoutClick
|
||||
|
||||
@@ -7,6 +7,7 @@ interface HotelEsimOffersProps {
|
||||
}
|
||||
|
||||
export function HotelEsimOffers({ onEsimsClick, onHotelDiscountsClick }: HotelEsimOffersProps) {
|
||||
const cityName = localStorage.getItem("cityName")
|
||||
return (
|
||||
<div>
|
||||
<div className="space-y-0">
|
||||
@@ -64,7 +65,7 @@ export function HotelEsimOffers({ onEsimsClick, onHotelDiscountsClick }: HotelEs
|
||||
>
|
||||
<Wifi className="w-4 h-4 text-primary" />
|
||||
<span className="font-poppins text-sm font-medium text-primary">
|
||||
Stay Connected in Melbourne
|
||||
Stay Connected in {cityName}
|
||||
</span>
|
||||
</motion.div>
|
||||
<h2 className="font-poppins text-3xl md:text-5xl lg:text-6xl leading-tight text-foreground mb-6">
|
||||
@@ -72,7 +73,7 @@ export function HotelEsimOffers({ onEsimsClick, onHotelDiscountsClick }: HotelEs
|
||||
<span className="font-bold text-primary italic">Connected</span>
|
||||
</h2>
|
||||
<p className="font-poppins text-xl leading-relaxed font-normal text-gray-700 max-w-2xl mx-auto">
|
||||
Get instant e-SIM connectivity across Australia. Stay online from the moment you land in Melbourne.
|
||||
Get instant e-SIM connectivity across Australia. Stay online from the moment you land in {cityName}.
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
@@ -105,10 +106,10 @@ export function HotelEsimOffers({ onEsimsClick, onHotelDiscountsClick }: HotelEs
|
||||
<span className="font-poppins text-xs font-semibold text-white">🇦🇺 AUSTRALIA-WIDE COVERAGE</span>
|
||||
</div>
|
||||
<h3 className="font-poppins text-3xl md:text-4xl font-semibold text-white mb-4 leading-tight">
|
||||
Exclusive e-SIM Offers for Melbourne Visitors
|
||||
Exclusive e-SIM Offers for {cityName} Visitors
|
||||
</h3>
|
||||
<p className="font-poppins text-base text-white/90 mb-6">
|
||||
No more hunting for local SIM cards at the airport. Activate your e-SIM instantly and explore Melbourne with seamless connectivity.
|
||||
No more hunting for local SIM cards at the airport. Activate your e-SIM instantly and explore {cityName} with seamless connectivity.
|
||||
</p>
|
||||
|
||||
<motion.div
|
||||
@@ -207,7 +208,7 @@ export function HotelEsimOffers({ onEsimsClick, onHotelDiscountsClick }: HotelEs
|
||||
>
|
||||
<Hotel className="w-4 h-4 text-primary" />
|
||||
<span className="font-poppins text-sm font-medium text-primary">
|
||||
Premium Melbourne Hotels
|
||||
Premium {cityName} Hotels
|
||||
</span>
|
||||
</motion.div>
|
||||
<h2 className="font-poppins text-3xl md:text-5xl lg:text-6xl leading-tight text-foreground mb-6">
|
||||
@@ -215,7 +216,7 @@ export function HotelEsimOffers({ onEsimsClick, onHotelDiscountsClick }: HotelEs
|
||||
<span className="font-bold text-primary italic">Luxury</span>
|
||||
</h2>
|
||||
<p className="font-poppins text-xl leading-relaxed font-normal text-gray-700 max-w-2xl mx-auto">
|
||||
Unlock exclusive rates at Melbourne's finest hotels. Your CityCard membership opens doors to premium CBD and waterfront stays.
|
||||
Unlock exclusive rates at {cityName}'s finest hotels. Your CityCard membership opens doors to premium CBD and waterfront stays.
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
@@ -236,10 +237,10 @@ export function HotelEsimOffers({ onEsimsClick, onHotelDiscountsClick }: HotelEs
|
||||
<span className="font-poppins text-xs font-semibold text-white">🔥 MARRIOTT BONVOY PARTNER</span>
|
||||
</div>
|
||||
<h3 className="font-poppins text-3xl md:text-4xl font-semibold text-foreground mb-4 leading-tight">
|
||||
Melbourne Premium Stays at <span className="text-primary italic">Unbeatable Prices</span>
|
||||
{cityName} Premium Stays at <span className="text-primary italic">Unbeatable Prices</span>
|
||||
</h3>
|
||||
<p className="font-poppins text-base text-gray-700 mb-6">
|
||||
Access exclusive member rates at Melbourne's top hotels including Crown Towers, W Melbourne, and premium CBD properties. Enjoy complimentary upgrades and special amenities.
|
||||
Access exclusive member rates at {cityName}'s top hotels including Crown Towers, W {cityName}, and premium CBD properties. Enjoy complimentary upgrades and special amenities.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -253,7 +254,7 @@ export function HotelEsimOffers({ onEsimsClick, onHotelDiscountsClick }: HotelEs
|
||||
<div className="bg-gradient-to-br from-primary to-orange-500 rounded-3xl p-8 text-center shadow-xl">
|
||||
<div className="font-poppins text-6xl font-bold text-white mb-2">25%</div>
|
||||
<div className="font-poppins text-lg text-white/90 mb-1">Average Savings</div>
|
||||
<div className="font-poppins text-sm text-white/70">on Melbourne hotels</div>
|
||||
<div className="font-poppins text-sm text-white/70">on {cityName} hotels</div>
|
||||
</div>
|
||||
<motion.div
|
||||
className="absolute -top-2 -right-2 bg-yellow-400 rounded-full px-3 py-1"
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useState } from 'react';
|
||||
import { ChevronLeft, ChevronRight, Clock, Users, Star, Zap, CheckCircle, MapPin, Volume2, Camera, Coffee, Palette, Eye } from 'lucide-react';
|
||||
import { ImageWithFallback } from './figma/ImageWithFallback';
|
||||
import { motion } from 'motion/react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
const melbourneAttractions = [
|
||||
{
|
||||
@@ -146,6 +147,8 @@ const categories = ["All", "Landmarks", "Gardens", "Markets", "Views", "Beach",
|
||||
|
||||
export function MelbourneAttractions() {
|
||||
const [activeCategory, setActiveCategory] = useState("All");
|
||||
const navigate = useNavigate();
|
||||
const cityName = localStorage.getItem("cityName")
|
||||
|
||||
const filteredAttractions = activeCategory === "All"
|
||||
? melbourneAttractions
|
||||
@@ -276,19 +279,19 @@ export function MelbourneAttractions() {
|
||||
<div className="inline-flex items-center gap-2 bg-gradient-to-r from-primary/10 to-secondary/10 px-4 py-2 rounded-full mb-6">
|
||||
<div className="w-2 h-2 bg-gradient-to-r from-primary to-secondary rounded-full"></div>
|
||||
<span className="text-sm font-medium bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent">
|
||||
Melbourne Must-Sees
|
||||
{cityName} Must-Sees
|
||||
</span>
|
||||
</div>
|
||||
<h2 className="heading-dynamic text-4xl md:text-5xl lg:text-6xl text-gray-900 mb-4">
|
||||
<span className="font-light">Discover</span>{' '}
|
||||
<span className="font-bold bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent italic pr-1">
|
||||
Melbourne's
|
||||
{cityName}'s
|
||||
</span>{' '}
|
||||
<span className="font-normal">Best</span>{' '}
|
||||
<span className="font-semibold text-emphasis">Experiences</span>
|
||||
</h2>
|
||||
<p className="text-xl text-gray-600 max-w-3xl mx-auto">
|
||||
Discover Melbourne's iconic landmarks, vibrant culture, world-class dining, and hidden gems - all included with your Melbourne CityCard
|
||||
Discover {cityName}'s iconic landmarks, vibrant culture, world-class dining, and hidden gems - all included with your {cityName} CityCard
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
@@ -382,8 +385,9 @@ export function MelbourneAttractions() {
|
||||
whileHover={{ scale: 1.05, boxShadow: "0 20px 40px rgba(99,102,241,0.3)" }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
className="relative bg-gradient-to-r from-primary to-secondary text-white py-4 px-12 rounded-lg text-lg shadow-xl transition-all duration-300 overflow-hidden group"
|
||||
onClick={()=>navigate('/passes')}
|
||||
>
|
||||
<span className="relative z-10">Get Your Melbourne Card</span>
|
||||
<span className="relative z-10">Get Your {cityName} Card</span>
|
||||
|
||||
{/* Shine animation */}
|
||||
<div className="absolute inset-0 opacity-30">
|
||||
|
||||
@@ -2,6 +2,8 @@ import { motion } from 'motion/react';
|
||||
import { ImageWithFallback } from './figma/ImageWithFallback';
|
||||
import { Calendar, Clock, User, ArrowRight, Coffee, Camera, MapPin, Star } from 'lucide-react';
|
||||
import { Button } from './ui/button';
|
||||
import { useRef } from "react";
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
const blogPosts = [
|
||||
{
|
||||
@@ -46,7 +48,7 @@ const blogPosts = [
|
||||
excerpt: "From the iconic MCG to Formula 1 racing, discover why Melbourne holds the title of Australia's sporting capital and home to major international events.",
|
||||
image: "https://images.unsplash.com/photo-1720347247737-9252d85d3027?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxtZWxib3VybmUlMjBjaXR5JTIwc2t5bGluZSUyMGZsaW5kZXJzJTIwc3RyZWV0fGVufDF8fHx8MTc1NzMzOTAyNHww&ixlib=rb-4.1.0&q=80&w=1080&utm_source=figma&utm_medium=referral",
|
||||
author: "Sports Fan",
|
||||
date: "Dec 8, 2024",
|
||||
date: "Dec 8, 2024",
|
||||
readTime: "6 min read",
|
||||
category: "Sports",
|
||||
featured: false,
|
||||
@@ -88,12 +90,19 @@ const categories = [
|
||||
];
|
||||
|
||||
export function MelbourneBlogs() {
|
||||
|
||||
const sectionRef = useRef(null);
|
||||
const navigate = useNavigate();
|
||||
const featuredPost = blogPosts.find(post => post.featured);
|
||||
const regularPosts = blogPosts.filter(post => !post.featured);
|
||||
|
||||
const cityName = localStorage.getItem('cityName');
|
||||
|
||||
return (
|
||||
<section className="py-20 bg-gradient-to-br from-gray-50 via-white to-gray-50 relative overflow-hidden">
|
||||
{/* Background Pattern */}
|
||||
<section
|
||||
ref={sectionRef}
|
||||
className="py-20 bg-gradient-to-br from-gray-50 via-white to-gray-50 relative overflow-hidden"
|
||||
> {/* Background Pattern */}
|
||||
<div className="absolute inset-0 opacity-[0.02]">
|
||||
<div className="absolute top-0 left-0 w-full h-full bg-gradient-to-br from-primary/20 via-secondary/20 to-primary/20"></div>
|
||||
</div>
|
||||
@@ -110,21 +119,21 @@ export function MelbourneBlogs() {
|
||||
<div className="inline-flex items-center gap-2 bg-gradient-to-r from-primary/10 to-secondary/10 px-4 py-2 rounded-full mb-6">
|
||||
<div className="w-2 h-2 bg-gradient-to-r from-primary to-secondary rounded-full"></div>
|
||||
<span className="text-sm font-medium bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent">
|
||||
Melbourne Stories
|
||||
{cityName} Stories
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
<h2 className="font-merchant text-4xl md:text-5xl lg:text-6xl text-gray-900 mb-6">
|
||||
<span className="font-normal">Melbourne</span>{' '}
|
||||
<span className="font-normal">{cityName}</span>{' '}
|
||||
<span className="font-bold bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent italic pr-2">
|
||||
Blogs
|
||||
</span>
|
||||
</h2>
|
||||
|
||||
|
||||
<p className="text-xl text-gray-600 max-w-4xl mx-auto leading-relaxed">
|
||||
Dive deep into Melbourne's rich cultural tapestry, from hidden laneway treasures to world-renowned
|
||||
coffee culture. Discover insider stories, local secrets, and expert guides to Australia's cultural capital
|
||||
that will transform your Melbourne experience into an unforgettable journey.
|
||||
Dive deep into {cityName}'s rich cultural tapestry, from hidden laneway treasures to world-renowned
|
||||
coffee culture. Discover insider stories, local secrets, and expert guides to Australia's cultural capital
|
||||
that will transform your {cityName} experience into an unforgettable journey.
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
@@ -189,7 +198,7 @@ export function MelbourneBlogs() {
|
||||
className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-700"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/20 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
|
||||
|
||||
{/* Category Badge */}
|
||||
<div className="absolute top-4 left-4 bg-white/95 backdrop-blur-sm text-gray-900 px-3 py-1 rounded-full text-xs font-medium">
|
||||
{post.category}
|
||||
@@ -217,7 +226,7 @@ export function MelbourneBlogs() {
|
||||
<h3 className="font-merchant text-xl font-semibold text-gray-900 mb-3 leading-tight group-hover:text-primary transition-colors duration-200 line-clamp-2">
|
||||
{post.title}
|
||||
</h3>
|
||||
|
||||
|
||||
<p className="text-gray-600 leading-relaxed mb-4 text-sm flex-1 line-clamp-3">
|
||||
{post.excerpt}
|
||||
</p>
|
||||
@@ -261,23 +270,30 @@ export function MelbourneBlogs() {
|
||||
>
|
||||
<div className="bg-gradient-to-br from-primary/5 via-secondary/5 to-primary/5 rounded-3xl p-8 md:p-12 border border-gray-100">
|
||||
<h3 className="font-merchant text-2xl md:text-3xl font-semibold text-gray-900 mb-4">
|
||||
Want to explore Melbourne yourself?
|
||||
Want to explore {cityName} yourself?
|
||||
</h3>
|
||||
<p className="text-gray-600 text-lg mb-8 max-w-2xl mx-auto">
|
||||
Get your Melbourne CityCard and unlock access to all these incredible experiences and more.
|
||||
Get your {cityName} CityCard and unlock access to all these incredible experiences and more.
|
||||
Start your adventure today with exclusive deals and insider access.
|
||||
</p>
|
||||
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<Button
|
||||
className="bg-gradient-to-r from-primary to-secondary text-white font-semibold px-8 py-4 rounded-2xl hover:scale-105 transition-all duration-300 shadow-lg hover:shadow-xl"
|
||||
onClick={() => { navigate(`/${cityName.toLowerCase()}`), window.scrollTo({ top: 0, behavior: 'smooth' }); }}
|
||||
>
|
||||
<MapPin className="w-5 h-5 mr-2" />
|
||||
Explore Melbourne
|
||||
Explore {cityName}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="border-2 border-gray-300 text-gray-700 font-semibold px-8 py-4 rounded-2xl hover:border-primary hover:text-primary hover:scale-105 transition-all duration-300"
|
||||
onClick={() => {
|
||||
sectionRef.current?.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "start",
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Coffee className="w-5 h-5 mr-2" />
|
||||
View All Blogs
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react';
|
||||
import { Check, X, Star, Users, MapPin, Calendar, Clock, Zap, Eye } from 'lucide-react';
|
||||
import { Button } from './ui/button';
|
||||
import { motion } from 'motion/react';
|
||||
import { useNavigate } from 'react-router';
|
||||
|
||||
// const cardOptions = [
|
||||
// {
|
||||
@@ -76,7 +77,10 @@ interface MelbourneCardComparisonProps {
|
||||
|
||||
export function MelbourneCardComparison({ onCheckoutClick, cards }: MelbourneCardComparisonProps) {
|
||||
const [selectedCard, setSelectedCard] = useState<string>('unlimited');
|
||||
const navigate = useNavigate();
|
||||
|
||||
const cityName=localStorage.getItem('cityName');
|
||||
|
||||
const cardOptions = [
|
||||
{
|
||||
id: cards[0]?.id,
|
||||
@@ -179,9 +183,18 @@ export function MelbourneCardComparison({ onCheckoutClick, cards }: MelbourneCar
|
||||
</h2>
|
||||
|
||||
<p className="text-xl text-gray-600 max-w-4xl mx-auto leading-relaxed">
|
||||
Melbourne is a must-visit cultural epicenter, and this spectacular trip unlocks
|
||||
your access around the city in one easy. Save over the cost of visiting Melbourne's
|
||||
landmarks, have lunch at Phi Phi Leh, snorkel at Bamboo Island, and visit Monkey Beach.
|
||||
{cityName === 'Melbourne' && (
|
||||
<span>
|
||||
Melbourne is a must-visit cultural epicenter, and this spectacular trip unlocks
|
||||
your access around the city in one easy. Save over the cost of visiting Melbourne's
|
||||
landmarks, have lunch at Phi Phi Leh, snorkel at Bamboo Island, and visit Monkey Beach.
|
||||
</span>
|
||||
)}
|
||||
{cityName === 'Sydney' && (
|
||||
<span>
|
||||
Sydney is a dazzling harbor city that blends iconic landmarks with vibrant coastal escapes. This unforgettable trip gives you seamless access across Sydney in one easy pass. Save on the cost of visiting Sydney’s world‑famous attractions, cruise past the Sydney Opera House and Harbour Bridge, relax on Bondi Beach, snorkel at Manly, and explore the wildlife at Taronga Zoo.
|
||||
</span>
|
||||
)}
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
@@ -255,7 +268,7 @@ export function MelbourneCardComparison({ onCheckoutClick, cards }: MelbourneCar
|
||||
withShine={true}
|
||||
className="w-full h-14 rounded-2xl text-white font-semibold text-lg hover:scale-105 transition-all duration-300 shadow-lg hover:shadow-xl cursor-pointer"
|
||||
style={{ backgroundColor: '#F95F62' }}
|
||||
onClick={onCheckoutClick}
|
||||
onClick={()=>navigate("/passes")}
|
||||
>
|
||||
Buy {card.name}
|
||||
</Button>
|
||||
|
||||
@@ -18,6 +18,8 @@ import {
|
||||
AccordionTrigger,
|
||||
} from "./ui/accordion";
|
||||
|
||||
const cityName = localStorage.getItem('cityName') || 'the city';
|
||||
|
||||
const faqData = [
|
||||
// {
|
||||
// id: "refund",
|
||||
@@ -27,50 +29,50 @@ const faqData = [
|
||||
// },
|
||||
{
|
||||
id: "duration",
|
||||
question: "How long is my Melbourne CityCard valid?",
|
||||
answer: "Melbourne CityCards are available in 1, 2, 3, and 5-day options. Your card activates on the first attraction you visit and is valid for consecutive days only. The 5-day Melbourne Unlimited Card provides the best value for extended stays with access to over 40 premium attractions.",
|
||||
question: `How long is my ${cityName} CityCard valid?`,
|
||||
answer: `${cityName} CityCards are available in 1, 2, 3, and 5-day options. Your card activates on the first attraction you visit and is valid for consecutive days only. The 5-day ${cityName} Unlimited Card provides the best value for extended stays with access to over 40 premium attractions.`,
|
||||
icon: Calendar
|
||||
},
|
||||
{
|
||||
id: "transportation",
|
||||
question: "Does the Melbourne CityCard include public transport?",
|
||||
answer: "The Melbourne Unlimited Card includes a complimentary Myki card loaded with travel credit for trams, trains, and buses within Melbourne's CBD and inner suburbs. The Selective Card focuses on attractions only, but we provide detailed transport guides for each venue.",
|
||||
question: `Does the ${cityName} CityCard include public transport?`,
|
||||
answer: `The ${cityName} Unlimited Card includes a complimentary Myki card loaded with travel credit for trams, trains, and buses within ${cityName}'s CBD and inner suburbs. The Selective Card focuses on attractions only, but we provide detailed transport guides for each venue.`,
|
||||
icon: Train
|
||||
},
|
||||
{
|
||||
id: "attractions",
|
||||
question: "What are the must-visit attractions included with my card?",
|
||||
answer: "Your Melbourne CityCard includes iconic experiences like Eureka Tower SkyDeck, Royal Botanic Gardens tours, Melbourne Zoo, SEA LIFE Melbourne Aquarium, and Melbourne Star observation wheel. Plus unique local experiences like laneways art tours, coffee culture walks, and rooftop dining discounts.",
|
||||
question: `What are the must-visit attractions included with my ${cityName} CityCard?`,
|
||||
answer: `Your ${cityName} CityCard includes iconic experiences like Eureka Tower SkyDeck, Royal Botanic Gardens tours, ${cityName} Zoo, SEA LIFE ${cityName} Aquarium, and ${cityName} Star observation wheel. Plus unique local experiences like laneways art tours, coffee culture walks, and rooftop dining discounts.`,
|
||||
icon: Camera
|
||||
},
|
||||
{
|
||||
id: "best-time",
|
||||
question: "When is the best time to visit Melbourne?",
|
||||
answer: "Melbourne is fantastic year-round! Spring (Sep-Nov) offers perfect weather and blooming gardens. Summer (Dec-Feb) brings outdoor festivals and rooftop season. Autumn (Mar-May) showcases beautiful foliage and harvest events. Winter (Jun-Aug) is ideal for cozy cafes, indoor attractions, and cultural experiences.",
|
||||
question: `When is the best time to visit ${cityName}?`,
|
||||
answer: `${cityName} is fantastic year-round! Spring (Sep-Nov) offers perfect weather and blooming gardens. Summer (Dec-Feb) brings outdoor festivals and rooftop season. Autumn (Mar-May) showcases beautiful foliage and harvest events. Winter (Jun-Aug) is ideal for cozy cafes, indoor attractions, and cultural experiences.`,
|
||||
icon: Clock
|
||||
},
|
||||
{
|
||||
id: "coffee-culture",
|
||||
question: "How can I experience Melbourne's famous coffee culture?",
|
||||
answer: "Your Melbourne CityCard includes guided coffee tours through famous laneways, visits to historic coffee roasters, and discounts at award-winning cafes. We've partnered with local baristas to offer exclusive tastings and behind-the-scenes experiences at Melbourne's most beloved coffee institutions.",
|
||||
question: `How can I experience ${cityName}'s famous coffee culture?`,
|
||||
answer: `Your ${cityName} CityCard includes guided coffee tours through famous laneways, visits to historic coffee roasters, and discounts at award-winning cafes. We've partnered with local baristas to offer exclusive tastings and behind-the-scenes experiences at ${cityName}'s most beloved coffee institutions.`,
|
||||
icon: Coffee
|
||||
},
|
||||
{
|
||||
id: "group-bookings",
|
||||
question: "Do you offer group discounts for families or friends?",
|
||||
answer: "Yes! Groups of 4+ receive automatic discounts, and families with children under 16 get special pricing. School groups and corporate bookings receive additional benefits. Contact our Melbourne team for custom packages that can include private tours and exclusive venue access.",
|
||||
question: `Do you offer group discounts for families or friends?`,
|
||||
answer: `Yes! Groups of 4+ receive automatic discounts, and families with children under 16 get special pricing. School groups and corporate bookings receive additional benefits. Contact our ${cityName} team for custom packages that can include private tours and exclusive venue access.`,
|
||||
icon: Users
|
||||
},
|
||||
{
|
||||
id: "mobile-app",
|
||||
question: "Do I need the mobile app to use my Melbourne CityCard?",
|
||||
answer: "While not required, our mobile app enhances your Melbourne experience with interactive maps, real-time attraction wait times, insider tips from locals, and the ability to skip lines at participating venues. Download it for offline access to your itinerary and exclusive app-only deals.",
|
||||
question: `Do I need the mobile app to use my ${cityName} CityCard?`,
|
||||
answer: `While not required, our mobile app enhances your ${cityName} experience with interactive maps, real-time attraction wait times, insider tips from locals, and the ability to skip lines at participating venues. Download it for offline access to your itinerary and exclusive app-only deals.`,
|
||||
icon: Smartphone
|
||||
},
|
||||
{
|
||||
id: "neighborhoods",
|
||||
question: "Which Melbourne neighborhoods should I explore?",
|
||||
answer: "Your CityCard provides access to experiences across Melbourne's diverse neighborhoods: Fitzroy for street art and vintage shopping, St. Kilda for beaches and nightlife, Southbank for dining and culture, CBD for iconic attractions, and Richmond for authentic Vietnamese food and shopping.",
|
||||
question: `Which ${cityName} neighborhoods should I explore?`,
|
||||
answer: `Your CityCard provides access to experiences across ${cityName}'s diverse neighborhoods: Fitzroy for street art and vintage shopping, St. Kilda for beaches and nightlife, Southbank for dining and culture, CBD for iconic attractions, and Richmond for authentic Vietnamese food and shopping.`,
|
||||
icon: MapPin
|
||||
}
|
||||
];
|
||||
@@ -95,7 +97,7 @@ export function MelbourneFAQ() {
|
||||
<div className="inline-flex items-center gap-2 bg-gradient-to-r from-primary/10 to-secondary/10 px-4 py-2 rounded-full mb-6">
|
||||
<HelpCircle className="w-4 h-4 text-primary" />
|
||||
<span className="text-sm font-medium bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent">
|
||||
Melbourne Guide
|
||||
{cityName} Guide
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -107,8 +109,8 @@ export function MelbourneFAQ() {
|
||||
</h2>
|
||||
|
||||
<p className="text-xl text-gray-600 max-w-4xl mx-auto leading-relaxed">
|
||||
Everything you need to know about exploring Melbourne with your CityCard. From iconic attractions
|
||||
to hidden local gems, we've got your Melbourne adventure covered.
|
||||
Everything you need to know about exploring {cityName} with your CityCard. From iconic attractions
|
||||
to hidden local gems, we've got your {cityName} adventure covered.
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
@@ -161,7 +163,7 @@ export function MelbourneFAQ() {
|
||||
</div>
|
||||
|
||||
{/* Call to Action */}
|
||||
<motion.div
|
||||
{/* <motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.5 }}
|
||||
@@ -205,7 +207,7 @@ export function MelbourneFAQ() {
|
||||
</motion.button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.div> */}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -36,7 +36,7 @@ export function MelbourneTourOverview() {
|
||||
}
|
||||
];
|
||||
|
||||
const tourHighlights = [
|
||||
const MelbourneTourHighlights = [
|
||||
{
|
||||
icon: Star,
|
||||
text: "Experience the cultural capital's vibrant arts scene and hidden laneways",
|
||||
@@ -69,6 +69,43 @@ export function MelbourneTourOverview() {
|
||||
}
|
||||
];
|
||||
|
||||
const SydneyTourHighlights = [
|
||||
{
|
||||
icon: Star,
|
||||
text: "Experience Sydney’s iconic harbour lifestyle with Opera House and Harbour Bridge views",
|
||||
color: "text-yellow-600"
|
||||
},
|
||||
{
|
||||
icon: Coffee,
|
||||
text: "Discover Sydney’s vibrant café culture, waterfront dining, and buzzing food markets",
|
||||
color: "text-amber-600"
|
||||
},
|
||||
{
|
||||
icon: Camera,
|
||||
text: "Capture panoramic views from Sydney Tower Eye and scenic harbour cruises",
|
||||
color: "text-purple-600"
|
||||
},
|
||||
{
|
||||
icon: Users,
|
||||
text: "Enjoy beachside vibes at Bondi and Manly, plus lively nightlife in Darling Harbour",
|
||||
color: "text-green-600"
|
||||
},
|
||||
{
|
||||
icon: MapPin,
|
||||
text: "Explore historic charm in The Rocks and coastal walks like Bondi to Coogee",
|
||||
color: "text-blue-600"
|
||||
},
|
||||
{
|
||||
icon: Calendar,
|
||||
text: "Access year-round festivals, cultural events, and dynamic harbour celebrations",
|
||||
color: "text-rose-600"
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
const cityName = localStorage.getItem("cityName")
|
||||
const selectedHighlights = cityName === 'Melbourne' ? MelbourneTourHighlights : SydneyTourHighlights;
|
||||
|
||||
return (
|
||||
<section className="py-20 bg-gradient-to-br from-white via-gray-50/30 to-white relative overflow-hidden">
|
||||
{/* Background Pattern */}
|
||||
@@ -88,7 +125,7 @@ export function MelbourneTourOverview() {
|
||||
className="mb-16"
|
||||
>
|
||||
<h2 className="heading-dynamic font-merchant text-4xl md:text-5xl lg:text-6xl text-gray-900 mb-8">
|
||||
<span className="font-light">Melbourne</span>{' '}
|
||||
<span className="font-light">{cityName}</span>{' '}
|
||||
<span className="font-bold bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent italic pr-2">
|
||||
Tour
|
||||
</span>{' '}
|
||||
@@ -108,11 +145,20 @@ export function MelbourneTourOverview() {
|
||||
viewport={{ once: true }}
|
||||
>
|
||||
<p className="text-lg md:text-xl text-gray-700 leading-relaxed">
|
||||
Melbourne is a must-visit cultural epicenter, and this spectacular experience unlocks
|
||||
your access around the city in one easy pass. Save over the cost of visiting Melbourne's
|
||||
landmarks, explore famous laneways and street art, enjoy world-class dining in hidden bars,
|
||||
and immerse yourself in the sports capital's vibrant atmosphere. From Royal Botanic Gardens
|
||||
to Federation Square, hotel pickup and drop-off all included.
|
||||
{ cityName === 'Melbourne' && (
|
||||
<span>
|
||||
Melbourne is a must-visit cultural epicenter, and this spectacular experience unlocks
|
||||
your access around the city in one easy pass. Save over the cost of visiting Melbourne's
|
||||
landmarks, explore famous laneways and street art, enjoy world-class dining in hidden bars,
|
||||
and immerse yourself in the sports capital's vibrant atmosphere. From Royal Botanic Gardens
|
||||
to Federation Square, hotel pickup and drop-off all included.
|
||||
</span>
|
||||
)}
|
||||
{ cityName === 'Sydney' && (
|
||||
<span>
|
||||
Sydney is a must-visit global destination, blending iconic landmarks with vibrant coastal charm, and this all-in-one experience gives you seamless access across the city. Save more while exploring Sydney’s top attractions, wander through historic neighborhoods like The Rocks, admire world-famous sights such as the Sydney Opera House and Harbour Bridge, and relax along stunning beaches like Bondi and Manly. Enjoy diverse dining from waterfront restaurants to hidden cafés, soak in the lively cultural scene, and experience the energy of Australia’s most dynamic harbor city—all with convenient access to key locations and experiences included.
|
||||
</span>
|
||||
)}
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
@@ -226,7 +272,7 @@ export function MelbourneTourOverview() {
|
||||
</h3>
|
||||
|
||||
<div className="space-y-6">
|
||||
{tourHighlights.map((highlight, index) => (
|
||||
{selectedHighlights.map((highlight, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { motion, AnimatePresence } from 'motion/react';
|
||||
import { Sparkles, MapPin, Calendar, Wand2, Clock } from 'lucide-react';
|
||||
// import { ImageWithFallback } from './figma/ImageWithFallback';
|
||||
import cityTourVideo from '../assets/citycards-vid.mp4';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
interface PersonalizedTourHeroProps {
|
||||
onCreateItineraryClick?: () => void;
|
||||
@@ -17,6 +18,7 @@ interface AttractionCard {
|
||||
}
|
||||
|
||||
export function PersonalizedTourHero({ onCreateItineraryClick }: PersonalizedTourHeroProps) {
|
||||
const navigate = useNavigate();
|
||||
const attractionCards: AttractionCard[] = [
|
||||
{
|
||||
id: 1,
|
||||
@@ -163,8 +165,8 @@ export function PersonalizedTourHero({ onCreateItineraryClick }: PersonalizedTou
|
||||
className="flex flex-col sm:flex-row gap-4 items-start sm:items-center"
|
||||
>
|
||||
<button
|
||||
onClick={onCreateItineraryClick}
|
||||
className="group relative px-8 py-4 rounded-lg flex items-center gap-2 overflow-hidden transition-all duration-300 hover:scale-105 shadow-lg hover:shadow-xl font-poppins font-semibold text-base text-white bg-gradient-to-r from-primary via-orange-500 to-rose-500 hover:from-primary/90 hover:via-orange-500/90 hover:to-rose-500/90"
|
||||
onClick={() => navigate('/create-itinerary')}
|
||||
className="group cursor-pointer px-8 py-4 rounded-lg flex items-center gap-2 overflow-hidden transition-all duration-300 hover:scale-105 shadow-lg hover:shadow-xl font-poppins font-semibold text-base text-white bg-gradient-to-r from-primary via-orange-500 to-rose-500 hover:from-primary/90 hover:via-orange-500/90 hover:to-rose-500/90"
|
||||
>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent -translate-x-full group-hover:translate-x-full transition-transform duration-700" />
|
||||
<Wand2 className="w-5 h-5 relative z-10 group-hover:rotate-12 transition-transform duration-300" />
|
||||
|
||||
@@ -504,7 +504,7 @@ export function CartPage({
|
||||
<div className="mb-8">
|
||||
<h2 className="font-poppins text-2xl md:text-3xl lg:text-4xl leading-tight">
|
||||
<span className="font-light">Your</span>{' '}
|
||||
<span className="font-bold italic bg-gradient-to-r from-[#F95F62] to-[#F95FAF] bg-clip-text text-transparent">Cart</span>
|
||||
<span className="font-bold italic bg-gradient-to-r from-[#F95F62] to-[#F95FAF] bg-clip-text text-transparent pr-2">Cart</span>
|
||||
</h2>
|
||||
<p className="font-poppins text-sm leading-relaxed font-normal text-[#8e8e8e] mt-1">
|
||||
{isEmpty ? 'Your cart is empty' : `${CartItems.length} ${CartItems.length === 1 ? 'item' : 'items'} in your cart`}
|
||||
|
||||
@@ -14,6 +14,8 @@ import { ImageWithFallback } from '../components/figma/ImageWithFallback';
|
||||
import { useCreateMagicItineraryMutation, useGetItineraryDetailsByIdQuery } from '../Redux/services/itinerary.service';
|
||||
import { toast } from 'sonner';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import Navbar from '../components/Navbar';
|
||||
import { Footer } from '../components/Footer';
|
||||
|
||||
const ItinerarySummaryPage = () => {
|
||||
const [viewMode, setViewMode] = useState<'daily' | 'summary'>('daily');
|
||||
@@ -33,10 +35,14 @@ const ItinerarySummaryPage = () => {
|
||||
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
{/* Navbar */}
|
||||
<Navbar
|
||||
/>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
className="space-y-8 max-w-3xl mx-auto"
|
||||
className="space-y-8 max-w-3xl mx-auto mt-25"
|
||||
>
|
||||
{/* Title */}
|
||||
<div className="text-center space-y-1">
|
||||
@@ -318,13 +324,16 @@ const ItinerarySummaryPage = () => {
|
||||
{/* Bottom Action */}
|
||||
<div className="flex justify-center pt-4 pb-8">
|
||||
<Button
|
||||
onClick={() => navigate('/create-itinerary-design')}
|
||||
onClick={() => navigate('/create-itinerary')}
|
||||
className="w-full font-poppins font-semibold px-8 py-3 rounded-xl bg-primary hover:bg-primary/90 text-white shadow-md shadow-primary/20"
|
||||
>
|
||||
Create Another Itinerary
|
||||
</Button>
|
||||
</div>
|
||||
</motion.div>
|
||||
<Footer
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import Navbar from '../components/Navbar';
|
||||
import { Footer } from '../components/Footer';
|
||||
import { ImageWithFallback } from '../components/figma/ImageWithFallback';
|
||||
import { useGetItineraryDetailsByIdQuery } from '../Redux/services/itinerary.service';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import LoadingSpinner from '../components/LoadingSpinner';
|
||||
|
||||
interface ItineraryViewPageProps {
|
||||
@@ -65,6 +65,7 @@ export function ItineraryViewPage({
|
||||
user
|
||||
}: ItineraryViewPageProps) {
|
||||
const [viewMode, setViewMode] = useState<'daily' | 'summary'>('daily');
|
||||
const navigate = useNavigate();
|
||||
// const [favorites, setFavorites] = useState<Set<string>>(new Set());
|
||||
|
||||
// ── API Integration ──────────────────────────────────────────────────────────
|
||||
@@ -76,17 +77,7 @@ export function ItineraryViewPage({
|
||||
const summaries = generatedItinerary?.summary ?? [];
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
// const toggleFavorite = (activityKey: string) => {
|
||||
// setFavorites(prev => {
|
||||
// const newSet = new Set(prev);
|
||||
// if (newSet.has(activityKey)) {
|
||||
// newSet.delete(activityKey);
|
||||
// } else {
|
||||
// newSet.add(activityKey);
|
||||
// }
|
||||
// return newSet;
|
||||
// });
|
||||
// };
|
||||
|
||||
|
||||
// ── Loading State ─────────────────────────────────────────────────────────────
|
||||
if (isLoading) {
|
||||
@@ -124,7 +115,7 @@ export function ItineraryViewPage({
|
||||
/>
|
||||
|
||||
{/* Header Section */}
|
||||
<section className="pt-32 pb-8 bg-gradient-to-br from-primary/5 to-secondary/5">
|
||||
<section className="pb-8 bg-gradient-to-br from-primary/5 to-secondary/5">
|
||||
<div className="container mx-auto px-4 pt-32">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
@@ -134,8 +125,8 @@ export function ItineraryViewPage({
|
||||
>
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={onBackClick}
|
||||
className="mb-6 hover:bg-primary/5 font-poppins font-medium"
|
||||
onClick={() => navigate(-1) }
|
||||
className="mb-6 hover:bg-primary/5 font-poppins font-medium cursor-pointer"
|
||||
>
|
||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||
Back to Magic Itinerary
|
||||
@@ -463,7 +454,7 @@ export function ItineraryViewPage({
|
||||
>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={onCreateItineraryClick}
|
||||
onClick={()=>navigate(`/create-itinerary`)}
|
||||
className="font-poppins font-medium px-8 py-3 text-lg"
|
||||
>
|
||||
<Heart className="w-5 h-5 mr-2" />
|
||||
|
||||
@@ -16,6 +16,7 @@ import { HeroBannerCarousel } from '../components/HeroBannerCarousel';
|
||||
import { HotelEsimOffers } from '../components/HotelEsimOffers';
|
||||
import { useGetSelectedCityDetailsQuery } from '../Redux/services/cities.service';
|
||||
import LoadingSpinner from '../components/LoadingSpinner';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
interface User {
|
||||
email: string;
|
||||
@@ -147,8 +148,10 @@ export function MelbournePage({
|
||||
// Magic Itinerary state
|
||||
const [currentCardIndex, setCurrentCardIndex] = useState(0);
|
||||
const [isAnimating, setIsAnimating] = useState(false);
|
||||
const navigate= useNavigate();
|
||||
|
||||
const cityId = localStorage.getItem("cityId")
|
||||
const cityName = localStorage.getItem("cityName")
|
||||
|
||||
const { data: cityDetails, isLoading: loadingCityDetails } = useGetSelectedCityDetailsQuery(cityId)
|
||||
|
||||
@@ -170,7 +173,7 @@ export function MelbournePage({
|
||||
<div className="min-h-screen bg-white">
|
||||
{/* Navigation */}
|
||||
<Layout
|
||||
activeCity="Melbourne"
|
||||
// activeCity="Melbourne"
|
||||
onSignInClick={onSignInClick}
|
||||
onSignOutClick={onSignOutClick}
|
||||
user={user}
|
||||
@@ -231,7 +234,7 @@ export function MelbournePage({
|
||||
{[
|
||||
{
|
||||
title: "50+ Top Attractions",
|
||||
description: "Unlimited access to Melbourne's finest museums, zoos, and observation decks.",
|
||||
description: `Unlimited access to ${cityName}'s finest museums, zoos, and observation decks.`,
|
||||
icon: MapPin,
|
||||
color: "text-blue-500",
|
||||
bg: "bg-blue-50"
|
||||
@@ -779,7 +782,7 @@ export function MelbournePage({
|
||||
viewport={{ once: true }}
|
||||
>
|
||||
<Button
|
||||
onClick={onCreateItineraryClick}
|
||||
onClick={() => {navigate('/create-itinerary');}}
|
||||
className="font-poppins py-7 px-16 rounded-full text-xl font-bold bg-gradient-to-r from-primary via-orange-500 to-rose-500 hover:from-primary/90 hover:via-orange-500/90 hover:to-rose-500/90 shadow-2xl hover:shadow-primary/50 transition-all hover:scale-105 hover:-translate-y-1"
|
||||
>
|
||||
<span className="flex items-center gap-3">
|
||||
|
||||
@@ -227,10 +227,10 @@ export function PassesPage({
|
||||
|
||||
<CardHeader className="text-center pb-4 pt-8 flex-shrink-0">
|
||||
<CardTitle className="font-merchant text-2xl leading-tight mb-3 text-gray-900">
|
||||
{cards[0].title}
|
||||
{cards[0]?.title}
|
||||
</CardTitle>
|
||||
<CardDescription className="font-poppins text-sm text-gray-600 leading-relaxed font-normal min-h-[48px] flex items-center justify-center px-4">
|
||||
{cards[0].description}
|
||||
{cards[0]?.description}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
|
||||
@@ -238,23 +238,23 @@ export function PassesPage({
|
||||
<div className="px-6 pb-6 flex-shrink-0">
|
||||
<div className="flex items-baseline justify-center gap-2 mb-2">
|
||||
<span className="text-5xl font-bold text-gray-900 font-poppins">
|
||||
${cards[0].adultPrice}
|
||||
${cards[0]?.adultPrice}
|
||||
</span>
|
||||
<span className="text-gray-500 font-poppins text-base">
|
||||
/ {passTypes[0].period}
|
||||
</span>
|
||||
</div>
|
||||
<div className="h-5 flex items-center justify-center">
|
||||
{cards[0].adultPrice && (
|
||||
{cards[0]?.adultPrice && (
|
||||
<div className="text-sm text-gray-500 font-poppins">
|
||||
{/* Strikethrough price = originalPrice + $5 */}
|
||||
<span className="line-through mr-2">
|
||||
${parseFloat(cards[0].adultPrice) + 5}
|
||||
${parseFloat(cards[0]?.adultPrice) + 5}
|
||||
</span>
|
||||
<span className="text-green-600 font-medium">
|
||||
Save{" "}
|
||||
{Math.round(
|
||||
((5) / (parseFloat(cards[0].adultPrice) + 5)) * 100
|
||||
((5) / (parseFloat(cards[0]?.adultPrice) + 5)) * 100
|
||||
)}
|
||||
%
|
||||
</span>
|
||||
@@ -299,14 +299,14 @@ export function PassesPage({
|
||||
{/* Unlimited Pass Card */}
|
||||
<div className="relative h-full">
|
||||
<Card
|
||||
className={`relative h-full flex flex-col transition-all duration-300 cursor-pointer ${selectedPass === passTypes[1].id
|
||||
className={`relative h-full flex flex-col transition-all duration-300 cursor-pointer ${selectedPass === passTypes[1]?.id
|
||||
? "ring-2 ring-red-500 shadow-lg" // 🔴 red border when selected
|
||||
: "border-gray-200 shadow-md hover:shadow-lg hover:border-primary/30"
|
||||
}`}
|
||||
onClick={() => setSelectedPass(passTypes[1].id)}
|
||||
onClick={() => setSelectedPass(passTypes[1]?.id)}
|
||||
|
||||
>
|
||||
{passTypes[1].popular && (
|
||||
{passTypes[1]?.popular && (
|
||||
<div className="absolute -top-3 left-1/2 transform -translate-x-1/2 z-10">
|
||||
<Badge className="bg-gradient-to-r from-yellow-400 to-orange-500 text-black px-6 py-1.5 font-semibold shadow-lg font-poppins">
|
||||
Most Popular
|
||||
@@ -320,30 +320,30 @@ export function PassesPage({
|
||||
|
||||
<CardHeader className="text-center pb-4 pt-8 flex-shrink-0">
|
||||
<CardTitle className="font-merchant text-2xl leading-tight mb-3 text-gray-900">
|
||||
{cards[1].title}
|
||||
{cards[1]?.title}
|
||||
</CardTitle>
|
||||
<CardDescription className="font-poppins text-sm text-gray-600 leading-relaxed font-normal min-h-[48px] flex items-center justify-center px-4">
|
||||
{cards[1].description}
|
||||
{cards[1]?.description}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
|
||||
{/* Pricing */}
|
||||
<div className="px-6 pb-6 flex-shrink-0">
|
||||
<div className="flex items-baseline justify-center gap-2 mb-2">
|
||||
<span className="text-5xl font-bold text-gray-900 font-poppins">${cards[1].adultPrice}</span>
|
||||
<span className="text-gray-500 font-poppins text-base">/ {passTypes[1].period}</span>
|
||||
<span className="text-5xl font-bold text-gray-900 font-poppins">${cards[1]?.adultPrice}</span>
|
||||
<span className="text-gray-500 font-poppins text-base">/ {passTypes[1]?.period}</span>
|
||||
</div>
|
||||
<div className="h-5 flex items-center justify-center">
|
||||
{cards[1].adultPrice && (
|
||||
{cards[1]?.adultPrice && (
|
||||
<div className="text-sm text-gray-500 font-poppins">
|
||||
{/* Strikethrough price = originalPrice + $5 */}
|
||||
<span className="line-through mr-2">
|
||||
${parseFloat(cards[1].adultPrice) + 5}
|
||||
${parseFloat(cards[1]?.adultPrice) + 5}
|
||||
</span>
|
||||
<span className="text-green-600 font-medium">
|
||||
Save{" "}
|
||||
{Math.round(
|
||||
((5) / (parseFloat(cards[1].adultPrice) + 5)) * 100
|
||||
((5) / (parseFloat(cards[1]?.adultPrice) + 5)) * 100
|
||||
)}
|
||||
%
|
||||
</span>
|
||||
@@ -355,7 +355,7 @@ export function PassesPage({
|
||||
<CardContent className="pt-0 pb-6 px-6 flex-grow flex flex-col">
|
||||
<div className="flex-grow mb-6">
|
||||
<div className="space-y-3">
|
||||
{passTypes[1].features.map((feature, index) => (
|
||||
{passTypes[1]?.features.map((feature, index) => (
|
||||
<div key={index} className="flex items-start gap-3">
|
||||
<Check className="w-4 h-4 text-green-500 mt-1 flex-shrink-0" />
|
||||
<span className="text-sm text-gray-700 font-poppins leading-relaxed font-normal">{feature}</span>
|
||||
|
||||
@@ -123,7 +123,7 @@ function Field({
|
||||
? 'border-[#F95F62] ring-2 ring-[#F95F62]/10'
|
||||
: prefilled
|
||||
? 'border-[#F95F62]/25 bg-[#F95F62]/[0.02]'
|
||||
: 'border-gray-200'
|
||||
: 'border-[#E4AFB1] bg-[#FFF5F5]'
|
||||
}`}
|
||||
/>
|
||||
{prefilled && !focused && !disabled && (
|
||||
@@ -448,7 +448,7 @@ export function PaymentDetailsPage({
|
||||
transition={{ duration: 0.25 }}
|
||||
className="overflow-hidden"
|
||||
>
|
||||
<div className="bg-[#F95F62]/[0.03] border border-[#F95F62]/15 rounded-xl px-5 py-4 space-y-4">
|
||||
<div className="border border-[#F95F62]/15 rounded-xl px-5 py-4 space-y-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Gift className="w-4 h-4 text-[#F95F62]" />
|
||||
<h3 className="font-poppins text-base font-semibold text-[#2a2a2a]">Gift Recipient Details</h3>
|
||||
|
||||
@@ -746,7 +746,7 @@ export function ProfilePage({
|
||||
</p>
|
||||
<Button
|
||||
className="bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 text-white font-poppins font-normal"
|
||||
onClick={onCreateItineraryClick}
|
||||
onClick={() => navigate("/create-itinerary")}
|
||||
>
|
||||
<Plus className="w-4 h-4 mr-2" />
|
||||
Create Itinerary
|
||||
|
||||
@@ -188,10 +188,10 @@ export function SuperSavingsPage({
|
||||
</section>
|
||||
|
||||
{/* Trusted By Companies Section */}
|
||||
<section className="py-12 bg-background">
|
||||
<section className="py-10 bg-background">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-6xl mx-auto text-center">
|
||||
<div className="mb-10">
|
||||
<div className="mb-1">
|
||||
<h2 className="font-poppins text-2xl md:text-3xl lg:text-4xl leading-tight mb-4">
|
||||
<span>Trusted by the </span>
|
||||
<span className="font-semibold bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent">world's best</span>
|
||||
@@ -206,7 +206,7 @@ export function SuperSavingsPage({
|
||||
</section>
|
||||
|
||||
{/* Featured Super Savings Section */}
|
||||
<section className="py-20">
|
||||
<section className="">
|
||||
<div className="container mx-auto px-4">
|
||||
<motion.div
|
||||
className="text-center mb-12"
|
||||
@@ -225,7 +225,7 @@ export function SuperSavingsPage({
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
<div className="container mx-auto px-4 pt-51 pb-16">
|
||||
<div className="container mx-auto px-4 pt-11 pb-16">
|
||||
<div className="flex gap-8">
|
||||
{/* Left Sidebar - Filters */}
|
||||
<div className="w-64 flex-shrink-0">
|
||||
@@ -269,7 +269,7 @@ export function SuperSavingsPage({
|
||||
{/* Main Content */}
|
||||
<div className="flex-1">
|
||||
{/* Breadcrumb */}
|
||||
<div className="mb-8">
|
||||
{/* <div className="mb-8">
|
||||
<p className="font-poppins text-sm text-gray-800">
|
||||
{fromSource === 'passes' ? (
|
||||
<>
|
||||
@@ -283,7 +283,7 @@ export function SuperSavingsPage({
|
||||
</>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div> */}
|
||||
|
||||
{/* Header Section */}
|
||||
<div className="mb-8">
|
||||
@@ -395,7 +395,7 @@ export function SuperSavingsPage({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-center">
|
||||
{/* <div className="text-center">
|
||||
<Button
|
||||
onClick={onSignInClick}
|
||||
variant="outline"
|
||||
@@ -403,7 +403,7 @@ export function SuperSavingsPage({
|
||||
>
|
||||
View All Super Savings
|
||||
</Button>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user