diff --git a/src/AppRouter.tsx b/src/AppRouter.tsx index 878eea2..3923134 100644 --- a/src/AppRouter.tsx +++ b/src/AppRouter.tsx @@ -30,6 +30,7 @@ import { ContactUsPage } from './components/ContactUsPage'; import { pageTransition } from './utils/animations'; import { LandingPage } from './pages/landingPage'; import ComingSoonPage from './pages/ComingSoonPage'; +import { SuperSavingsPage } from './components/SuperSavingsPage'; // User type definition interface User { @@ -252,6 +253,11 @@ export function AppRouter({ } /> + + + + } /> diff --git a/src/assets/melbourne-logo.png b/src/assets/melbourne-logo.png new file mode 100644 index 0000000..0d99a5c Binary files /dev/null and b/src/assets/melbourne-logo.png differ diff --git a/src/components/CitySelectionDialog.tsx b/src/components/CitySelectionDialog.tsx new file mode 100644 index 0000000..72f6365 --- /dev/null +++ b/src/components/CitySelectionDialog.tsx @@ -0,0 +1,126 @@ +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; // ✅ import navigation hook +import { Dialog, DialogContent, DialogTitle, DialogDescription } from './ui/dialog'; +import { ArrowLeft, Search } from 'lucide-react'; +import { Input } from './ui/input'; +import { motion, AnimatePresence } from 'motion/react'; +import { ImageWithFallback } from './figma/ImageWithFallback'; + +interface City { + id: string; + name: string; + imageUrl: string; +} + +interface CitySelectionDialogProps { + isOpen: boolean; + onClose: () => void; +} + +const cities: City[] = [ + { id: 'melbourne', name: 'Melbourne', imageUrl: 'https://images.unsplash.com/photo-1624341373902-70e3a8dc9acc?...' }, + { id: 'new-york', name: 'New York', imageUrl: 'https://images.unsplash.com/photo-1514565131-fce0801e5785?...' }, + { id: 'abu-dhabi', name: 'Abu Dhabi', imageUrl: 'https://images.unsplash.com/photo-1584551246679-0daf3d275d0f?...' }, + { id: 'dubai', name: 'Dubai', imageUrl: 'https://images.unsplash.com/photo-1518684079-3c830dcef090?...' }, + { id: 'tokyo', name: 'Tokyo', imageUrl: 'https://images.unsplash.com/photo-1613487897980-50cc440ce118?...' }, + { id: 'ontario', name: 'Ontario', imageUrl: 'https://images.unsplash.com/photo-1542704792-e30dac463c90?...' }, + { id: 'mumbai', name: 'Mumbai', imageUrl: 'https://images.unsplash.com/photo-1600867161422-79f8f6e08c84?...' }, + { id: 'louisiana', name: 'Louisiana', imageUrl: 'https://images.unsplash.com/photo-1646508262200-455d62c22182?...' }, +]; + +export function CitySelectionDialog({ isOpen, onClose }: CitySelectionDialogProps) { + const [searchQuery, setSearchQuery] = useState(''); + const navigate = useNavigate(); // ✅ navigation hook + + const filteredCities = cities.filter(city => + city.name.toLowerCase().includes(searchQuery.toLowerCase()) + ); + + const handleCityClick = (city: City) => { + console.log('Selected city:', city.name); + onClose(); + + // ✅ navigate to /passes with selected city info (optional query param) + navigate(`/passes?city=${encodeURIComponent(city.name)}`); + }; + + return ( + + + {/* Accessible Title */} + Select a City + + Choose from our available cities to explore attractions and experiences + + + {/* Header */} +
+ + +
+ + {/* Search Bar */} +
+
+ + setSearchQuery(e.target.value)} + className="pl-10 bg-input border-0 rounded-lg h-11 font-poppins placeholder:text-gray-400" + /> +
+
+ + {/* City Grid */} +
+ +
+ {filteredCities.map((city, index) => ( + handleCityClick(city)} // ✅ navigate on click + initial={{ opacity: 0, scale: 0.9 }} + animate={{ opacity: 1, scale: 1 }} + exit={{ opacity: 0, scale: 0.9 }} + transition={{ delay: index * 0.05 }} + whileHover={{ scale: 1.03 }} + whileTap={{ scale: 0.98 }} + className="relative h-28 rounded-2xl overflow-hidden group cursor-pointer" + > + +
+
+

+ {city.name} +

+
+ + ))} +
+ + + {/* No Results */} + {filteredCities.length === 0 && ( +
+

+ No cities found matching "{searchQuery}" +

+
+ )} +
+ +
+ ); +} diff --git a/src/components/CustomPostcards.tsx b/src/components/CustomPostcards.tsx index f214a65..85f9779 100644 --- a/src/components/CustomPostcards.tsx +++ b/src/components/CustomPostcards.tsx @@ -4,7 +4,7 @@ import { Button } from './ui/button'; import { ImageWithFallback } from './figma/ImageWithFallback'; import { motion, useMotionValue, useSpring, useTransform, useInView } from 'motion/react'; import { HandwrittenText, useHandwrittenText } from './HandwrittenText'; -import postcardImage from '../assets/eaf15191e9a315d2d4b384ffcb22910687c3d328.png'; +import postcardImage from 'figma:asset/d3a880cf8b7f1bec6da9b3f2ce4a76e822e483cf.png'; interface EditableCardProps { isEditing: boolean; @@ -17,8 +17,11 @@ interface EditableCardProps { export function CustomPostcards() { const [editingCard, setEditingCard] = useState(null); + const [isFlipped, setIsFlipped] = useState(false); + const [uploadedImage, setUploadedImage] = useState(null); const postcardRef = useRef(null); const sectionRef = useRef(null); + const fileInputRef = useRef(null); // 3D tilt effect using mouse position const mouseX = useMotionValue(0); @@ -44,9 +47,9 @@ export function CustomPostcards() { // Handwritten text control const handwrittenControl = useHandwrittenText(false); - // Handle mouse movement for 3D effect + // Handle mouse movement for 3D effect (disabled when flipped) const handleMouseMove = (event: React.MouseEvent) => { - if (!postcardRef.current) return; + if (!postcardRef.current || isFlipped) return; const rect = postcardRef.current.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; @@ -60,6 +63,7 @@ export function CustomPostcards() { }; const handleMouseLeave = () => { + if (isFlipped) return; mouseX.set(0); mouseY.set(0); }; @@ -75,6 +79,25 @@ export function CustomPostcards() { console.log('Navigate to postcard creation page...'); }; + // Handle image upload + const handleImageUpload = (event: React.ChangeEvent) => { + const file = event.target.files?.[0]; + if (file) { + const reader = new FileReader(); + reader.onloadend = () => { + setUploadedImage(reader.result as string); + // Automatically flip to show the uploaded image + setIsFlipped(true); + }; + reader.readAsDataURL(file); + } + }; + + // Trigger file input + const triggerFileInput = () => { + fileInputRef.current?.click(); + }; + // Start handwriting animation when section comes into view useEffect(() => { if (isInView && !editingCard) { @@ -93,6 +116,14 @@ export function CustomPostcards() { } }, [editingCard, handwrittenControl]); + // Reset 3D tilt when card is flipped + useEffect(() => { + if (isFlipped) { + mouseX.set(0); + mouseY.set(0); + } + }, [isFlipped, mouseX, mouseY]); + const EditableCard = ({ isEditing, onEdit, children, className = "", style = {}, editIcon }: EditableCardProps) => { return ( - {/* Interactive 3D Container with Flip */} - setIsFlipped(false)} + className={`hidden md:flex items-center justify-center w-12 h-12 rounded-full bg-white shadow-lg border-2 border-primary hover:bg-primary hover:text-white transition-all duration-300 ${isFlipped ? 'opacity-100' : 'opacity-0 pointer-events-none'}`} + whileHover={{ scale: 1.1 }} + whileTap={{ scale: 0.95 }} + initial={{ opacity: 0, x: -20 }} + animate={{ opacity: isFlipped ? 1 : 0, x: isFlipped ? 0 : -20 }} + transition={{ duration: 0.3 }} > - {/* Front Side - Postcard Design */} - - - - {/* Subtle glow effect */} - - + + - {/* Back Side - Full Image */} + {/* Postcard Container */} +
+ {/* Interactive 3D Container with Flip */} - - {/* Subtle gradient overlay */} -
- - - - {/* Animated Edit Instructions */} - {editingCard && ( - - + {/* Front Side - Postcard Design */} + - Click on any element to edit it - -
+ + + {/* Subtle glow effect */} + + + + {/* Back Side - Postcard Frame with Upload */} + + {/* Postcard frame with gradient background - matching Figma import */} +
+
+
+
+ +
+
+ + + {/* Hidden file input */} + + - )} + + {/* Animated Edit Instructions */} + {editingCard && ( + + + Click on any element to edit it + +
+
+ )} + + {/* Mobile Flip Button - Below postcard on mobile */} + setIsFlipped(!isFlipped)} + className="md:hidden mt-4 mx-auto flex items-center justify-center gap-2 px-6 py-3 rounded-full bg-primary text-white font-poppins font-semibold shadow-lg hover:bg-primary/90 transition-all duration-300" + whileTap={{ scale: 0.95 }} + > + + {isFlipped ? 'View Postcard' : 'View Image'} + +
+ + {/* Right Flip Button - Show when viewing front (not flipped) */} + setIsFlipped(true)} + className={`hidden md:flex items-center justify-center w-12 h-12 rounded-full bg-white shadow-lg border-2 border-primary hover:bg-primary hover:text-white transition-all duration-300 ${!isFlipped ? 'opacity-100' : 'opacity-0 pointer-events-none'}`} + whileHover={{ scale: 1.1 }} + whileTap={{ scale: 0.95 }} + initial={{ opacity: 0, x: 20 }} + animate={{ opacity: !isFlipped ? 1 : 0, x: !isFlipped ? 0 : 20 }} + transition={{ duration: 0.3 }} + > + +
diff --git a/src/components/FooterBrand.tsx b/src/components/FooterBrand.tsx index 2b8d9d7..f7a0307 100644 --- a/src/components/FooterBrand.tsx +++ b/src/components/FooterBrand.tsx @@ -2,7 +2,7 @@ import image_bc70aef6686e5f4d059b5ef3380fd4f44bb9f4c6 from '../assets/bc70aef668 import { motion } from 'motion/react'; import { Apple, Play } from 'lucide-react'; import { ImageWithFallback } from './figma/ImageWithFallback'; -import cityCardsLogo from '../assets/cityLogo.png'; +import cityCardsLogo from '../assets/cit-logo.png'; export function FooterBrand() { return ( diff --git a/src/components/MelbournePage.tsx b/src/components/MelbournePage.tsx index bbbc09b..b6094b6 100644 --- a/src/components/MelbournePage.tsx +++ b/src/components/MelbournePage.tsx @@ -4,7 +4,6 @@ import { ArrowRight, Calendar, Thermometer, Eye } from 'lucide-react'; import { useEffect, useRef, useState } from 'react'; import Navbar from './Navbar'; import { ImageWithFallback } from './figma/ImageWithFallback'; -import { CitySubmenu } from './CitySubmenu'; import { MelbourneAttractions } from './MelbourneAttractions'; import { MelbourneCardComparison } from './MelbourneCardComparison'; import { MelbourneTourOverview } from './MelbourneTourOverview'; @@ -294,7 +293,6 @@ export function MelbournePage({ return ( {/* Hero Banner Carousel */} - {/* */} - + /> + {/* */} {/* Main Content */}
diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 73a14ae..27772ba 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -6,7 +6,9 @@ import Frame1597884853 from '../imports/Frame1597884853'; import { Button } from './ui/button'; import { ImageWithFallback } from './figma/ImageWithFallback'; import { CTAButton } from './CTAButton'; -import logoImage from '../assets/cityLogo.png'; +import logoImage from '../assets/cit-logo.png'; +import melbourneLogo from '../assets/melbourne-logo.png'; +import { CitySelectionDialog } from './CitySelectionDialog'; interface NavbarProps { activeCity: string; @@ -57,6 +59,7 @@ export default function Navbar({ const [activeCartDropdown, setActiveCartDropdown] = useState(false); const [activeUserDropdown, setActiveUserDropdown] = useState(false); const [activeCityDropdown, setActiveCityDropdown] = useState(false); + const [isCityDialogOpen, setIsCityDialogOpen] = useState(false); const languageRef = useRef(null); const cartRef = useRef(null); @@ -66,6 +69,14 @@ export default function Navbar({ const location = useLocation(); const navigate = useNavigate(); + const handleOpenCityDialog = () => { + setIsCityDialogOpen(true); + }; + + const handleCloseCityDialog = () => { + setIsCityDialogOpen(false); + }; + // Available cities const cities = [ { id: 'melbourne', label: 'Melbourne' }, @@ -90,7 +101,7 @@ export default function Navbar({ const melbourneNavigationItems = [ { label: 'Attractions', path: '/attractions' }, { label: 'Magic Itinerary', path: '/magic-itinerary' }, - { label: 'Super Savings', path: '/comming-soon' }, + { label: 'Super Savings', path: '/super-savings' }, { label: 'How It Works', path: '/how-it-works' }, { label: 'Your Card', path: '/passes' } ]; @@ -114,6 +125,34 @@ export default function Navbar({ { id: '2', name: 'Melbourne Premium Pass', price: '$129', quantity: 1 }, ]; + // Calculate cart total + const cartTotal = cartItems.reduce((total, item) => { + const price = parseFloat(item.price.replace('$', '')); + return total + (price * item.quantity); + }, 0); + + // Cart dropdown items with proper navigation for checkout + const cartDropdownItems: DropdownItem[] = [ + ...cartItems.map(item => ({ + id: item.id, + label: `${item.name} - ${item.price}`, + badge: `${item.quantity}x` + })), + { + id: 'total', + label: `Total: $${cartTotal.toFixed(2)}`, + icon: + }, + { + id: 'checkout', + label: 'Proceed to Checkout', + action: () => { + navigate('/checkout'); + setActiveCartDropdown(false); // Close dropdown after navigation + } + } + ]; + const scrollToSection = (index: number) => { const sectionIds = [ 'hero-section', @@ -151,29 +190,6 @@ export default function Navbar({ return () => window.removeEventListener('scroll', handleScroll); }, []); - // Close dropdowns when clicking outside - // useEffect(() => { - // const handleClickOutside = (event: MouseEvent) => { - // setTimeout(() => { - // if (languageRef.current && !languageRef.current.contains(event.target as Node)) { - // setActiveLanguageDropdown(false); - // } - // if (cartRef.current && !cartRef.current.contains(event.target as Node)) { - // setActiveCartDropdown(false); - // } - // if (userRef.current && !userRef.current.contains(event.target as Node)) { - // setActiveUserDropdown(false); - // } - // if (cityRef.current && !cityRef.current.contains(event.target as Node)) { - // setActiveCityDropdown(false); - // } - // }, 10); - // }; - - // document.addEventListener('mousedown', handleClickOutside); - // return () => document.removeEventListener('mousedown', handleClickOutside); - // }, []); - const handleNavClick = (path: string) => { navigate(path); closeMobileMenu(); @@ -183,7 +199,6 @@ export default function Navbar({ return location.pathname === path; }; - // Handle city change // Handle city change const handleCityChange = (city: string) => { console.log('City selected:', city); // Debug log @@ -200,12 +215,6 @@ export default function Navbar({ } }; - // Calculate cart total - const cartTotal = cartItems.reduce((total, item) => { - const price = parseFloat(item.price.replace('$', '')); - return total + (price * item.quantity); - }, 0); - // Simple Dropdown component without blinking const Dropdown = forwardRef(({ isOpen, @@ -262,7 +271,7 @@ export default function Navbar({ key={item.id} onClick={(e) => { e.stopPropagation(); - console.log('City dropdown item clicked:', item.label); + console.log('Dropdown item clicked:', item.label); if (item.action) { item.action(); @@ -273,6 +282,11 @@ export default function Navbar({ >
{item.label} + {item.badge && ( + + {item.badge} + + )}
))} @@ -319,10 +333,15 @@ export default function Navbar({ > + @@ -418,28 +437,12 @@ export default function Navbar({ } /> - {/* Shopping Cart */} + {/* Shopping Cart - UPDATED: using cartDropdownItems */} setActiveCartDropdown(prev => !prev)} - items={[ - ...cartItems.map(item => ({ - id: item.id, - label: `${item.name} - ${item.price}`, - badge: `${item.quantity}x` - })), - { - id: 'total', - label: `Total: ${cartTotal.toFixed(2)}`, - icon: - }, - { - id: 'checkout', - label: 'Proceed to Checkout', - path: '/checkout' - } - ]} + items={cartDropdownItems} // Using the updated array with navigation title="Shopping Cart" trigger={
@@ -457,43 +460,61 @@ export default function Navbar({ {/* City Card Button */}
-
- setActiveUserDropdown(prev => !prev) : onSignInClick} - className="hover:scale-105 transition-transform duration-200" - /> +
+ - {/* User Profile Dropdown attached to CTA Button */} - {isUserSignedIn && user && ( - setActiveUserDropdown(prev => !prev)} - items={[ - { - id: 'profile', - label: 'My Profile', - icon: , - path: '/profile' - }, - { - id: 'settings', - label: 'Settings', - icon: - }, - { - id: 'logout', - label: 'Sign Out', - icon: , - action: onSignOutClick - } - ]} - title="Account" - trigger={null} - /> - )} -
+ {/* ✅ City Selection Dialog */} + + + {isUserSignedIn && user && ( + setActiveUserDropdown(prev => !prev)} + items={[ + { + id: 'profile', + label: 'My Profile', + icon: , + action: () => { + navigate('/profile'); + setActiveUserDropdown(false); + }, + }, + { + id: 'settings', + label: 'Settings', + icon: , + action: () => { + navigate('/settings'); + setActiveUserDropdown(false); + }, + }, + { + id: 'logout', + label: 'Sign Out', + icon: , + action: () => { + if (onSignOutClick) { + onSignOutClick(); + } + setActiveUserDropdown(false); + }, + }, + ]} + title="Account" + trigger={null} + /> + )} +
@@ -650,11 +671,10 @@ export default function Navbar({ {/* Mobile CTA Button */} diff --git a/src/components/SuperSavingsPage.tsx b/src/components/SuperSavingsPage.tsx new file mode 100644 index 0000000..0624cb1 --- /dev/null +++ b/src/components/SuperSavingsPage.tsx @@ -0,0 +1,672 @@ +import { useState } from 'react'; +import { motion } from 'motion/react'; +import { ArrowLeft, Search, Filter, Star, MapPin, Clock, Tag, Heart, Share2, ChevronDown, ChevronRight, Check, Hotel, Plane, Building2, MapPinned, Home, Gift, Percent } from 'lucide-react'; +import { Button } from './ui/button'; +import { Input } from './ui/input'; +import { Card, CardContent, CardHeader, CardTitle } from './ui/card'; +import { Badge } from './ui/badge'; +import { Separator } from './ui/separator'; +import { Checkbox } from './ui/checkbox'; +import Navbar from './Navbar'; +import { Footer } from './Footer'; +import { ImageWithFallback } from './figma/ImageWithFallback'; +import { TrustSection } from './TrustSection'; +import { MobileAppSection } from './MobileAppSection'; +import { ReviewsSection } from './ReviewsSection'; +import { TrustedCompanies } from './TrustedCompanies'; +import { Layout } from '../Layout'; + +interface SuperSavingsPageProps { + onBackClick: () => void; + onHomeClick: () => void; + onMelbourneClick: () => void; + onPassesClick: () => void; + onCheckoutClick: () => void; + onSignInClick: () => void; + onSignOutClick: () => void; + onAttractionsClick: () => void; + onBlogsClick: () => void; + onHowItWorksClick: () => void; + onFAQClick: () => void; + onPrivacyPolicyClick: () => void; + onAboutUsClick: () => void; + onProfileClick: () => void; + onCityCardsClick: () => void; + onMagicItineraryClick: () => void; + onPostCardsClick: () => void; + onOffersClick: () => void; + onSuperSavingsClick: () => void; + onContactUsClick?: () => void; + onEsimsClick?: () => void; + onHotelDiscountsClick?: () => void; + fromSource?: 'products' | 'passes'; + currentPage: string; + user?: { email: string; name: string; } | null; +} + +// Mock super savings data +const savingsData = [ + { + id: '1', + business: 'Grand Hotels Melbourne', + title: 'Up to 50% Off on luxury hotel stays across Melbourne', + discount: '50% OFF', + savedAmount: 'Save up to $300', + image: 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=400', + category: 'hotels' + }, + { + id: '2', + business: 'Adventure Tours', + title: '40% Off on guided adventure tours and experiences', + discount: '40% OFF', + savedAmount: 'Save up to $150', + image: 'https://images.unsplash.com/photo-1571019613454-1cb2f99b2d8b?w=400', + category: 'tours' + }, + { + id: '3', + business: 'Premium Spa & Wellness', + title: '45% Off on spa packages and wellness treatments', + discount: '45% OFF', + savedAmount: 'Save up to $200', + image: 'https://images.unsplash.com/photo-1544161515-4ab6ce6db874?w=400', + category: 'wellness' + }, + { + id: '4', + business: 'Culinary Delights', + title: '35% Off on fine dining at Michelin-starred restaurants', + discount: '35% OFF', + savedAmount: 'Save up to $120', + image: 'https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=400', + category: 'dining' + }, + { + id: '5', + business: 'Entertainment Pass', + title: '60% Off on theater shows and concert tickets', + discount: '60% OFF', + savedAmount: 'Save up to $250', + image: 'https://images.unsplash.com/photo-1514306191717-452ec28c7814?w=400', + category: 'entertainment' + }, + { + id: '6', + business: 'Museum Pass', + title: '55% Off on museum entries and special exhibitions', + discount: '55% OFF', + savedAmount: 'Save up to $180', + image: 'https://images.unsplash.com/photo-1566127992631-137a642a90f4?w=400', + category: 'museums' + }, + { + id: '7', + business: 'Luxury Shopping', + title: '30% Off on designer boutiques and luxury shopping', + discount: '30% OFF', + savedAmount: 'Save up to $500', + image: 'https://images.unsplash.com/photo-1441986300917-64674bd600d8?w=400', + category: 'shopping' + }, + { + id: '8', + business: 'Water Sports', + title: '45% Off on water sports and beach activities', + discount: '45% OFF', + savedAmount: 'Save up to $175', + image: 'https://images.unsplash.com/photo-1476514525535-07fb3b4ae5f1?w=400', + category: 'sports' + }, + { + id: '9', + business: 'Wine Tasting Tours', + title: '40% Off on wine country tours and tastings', + discount: '40% OFF', + savedAmount: 'Save up to $160', + image: 'https://images.unsplash.com/photo-1506377247377-2a5b3b417ebb?w=400', + category: 'tours' + }, + { + id: '10', + business: 'Family Fun Parks', + title: '50% Off on family entertainment and theme parks', + discount: '50% OFF', + savedAmount: 'Save up to $220', + image: 'https://images.unsplash.com/photo-1524850011238-e3d235c7d4c9?w=400', + category: 'entertainment' + }, + { + id: '11', + business: 'Boutique Stays', + title: '55% Off on boutique hotels and bed & breakfasts', + discount: '55% OFF', + savedAmount: 'Save up to $280', + image: 'https://images.unsplash.com/photo-1551882547-ff40c63fe5fa?w=400', + category: 'hotels' + }, + { + id: '12', + business: 'Art Galleries', + title: '35% Off on contemporary art galleries and workshops', + discount: '35% OFF', + savedAmount: 'Save up to $140', + image: 'https://images.unsplash.com/photo-1561214115-f2f134cc4912?w=400', + category: 'museums' + }, + { + id: '13', + business: 'Luxury Cruises', + title: '65% Off on harbor cruises and yacht experiences', + discount: '65% OFF', + savedAmount: 'Save up to $400', + image: 'https://images.unsplash.com/photo-1544551763-46a013bb70d5?w=400', + category: 'tours' + } +]; + +const filterCategories = [ + { value: 'hotels', label: 'Hotels', count: 2 }, + { value: 'tours', label: 'Tours', count: 3 }, + { value: 'wellness', label: 'Wellness', count: 1 }, + { value: 'dining', label: 'Dining', count: 1 }, + { value: 'entertainment', label: 'Entertainment', count: 2 }, + { value: 'museums', label: 'Museums', count: 2 }, + { value: 'shopping', label: 'Shopping', count: 1 }, + { value: 'sports', label: 'Sports', count: 1 } +]; + +// Categories data for the Super Savings Categories section +const categoriesData = [ + { + icon: Hotel, + title: 'Luxury Hotels', + description: 'Premium stays at unbeatable prices', + savings: 'Up to 50% off', + color: 'from-primary to-primary/80' + }, + { + icon: Plane, + title: 'Travel Tours', + description: 'Guided experiences worth your time', + savings: 'Up to 45% off', + color: 'from-primary to-primary/80' + }, + { + icon: MapPinned, + title: 'Attractions', + description: 'Must-see landmarks and experiences', + savings: 'Up to 60% off', + color: 'from-primary to-primary/80' + }, + { + icon: Building2, + title: 'Shopping', + description: 'Designer brands and local boutiques', + savings: 'Up to 35% off', + color: 'from-primary to-primary/80' + }, + { + icon: Gift, + title: 'Wellness', + description: 'Spa treatments and relaxation', + savings: 'Up to 45% off', + color: 'from-primary to-primary/80' + } +]; + +export function SuperSavingsPage({ + onBackClick, + onHomeClick, + onMelbourneClick, + onPassesClick, + onCheckoutClick, + onSignInClick, + onSignOutClick, + onAttractionsClick, + onBlogsClick, + onHowItWorksClick, + onFAQClick, + onPrivacyPolicyClick, + onAboutUsClick, + onProfileClick, + onCityCardsClick, + onMagicItineraryClick, + onPostCardsClick, + onOffersClick, + onSuperSavingsClick, + onContactUsClick, + onEsimsClick, + onHotelDiscountsClick, + fromSource = 'products', + currentPage, + user +}: SuperSavingsPageProps) { + const [searchQuery, setSearchQuery] = useState(''); + const [selectedCategories, setSelectedCategories] = useState([]); + const [currentPage_, setCurrentPage_] = useState(1); + const [showLoadMore, setShowLoadMore] = useState(true); + + const toggleCategory = (category: string) => { + setSelectedCategories(prev => + prev.includes(category) + ? prev.filter(c => c !== category) + : [...prev, category] + ); + }; + + const filteredSavings = savingsData.filter(saving => { + const matchesSearch = saving.title.toLowerCase().includes(searchQuery.toLowerCase()) || + saving.business.toLowerCase().includes(searchQuery.toLowerCase()); + const matchesCategory = selectedCategories.length === 0 || selectedCategories.includes(saving.category); + + return matchesSearch && matchesCategory; + }); + + const itemsPerPage = 12; + const displayedSavings = filteredSavings.slice(0, currentPage_ * itemsPerPage); + const hasMoreItems = filteredSavings.length > displayedSavings.length; + + const handleLoadMore = () => { + setCurrentPage_(prev => prev + 1); + if (!hasMoreItems) setShowLoadMore(false); + }; + + // Show different layouts based on login state + if (!user) { + // Not logged in - show marketing/landing page + return ( + +
+ + {/* Hero Section */} +
+ {/* Background gradient */} +
+ +
+ +

+ Unlock{' '} + + Super Savings + +

+

+ Experience incredible discounts up to 65% off on premium experiences, luxury stays, and unforgettable attractions. +

+ +
+
+ + {/* Decorative elements */} +
+
+
+ + {/* Trusted By Companies Section */} +
+
+
+
+

+ Trusted by the + world's best +

+

+ Join thousands of savvy travelers enjoying massive savings on premium experiences +

+
+ +
+
+
+ + {/* Featured Super Savings Section */} +
+
+ +

+ Featured{' '} + + Super Savings + +

+

+ Check out our biggest discounts and start saving on premium experiences +

+
+ +
+
+ {/* Left Sidebar - Filters */} +
+ +
+ {/* Search by header */} +
+
+

Search by

+
+ + {/* Filter categories */} +
+ {filterCategories.map(category => ( +
+ toggleCategory(category.value)} + className="border-gray-400" + /> + +
+ ))} +
+
+
+
+ + {/* Main Content */} +
+ {/* Breadcrumb */} +
+

+ {fromSource === 'passes' ? ( + <> + My Profile{'>'}My passes{'>'} + Super Savings + + ) : ( + <> + Our Products{'>'} + Super Savings + + )} +

+
+ + {/* Header Section */} +
+

+ Super Savings +

+

+ Exclusive discounts up to 65% off on premium experiences +

+
+ + {/* Savings Grid */} +
+ {displayedSavings.map((saving, index) => ( + + + {/* Image */} +
+ + + + {/* Discount Badge */} +
+ {saving.discount} +
+
+ + + {/* Business Name */} +
+
+ {saving.business} +
+ + {/* Title */} +

+ {saving.title} +

+ + {/* Saved Amount Display */} +
+
+ + + {saving.savedAmount} + +
+
+
+
+
+ ))} +
+ + {/* Minimal Pagination */} +
+
+ + +
+ {[1, 2, 3].map((page) => ( + + ))} +
+ + +
+
+
+
+
+ +
+ +
+
+
+ + {/* How It Works Section */} +
+
+ +

+ How{' '} + + It Works + +

+

+ Access massive discounts in three simple steps +

+
+ +
+ {[ + { + step: '01', + title: 'Get Your Pass', + description: 'Purchase a CityCards pass and unlock instant access', + icon: '🎫' + }, + { + step: '02', + title: 'Browse Deals', + description: 'Explore hundreds of exclusive super savings across categories', + icon: '💎' + }, + { + step: '03', + title: 'Save Big', + description: 'Enjoy discounts up to 65% on premium experiences', + icon: '🎉' + } + ].map((item, index) => ( + + +
{item.icon}
+
+ {item.step} +
+

+ {item.title} +

+

+ {item.description} +

+
+
+ ))} +
+
+
+ + {/* Categories Section */} +
+
+ +

+ + Top Categories + {' '} + to Save +

+

+ From luxury hotels to exciting tours, find massive savings on everything you love +

+
+ +
+ {categoriesData.map((category, index) => ( + + +
+ +
+

+ {category.title} +

+

+ {category.description} +

+
+ + {category.savings} + + +
+
+
+ ))} +
+ +
+ +
+
+
+ + {/* Access Your CityCards Section */} +
+ +
+ +
+
+ ); + } + +} diff --git a/src/pages/landingPage.tsx b/src/pages/landingPage.tsx index bb16c5a..d855e88 100644 --- a/src/pages/landingPage.tsx +++ b/src/pages/landingPage.tsx @@ -16,6 +16,7 @@ import { LandingUpcomingCities } from '../components/LandingUpcomingCities'; import { LandingTrustSection } from '../components/LandingTrustSection'; import { LandingMobileAppSection } from '../components/LandingMobileAppSection'; import { LandingNewsletterSection } from '../components/LandingNewsletterSection'; +import { CustomPostcards } from '../components/CustomPostcards'; @@ -193,7 +194,8 @@ export function LandingPage({ onSignInClick, {/* CustomPostcards Section */} - + {/* */} + {/* UpcomingCities Section */}