From a55e473e3c17a732cc5a824d0fa4a08b0419c888 Mon Sep 17 00:00:00 2001 From: priyanshuvish Date: Mon, 3 Nov 2025 19:57:32 +0530 Subject: [PATCH] new fixes --- src/AppRouter.tsx | 6 + src/assets/melbourne-logo.png | Bin 0 -> 36763 bytes src/components/CitySelectionDialog.tsx | 126 +++++ src/components/CustomPostcards.tsx | 307 +++++++---- src/components/FooterBrand.tsx | 2 +- src/components/MelbournePage.tsx | 8 +- src/components/Navbar.tsx | 208 ++++---- src/components/SuperSavingsPage.tsx | 672 +++++++++++++++++++++++++ src/pages/landingPage.tsx | 4 +- 9 files changed, 1139 insertions(+), 194 deletions(-) create mode 100644 src/assets/melbourne-logo.png create mode 100644 src/components/CitySelectionDialog.tsx create mode 100644 src/components/SuperSavingsPage.tsx 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 0000000000000000000000000000000000000000..0d99a5cb45139b4c75a0d086442043ae75b5965d GIT binary patch literal 36763 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 D)Gzg<1w`U}o5`+PQ-cpnf+@l@p+~tjS8NQ#AQP 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 KT-G@yGywp;!$(2@ literal 0 HcmV?d00001 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 */}