732 lines
31 KiB
TypeScript
732 lines
31 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { motion } from 'motion/react';
|
|
import { ArrowLeft, Calendar, Clock, MapPin, Users, Star, Heart, Share2, Download, CheckCircle, Navigation, Cloud, Sun } from 'lucide-react';
|
|
import { Button } from './ui/button';
|
|
import { Card, CardContent } from './ui/card';
|
|
import { Badge } from './ui/badge';
|
|
import Navbar from './Navbar';
|
|
import { Footer } from './Footer';
|
|
import { ImageWithFallback } from './figma/ImageWithFallback';
|
|
|
|
interface ItineraryViewPageProps {
|
|
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;
|
|
onCreateItineraryClick: () => void;
|
|
onContactUsClick?: () => void;
|
|
onEsimsClick?: () => void;
|
|
onHotelDiscountsClick?: () => void;
|
|
currentPage: string;
|
|
user?: { email: string; name: string; } | null;
|
|
}
|
|
|
|
// Enhanced activity type with more details
|
|
interface Activity {
|
|
time: string;
|
|
activity: string;
|
|
location: string;
|
|
address: string;
|
|
image: string;
|
|
categories: string[];
|
|
description: string[];
|
|
isFavorite?: boolean;
|
|
}
|
|
|
|
export function ItineraryViewPage({
|
|
onBackClick,
|
|
onHomeClick,
|
|
onMelbourneClick,
|
|
onPassesClick,
|
|
onCheckoutClick,
|
|
onSignInClick,
|
|
onSignOutClick,
|
|
onAttractionsClick,
|
|
onBlogsClick,
|
|
onHowItWorksClick,
|
|
onFAQClick,
|
|
onPrivacyPolicyClick,
|
|
onAboutUsClick,
|
|
onProfileClick,
|
|
onCityCardsClick,
|
|
onMagicItineraryClick,
|
|
onPostCardsClick,
|
|
onOffersClick,
|
|
onCreateItineraryClick,
|
|
onContactUsClick,
|
|
onEsimsClick,
|
|
onHotelDiscountsClick,
|
|
currentPage,
|
|
user
|
|
}: ItineraryViewPageProps) {
|
|
const [viewMode, setViewMode] = useState<'daily' | 'summary'>('daily');
|
|
const [favorites, setFavorites] = useState<Set<string>>(new Set());
|
|
|
|
const toggleFavorite = (activityKey: string) => {
|
|
setFavorites(prev => {
|
|
const newSet = new Set(prev);
|
|
if (newSet.has(activityKey)) {
|
|
newSet.delete(activityKey);
|
|
} else {
|
|
newSet.add(activityKey);
|
|
}
|
|
return newSet;
|
|
});
|
|
};
|
|
|
|
// Enhanced itinerary data with images, addresses, and detailed info
|
|
const generatedItinerary = {
|
|
destination: {
|
|
name: 'Melbourne',
|
|
country: 'Australia',
|
|
weather: '18°C, Sunny',
|
|
image: 'https://images.unsplash.com/photo-1514395462725-fb4566210144?w=400&h=300&fit=crop'
|
|
},
|
|
totalDays: 3,
|
|
estimatedCost: '$450 AUD',
|
|
includedActivities: 18,
|
|
dailyPlans: [
|
|
{
|
|
day: 1,
|
|
title: "City Center & Culture",
|
|
activities: [
|
|
{
|
|
time: '8:00 am',
|
|
activity: 'The Langham Melbourne',
|
|
location: 'The Langham Melbourne',
|
|
address: '1 Southgate Avenue, Southbank VIC 3006',
|
|
image: 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=800&h=600&fit=crop',
|
|
categories: ['Accommodation', 'Luxury'],
|
|
description: [
|
|
'Check-in at luxury riverside hotel',
|
|
'Enjoy complimentary breakfast',
|
|
'Relax at the spa facilities',
|
|
'Explore the surrounding Southbank area'
|
|
]
|
|
},
|
|
{
|
|
time: '10:00 am',
|
|
activity: 'Federation Square',
|
|
location: 'Federation Square',
|
|
address: 'Corner Swanston & Flinders Streets, Melbourne VIC 3000',
|
|
image: 'https://images.unsplash.com/photo-1514395462725-fb4566210144?w=800&h=600&fit=crop',
|
|
categories: ['Culture', 'Landmark'],
|
|
description: [
|
|
'Explore Melbourne\'s cultural precinct',
|
|
'Visit the ACMI museum',
|
|
'Enjoy street performances',
|
|
'Take photos at iconic locations'
|
|
]
|
|
},
|
|
{
|
|
time: '12:00 pm',
|
|
activity: 'Degrave Street Café',
|
|
location: 'Degrave Street Espresso Bar',
|
|
address: '23-25 Degraves Street, Melbourne VIC 3000',
|
|
image: 'https://images.unsplash.com/photo-1554118811-1e0d58224f24?w=800&h=600&fit=crop',
|
|
categories: ['Food', 'Drinks', 'Culture'],
|
|
description: [
|
|
'Coffee at Pellegrini\'s Espresso Bar (iconic old-school cafe)',
|
|
'Try the famous jam doughnuts',
|
|
'Shop for fresh produce in the Deli Hall',
|
|
'Pick up unique souvenirs in the General Merchandise section'
|
|
]
|
|
},
|
|
{
|
|
time: '2:00 pm',
|
|
activity: 'Royal Botanic Gardens',
|
|
location: 'Royal Botanic Gardens Victoria',
|
|
address: 'Birdwood Avenue, South Yarra VIC 3141',
|
|
image: 'https://images.unsplash.com/photo-1585320806297-9794b3e4eeae?w=800&h=600&fit=crop',
|
|
categories: ['Nature', 'Culture'],
|
|
description: [
|
|
'Stroll through stunning landscaped gardens',
|
|
'Visit the Australian Forest Walk',
|
|
'Relax by the Ornamental Lake',
|
|
'Join a free guided walking tour'
|
|
]
|
|
},
|
|
{
|
|
time: '4:00 pm',
|
|
activity: 'National Gallery of Victoria',
|
|
location: 'NGV International',
|
|
address: '180 St Kilda Road, Melbourne VIC 3006',
|
|
image: 'https://images.unsplash.com/photo-1564399577149-749794d74eee?w=800&h=600&fit=crop',
|
|
categories: ['Culture', 'Art'],
|
|
description: [
|
|
'Explore Australia\'s oldest art museum',
|
|
'View international and Australian art collections',
|
|
'Visit the stunning water wall entrance',
|
|
'Browse the NGV design store'
|
|
]
|
|
},
|
|
{
|
|
time: '7:00 pm',
|
|
activity: 'Dinner at Chin Chin',
|
|
location: 'Chin Chin Restaurant',
|
|
address: '125 Flinders Lane, Melbourne VIC 3000',
|
|
image: 'https://images.unsplash.com/photo-1552566626-52f8b828add9?w=800&h=600&fit=crop',
|
|
categories: ['Food', 'Drinks'],
|
|
description: [
|
|
'Experience modern Thai cuisine',
|
|
'Try signature dishes like the Betel Leaf',
|
|
'Enjoy the vibrant atmosphere',
|
|
'Book ahead or walk-in for bar seating'
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
day: 2,
|
|
title: "Markets & Neighborhoods",
|
|
activities: [
|
|
{
|
|
time: '8:00 am',
|
|
activity: 'Queen Victoria Market',
|
|
location: 'Queen Victoria Market',
|
|
address: 'Queen Street, Melbourne VIC 3000',
|
|
image: 'https://images.unsplash.com/photo-1555939594-58d7cb561ad1?w=800&h=600&fit=crop',
|
|
categories: ['Food', 'Shopping', 'Culture'],
|
|
description: [
|
|
'Explore Melbourne\'s historic market (since 1878)',
|
|
'Sample fresh local produce',
|
|
'Shop for artisan goods and souvenirs',
|
|
'Grab breakfast at the Deli Hall'
|
|
]
|
|
},
|
|
{
|
|
time: '10:30 am',
|
|
activity: 'Fitzroy Street Art Tour',
|
|
location: 'Fitzroy Arts Precinct',
|
|
address: 'Gertrude Street, Fitzroy VIC 3065',
|
|
image: 'https://images.unsplash.com/photo-1499781350541-7783f6c6a0c8?w=800&h=600&fit=crop',
|
|
categories: ['Culture', 'Art'],
|
|
description: [
|
|
'Walk through famous street art laneways',
|
|
'Discover works by renowned artists',
|
|
'Visit independent galleries',
|
|
'Explore vintage and record stores'
|
|
]
|
|
},
|
|
{
|
|
time: '12:30 pm',
|
|
activity: 'Brunswick Street Lunch',
|
|
location: 'Brunswick Street Precinct',
|
|
address: 'Brunswick Street, Fitzroy VIC 3065',
|
|
image: 'https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?w=800&h=600&fit=crop',
|
|
categories: ['Food', 'Drinks'],
|
|
description: [
|
|
'Choose from diverse dining options',
|
|
'Try local cafes and restaurants',
|
|
'Explore bookshops and boutiques',
|
|
'Enjoy the vibrant neighborhood atmosphere'
|
|
]
|
|
},
|
|
{
|
|
time: '2:30 pm',
|
|
activity: 'Carlton Gardens',
|
|
location: 'Carlton Gardens',
|
|
address: 'Carlton Gardens, Carlton VIC 3053',
|
|
image: 'https://images.unsplash.com/photo-1519331379826-f10be5486c6f?w=800&h=600&fit=crop',
|
|
categories: ['Nature', 'Culture', 'Landmark'],
|
|
description: [
|
|
'Visit the UNESCO World Heritage site',
|
|
'See the Royal Exhibition Building',
|
|
'Stroll through Victorian-era gardens',
|
|
'Relax by the ornamental fountains'
|
|
]
|
|
},
|
|
{
|
|
time: '4:00 pm',
|
|
activity: 'Melbourne Museum',
|
|
location: 'Melbourne Museum',
|
|
address: '11 Nicholson Street, Carlton VIC 3053',
|
|
image: 'https://images.unsplash.com/photo-1566127992631-137a642a90f4?w=800&h=600&fit=crop',
|
|
categories: ['Culture', 'Museum'],
|
|
description: [
|
|
'Explore natural and cultural history',
|
|
'Visit the Bunjilaka Aboriginal Centre',
|
|
'See the Forest Gallery living ecosystem',
|
|
'Discover Melbourne\'s story exhibition'
|
|
]
|
|
},
|
|
{
|
|
time: '7:00 pm',
|
|
activity: 'Rooftop Bar Experience',
|
|
location: 'Naked for Satan',
|
|
address: '285 Brunswick Street, Fitzroy VIC 3065',
|
|
image: 'https://images.unsplash.com/photo-1514933651103-005eec06c04b?w=800&h=600&fit=crop',
|
|
categories: ['Drinks', 'Food'],
|
|
description: [
|
|
'Enjoy sunset views from the rooftop',
|
|
'Try Spanish-style pintxos',
|
|
'Sample craft cocktails and local beers',
|
|
'Experience Melbourne\'s bar culture'
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
day: 3,
|
|
title: "Coastal Adventure",
|
|
activities: [
|
|
{
|
|
time: '8:00 am',
|
|
activity: 'St. Kilda Beach',
|
|
location: 'St. Kilda Beach',
|
|
address: 'Jacka Boulevard, St Kilda VIC 3182',
|
|
image: 'https://images.unsplash.com/photo-1505142468610-359e7d316be0?w=800&h=600&fit=crop',
|
|
categories: ['Nature', 'Beach'],
|
|
description: [
|
|
'Morning walk along the iconic beach',
|
|
'Visit the historic St Kilda Pier',
|
|
'See the little penguins at sunset',
|
|
'Explore the Sunday Esplanade Market (weekends)'
|
|
]
|
|
},
|
|
{
|
|
time: '10:00 am',
|
|
activity: 'Acland Street Cafes',
|
|
location: 'Acland Street',
|
|
address: 'Acland Street, St Kilda VIC 3182',
|
|
image: 'https://images.unsplash.com/photo-1495474472287-4d71bcdd2085?w=800&h=600&fit=crop',
|
|
categories: ['Food', 'Drinks'],
|
|
description: [
|
|
'Brunch at famous cake shops',
|
|
'Try traditional European pastries',
|
|
'Visit Lentil as Anything (pay-as-you-feel)',
|
|
'Browse vintage shops and bookstores'
|
|
]
|
|
},
|
|
{
|
|
time: '12:00 pm',
|
|
activity: 'Luna Park Melbourne',
|
|
location: 'Luna Park Melbourne',
|
|
address: '18 Lower Esplanade, St Kilda VIC 3182',
|
|
image: 'https://images.unsplash.com/photo-1513026705753-bc3fffca8bf4?w=800&h=600&fit=crop',
|
|
categories: ['Entertainment', 'Landmark'],
|
|
description: [
|
|
'Visit Melbourne\'s iconic amusement park',
|
|
'Ride the historic Scenic Railway (1912)',
|
|
'Take photos at Mr Moon entrance',
|
|
'Enjoy carnival games and rides'
|
|
]
|
|
},
|
|
{
|
|
time: '2:00 pm',
|
|
activity: 'Brighton Beach Boxes',
|
|
location: 'Brighton Beach',
|
|
address: 'Esplanade, Brighton VIC 3186',
|
|
image: 'https://images.unsplash.com/photo-1520208422220-d12a3c588e6c?w=800&h=600&fit=crop',
|
|
categories: ['Culture', 'Landmark'],
|
|
description: [
|
|
'Photograph the famous colorful bathing boxes',
|
|
'Walk along the pristine beach',
|
|
'Learn about the heritage structures',
|
|
'Relax in the beachside atmosphere'
|
|
]
|
|
},
|
|
{
|
|
time: '4:00 pm',
|
|
activity: 'Southbank Promenade',
|
|
location: 'Southbank',
|
|
address: 'Southbank Promenade, Southbank VIC 3006',
|
|
image: 'https://images.unsplash.com/photo-1559827260-dc66d52bef19?w=800&h=600&fit=crop',
|
|
categories: ['Culture', 'Shopping'],
|
|
description: [
|
|
'Stroll along the Yarra River',
|
|
'Visit arts and craft markets',
|
|
'Explore restaurants and cafes',
|
|
'Enjoy river views and street performers'
|
|
]
|
|
},
|
|
{
|
|
time: '7:00 pm',
|
|
activity: 'Farewell Dinner at Vue de Monde',
|
|
location: 'Vue de Monde',
|
|
address: 'Level 55, Rialto, 525 Collins Street, Melbourne VIC 3000',
|
|
image: 'https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=800&h=600&fit=crop',
|
|
categories: ['Food', 'Drinks', 'Luxury'],
|
|
description: [
|
|
'Experience fine dining at 55th floor',
|
|
'Enjoy panoramic Melbourne views',
|
|
'Taste modern Australian cuisine',
|
|
'Celebrate the end of your journey'
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
};
|
|
|
|
return (
|
|
<div className="min-h-screen bg-background">
|
|
{/* Navbar */}
|
|
<Navbar
|
|
activeCity=""
|
|
onCityChange={() => {}}
|
|
onSignInClick={onSignInClick}
|
|
onPassesClick={onPassesClick}
|
|
onCheckoutClick={onCheckoutClick}
|
|
onHomeClick={onHomeClick}
|
|
onMelbourneClick={onMelbourneClick}
|
|
onAttractionsClick={onAttractionsClick}
|
|
onBlogsClick={onBlogsClick}
|
|
onHowItWorksClick={onHowItWorksClick}
|
|
onFAQClick={onFAQClick}
|
|
onPrivacyPolicyClick={onPrivacyPolicyClick}
|
|
onAboutUsClick={onAboutUsClick}
|
|
onProfileClick={onProfileClick}
|
|
onCityCardsClick={onCityCardsClick}
|
|
onMagicItineraryClick={onMagicItineraryClick}
|
|
onPostCardsClick={onPostCardsClick}
|
|
onOffersClick={onOffersClick}
|
|
currentPage="itinerary-view"
|
|
isUserSignedIn={!!user}
|
|
user={user}
|
|
/>
|
|
|
|
{/* Header Section */}
|
|
<section className="pt-32 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 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.6 }}
|
|
className="text-center"
|
|
>
|
|
<Button
|
|
variant="ghost"
|
|
onClick={onBackClick}
|
|
className="mb-6 hover:bg-primary/5 font-poppins font-medium"
|
|
>
|
|
<ArrowLeft className="w-4 h-4 mr-2" />
|
|
Back to Magic Itinerary
|
|
</Button>
|
|
|
|
<div className="flex items-center justify-center gap-2 text-primary mb-4">
|
|
<Star className="w-6 h-6 fill-current" />
|
|
<h1 className="font-merchant text-4xl md:text-5xl lg:text-6xl leading-tight">
|
|
<span className="font-light">Your</span>{' '}
|
|
<span className="font-bold italic bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent">Magic Itinerary</span>
|
|
</h1>
|
|
<Star className="w-6 h-6 fill-current" />
|
|
</div>
|
|
<p className="font-poppins text-xl leading-relaxed font-normal text-gray-600 max-w-2xl mx-auto">
|
|
Here's your personalized {generatedItinerary.totalDays}-day adventure in {generatedItinerary.destination.name}!
|
|
</p>
|
|
</motion.div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Main Content */}
|
|
<section className="py-8">
|
|
<div className="container mx-auto px-4">
|
|
<div className="max-w-6xl mx-auto space-y-8">
|
|
{/* View Toggle */}
|
|
<div className="flex justify-center">
|
|
<div className="bg-muted p-1 rounded-lg">
|
|
<Button
|
|
variant={viewMode === 'daily' ? 'default' : 'ghost'}
|
|
size="sm"
|
|
onClick={() => setViewMode('daily')}
|
|
className="rounded-md font-poppins font-medium"
|
|
>
|
|
Daily View
|
|
</Button>
|
|
<Button
|
|
variant={viewMode === 'summary' ? 'default' : 'ghost'}
|
|
size="sm"
|
|
onClick={() => setViewMode('summary')}
|
|
className="rounded-md font-poppins font-medium"
|
|
>
|
|
Summary
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Itinerary Overview */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.6, delay: 0.2 }}
|
|
>
|
|
<Card className="p-6">
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
<div className="text-center">
|
|
<div className="font-merchant text-3xl text-primary mb-2">{generatedItinerary.totalDays}</div>
|
|
<div className="font-poppins text-sm text-muted-foreground font-normal">Days</div>
|
|
</div>
|
|
<div className="text-center">
|
|
<div className="font-merchant text-3xl text-primary mb-2">{generatedItinerary.includedActivities}</div>
|
|
<div className="font-poppins text-sm text-muted-foreground font-normal">Activities</div>
|
|
</div>
|
|
<div className="text-center">
|
|
<div className="font-merchant text-3xl text-primary mb-2">{generatedItinerary.estimatedCost}</div>
|
|
<div className="font-poppins text-sm text-muted-foreground font-normal">Estimated Cost</div>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
</motion.div>
|
|
|
|
{/* Daily Plans - Enhanced View */}
|
|
{viewMode === 'daily' && (
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.6, delay: 0.3 }}
|
|
className="space-y-12"
|
|
>
|
|
{generatedItinerary.dailyPlans.map((day, dayIndex) => (
|
|
<div key={dayIndex} className="space-y-6">
|
|
{/* Location Header with Weather - Only show for first day or when location changes */}
|
|
{(dayIndex === 0 ||
|
|
(dayIndex > 0 &&
|
|
generatedItinerary.dailyPlans[dayIndex - 1] &&
|
|
(generatedItinerary.dailyPlans[dayIndex - 1] as any).destination?.name !== generatedItinerary.destination.name)) && (
|
|
<motion.div
|
|
initial={{ opacity: 0, x: -20 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
transition={{ duration: 0.6, delay: 0.4 + dayIndex * 0.1 }}
|
|
className="bg-gray-50 rounded-2xl p-6 shadow-sm border border-gray-200"
|
|
>
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h2 className="font-merchant text-3xl md:text-4xl leading-tight mb-2">
|
|
{generatedItinerary.destination.name}, {generatedItinerary.destination.country}
|
|
</h2>
|
|
<p className="font-poppins text-base text-primary font-medium">{generatedItinerary.destination.weather}</p>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<Sun className="w-10 h-10 text-amber-500" />
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
)}
|
|
|
|
{/* Day Header */}
|
|
<motion.div
|
|
initial={{ opacity: 0, x: -20 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
transition={{ duration: 0.6, delay: 0.5 + dayIndex * 0.1 }}
|
|
className="flex items-center gap-4 pl-2"
|
|
>
|
|
<div className="bg-gradient-to-br from-primary to-secondary text-white w-16 h-16 rounded-full flex items-center justify-center shadow-lg">
|
|
<span className="font-merchant text-2xl font-semibold">{day.day}</span>
|
|
</div>
|
|
<div>
|
|
<h3 className="font-merchant text-2xl md:text-3xl leading-snug font-semibold">Day {day.day}</h3>
|
|
<p className="font-poppins text-base text-muted-foreground font-normal">{day.title}</p>
|
|
</div>
|
|
</motion.div>
|
|
|
|
{/* GMT Label */}
|
|
<div className="pl-2">
|
|
<p className="font-poppins text-sm text-gray-500 font-normal">GMT</p>
|
|
</div>
|
|
|
|
{/* Activity Cards - Desktop Grid Layout */}
|
|
<div className="space-y-8">
|
|
{day.activities.map((activity, actIndex) => {
|
|
const activityKey = `day${day.day}-act${actIndex}`;
|
|
const isFavorite = favorites.has(activityKey);
|
|
|
|
return (
|
|
<motion.div
|
|
key={actIndex}
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.5, delay: 0.6 + dayIndex * 0.1 + actIndex * 0.05 }}
|
|
className="flex gap-6"
|
|
>
|
|
{/* Time Column */}
|
|
<div className="flex-shrink-0 w-24 pt-2">
|
|
<div className="font-poppins text-base font-medium text-gray-700">{activity.time}</div>
|
|
</div>
|
|
|
|
{/* Activity Card */}
|
|
<div className="flex-1">
|
|
<Card className="overflow-hidden hover:shadow-xl transition-shadow duration-300 border-2 border-gray-100">
|
|
<CardContent className="p-0">
|
|
{/* Hero Image with Overlay Buttons */}
|
|
<div className="relative h-64 md:h-72 bg-gray-200">
|
|
<ImageWithFallback
|
|
src={activity.image}
|
|
alt={activity.activity}
|
|
className="w-full h-full object-cover"
|
|
/>
|
|
|
|
{/* Favorite Heart Button - Top Right */}
|
|
<div className="absolute top-4 right-4">
|
|
<Button
|
|
size="icon"
|
|
variant="secondary"
|
|
className="bg-white/95 hover:bg-white shadow-lg backdrop-blur-sm rounded-full w-12 h-12"
|
|
onClick={() => toggleFavorite(activityKey)}
|
|
>
|
|
<Heart className={`w-5 h-5 ${isFavorite ? 'fill-primary text-primary' : 'text-gray-700'}`} />
|
|
</Button>
|
|
</div>
|
|
|
|
{/* Get Directions Button - Bottom Left */}
|
|
<div className="absolute bottom-4 left-4">
|
|
<Button
|
|
className="bg-primary hover:bg-primary/90 text-white font-poppins font-semibold shadow-lg px-6 py-3 rounded-xl"
|
|
>
|
|
<Navigation className="w-4 h-4 mr-2" />
|
|
Get Directions
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Content Section */}
|
|
<div className="p-6 space-y-4">
|
|
{/* Location Name & Address */}
|
|
<div className="space-y-2">
|
|
<h4 className="font-merchant text-xl md:text-2xl leading-snug font-semibold text-gray-900">
|
|
{activity.activity}
|
|
</h4>
|
|
<div className="flex items-start gap-2 text-gray-600">
|
|
<MapPin className="w-4 h-4 mt-1 flex-shrink-0 text-primary" />
|
|
<span className="font-poppins text-sm font-normal leading-relaxed">{activity.address}</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Category Badges */}
|
|
<div className="flex flex-wrap gap-2">
|
|
{activity.categories.map((category, catIndex) => (
|
|
<Badge
|
|
key={catIndex}
|
|
variant="secondary"
|
|
className="font-poppins font-normal text-sm bg-primary/10 text-primary hover:bg-primary/20 px-3 py-1"
|
|
>
|
|
{category}
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
|
|
{/* Activity Details - Bullet Points */}
|
|
<div className="space-y-2 pt-2">
|
|
{activity.description.map((detail, detailIndex) => (
|
|
<div key={detailIndex} className="flex items-start gap-3">
|
|
<span className="text-primary font-semibold mt-1.5 flex-shrink-0">•</span>
|
|
<span className="font-poppins text-sm font-normal text-gray-600 leading-relaxed">{detail}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
</motion.div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</motion.div>
|
|
)}
|
|
|
|
{/* Summary View */}
|
|
{viewMode === 'summary' && (
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.6, delay: 0.3 }}
|
|
className="space-y-4"
|
|
>
|
|
<h3 className="font-merchant text-2xl md:text-3xl text-center mb-8 leading-tight font-semibold">Trip Summary</h3>
|
|
<Card className="p-6">
|
|
<div className="space-y-6">
|
|
{generatedItinerary.dailyPlans.map((day, index) => (
|
|
<div key={index} className="border-l-4 border-primary pl-6">
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<Calendar className="w-5 h-5 text-primary" />
|
|
<h4 className="font-merchant text-lg md:text-xl leading-snug font-semibold">Day {day.day}: {day.title}</h4>
|
|
</div>
|
|
<div className="space-y-2">
|
|
{day.activities.map((activity, actIndex) => (
|
|
<div key={actIndex} className="flex items-start gap-3 text-sm">
|
|
<CheckCircle className="w-4 h-4 text-green-500 flex-shrink-0 mt-0.5" />
|
|
<div className="flex-1">
|
|
<span className="font-poppins text-gray-700 font-medium">{activity.activity}</span>
|
|
<div className="flex items-center gap-2 mt-1">
|
|
<span className="font-poppins text-gray-500 text-xs font-normal">{activity.time}</span>
|
|
<span className="text-gray-400">•</span>
|
|
<span className="font-poppins text-gray-500 text-xs font-normal">{activity.location}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</Card>
|
|
</motion.div>
|
|
)}
|
|
|
|
{/* Action Buttons */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.6, delay: 0.5 }}
|
|
className="flex flex-col sm:flex-row gap-4 justify-center pt-8"
|
|
>
|
|
<Button
|
|
variant="outline"
|
|
onClick={onCreateItineraryClick}
|
|
className="font-poppins font-medium px-8 py-3 text-lg"
|
|
>
|
|
<Heart className="w-5 h-5 mr-2" />
|
|
Create Another
|
|
</Button>
|
|
<Button
|
|
className="bg-primary hover:bg-primary/90 font-poppins font-semibold px-8 py-3 text-lg"
|
|
>
|
|
<Download className="w-5 h-5 mr-2" />
|
|
Save Itinerary
|
|
</Button>
|
|
<Button
|
|
variant="outline"
|
|
className="font-poppins font-medium px-8 py-3 text-lg"
|
|
>
|
|
<Share2 className="w-5 h-5 mr-2" />
|
|
Share Trip
|
|
</Button>
|
|
</motion.div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Footer */}
|
|
<Footer
|
|
onHomeClick={onHomeClick}
|
|
onMelbourneClick={onMelbourneClick}
|
|
onPassesClick={onPassesClick}
|
|
onSignInClick={onSignInClick}
|
|
onAttractionsClick={onAttractionsClick}
|
|
onBlogsClick={onBlogsClick}
|
|
onHowItWorksClick={onHowItWorksClick}
|
|
onFAQClick={onFAQClick}
|
|
onPrivacyPolicyClick={onPrivacyPolicyClick}
|
|
onContactUsClick={onContactUsClick}
|
|
currentPage={currentPage}
|
|
/>
|
|
</div>
|
|
);
|
|
} |