Premium Travel Dashboard Template
Preview
Edit
Download
Run
Download Options
HTML File
Download as .html file
CSS File
Download as .css file
JavaScript File
Download as .js file
Combined HTML
All code in one HTML file
Project ZIP
All files in a ZIP archive
Cancel
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>WanderLux - Premium Travel Management Platform</title> </head> <body class="bg-gray-50 min-h-screen"> <!-- Navigation --> <nav class="bg-white shadow-lg border-b border-gray-200"> <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div class="flex justify-between h-16"> <div class="flex items-center"> <div class="flex-shrink-0 flex items-center"> <div class="w-10 h-10 gradient-bg rounded-xl flex items-center justify-center"> <span class="text-white font-bold text-lg">✈</span> </div> <span class="ml-3 text-xl font-bold bg-gradient-to-r from-purple-600 to-pink-600 bg-clip-text text-transparent">WanderLux</span> </div> <div class="hidden md:ml-10 md:flex md:space-x-8"> <button onclick="showSection('dashboard')" class="nav-btn text-purple-600 border-purple-500 px-3 py-2 text-sm font-medium border-b-2">Dashboard</button> <button onclick="showSection('bookings')" class="nav-btn text-gray-500 hover:text-gray-700 px-3 py-2 text-sm font-medium">Bookings</button> <button onclick="showSection('destinations')" class="nav-btn text-gray-500 hover:text-gray-700 px-3 py-2 text-sm font-medium">Destinations</button> <button onclick="showSection('customers')" class="nav-btn text-gray-500 hover:text-gray-700 px-3 py-2 text-sm font-medium">Customers</button> <button onclick="showSection('packages')" class="nav-btn text-gray-500 hover:text-gray-700 px-3 py-2 text-sm font-medium">Packages</button> <button onclick="showSection('weather')" class="nav-btn text-gray-500 hover:text-gray-700 px-3 py-2 text-sm font-medium">Weather</button> <button onclick="showSection('analytics')" class="nav-btn text-gray-500 hover:text-gray-700 px-3 py-2 text-sm font-medium">Analytics</button> </div> </div> <div class="flex items-center space-x-4"> <div class="relative"> <button class="p-2 text-gray-400 hover:text-gray-500 relative"> <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-5 5-5-5h5v-12"></path> </svg> <span class="absolute -top-1 -right-1 bg-pink-500 text-white text-xs rounded-full w-5 h-5 flex items-center justify-center pulse-dot">12</span> </button> </div> <div class="flex items-center space-x-2"> <div class="w-8 h-8 gradient-bg rounded-full flex items-center justify-center"> <span class="text-sm font-medium text-white">TA</span> </div> <span class="text-sm font-medium text-gray-700"> Agent</span> </div> </div> </div> </div> </nav> <!-- Main Content --> <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8"> <!-- Dashboard Section --> <div id="dashboard" class="section"> <!-- Welcome Banner --> <div class="gradient-bg rounded-2xl p-8 mb-8 text-white relative overflow-hidden"> <div class="relative z-10"> <h1 class="text-3xl font-bold mb-2">Welcome to WanderLux Travel</h1> <p class="text-purple-100 text-lg">Manage your travel business with our comprehensive platform</p> </div> <div class="absolute top-0 right-0 w-64 h-64 bg-white opacity-10 rounded-full -mr-32 -mt-32 floating"></div> <div class="absolute bottom-0 left-0 w-48 h-48 bg-white opacity-5 rounded-full -ml-24 -mb-24"></div> </div> <!-- Stats Cards --> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8"> <div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100"> <div class="flex items-center justify-between"> <div> <p class="text-sm font-medium text-gray-600">Total Bookings</p> <p class="text-2xl font-bold text-gray-900">1,247</p> <p class="text-sm text-green-600 mt-1">+18% this month</p> </div> <div class="w-12 h-12 travel-gradient rounded-lg flex items-center justify-center"> <svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path> </svg> </div> </div> </div> <div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100"> <div class="flex items-center justify-between"> <div> <p class="text-sm font-medium text-gray-600">Active Travelers</p> <p class="text-2xl font-bold text-gray-900">892</p> <p class="text-sm text-blue-600 mt-1">Currently traveling</p> </div> <div class="w-12 h-12 ocean-gradient rounded-lg flex items-center justify-center"> <svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"></path> </svg> </div> </div> </div> <div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100"> <div class="flex items-center justify-between"> <div> <p class="text-sm font-medium text-gray-600">Revenue</p> <p class="text-2xl font-bold text-gray-900">$485K</p> <p class="text-sm text-purple-600 mt-1">This month</p> </div> <div class="w-12 h-12 sunset-gradient rounded-lg flex items-center justify-center"> <svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1"></path> </svg> </div> </div> </div> <div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100"> <div class="flex items-center justify-between"> <div> <p class="text-sm font-medium text-gray-600">Destinations</p> <p class="text-2xl font-bold text-gray-900">156</p> <p class="text-sm text-pink-600 mt-1">Worldwide</p> </div> <div class="w-12 h-12 forest-gradient rounded-lg flex items-center justify-center"> <svg class="w-6 h-6 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path> </svg> </div> </div> </div> </div> <!-- Quick Actions & Recent Activity --> <div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-8"> <!-- Quick Actions --> <div class="bg-white rounded-xl shadow-sm border border-gray-100"> <div class="p-6 border-b border-gray-100"> <h3 class="text-lg font-semibold text-gray-900">Quick Actions</h3> </div> <div class="p-6"> <div class="grid grid-cols-2 gap-4"> <button onclick="showSection('bookings')" class="p-4 travel-gradient hover:opacity-90 rounded-lg text-center transition-all text-white"> <div class="w-8 h-8 bg-white bg-opacity-20 rounded-lg mx-auto mb-2 flex items-center justify-center"> <svg class="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path> </svg> </div> <p class="text-sm font-medium">New Booking</p> </button> <button onclick="showSection('packages')" class="p-4 ocean-gradient hover:opacity-90 rounded-lg text-center transition-all text-white"> <div class="w-8 h-8 bg-white bg-opacity-20 rounded-lg mx-auto mb-2 flex items-center justify-center"> <svg class="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"></path> </svg> </div> <p class="text-sm font-medium">Create Package</p> </button> <button onclick="showSection('customers')" class="p-4 sunset-gradient hover:opacity-90 rounded-lg text-center transition-all text-white"> <div class="w-8 h-8 bg-white bg-opacity-20 rounded-lg mx-auto mb-2 flex items-center justify-center"> <svg class="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path> </svg> </div> <p class="text-sm font-medium">Add Customer</p> </button> <button onclick="showSection('weather')" class="p-4 forest-gradient hover:opacity-90 rounded-lg text-center transition-all text-gray-700"> <div class="w-8 h-8 bg-white bg-opacity-50 rounded-lg mx-auto mb-2 flex items-center justify-center"> <svg class="w-4 h-4 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z"></path> </svg> </div> <p class="text-sm font-medium">Check Weather</p> </button> </div> </div> </div> <!-- Recent Bookings --> <div class="bg-white rounded-xl shadow-sm border border-gray-100"> <div class="p-6 border-b border-gray-100"> <h3 class="text-lg font-semibold text-gray-900">Recent Bookings</h3> </div> <div class="p-6"> <div class="space-y-4"> <div class="flex items-center justify-between p-4 bg-gradient-to-r from-purple-50 to-pink-50 rounded-lg"> <div class="flex items-center space-x-3"> <div class="w-12 h-12 travel-gradient rounded-lg flex items-center justify-center"> <span class="text-white font-medium text-sm">?️</span> </div> <div> <p class="font-medium text-gray-900">Maldives Paradise</p> <p class="text-sm text-gray-500">Sarah Johnson • 7 days</p> </div> </div> <div class="text-right"> <p class="font-medium text-gray-900">$3,450</p> <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">Confirmed</span> </div> </div> <div class="flex items-center justify-between p-4 bg-gradient-to-r from-blue-50 to-cyan-50 rounded-lg"> <div class="flex items-center space-x-3"> <div class="w-12 h-12 ocean-gradient rounded-lg flex items-center justify-center"> <span class="text-white font-medium text-sm">?</span> </div> <div> <p class="font-medium text-gray-900">Paris Adventure</p> <p class="text-sm text-gray-500">Mike Chen • 5 days</p> </div> </div> <div class="text-right"> <p class="font-medium text-gray-900">$2,890</p> <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800">Pending</span> </div> </div> <div class="flex items-center justify-between p-4 bg-gradient-to-r from-orange-50 to-red-50 rounded-lg"> <div class="flex items-center space-x-3"> <div class="w-12 h-12 sunset-gradient rounded-lg flex items-center justify-center"> <span class="text-white font-medium text-sm">?️</span> </div> <div> <p class="font-medium text-gray-900">Swiss Alps Trek</p> <p class="text-sm text-gray-500">Emma Davis • 10 days</p> </div> </div> <div class="text-right"> <p class="font-medium text-gray-900">$4,200</p> <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800">In Progress</span> </div> </div> </div> </div> </div> </div> <!-- Live Travel Map --> <div class="bg-white rounded-xl shadow-sm border border-gray-100 mb-8"> <div class="p-6 border-b border-gray-100"> <h3 class="text-lg font-semibold text-gray-900">Live Travel Map</h3> <p class="text-sm text-gray-500">Real-time traveler locations</p> </div> <div class="p-6"> <div class="h-64 bg-gradient-to-br from-blue-100 via-green-50 to-yellow-50 rounded-lg relative overflow-hidden"> <!-- Map pins --> <div class="absolute top-8 left-12 w-4 h-4 bg-red-500 rounded-full map-pin flex items-center justify-center"> <div class="w-2 h-2 bg-white rounded-full"></div> </div> <div class="absolute top-16 right-20 w-4 h-4 bg-blue-500 rounded-full map-pin flex items-center justify-center"> <div class="w-2 h-2 bg-white rounded-full"></div> </div> <div class="absolute bottom-12 left-1/3 w-4 h-4 bg-green-500 rounded-full map-pin flex items-center justify-center"> <div class="w-2 h-2 bg-white rounded-full"></div> </div> <div class="absolute top-1/2 right-1/4 w-4 h-4 bg-purple-500 rounded-full map-pin flex items-center justify-center"> <div class="w-2 h-2 bg-white rounded-full"></div> </div> <!-- Map legend --> <div class="absolute bottom-4 left-4 bg-white bg-opacity-90 rounded-lg p-3"> <div class="flex items-center space-x-4 text-xs"> <div class="flex items-center space-x-1"> <div class="w-2 h-2 bg-red-500 rounded-full"></div> <span>Europe (23)</span> </div> <div class="flex items-center space-x-1"> <div class="w-2 h-2 bg-blue-500 rounded-full"></div> <span>Asia (18)</span> </div> <div class="flex items-center space-x-1"> <div class="w-2 h-2 bg-green-500 rounded-full"></div> <span>Americas (12)</span> </div> <div class="flex items-center space-x-1"> <div class="w-2 h-2 bg-purple-500 rounded-full"></div> <span>Africa (8)</span> </div> </div> </div> <!-- Center text --> <div class="absolute inset-0 flex items-center justify-center"> <div class="text-center"> <svg class="w-16 h-16 text-gray-300 mx-auto mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path> </svg> <p class="text-gray-500 font-medium">61 Active Travelers</p> </div> </div> </div> </div> </div> </div> <!-- Bookings Section --> <div id="bookings" class="section hidden"> <div class="flex justify-between items-center mb-6"> <h2 class="text-2xl font-bold text-gray-900">Booking Management</h2> <button onclick="openAddBookingModal()" class="bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-700 hover:to-pink-700 text-white px-4 py-2 rounded-lg font-medium transition-all"> + New Booking </button> </div> <!-- Booking Filters --> <div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6 mb-6"> <div class="flex flex-wrap gap-4"> <button onclick="filterBookings('all')" class="booking-filter-btn bg-purple-100 text-purple-700 px-4 py-2 rounded-lg font-medium">All Bookings</button> <button onclick="filterBookings('confirmed')" class="booking-filter-btn bg-gray-100 text-gray-700 px-4 py-2 rounded-lg font-medium">Confirmed</button> <button onclick="filterBookings('pending')" class="booking-filter-btn bg-gray-100 text-gray-700 px-4 py-2 rounded-lg font-medium">Pending</button> <button onclick="filterBookings('in-progress')" class="booking-filter-btn bg-gray-100 text-gray-700 px-4 py-2 rounded-lg font-medium">In Progress</button> <button onclick="filterBookings('completed')" class="booking-filter-btn bg-gray-100 text-gray-700 px-4 py-2 rounded-lg font-medium">Completed</button> </div> </div> <!-- Bookings Grid --> <div id="bookingsGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <!-- Bookings will be populated by JavaScript --> </div> </div> <!-- Destinations Section --> <div id="destinations" class="section hidden"> <div class="flex justify-between items-center mb-6"> <h2 class="text-2xl font-bold text-gray-900">Destination Management</h2> <button onclick="openAddDestinationModal()" class="bg-gradient-to-r from-blue-500 to-cyan-500 hover:from-blue-600 hover:to-cyan-600 text-white px-4 py-2 rounded-lg font-medium transition-all"> + Add Destination </button> </div> <!-- Popular Destinations --> <div id="destinationsGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <!-- Destinations will be populated by JavaScript --> </div> </div> <!-- Customers Section --> <div id="customers" class="section hidden"> <div class="flex justify-between items-center mb-6"> <h2 class="text-2xl font-bold text-gray-900">Customer Management</h2> <button onclick="openAddCustomerModal()" class="bg-gradient-to-r from-green-500 to-teal-500 hover:from-green-600 hover:to-teal-600 text-white px-4 py-2 rounded-lg font-medium transition-all"> + Add Customer </button> </div> <!-- Customer Stats --> <div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8"> <div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100"> <div class="flex items-center justify-between"> <div> <p class="text-sm font-medium text-gray-600">Total Customers</p> <p class="text-2xl font-bold text-gray-900">2,847</p> </div> <div class="w-12 h-12 travel-gradient rounded-lg flex items-center justify-center"> <svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"></path> </svg> </div> </div> </div> <div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100"> <div class="flex items-center justify-between"> <div> <p class="text-sm font-medium text-gray-600">VIP Members</p> <p class="text-2xl font-bold text-purple-600">342</p> </div> <div class="w-12 h-12 sunset-gradient rounded-lg flex items-center justify-center"> <svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z"></path> </svg> </div> </div> </div> <div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100"> <div class="flex items-center justify-between"> <div> <p class="text-sm font-medium text-gray-600">Repeat Customers</p> <p class="text-2xl font-bold text-green-600">1,456</p> </div> <div class="w-12 h-12 forest-gradient rounded-lg flex items-center justify-center"> <svg class="w-6 h-6 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path> </svg> </div> </div> </div> </div> <!-- Customers Table --> <div class="bg-white rounded-xl shadow-sm border border-gray-100"> <div class="p-6 border-b border-gray-100"> <h3 class="text-lg font-semibold text-gray-900">Customer Directory</h3> </div> <div class="overflow-x-auto"> <table class="min-w-full divide-y divide-gray-200"> <thead class="bg-gray-50"> <tr> <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Customer</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Membership</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Total Spent</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Last Trip</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th> </tr> </thead> <tbody id="customersTable" class="bg-white divide-y divide-gray-200"> <!-- Customer rows will be populated by JavaScript --> </tbody> </table> </div> </div> </div> <!-- Packages Section --> <div id="packages" class="section hidden"> <div class="flex justify-between items-center mb-6"> <h2 class="text-2xl font-bold text-gray-900">Travel Packages</h2> <button onclick="openAddPackageModal()" class="bg-gradient-to-r from-orange-500 to-red-500 hover:from-orange-600 hover:to-red-600 text-white px-4 py-2 rounded-lg font-medium transition-all"> + Create Package </button> </div> <!-- Package Categories --> <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8"> <div class="bg-gradient-to-br from-purple-500 to-pink-500 rounded-xl p-6 text-white"> <div class="flex items-center justify-between"> <div> <p class="text-purple-100">Luxury Packages</p> <p class="text-2xl font-bold">24</p> </div> <div class="text-3xl">?</div> </div> </div> <div class="bg-gradient-to-br from-blue-500 to-cyan-500 rounded-xl p-6 text-white"> <div class="flex items-center justify-between"> <div> <p class="text-blue-100">Adventure Tours</p> <p class="text-2xl font-bold">18</p> </div> <div class="text-3xl">?️</div> </div> </div> <div class="bg-gradient-to-br from-green-500 to-teal-500 rounded-xl p-6 text-white"> <div class="flex items-center justify-between"> <div> <p class="text-green-100">Family Trips</p> <p class="text-2xl font-bold">32</p> </div> <div class="text-3xl">????</div> </div> </div> <div class="bg-gradient-to-br from-orange-500 to-red-500 rounded-xl p-6 text-white"> <div class="flex items-center justify-between"> <div> <p class="text-orange-100">Beach Holidays</p> <p class="text-2xl font-bold">28</p> </div> <div class="text-3xl">?️</div> </div> </div> </div> <!-- Packages Grid --> <div id="packagesGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <!-- Packages will be populated by JavaScript --> </div> </div> <!-- Weather Section --> <div id="weather" class="section hidden"> <div class="flex justify-between items-center mb-6"> <h2 class="text-2xl font-bold text-gray-900">Weather Dashboard</h2> <button onclick="refreshWeather()" class="bg-gradient-to-r from-blue-500 to-purple-500 hover:from-blue-600 hover:to-purple-600 text-white px-4 py-2 rounded-lg font-medium transition-all"> ? Refresh Weather </button> </div> <!-- Current Weather --> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8"> <div class="bg-gradient-to-br from-yellow-400 to-orange-500 rounded-xl p-6 text-white"> <div class="flex items-center justify-between"> <div> <p class="text-yellow-100">Paris, France</p> <p class="text-3xl font-bold">22°C</p> <p class="text-yellow-100">Sunny</p> </div> <div class="text-4xl weather-icon">☀️</div> </div> </div> <div class="bg-gradient-to-br from-blue-400 to-blue-600 rounded-xl p-6 text-white"> <div class="flex items-center justify-between"> <div> <p class="text-blue-100">Tokyo, Japan</p> <p class="text-3xl font-bold">18°C</p> <p class="text-blue-100">Rainy</p> </div> <div class="text-4xl weather-icon">?️</div> </div> </div> <div class="bg-gradient-to-br from-green-400 to-green-600 rounded-xl p-6 text-white"> <div class="flex items-center justify-between"> <div> <p class="text-green-100">Maldives</p> <p class="text-3xl font-bold">28°C</p> <p class="text-green-100">Tropical</p> </div> <div class="text-4xl weather-icon">?</div> </div> </div> <div class="bg-gradient-to-br from-purple-400 to-purple-600 rounded-xl p-6 text-white"> <div class="flex items-center justify-between"> <div> <p class="text-purple-100">New York, USA</p> <p class="text-3xl font-bold">15°C</p> <p class="text-purple-100">Cloudy</p> </div> <div class="text-4xl weather-icon">☁️</div> </div> </div> </div> <!-- Weather Alerts --> <div class="bg-white rounded-xl shadow-sm border border-gray-100 mb-8"> <div class="p-6 border-b border-gray-100"> <h3 class="text-lg font-semibold text-gray-900">Weather Alerts</h3> </div> <div class="p-6"> <div class="space-y-4"> <div class="flex items-center p-4 bg-yellow-50 border border-yellow-200 rounded-lg"> <div class="text-2xl mr-3">⚠️</div> <div> <p class="font-medium text-yellow-800">Storm Warning - Bali, Indonesia</p> <p class="text-sm text-yellow-600">Heavy rainfall expected for next 3 days. Advise travelers to postpone outdoor activities.</p> </div> </div> <div class="flex items-center p-4 bg-red-50 border border-red-200 rounded-lg"> <div class="text-2xl mr-3">?️</div> <div> <p class="font-medium text-red-800">Heat Wave - Dubai, UAE</p> <p class="text-sm text-red-600">Extreme temperatures (45°C+) expected. Recommend indoor activities during peak hours.</p> </div> </div> <div class="flex items-center p-4 bg-blue-50 border border-blue-200 rounded-lg"> <div class="text-2xl mr-3">❄️</div> <div> <p class="font-medium text-blue-800">Snow Advisory - Swiss Alps</p> <p class="text-sm text-blue-600">Perfect skiing conditions! Fresh powder expected for the weekend.</p> </div> </div> </div> </div> </div> </div> <!-- Analytics Section --> <div id="analytics" class="section hidden"> <h2 class="text-2xl font-bold text-gray-900 mb-6">Analytics & Reports</h2> <!-- Analytics Cards --> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8"> <div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100"> <div class="flex items-center justify-between"> <div> <p class="text-sm font-medium text-gray-600">Avg. Trip Value</p> <p class="text-2xl font-bold text-gray-900">$2,847</p> <p class="text-sm text-green-600 mt-1">+12.5% from last month</p> </div> <div class="w-12 h-12 travel-gradient rounded-lg flex items-center justify-center"> <svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"></path> </svg> </div> </div> </div> <div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100"> <div class="flex items-center justify-between"> <div> <p class="text-sm font-medium text-gray-600">Customer Satisfaction</p> <p class="text-2xl font-bold text-gray-900">4.8/5</p> <p class="text-sm text-blue-600 mt-1">Based on 1,247 reviews</p> </div> <div class="w-12 h-12 ocean-gradient rounded-lg flex items-center justify-center"> <svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path> </svg> </div> </div> </div> <div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100"> <div class="flex items-center justify-between"> <div> <p class="text-sm font-medium text-gray-600">Booking Conversion</p> <p class="text-2xl font-bold text-gray-900">68%</p> <p class="text-sm text-purple-600 mt-1">Inquiries to bookings</p> </div> <div class="w-12 h-12 sunset-gradient rounded-lg flex items-center justify-center"> <svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"></path> </svg> </div> </div> </div> <div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100"> <div class="flex items-center justify-between"> <div> <p class="text-sm font-medium text-gray-600">Repeat Rate</p> <p class="text-2xl font-bold text-gray-900">42%</p> <p class="text-sm text-pink-600 mt-1">Customer retention</p> </div> <div class="w-12 h-12 forest-gradient rounded-lg flex items-center justify-center"> <svg class="w-6 h-6 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path> </svg> </div> </div> </div> </div> <!-- Charts --> <div class="grid grid-cols-1 lg:grid-cols-2 gap-8"> <!-- Revenue Chart --> <div class="bg-white rounded-xl shadow-sm border border-gray-100"> <div class="p-6 border-b border-gray-100"> <h3 class="text-lg font-semibold text-gray-900">Monthly Revenue</h3> </div> <div class="p-6"> <div class="flex items-end space-x-2 h-64"> <div class="flex-1 bg-purple-200 chart-bar" style="height: 45%"></div> <div class="flex-1 bg-purple-300 chart-bar" style="height: 60%"></div> <div class="flex-1 bg-purple-400 chart-bar" style="height: 80%"></div> <div class="flex-1 bg-purple-500 chart-bar" style="height: 55%"></div> <div class="flex-1 bg-purple-600 chart-bar" style="height: 90%"></div> <div class="flex-1 bg-purple-700 chart-bar" style="height: 75%"></div> <div class="flex-1 bg-purple-800 chart-bar" style="height: 100%"></div> </div> <div class="flex justify-between text-sm text-gray-500 mt-2"> <span>Jan</span> <span>Feb</span> <span>Mar</span> <span>Apr</span> <span>May</span> <span>Jun</span> <span>Jul</span> </div> </div> </div> <!-- Popular Destinations --> <div class="bg-white rounded-xl shadow-sm border border-gray-100"> <div class="p-6 border-b border-gray-100"> <h3 class="text-lg font-semibold text-gray-900">Top Destinations</h3> </div> <div class="p-6"> <div class="space-y-4"> <div class="flex items-center justify-between"> <div class="flex items-center space-x-3"> <div class="w-4 h-4 travel-gradient rounded"></div> <span class="font-medium text-gray-900">Maldives</span> </div> <span class="text-sm text-gray-500">28%</span> </div> <div class="flex items-center justify-between"> <div class="flex items-center space-x-3"> <div class="w-4 h-4 ocean-gradient rounded"></div> <span class="font-medium text-gray-900">Paris, France</span> </div> <span class="text-sm text-gray-500">22%</span> </div> <div class="flex items-center justify-between"> <div class="flex items-center space-x-3"> <div class="w-4 h-4 sunset-gradient rounded"></div> <span class="font-medium text-gray-900">Tokyo, Japan</span> </div> <span class="text-sm text-gray-500">18%</span> </div> <div class="flex items-center justify-between"> <div class="flex items-center space-x-3"> <div class="w-4 h-4 forest-gradient rounded"></div> <span class="font-medium text-gray-900">Swiss Alps</span> </div> <span class="text-sm text-gray-500">15%</span> </div> <div class="flex items-center justify-between"> <div class="flex items-center space-x-3"> <div class="w-4 h-4 bg-yellow-500 rounded"></div> <span class="font-medium text-gray-900">Bali, Indonesia</span> </div> <span class="text-sm text-gray-500">12%</span> </div> <div class="flex items-center justify-between"> <div class="flex items-center space-x-3"> <div class="w-4 h-4 bg-red-500 rounded"></div> <span class="font-medium text-gray-900">Others</span> </div> <span class="text-sm text-gray-500">5%</span> </div> </div> </div> </div> </div> </div> </div> <!-- Modals --> <!-- Add Booking Modal --> <div id="addBookingModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50"> <div class="flex items-center justify-center min-h-screen p-4"> <div class="bg-white rounded-xl shadow-xl max-w-2xl w-full max-h-screen overflow-y-auto"> <div class="p-6 border-b border-gray-100"> <div class="flex justify-between items-center"> <h3 class="text-lg font-semibold text-gray-900">Create New Booking</h3> <button onclick="closeModal('addBookingModal')" class="text-gray-400 hover:text-gray-600"> <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path> </svg> </button> </div> </div> <div class="p-6"> <form onsubmit="addBooking(event)"> <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Customer Name</label> <input type="text" id="bookingCustomer" placeholder="Enter customer name..." class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Destination</label> <input type="text" id="bookingDestination" placeholder="Enter destination..." class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Start Date</label> <input type="date" id="bookingStartDate" class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">End Date</label> <input type="date" id="bookingEndDate" class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Package Type</label> <select id="bookingPackage" class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500"> <option value="luxury">Luxury Package</option> <option value="adventure">Adventure Tour</option> <option value="family">Family Trip</option> <option value="beach">Beach Holiday</option> <option value="cultural">Cultural Experience</option> </select> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Total Price</label> <input type="number" id="bookingPrice" placeholder="0" class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Number of Travelers</label> <input type="number" id="bookingTravelers" placeholder="1" min="1" class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Status</label> <select id="bookingStatus" class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500"> <option value="pending">Pending</option> <option value="confirmed">Confirmed</option> <option value="in-progress">In Progress</option> <option value="completed">Completed</option> </select> </div> <div class="md:col-span-2"> <label class="block text-sm font-medium text-gray-700 mb-2">Special Requirements</label> <textarea id="bookingNotes" placeholder="Any special requirements or notes..." class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-purple-500" rows="3"></textarea> </div> </div> <div class="flex justify-end space-x-3 mt-6"> <button type="button" onclick="closeModal('addBookingModal')" class="px-4 py-2 text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-lg font-medium transition-colors">Cancel</button> <button type="submit" class="px-4 py-2 bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-700 hover:to-pink-700 text-white rounded-lg font-medium transition-all">Create Booking</button> </div> </form> </div> </div> </div> </div> <!-- Add Customer Modal --> <div id="addCustomerModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50"> <div class="flex items-center justify-center min-h-screen p-4"> <div class="bg-white rounded-xl shadow-xl max-w-md w-full"> <div class="p-6 border-b border-gray-100"> <div class="flex justify-between items-center"> <h3 class="text-lg font-semibold text-gray-900">Add New Customer</h3> <button onclick="closeModal('addCustomerModal')" class="text-gray-400 hover:text-gray-600"> <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path> </svg> </button> </div> </div> <div class="p-6"> <form onsubmit="addCustomer(event)"> <div class="space-y-4"> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Full Name</label> <input type="text" id="customerName" placeholder="Enter full name..." class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-green-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Email</label> <input type="email" id="customerEmail" placeholder="Enter email..." class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-green-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Phone</label> <input type="tel" id="customerPhone" placeholder="Enter phone number..." class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-green-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Membership Level</label> <select id="customerMembership" class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-green-500"> <option value="standard">Standard</option> <option value="premium">Premium</option> <option value="vip">VIP</option> </select> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Preferred Destinations</label> <input type="text" id="customerPreferences" placeholder="e.g., Beach, Mountains, Cities..." class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-green-500"> </div> </div> <div class="flex justify-end space-x-3 mt-6"> <button type="button" onclick="closeModal('addCustomerModal')" class="px-4 py-2 text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-lg font-medium transition-colors">Cancel</button> <button type="submit" class="px-4 py-2 bg-gradient-to-r from-green-500 to-teal-500 hover:from-green-600 hover:to-teal-600 text-white rounded-lg font-medium transition-all">Add Customer</button> </div> </form> </div> </div> </div> </div> <!-- Add Destination Modal --> <div id="addDestinationModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50"> <div class="flex items-center justify-center min-h-screen p-4"> <div class="bg-white rounded-xl shadow-xl max-w-md w-full"> <div class="p-6 border-b border-gray-100"> <div class="flex justify-between items-center"> <h3 class="text-lg font-semibold text-gray-900">Add New Destination</h3> <button onclick="closeModal('addDestinationModal')" class="text-gray-400 hover:text-gray-600"> <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path> </svg> </button> </div> </div> <div class="p-6"> <form onsubmit="addDestination(event)"> <div class="space-y-4"> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Destination Name</label> <input type="text" id="destinationName" placeholder="Enter destination name..." class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Country</label> <input type="text" id="destinationCountry" placeholder="Enter country..." class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Category</label> <select id="destinationCategory" class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"> <option value="beach">Beach</option> <option value="mountain">Mountain</option> <option value="city">City</option> <option value="cultural">Cultural</option> <option value="adventure">Adventure</option> <option value="luxury">Luxury</option> </select> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Best Season</label> <select id="destinationSeason" class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"> <option value="spring">Spring</option> <option value="summer">Summer</option> <option value="autumn">Autumn</option> <option value="winter">Winter</option> <option value="year-round">Year Round</option> </select> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Average Cost (per person)</label> <input type="number" id="destinationCost" placeholder="0" class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Description</label> <textarea id="destinationDescription" placeholder="Enter destination description..." class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500" rows="3"></textarea> </div> </div> <div class="flex justify-end space-x-3 mt-6"> <button type="button" onclick="closeModal('addDestinationModal')" class="px-4 py-2 text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-lg font-medium transition-colors">Cancel</button> <button type="submit" class="px-4 py-2 bg-gradient-to-r from-blue-500 to-cyan-500 hover:from-blue-600 hover:to-cyan-600 text-white rounded-lg font-medium transition-all">Add Destination</button> </div> </form> </div> </div> </div> </div> <!-- Add Package Modal --> <div id="addPackageModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50"> <div class="flex items-center justify-center min-h-screen p-4"> <div class="bg-white rounded-xl shadow-xl max-w-2xl w-full max-h-screen overflow-y-auto"> <div class="p-6 border-b border-gray-100"> <div class="flex justify-between items-center"> <h3 class="text-lg font-semibold text-gray-900">Create Travel Package</h3> <button onclick="closeModal('addPackageModal')" class="text-gray-400 hover:text-gray-600"> <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path> </svg> </button> </div> </div> <div class="p-6"> <form onsubmit="addPackage(event)"> <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Package Name</label> <input type="text" id="packageName" placeholder="Enter package name..." class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-orange-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Category</label> <select id="packageCategory" class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-orange-500"> <option value="luxury">Luxury</option> <option value="adventure">Adventure</option> <option value="family">Family</option> <option value="beach">Beach</option> <option value="cultural">Cultural</option> <option value="honeymoon">Honeymoon</option> </select> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Duration (days)</label> <input type="number" id="packageDuration" placeholder="7" min="1" class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-orange-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Price per Person</l
CSS
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap'); * { font-family: 'Poppins', sans-serif; } .fade-in { animation: fadeIn 0.3s ease-in; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .pulse-dot { animation: pulse 2s infinite; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } .slide-in { animation: slideIn 0.4s ease-out; } @keyframes slideIn { from { transform: translateX(100%); } to { transform: translateX(0); } } .chart-bar { transition: height 0.5s ease-in-out; } .notification-enter { animation: notificationSlide 0.3s ease-out; } @keyframes notificationSlide { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } .travel-card { transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out; } .travel-card:hover { transform: translateY(-4px); box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); } .gradient-bg { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); } .travel-gradient { background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); } .ocean-gradient { background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); } .sunset-gradient { background: linear-gradient(135deg, #fa709a 0%, #fee140 100%); } .forest-gradient { background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%); } .floating { animation: floating 3s ease-in-out infinite; } @keyframes floating { 0%, 100% { transform: translateY(0px); } 50% { transform: translateY(-10px); } } .weather-icon { animation: bounce 2s infinite; } @keyframes bounce { 0%, 20%, 50%, 80%, 100% { transform: translateY(0); } 40% { transform: translateY(-10px); } 60% { transform: translateY(-5px); } } .map-pin { animation: mapPulse 2s infinite; } @keyframes mapPulse { 0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); } }
JavaScript
// Global data storage let bookings = [ { id: 1, customer: 'Sarah Johnson', destination: 'Maldives Paradise', startDate: '2024-02-15', endDate: '2024-02-22', package: 'luxury', price: 3450, travelers: 2, status: 'confirmed', notes: 'Honeymoon trip, special arrangements needed' }, { id: 2, customer: 'Mike Chen', destination: 'Paris Adventure', startDate: '2024-02-20', endDate: '2024-02-25', package: 'cultural', price: 2890, travelers: 1, status: 'pending', notes: 'First time visitor, interested in museums' }, { id: 3, customer: 'Emma Davis', destination: 'Swiss Alps Trek', startDate: '2024-03-01', endDate: '2024-03-11', package: 'adventure', price: 4200, travelers: 4, status: 'in-progress', notes: 'Experienced hikers, need advanced trails' }, { id: 4, customer: 'John Smith', destination: 'Bali Retreat', startDate: '2024-02-28', endDate: '2024-03-07', package: 'beach', price: 2650, travelers: 2, status: 'completed', notes: 'Yoga and wellness focused' }, { id: 5, customer: 'Lisa Wang', destination: 'Tokyo Experience', startDate: '2024-03-15', endDate: '2024-03-22', package: 'cultural', price: 3200, travelers: 3, status: 'confirmed', notes: 'Family with teenager, interested in anime culture' } ]; let destinations = [ { id: 1, name: 'Maldives Paradise', country: 'Maldives', category: 'beach', season: 'year-round', cost: 3500, description: 'Crystal clear waters and overwater bungalows', rating: 4.9, popularity: 95 }, { id: 2, name: 'Swiss Alps Adventure', country: 'Switzerland', category: 'mountain', season: 'winter', cost: 4200, description: 'World-class skiing and mountain hiking', rating: 4.8, popularity: 88 }, { id: 3, name: 'Tokyo Cultural Tour', country: 'Japan', category: 'cultural', season: 'spring', cost: 3200, description: 'Ancient traditions meet modern innovation', rating: 4.7, popularity: 92 }, { id: 4, name: 'Paris Romance', country: 'France', category: 'city', season: 'year-round', cost: 2800, description: 'The city of love and lights', rating: 4.6, popularity: 90 }, { id: 5, name: 'Bali Wellness Retreat', country: 'Indonesia', category: 'beach', season: 'summer', cost: 2400, description: 'Tropical paradise with spiritual healing', rating: 4.8, popularity: 85 }, { id: 6, name: 'African Safari', country: 'Kenya', category: 'adventure', season: 'autumn', cost: 5200, description: 'Wildlife adventure in the Serengeti', rating: 4.9, popularity: 78 } ]; let customers = [ { id: 1, name: 'Sarah Johnson', email: 'sarah@email.com', phone: '(555) 123-4567', membership: 'vip', totalSpent: 12450, lastTrip: 'Maldives Paradise', preferences: 'Luxury Beach Resorts' }, { id: 2, name: 'Mike Chen', email: 'mike@email.com', phone: '(555) 234-5678', membership: 'premium', totalSpent: 8900, lastTrip: 'Tokyo Experience', preferences: 'Cultural Tours' }, { id: 3, name: 'Emma Davis', email: 'emma@email.com', phone: '(555) 345-6789', membership: 'standard', totalSpent: 4200, lastTrip: 'Swiss Alps Trek', preferences: 'Adventure Sports' }, { id: 4, name: 'John Smith', email: 'john@email.com', phone: '(555) 456-7890', membership: 'premium', totalSpent: 7650, lastTrip: 'Bali Retreat', preferences: 'Wellness & Spa' }, { id: 5, name: 'Lisa Wang', email: 'lisa@email.com', phone: '(555) 567-8901', membership: 'vip', totalSpent: 15200, lastTrip: 'African Safari', preferences: 'Luxury Adventures' } ]; let packages = [ { id: 1, name: 'Maldives Luxury Escape', category: 'luxury', duration: 7, price: 3450, maxSize: 2, difficulty: 'easy', destinations: 'Maldives', inclusions: 'Overwater villa, all meals, spa treatments, private transfers', description: 'Ultimate luxury experience in paradise' }, { id: 2, name: 'European Grand Tour', category: 'cultural', duration: 14, price: 4200, maxSize: 8, difficulty: 'moderate', destinations: 'Paris, Rome, Barcelona, Amsterdam', inclusions: 'Hotels, guided tours, some meals, train tickets', description: 'Explore the best of European culture and history' }, { id: 3, name: 'Himalayan Adventure Trek', category: 'adventure', duration: 12, price: 2800, maxSize: 6, difficulty: 'challenging', destinations: 'Nepal, Tibet', inclusions: 'Camping gear, guides, permits, meals', description: 'Challenge yourself in the world\'s highest mountains' }, { id: 4, name: 'Caribbean Family Fun', category: 'family', duration: 10, price: 2200, maxSize: 6, difficulty: 'easy', destinations: 'Barbados, Jamaica', inclusions: 'Family rooms, kids activities, water sports, meals', description: 'Perfect family vacation in tropical paradise' }, { id: 5, name: 'Bali Wellness Retreat', category: 'beach', duration: 8, price: 1800, maxSize: 12, difficulty: 'easy', destinations: 'Bali, Indonesia', inclusions: 'Yoga classes, spa treatments, healthy meals, accommodation', description: 'Rejuvenate your mind, body and soul' }, { id: 6, name: 'Romantic Honeymoon Package', category: 'honeymoon', duration: 9, price: 3800, maxSize: 2, difficulty: 'easy', destinations: 'Santorini, Mykonos', inclusions: 'Luxury suites, private dinners, couples spa, transfers', description: 'Celebrate your love in the Greek islands' } ]; // Navigation functions function showSection(sectionName) { // Hide all sections document.querySelectorAll('.section').forEach(section => { section.classList.add('hidden'); }); // Show selected section document.getElementById(sectionName).classList.remove('hidden'); document.getElementById(sectionName).classList.add('fade-in'); // Update navigation document.querySelectorAll('.nav-btn').forEach(btn => { btn.classList.remove('text-purple-600', 'border-purple-500', 'border-b-2'); btn.classList.add('text-gray-500'); }); event.target.classList.remove('text-gray-500'); event.target.classList.add('text-purple-600', 'border-purple-500', 'border-b-2'); // Load section-specific data if (sectionName === 'bookings') { renderBookings(); } else if (sectionName === 'destinations') { renderDestinations(); } else if (sectionName === 'customers') { renderCustomers(); } else if (sectionName === 'packages') { renderPackages(); } } // Booking management functions function renderBookings(filter = 'all') { const bookingsGrid = document.getElementById('bookingsGrid'); const filteredBookings = filter === 'all' ? bookings : bookings.filter(booking => booking.status === filter); bookingsGrid.innerHTML = filteredBookings.map(booking => ` <div class="travel-card bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden"> <div class="h-32 ${getBookingGradient(booking.package)} flex items-center justify-center"> <div class="text-center text-white"> <div class="text-3xl mb-2">${getDestinationEmoji(booking.destination)}</div> <p class="font-medium">${booking.destination}</p> </div> </div> <div class="p-6"> <div class="flex justify-between items-start mb-4"> <h3 class="text-lg font-semibold text-gray-900">${booking.customer}</h3> <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-${getStatusColor(booking.status)}-100 text-${getStatusColor(booking.status)}-800"> ${booking.status.charAt(0).toUpperCase() + booking.status.slice(1)} </span> </div> <p class="text-2xl font-bold text-purple-600 mb-2">$${booking.price.toLocaleString()}</p> <p class="text-gray-600 mb-2">${booking.travelers} traveler${booking.travelers > 1 ? 's' : ''} • ${booking.package.charAt(0).toUpperCase() + booking.package.slice(1)}</p> <p class="text-sm text-gray-500 mb-2">${formatDate(booking.startDate)} - ${formatDate(booking.endDate)}</p> <p class="text-sm text-gray-600 mb-4">${booking.notes}</p> <div class="flex space-x-2"> <button onclick="editBooking(${booking.id})" class="flex-1 px-3 py-2 bg-purple-600 hover:bg-purple-700 text-white text-sm rounded-lg transition-colors"> Edit </button> <button onclick="deleteBooking(${booking.id})" class="flex-1 px-3 py-2 bg-red-600 hover:bg-red-700 text-white text-sm rounded-lg transition-colors"> Cancel </button> </div> </div> </div> `).join(''); } function getBookingGradient(packageType) { const gradients = { 'luxury': 'travel-gradient', 'adventure': 'ocean-gradient', 'family': 'forest-gradient', 'beach': 'sunset-gradient', 'cultural': 'gradient-bg', 'honeymoon': 'travel-gradient' }; return gradients[packageType] || 'gradient-bg'; } function getDestinationEmoji(destination) { if (destination.includes('Maldives')) return '?️'; if (destination.includes('Paris')) return '?'; if (destination.includes('Alps')) return '?️'; if (destination.includes('Bali')) return '?'; if (destination.includes('Tokyo')) return '?'; if (destination.includes('Safari')) return '?'; return '✈️'; } function getStatusColor(status) { const colors = { 'confirmed': 'green', 'pending': 'yellow', 'in-progress': 'blue', 'completed': 'purple' }; return colors[status] || 'gray'; } function formatDate(dateString) { const date = new Date(dateString); return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }); } function filterBookings(status) { // Update filter buttons document.querySelectorAll('.booking-filter-btn').forEach(btn => { btn.classList.remove('bg-purple-100', 'text-purple-700'); btn.classList.add('bg-gray-100', 'text-gray-700'); }); event.target.classList.remove('bg-gray-100', 'text-gray-700'); event.target.classList.add('bg-purple-100', 'text-purple-700'); renderBookings(status); } function addBooking(event) { event.preventDefault(); const customer = document.getElementById('bookingCustomer').value; const destination = document.getElementById('bookingDestination').value; const startDate = document.getElementById('bookingStartDate').value; const endDate = document.getElementById('bookingEndDate').value; const packageType = document.getElementById('bookingPackage').value; const price = parseFloat(document.getElementById('bookingPrice').value); const travelers = parseInt(document.getElementById('bookingTravelers').value); const status = document.getElementById('bookingStatus').value; const notes = document.getElementById('bookingNotes').value; if (!customer || !destination || !startDate || !endDate || !price) { showNotification('Please fill in all required fields', 'error'); return; } const newBooking = { id: bookings.length + 1, customer: customer, destination: destination, startDate: startDate, endDate: endDate, package: packageType, price: price, travelers: travelers, status: status, notes: notes }; bookings.unshift(newBooking); closeModal('addBookingModal'); renderBookings(); showNotification('Booking created successfully!', 'success'); // Reset form document.getElementById('bookingCustomer').value = ''; document.getElementById('bookingDestination').value = ''; document.getElementById('bookingStartDate').value = ''; document.getElementById('bookingEndDate').value = ''; document.getElementById('bookingPrice').value = ''; document.getElementById('bookingTravelers').value = ''; document.getElementById('bookingNotes').value = ''; } function editBooking(bookingId) { showNotification('Edit functionality would open a detailed form', 'info'); } function deleteBooking(bookingId) { bookings = bookings.filter(booking => booking.id !== bookingId); renderBookings(); showNotification('Booking cancelled successfully!', 'success'); } // Destination management functions function renderDestinations() { const destinationsGrid = document.getElementById('destinationsGrid'); destinationsGrid.innerHTML = destinations.map(destination => ` <div class="travel-card bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden"> <div class="h-48 ${getCategoryGradient(destination.category)} flex items-center justify-center"> <div class="text-center text-white"> <div class="text-4xl mb-2">${getCategoryEmoji(destination.category)}</div> <p class="font-medium">${destination.name}</p> </div> </div> <div class="p-6"> <div class="flex justify-between items-start mb-4"> <h3 class="text-lg font-semibold text-gray-900">${destination.name}</h3> <div class="flex items-center space-x-1"> <span class="text-yellow-400">⭐</span> <span class="text-sm font-medium text-gray-600">${destination.rating}</span> </div> </div> <p class="text-gray-600 mb-2">${destination.country} • ${destination.category.charAt(0).toUpperCase() + destination.category.slice(1)}</p> <p class="text-sm text-gray-500 mb-3">Best time: ${destination.season.charAt(0).toUpperCase() + destination.season.slice(1)}</p> <p class="text-sm text-gray-600 mb-4">${destination.description}</p> <div class="flex justify-between items-center"> <div> <p class="text-2xl font-bold text-purple-600">$${destination.cost.toLocaleString()}</p> <p class="text-xs text-gray-500">per person</p> </div> <div class="text-right"> <div class="w-16 h-2 bg-gray-200 rounded-full"> <div class="h-2 bg-gradient-to-r from-purple-500 to-pink-500 rounded-full" style="width: ${destination.popularity}%"></div> </div> <p class="text-xs text-gray-500 mt-1">${destination.popularity}% popular</p> </div> </div> </div> </div> `).join(''); } function getCategoryGradient(category) { const gradients = { 'beach': 'ocean-gradient', 'mountain': 'forest-gradient', 'city': 'gradient-bg', 'cultural': 'sunset-gradient', 'adventure': 'travel-gradient', 'luxury': 'travel-gradient' }; return gradients[category] || 'gradient-bg'; } function getCategoryEmoji(category) { const emojis = { 'beach': '?️', 'mountain': '?️', 'city': '?️', 'cultural': '?️', 'adventure': '?♂️', 'luxury': '?' }; return emojis[category] || '✈️'; } function addDestination(event) { event.preventDefault(); const name = document.getElementById('destinationName').value; const country = document.getElementById('destinationCountry').value; const category = document.getElementById('destinationCategory').value; const season = document.getElementById('destinationSeason').value; const cost = parseFloat(document.getElementById('destinationCost').value); const description = document.getElementById('destinationDescription').value; if (!name || !country || !cost || !description) { showNotification('Please fill in all required fields', 'error'); return; } const newDestination = { id: destinations.length + 1, name: name, country: country, category: category, season: season, cost: cost, description: description, rating: 4.5, popularity: Math.floor(Math.random() * 30) + 70 }; destinations.push(newDestination); closeModal('addDestinationModal'); renderDestinations(); showNotification('Destination added successfully!', 'success'); // Reset form document.getElementById('destinationName').value = ''; document.getElementById('destinationCountry').value = ''; document.getElementById('destinationCost').value = ''; document.getElementById('destinationDescription').value = ''; } // Customer management functions function renderCustomers() { const customersTable = document.getElementById('customersTable'); customersTable.innerHTML = customers.map(customer => ` <tr> <td class="px-6 py-4 whitespace-nowrap"> <div class="flex items-center"> <div class="w-10 h-10 ${getMembershipGradient(customer.membership)} rounded-full flex items-center justify-center"> <span class="text-sm font-medium text-white">${customer.name.split(' ').map(n => n[0]).join('')}</span> </div> <div class="ml-4"> <div class="text-sm font-medium text-gray-900">${customer.name}</div> <div class="text-sm text-gray-500">${customer.email}</div> </div> </div> </td> <td class="px-6 py-4 whitespace-nowrap"> <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-${getMembershipColor(customer.membership)}-100 text-${getMembershipColor(customer.membership)}-800"> ${customer.membership.toUpperCase()} </span> </td> <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900"> $${customer.totalSpent.toLocaleString()} </td> <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"> ${customer.lastTrip} </td> <td class="px-6 py-4 whitespace-nowrap text-sm font-medium space-x-2"> <button onclick="contactCustomer(${customer.id})" class="text-purple-600 hover:text-purple-900"> Contact </button> <button onclick="viewCustomerHistory(${customer.id})" class="text-blue-600 hover:text-blue-900"> History </button> </td> </tr> `).join(''); } function getMembershipGradient(membership) { const gradients = { 'standard': 'bg-gray-400', 'premium': 'travel-gradient', 'vip': 'sunset-gradient' }; return gradients[membership] || 'bg-gray-400'; } function getMembershipColor(membership) { const colors = { 'standard': 'gray', 'premium': 'purple', 'vip': 'yellow' }; return colors[membership] || 'gray'; } function addCustomer(event) { event.preventDefault(); const name = document.getElementById('customerName').value; const email = document.getElementById('customerEmail').value; const phone = document.getElementById('customerPhone').value; const membership = document.getElementById('customerMembership').value; const preferences = document.getElementById('customerPreferences').value; if (!name || !email || !phone) { showNotification('Please fill in all required fields', 'error'); return; } const newCustomer = { id: customers.length + 1, name: name, email: email, phone: phone, membership: membership, totalSpent: 0, lastTrip: 'None', preferences: preferences }; customers.push(newCustomer); closeModal('addCustomerModal'); renderCustomers(); showNotification('Customer added successfully!', 'success'); // Reset form document.getElementById('customerName').value = ''; document.getElementById('customerEmail').value = ''; document.getElementById('customerPhone').value = ''; document.getElementById('customerPreferences').value = ''; } function contactCustomer(customerId) { const customer = customers.find(c => c.id === customerId); showNotification(`Contacting ${customer.name} at ${customer.phone}`, 'info'); } function viewCustomerHistory(customerId) { const customer = customers.find(c => c.id === customerId); showNotification(`Viewing travel history for ${customer.name}`, 'info'); } // Package management functions function renderPackages() { const packagesGrid = document.getElementById('packagesGrid'); packagesGrid.innerHTML = packages.map(packageItem => ` <div class="travel-card bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden"> <div class="h-40 ${getPackageGradient(packageItem.category)} flex items-center justify-center"> <div class="text-center text-white"> <div class="text-3xl mb-2">${getPackageEmoji(packageItem.category)}</div> <p class="font-medium">${packageItem.name}</p> </div> </div> <div class="p-6"> <div class="flex justify-between items-start mb-4"> <h3 class="text-lg font-semibold text-gray-900">${packageItem.name}</h3> <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-${getPackageCategoryColor(packageItem.category)}-100 text-${getPackageCategoryColor(packageItem.category)}-800"> ${packageItem.category.charAt(0).toUpperCase() + packageItem.category.slice(1)} </span> </div> <p class="text-2xl font-bold text-purple-600 mb-2">$${packageItem.price.toLocaleString()}</p> <p class="text-gray-600 mb-2">${packageItem.duration} days • Max ${packageItem.maxSize} people</p> <p class="text-sm text-gray-500 mb-3">Difficulty: ${packageItem.difficulty.charAt(0).toUpperCase() + packageItem.difficulty.slice(1)}</p> <p class="text-sm text-gray-600 mb-3">${packageItem.destinations}</p> <p class="text-sm text-gray-600 mb-4">${packageItem.description}</p> <div class="flex space-x-2"> <button onclick="editPackage(${packageItem.id})" class="flex-1 px-3 py-2 bg-orange-600 hover:bg-orange-700 text-white text-sm rounded-lg transition-colors"> Edit </button> <button onclick="duplicatePackage(${packageItem.id})" class="flex-1 px-3 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm rounded-lg transition-colors"> Duplicate </button> </div> </div> </div> `).join(''); } function getPackageGradient(category) { const gradients = { 'luxury': 'sunset-gradient', 'cultural': 'gradient-bg', 'adventure': 'ocean-gradient', 'family': 'forest-gradient', 'beach': 'travel-gradient', 'honeymoon': 'travel-gradient' }; return gradients[category] || 'gradient-bg'; } function getPackageEmoji(category) { const emojis = { 'luxury': '?', 'cultural': '?️', 'adventure': '?♂️', 'family': '????', 'beach': '?️', 'honeymoon': '?' }; return emojis[category] || '✈️'; } function getPackageCategoryColor(category) { const colors = { 'luxury': 'yellow', 'cultural': 'purple', 'adventure': 'blue', 'family': 'green', 'beach': 'cyan', 'honeymoon': 'pink' }; return colors[category] || 'gray'; } function addPackage(event) { event.preventDefault(); const name = document.getElementById('packageName').value; const category = document.getElementById('packageCategory').value; const duration = parseInt(document.getElementById('packageDuration').value); const price = parseFloat(document.getElementById('packagePrice').value); const maxSize = parseInt(document.getElementById('packageMaxSize').value); const difficulty = document.getElementById('packageDifficulty').value; const destinations = document.getElementById('packageDestinations').value; const inclusions = document.getElementById('packageInclusions').value; const description = document.getElementById('packageDescription').value; if (!name || !duration || !price || !destinations || !description) { showNotification('Please fill in all required fields', 'error'); return; } const newPackage = { id: packages.length + 1, name: name, category: category, duration: duration, price: price, maxSize: maxSize, difficulty: difficulty, destinations: destinations, inclusions: inclusions, description: description }; packages.push(newPackage); closeModal('addPackageModal'); renderPackages(); showNotification('Package created successfully!', 'success'); // Reset form document.getElementById('packageName').value = ''; document.getElementById('packageDuration').value = ''; document.getElementById('packagePrice').value = ''; document.getElementById('packageMaxSize').value = ''; document.getElementById('packageDestinations').value = ''; document.getElementById('packageInclusions').value = ''; document.getElementById('packageDescription').value = ''; } function editPackage(packageId) { showNotification('Edit functionality would open a detailed form', 'info'); } function duplicatePackage(packageId) { const originalPackage = packages.find(p => p.id === packageId); const duplicatedPackage = { ...originalPackage, id: packages.length + 1, name: originalPackage.name + ' (Copy)' }; packages.push(duplicatedPackage); renderPackages(); showNotification('Package duplicated successfully!', 'success'); } // Weather functions function refreshWeather() { showNotification('Weather data refreshed!', 'success'); // Simulate weather update with animation document.querySelectorAll('.weather-icon').forEach(icon => { icon.style.animation = 'none'; setTimeout(() => { icon.style.animation = 'bounce 2s infinite'; }, 100); }); } // Modal functions function openAddBookingModal() { document.getElementById('addBookingModal').classList.remove('hidden'); } function openAddCustomerModal() { document.getElementById('addCustomerModal').classList.remove('hidden'); } function openAddDestinationModal() { document.getElementById('addDestinationModal').classList.remove('hidden'); } function openAddPackageModal() { document.getElementById('addPackageModal').classList.remove('hidden'); } function closeModal(modalId) { document.getElementById(modalId).classList.add('hidden'); } // Notification system function showNotification(message, type = 'info') { const notification = document.createElement('div'); notification.className = `notification-enter bg-white border-l-4 border-${type === 'success' ? 'green' : type === 'error' ? 'red' : 'purple'}-500 p-4 shadow-lg rounded-lg max-w-sm`; notification.innerHTML = ` <div class="flex"> <div class="flex-shrink-0"> <svg class="w-5 h-5 text-${type === 'success' ? 'green' : type === 'error' ? 'red' : 'purple'}-500" fill="currentColor" viewBox="0 0 20 20"> <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path> </svg> </div> <div class="ml-3"> <p class="text-sm font-medium text-gray-900">${message}</p> </div> <div class="ml-auto pl-3"> <button onclick="this.parentElement.parentElement.parentElement.remove()" class="text-gray-400 hover:text-gray-600"> <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20"> <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path> </svg> </button> </div> </div> `; document.getElementById('notifications').appendChild(notification); // Auto remove after 5 seconds setTimeout(() => { if (notification.parentElement) { notification.remove(); } }, 5000); } // Close modals when clicking outside document.addEventListener('click', function(event) { const modals = ['addBookingModal', 'addCustomerModal', 'addDestinationModal', 'addPackageModal']; modals.forEach(modalId => { const modal = document.getElementById(modalId); if (event.target === modal) { closeModal(modalId); } }); }); // Initialize the app document.addEventListener('DOMContentLoaded', function() { renderBookings(); renderDestinations(); renderCustomers(); renderPackages(); // Show welcome notification setTimeout(() => { showNotification('Welcome to WanderLux! Your premium travel management platform is ready.', 'success'); }, 1000); });
Output Preview
Desktop
Mobile
Fullscreen