Spaces:
Running
Running
| <html lang="en" class="scroll-smooth"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <meta name="description" content="FlySaver ZA - Find the cheapest flights from South Africa to local and international destinations. Compare prices across airlines and save on your next trip."> | |
| <meta property="og:title" content="FlySaver ZA | Cheap Flights from South Africa"> | |
| <meta property="og:description" content="Compare and book cheap flights from South Africa to local and international destinations."> | |
| <meta property="og:type" content="website"> | |
| <meta property="og:url" content="https://flysaverza.co.za"> | |
| <title>FlySaver ZA | Cheap Flights from South Africa</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css"> | |
| <script src="https://cdn.jsdelivr.net/npm/flatpickr"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap'); | |
| body { | |
| font-family: 'Poppins', sans-serif; | |
| transition: background-color 0.3s, color 0.3s; | |
| } | |
| .flight-card:hover { | |
| transform: translateY(-5px); | |
| box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); | |
| } | |
| .deal-card:hover { | |
| transform: scale(1.03); | |
| } | |
| .search-form { | |
| box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); | |
| } | |
| .dark .search-form { | |
| box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3); | |
| } | |
| .airline-logo { | |
| height: 30px; | |
| width: auto; | |
| object-fit: contain; | |
| } | |
| /* Custom scrollbar */ | |
| ::-webkit-scrollbar { | |
| width: 8px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: #f1f1f1; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: #888; | |
| border-radius: 4px; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: #555; | |
| } | |
| .dark ::-webkit-scrollbar-track { | |
| background: #374151; | |
| } | |
| .dark ::-webkit-scrollbar-thumb { | |
| background: #6b7280; | |
| } | |
| .dark ::-webkit-scrollbar-thumb:hover { | |
| background: #9ca3af; | |
| } | |
| /* Text selection styles */ | |
| ::selection { | |
| background: #2563eb; | |
| color: white; | |
| text-shadow: none; | |
| } | |
| .dark ::selection { | |
| background: #93c5fd; | |
| color: #111827; | |
| } | |
| /* Animation for flight cards */ | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(20px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .animate-fade-in { | |
| animation: fadeIn 0.5s ease-out forwards; | |
| } | |
| /* Delay for each card */ | |
| .flight-card { | |
| animation-delay: calc(var(--order) * 0.1s); | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 dark:bg-gray-900 text-gray-800 dark:text-gray-200"> | |
| <!-- Navigation --> | |
| <nav class="bg-white dark:bg-gray-800 shadow-md sticky top-0 z-50"> | |
| <div class="container mx-auto px-4 py-3 flex justify-between items-center"> | |
| <div class="flex items-center space-x-2"> | |
| <i class="fas fa-plane-departure text-blue-600 dark:text-blue-400 text-2xl"></i> | |
| <a href="#" class="text-xl font-bold text-blue-600 dark:text-blue-400">FlySaver ZA</a> | |
| </div> | |
| <div class="hidden md:flex space-x-6"> | |
| <a href="#" class="hover:text-blue-600 dark:hover:text-blue-400 font-medium">Home</a> | |
| <a href="#popular-routes" class="hover:text-blue-600 dark:hover:text-blue-400 font-medium">Popular Routes</a> | |
| <a href="#deals" class="hover:text-blue-600 dark:hover:text-blue-400 font-medium">Deals</a> | |
| <a href="#about" class="hover:text-blue-600 dark:hover:text-blue-400 font-medium">About</a> | |
| <a href="#contact" class="hover:text-blue-600 dark:hover:text-blue-400 font-medium">Contact</a> | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| <button id="theme-toggle" class="p-2 rounded-full hover:bg-gray-200 dark:hover:bg-gray-700"> | |
| <i class="fas fa-moon dark:hidden"></i> | |
| <i class="fas fa-sun hidden dark:inline"></i> | |
| </button> | |
| <button id="mobile-menu-button" class="md:hidden p-2 rounded-full hover:bg-gray-200 dark:hover:bg-gray-700"> | |
| <i class="fas fa-bars"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Mobile menu --> | |
| <div id="mobile-menu" class="hidden md:hidden bg-white dark:bg-gray-800 px-4 py-2 shadow-lg"> | |
| <a href="#" class="block py-2 hover:text-blue-600 dark:hover:text-blue-400">Home</a> | |
| <a href="#popular-routes" class="block py-2 hover:text-blue-600 dark:hover:text-blue-400">Popular Routes</a> | |
| <a href="#deals" class="block py-2 hover:text-blue-600 dark:hover:text-blue-400">Deals</a> | |
| <a href="#about" class="block py-2 hover:text-blue-600 dark:hover:text-blue-400">About</a> | |
| <a href="#contact" class="block py-2 hover:text-blue-600 dark:hover:text-blue-400">Contact</a> | |
| </div> | |
| </nav> | |
| <!-- Hero Section --> | |
| <section class="relative bg-gradient-to-r from-blue-500 to-blue-700 dark:from-blue-800 dark:to-blue-900 text-white py-16 md:py-24"> | |
| <div class="container mx-auto px-4 text-center"> | |
| <h1 class="text-4xl md:text-5xl font-bold mb-4">Find Cheap Flights from South Africa</h1> | |
| <p class="text-xl md:text-2xl mb-8">Compare prices across airlines and save up to 40% on your next trip</p> | |
| <!-- Search Form --> | |
| <div class="max-w-4xl mx-auto bg-white dark:bg-gray-800 rounded-xl p-6 search-form"> | |
| <form id="flight-search-form" class="grid grid-cols-1 md:grid-cols-3 gap-4"> | |
| <div> | |
| <label for="origin" class="block text-left text-gray-700 dark:text-gray-300 mb-1">From</label> | |
| <select id="origin" class="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <option value="">Select airport</option> | |
| <option value="JNB">Johannesburg (JNB)</option> | |
| <option value="CPT">Cape Town (CPT)</option> | |
| <option value="DUR">Durban (DUR)</option> | |
| <option value="PLZ">Port Elizabeth (PLZ)</option> | |
| <option value="BFN">Bloemfontein (BFN)</option> | |
| <option value="GRJ">George (GRJ)</option> | |
| <option value="KIM">Kimberley (KIM)</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label for="destination" class="block text-left text-gray-700 dark:text-gray-300 mb-1">To</label> | |
| <select id="destination" class="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <option value="">Select airport</option> | |
| <option value="JNB">Johannesburg (JNB)</option> | |
| <option value="CPT">Cape Town (CPT)</option> | |
| <option value="DUR">Durban (DUR)</option> | |
| <option value="PLZ">Port Elizabeth (PLZ)</option> | |
| <option value="BFN">Bloemfontein (BFN)</option> | |
| <option value="GRJ">George (GRJ)</option> | |
| <option value="KIM">Kimberley (KIM)</option> | |
| <option value="LON">London (LON)</option> | |
| <option value="NYC">New York (NYC)</option> | |
| <option value="DXB">Dubai (DXB)</option> | |
| <option value="HRE">Harare (HRE)</option> | |
| <option value="LVI">Livingstone (LVI)</option> | |
| <option value="MRU">Mauritius (MRU)</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label for="trip-type" class="block text-left text-gray-700 dark:text-gray-300 mb-1">Trip Type</label> | |
| <div class="flex border border-gray-300 dark:border-gray-600 rounded-lg overflow-hidden bg-white dark:bg-gray-700"> | |
| <button type="button" id="round-trip-btn" class="flex-1 py-2 px-4 bg-blue-600 text-white">Round Trip</button> | |
| <button type="button" id="one-way-btn" class="flex-1 py-2 px-4">One Way</button> | |
| </div> | |
| <input type="hidden" id="trip-type" value="round-trip"> | |
| </div> | |
| <div> | |
| <label for="departure-date" class="block text-left text-gray-700 dark:text-gray-300 mb-1">Departure</label> | |
| <input type="text" id="departure-date" class="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Select date"> | |
| </div> | |
| <div id="return-date-container"> | |
| <label for="return-date" class="block text-left text-gray-700 dark:text-gray-300 mb-1">Return</label> | |
| <input type="text" id="return-date" class="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Select date"> | |
| </div> | |
| <div class="grid grid-cols-2 gap-4"> | |
| <div> | |
| <label for="passengers" class="block text-left text-gray-700 dark:text-gray-300 mb-1">Passengers</label> | |
| <select id="passengers" class="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <option value="1">1 Passenger</option> | |
| <option value="2">2 Passengers</option> | |
| <option value="3">3 Passengers</option> | |
| <option value="4">4 Passengers</option> | |
| <option value="5">5 Passengers</option> | |
| <option value="6">6 Passengers</option> | |
| <option value="7">7 Passengers</option> | |
| <option value="8">8 Passengers</option> | |
| <option value="9">9 Passengers</option> | |
| <option value="10">10 Passengers</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label for="cabin-class" class="block text-left text-gray-700 dark:text-gray-300 mb-1">Cabin Class</label> | |
| <select id="cabin-class" class="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <option value="economy">Economy</option> | |
| <option value="business">Business</option> | |
| <option value="first">First Class</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="md:col-span-3"> | |
| <button type="submit" class="w-full py-3 px-6 bg-blue-600 hover:bg-blue-700 text-white font-bold rounded-lg transition duration-300"> | |
| <i class="fas fa-search mr-2"></i> Search Flights | |
| </button> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Popular Routes Section --> | |
| <section id="popular-routes" class="py-12 bg-gray-100 dark:bg-gray-800"> | |
| <div class="container mx-auto px-4"> | |
| <h2 class="text-3xl font-bold text-center mb-8">Popular Flight Routes</h2> | |
| <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6"> | |
| <div class="bg-white dark:bg-gray-700 rounded-xl shadow-md p-6 hover:shadow-lg transition duration-300"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <div> | |
| <h3 class="font-bold text-lg">JNB → CPT</h3> | |
| <p class="text-gray-600 dark:text-gray-300">Johannesburg to Cape Town</p> | |
| </div> | |
| <i class="fas fa-plane text-blue-500 text-xl"></i> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <p class="text-gray-500 dark:text-gray-400 text-sm">From</p> | |
| <p class="text-2xl font-bold text-blue-600 dark:text-blue-400">R 1,299</p> | |
| </div> | |
| <a href="#" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg text-sm font-medium transition duration-300">Search</a> | |
| </div> | |
| </div> | |
| <div class="bg-white dark:bg-gray-700 rounded-xl shadow-md p-6 hover:shadow-lg transition duration-300"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <div> | |
| <h3 class="font-bold text-lg">CPT → DUR</h3> | |
| <p class="text-gray-600 dark:text-gray-300">Cape Town to Durban</p> | |
| </div> | |
| <i class="fas fa-plane text-blue-500 text-xl"></i> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <p class="text-gray-500 dark:text-gray-400 text-sm">From</p> | |
| <p class="text-2xl font-bold text-blue-600 dark:text-blue-400">R 1,499</p> | |
| </div> | |
| <a href="#" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg text-sm font-medium transition duration-300">Search</a> | |
| </div> | |
| </div> | |
| <div class="bg-white dark:bg-gray-700 rounded-xl shadow-md p-6 hover:shadow-lg transition duration-300"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <div> | |
| <h3 class="font-bold text-lg">JNB → DXB</h3> | |
| <p class="text-gray-600 dark:text-gray-300">Johannesburg to Dubai</p> | |
| </div> | |
| <i class="fas fa-plane text-blue-500 text-xl"></i> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <p class="text-gray-500 dark:text-gray-400 text-sm">From</p> | |
| <p class="text-2xl font-bold text-blue-600 dark:text-blue-400">R 6,799</p> | |
| </div> | |
| <a href="#" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg text-sm font-medium transition duration-300">Search</a> | |
| </div> | |
| </div> | |
| <div class="bg-white dark:bg-gray-700 rounded-xl shadow-md p-6 hover:shadow-lg transition duration-300"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <div> | |
| <h3 class="font-bold text-lg">CPT → MRU</h3> | |
| <p class="text-gray-600 dark:text-gray-300">Cape Town to Mauritius</p> | |
| </div> | |
| <i class="fas fa-plane text-blue-500 text-xl"></i> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <p class="text-gray-500 dark:text-gray-400 text-sm">From</p> | |
| <p class="text-2xl font-bold text-blue-600 dark:text-blue-400">R 4,299</p> | |
| </div> | |
| <a href="#" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg text-sm font-medium transition duration-300">Search</a> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Flight Deals Section --> | |
| <section id="deals" class="py-12"> | |
| <div class="container mx-auto px-4"> | |
| <h2 class="text-3xl font-bold text-center mb-2">Hot Flight Deals</h2> | |
| <p class="text-center text-gray-600 dark:text-gray-400 mb-8">Special offers for South African travelers</p> | |
| <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6"> | |
| <div class="bg-white dark:bg-gray-700 rounded-xl shadow-md overflow-hidden deal-card transition duration-300"> | |
| <div class="relative h-48 bg-blue-500"> | |
| <img src="https://images.unsplash.com/photo-1506929562872-bb421503ef21?ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60" alt="Cape Town" class="w-full h-full object-cover"> | |
| <div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div> | |
| <div class="absolute bottom-4 left-4 text-white"> | |
| <h3 class="font-bold text-xl">Cape Town</h3> | |
| <p class="text-sm">From Johannesburg</p> | |
| </div> | |
| </div> | |
| <div class="p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <span class="text-sm text-gray-500 dark:text-gray-400">FlySafair • Economy</span> | |
| <span class="text-xs bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200 px-2 py-1 rounded">SAVE 15%</span> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <p class="text-gray-500 dark:text-gray-400 text-sm">From</p> | |
| <p class="text-2xl font-bold text-blue-600 dark:text-blue-400">R 1,199</p> | |
| </div> | |
| <a href="#" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg text-sm font-medium transition duration-300">View Deal</a> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-white dark:bg-gray-700 rounded-xl shadow-md overflow-hidden deal-card transition duration-300"> | |
| <div class="relative h-48 bg-blue-500"> | |
| <img src="https://images.unsplash.com/photo-1518684079-3c830dcef090?ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60" alt="Dubai" class="w-full h-full object-cover"> | |
| <div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div> | |
| <div class="absolute bottom-4 left-4 text-white"> | |
| <h3 class="font-bold text-xl">Dubai</h3> | |
| <p class="text-sm">From Johannesburg</p> | |
| </div> | |
| </div> | |
| <div class="p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <span class="text-sm text-gray-500 dark:text-gray-400">Emirates • Economy</span> | |
| <span class="text-xs bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200 px-2 py-1 rounded">SAVE 20%</span> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <p class="text-gray-500 dark:text-gray-400 text-sm">From</p> | |
| <p class="text-2xl font-bold text-blue-600 dark:text-blue-400">R 5,499</p> | |
| </div> | |
| <a href="#" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg text-sm font-medium transition duration-300">View Deal</a> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-white dark:bg-gray-700 rounded-xl shadow-md overflow-hidden deal-card transition duration-300"> | |
| <div class="relative h-48 bg-blue-500"> | |
| <img src="https://images.unsplash.com/photo-1523482580672-f109ba8cb9be?ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60" alt="Victoria Falls" class="w-full h-full object-cover"> | |
| <div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div> | |
| <div class="absolute bottom-4 left-4 text-white"> | |
| <h3 class="font-bold text-xl">Victoria Falls</h3> | |
| <p class="text-sm">From Cape Town</p> | |
| </div> | |
| </div> | |
| <div class="p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <span class="text-sm text-gray-500 dark:text-gray-400">SAA • Economy</span> | |
| <span class="text-xs bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200 px-2 py-1 rounded">SAVE 10%</span> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <p class="text-gray-500 dark:text-gray-400 text-sm">From</p> | |
| <p class="text-2xl font-bold text-blue-600 dark:text-blue-400">R 2,999</p> | |
| </div> | |
| <a href="#" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg text-sm font-medium transition duration-300">View Deal</a> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-white dark:bg-gray-700 rounded-xl shadow-md overflow-hidden deal-card transition duration-300"> | |
| <div class="relative h-48 bg-blue-500"> | |
| <img src="https://images.unsplash.com/photo-1566073771259-6a8506099945?ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60" alt="Mauritius" class="w-full h-full object-cover"> | |
| <div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div> | |
| <div class="absolute bottom-4 left-4 text-white"> | |
| <h3 class="font-bold text-xl">Mauritius</h3> | |
| <p class="text-sm">From Durban</p> | |
| </div> | |
| </div> | |
| <div class="p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <span class="text-sm text-gray-500 dark:text-gray-400">Air Mauritius • Economy</span> | |
| <span class="text-xs bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200 px-2 py-1 rounded">SAVE 25%</span> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <p class="text-gray-500 dark:text-gray-400 text-sm">From</p> | |
| <p class="text-2xl font-bold text-blue-600 dark:text-blue-400">R 3,799</p> | |
| </div> | |
| <a href="#" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg text-sm font-medium transition duration-300">View Deal</a> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="text-center mt-8"> | |
| <a href="#" class="inline-block px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition duration-300"> | |
| View All Deals <i class="fas fa-arrow-right ml-2"></i> | |
| </a> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- How It Works Section --> | |
| <section class="py-12 bg-gray-100 dark:bg-gray-800"> | |
| <div class="container mx-auto px-4"> | |
| <h2 class="text-3xl font-bold text-center mb-8">How FlySaver ZA Works</h2> | |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-8"> | |
| <div class="text-center"> | |
| <div class="bg-blue-100 dark:bg-blue-900 w-16 h-16 mx-auto rounded-full flex items-center justify-center mb-4"> | |
| <i class="fas fa-search text-blue-600 dark:text-blue-400 text-2xl"></i> | |
| </div> | |
| <h3 class="text-xl font-bold mb-2">Search</h3> | |
| <p class="text-gray-600 dark:text-gray-400">Enter your travel details and compare flights from multiple airlines in seconds.</p> | |
| </div> | |
| <div class="text-center"> | |
| <div class="bg-blue-100 dark:bg-blue-900 w-16 h-16 mx-auto rounded-full flex items-center justify-center mb-4"> | |
| <i class="fas fa-filter text-blue-600 dark:text-blue-400 text-2xl"></i> | |
| </div> | |
| <h3 class="text-xl font-bold mb-2">Filter & Sort</h3> | |
| <p class="text-gray-600 dark:text-gray-400">Refine results by price, duration, airline, or departure time to find your perfect flight.</p> | |
| </div> | |
| <div class="text-center"> | |
| <div class="bg-blue-100 dark:bg-blue-900 w-16 h-16 mx-auto rounded-full flex items-center justify-center mb-4"> | |
| <i class="fas fa-ticket-alt text-blue-600 dark:text-blue-400 text-2xl"></i> | |
| </div> | |
| <h3 class="text-xl font-bold mb-2">Book & Save</h3> | |
| <p class="text-gray-600 dark:text-gray-400">Book directly with the airline or through our trusted partners at the best price.</p> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Testimonials Section --> | |
| <section class="py-12"> | |
| <div class="container mx-auto px-4"> | |
| <h2 class="text-3xl font-bold text-center mb-8">What Our Users Say</h2> | |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-6"> | |
| <div class="bg-white dark:bg-gray-700 rounded-xl shadow-md p-6"> | |
| <div class="flex items-center mb-4"> | |
| <div class="w-12 h-12 rounded-full bg-gray-300 dark:bg-gray-600 overflow-hidden mr-4"> | |
| <img src="https://randomuser.me/api/portraits/women/43.jpg" alt="User" class="w-full h-full object-cover"> | |
| </div> | |
| <div> | |
| <h4 class="font-bold">Sarah K.</h4> | |
| <div class="flex text-yellow-400"> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <p class="text-gray-600 dark:text-gray-400">"Found a flight from JNB to CPT for R1,200 when other sites were showing R1,800+. Saved enough for an extra night's accommodation!"</p> | |
| </div> | |
| <div class="bg-white dark:bg-gray-700 rounded-xl shadow-md p-6"> | |
| <div class="flex items-center mb-4"> | |
| <div class="w-12 h-12 rounded-full bg-gray-300 dark:bg-gray-600 overflow-hidden mr-4"> | |
| <img src="https://randomuser.me/api/portraits/men/32.jpg" alt="User" class="w-full h-full object-cover"> | |
| </div> | |
| <div> | |
| <h4 class="font-bold">Thabo M.</h4> | |
| <div class="flex text-yellow-400"> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star-half-alt"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <p class="text-gray-600 dark:text-gray-400">"The interface is so easy to use. I booked flights to Mauritius for my family in under 5 minutes."</p> | |
| </div> | |
| <div class="bg-white dark:bg-gray-700 rounded-xl shadow-md p-6"> | |
| <div class="flex items-center mb-4"> | |
| <div class="w-12 h-12 rounded-full bg-gray-300 dark:bg-gray-600 overflow-hidden mr-4"> | |
| <img src="https://randomuser.me/api/portraits/women/65.jpg" alt="User" class="w-full h-full object-cover"> | |
| </div> | |
| <div> | |
| <h4 class="font-bold">Nomsa D.</h4> | |
| <div class="flex text-yellow-400"> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <p class="text-gray-600 dark:text-gray-400">"I use FlySaver ZA for all my business trips. The price alerts feature helps me book at the right time."</p> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- About Section --> | |
| <section id="about" class="py-12 bg-gray-100 dark:bg-gray-800"> | |
| <div class="container mx-auto px-4"> | |
| <div class="max-w-4xl mx-auto"> | |
| <h2 class="text-3xl font-bold text-center mb-8">About FlySaver ZA</h2> | |
| <div class="bg-white dark:bg-gray-700 rounded-xl shadow-md p-8"> | |
| <p class="text-gray-600 dark:text-gray-400 mb-6">FlySaver ZA was founded in 2023 with a simple mission: to help South Africans find the cheapest flights without the hassle of checking multiple airline websites.</p> | |
| <p class="text-gray-600 dark:text-gray-400 mb-6">Our platform compares prices across all major airlines and online travel agencies to ensure you get the best deal on your next trip, whether you're flying domestically or internationally.</p> | |
| <p class="text-gray-600 dark:text-gray-400 mb-6">We're committed to transparency - we don't add hidden fees to the prices you see. What you see is what you'll pay (plus any airline fees).</p> | |
| <h3 class="text-xl font-bold mb-4">Our Team</h3> | |
| <p class="text-gray-600 dark:text-gray-400">Based in Johannesburg, our team of travel enthusiasts and tech experts work tirelessly to improve the flight search experience for South African travelers.</p> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Contact Section --> | |
| <section id="contact" class="py-12"> | |
| <div class="container mx-auto px-4"> | |
| <h2 class="text-3xl font-bold text-center mb-8">Contact Us</h2> | |
| <div class="max-w-2xl mx-auto bg-white dark:bg-gray-700 rounded-xl shadow-md p-8"> | |
| <form id="contact-form" class="space-y-6"> | |
| <div> | |
| <label for="name" class="block text-gray-700 dark:text-gray-300 mb-1">Full Name</label> | |
| <input type="text" id="name" class="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500" required> | |
| </div> | |
| <div> | |
| <label for="email" class="block text-gray-700 dark:text-gray-300 mb-1">Email Address</label> | |
| <input type="email" id="email" class="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500" required> | |
| </div> | |
| <div> | |
| <label for="subject" class="block text-gray-700 dark:text-gray-300 mb-1">Subject</label> | |
| <select id="subject" class="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <option value="general">General Inquiry</option> | |
| <option value="feedback">Feedback</option> | |
| <option value="business">Business Partnership</option> | |
| <option value="press">Press Inquiry</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label for="message" class="block text-gray-700 dark:text-gray-300 mb-1">Message</label> | |
| <textarea id="message" rows="5" class="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500" required></textarea> | |
| </div> | |
| <button type="submit" class="w-full py-3 px-6 bg-blue-600 hover:bg-blue-700 text-white font-bold rounded-lg transition duration-300"> | |
| Send Message | |
| </button> | |
| </form> | |
| <div id="form-success" class="hidden mt-4 p-4 bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200 rounded-lg"> | |
| <i class="fas fa-check-circle mr-2"></i> Your message has been sent successfully! | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Newsletter Section --> | |
| <section class="py-12 bg-blue-600 dark:bg-blue-800 text-white"> | |
| <div class="container mx-auto px-4 text-center"> | |
| <h2 class="text-3xl font-bold mb-4">Get the Best Flight Deals</h2> | |
| <p class="max-w-2xl mx-auto mb-8">Subscribe to our newsletter and receive exclusive flight deals, travel tips, and special offers directly to your inbox.</p> | |
| <form class="max-w-md mx-auto flex"> | |
| <input type="email" placeholder="Your email address" class="flex-1 p-3 rounded-l-lg focus:outline-none text-gray-900"> | |
| <button type="submit" class="bg-blue-800 dark:bg-blue-900 hover:bg-blue-900 dark:hover:bg-blue-950 px-6 py-3 rounded-r-lg font-medium transition duration-300"> | |
| Subscribe | |
| </button> | |
| </form> | |
| </div> | |
| </section> | |
| <!-- Footer --> | |
| <footer class="bg-gray-800 dark:bg-gray-900 text-gray-300 py-12"> | |
| <div class="container mx-auto px-4"> | |
| <div class="grid grid-cols-1 md:grid-cols-4 gap-8"> | |
| <div> | |
| <div class="flex items-center space-x-2 mb-4"> | |
| <i class="fas fa-plane-departure text-blue-400 text-2xl"></i> | |
| <span class="text-xl font-bold text-white">FlySaver ZA</span> | |
| </div> | |
| <p class="mb-4">Find the cheapest flights from South Africa to local and international destinations.</p> | |
| <div class="flex space-x-4"> | |
| <a href="#" class="text-blue-400 hover:text-blue-300"><i class="fab fa-facebook-f"></i></a> | |
| <a href="#" class="text-blue-400 hover:text-blue-300"><i class="fab fa-twitter"></i></a> | |
| <a href="#" class="text-blue-400 hover:text-blue-300"><i class="fab fa-instagram"></i></a> | |
| <a href="#" class="text-blue-400 hover:text-blue-300"><i class="fab fa-linkedin-in"></i></a> | |
| </div> | |
| </div> | |
| <div> | |
| <h3 class="text-white font-bold text-lg mb-4">Quick Links</h3> | |
| <ul class="space-y-2"> | |
| <li><a href="#" class="hover:text-blue-400 transition duration-300">Home</a></li> | |
| <li><a href="#popular-routes" class="hover:text-blue-400 transition duration-300">Popular Routes</a></li> | |
| <li><a href="#deals" class="hover:text-blue-400 transition duration-300">Flight Deals</a></li> | |
| <li><a href="#about" class="hover:text-blue-400 transition duration-300">About Us</a></li> | |
| <li><a href="#contact" class="hover:text-blue-400 transition duration-300">Contact</a></li> | |
| </ul> | |
| </div> | |
| <div> | |
| <h3 class="text-white font-bold text-lg mb-4">Destinations</h3> | |
| <ul class="space-y-2"> | |
| <li><a href="#" class="hover:text-blue-400 transition duration-300">Domestic Flights</a></li> | |
| <li><a href="#" class="hover:text-blue-400 transition duration-300">Africa Flights</a></li> | |
| <li><a href="#" class="hover:text-blue-400 transition duration-300">Europe Flights</a></li> | |
| <li><a href="#" class="hover:text-blue-400 transition duration-300">Asia Flights</a></li> | |
| <li><a href="#" class="hover:text-blue-400 transition duration-300">Americas Flights</a></li> | |
| </ul> | |
| </div> | |
| <div> | |
| <h3 class="text-white font-bold text-lg mb-4">Contact Info</h3> | |
| <ul class="space-y-2"> | |
| <li class="flex items-start"> | |
| <i class="fas fa-map-marker-alt mt-1 mr-2 text-blue-400"></i> | |
| <span>123 Aviation Rd, Johannesburg, 2000</span> | |
| </li> | |
| <li class="flex items-center"> | |
| <i class="fas fa-phone-alt mr-2 text-blue-400"></i> | |
| <span>+27 11 123 4567</span> | |
| </li> | |
| <li class="flex items-center"> | |
| <i class="fas fa-envelope mr-2 text-blue-400"></i> | |
| <span>info@flysaverza.co.za</span> | |
| </li> | |
| </ul> | |
| </div> | |
| </div> | |
| <div class="border-t border-gray-700 mt-8 pt-8 text-center"> | |
| <p>© 2023 FlySaver ZA. All rights reserved.</p> | |
| <div class="flex justify-center space-x-6 mt-4"> | |
| <a href="#" class="text-sm hover:text-blue-400">Privacy Policy</a> | |
| <a href="#" class="text-sm hover:text-blue-400">Terms of Service</a> | |
| <a href="#" class="text-sm hover:text-blue-400">Cookie Policy</a> | |
| </div> | |
| </div> | |
| </div> | |
| </footer> | |
| <!-- Flight Results Modal (hidden by default) --> | |
| <div id="flight-results-modal" class="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4 hidden"> | |
| <div class="bg-white dark:bg-gray-800 rounded-xl w-full max-w-6xl max-h-[90vh] overflow-y-auto"> | |
| <div class="sticky top-0 bg-white dark:bg-gray-800 p-4 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center"> | |
| <h3 class="text-xl font-bold">Flight Results</h3> | |
| <button id="close-results-modal" class="text-gray-500 hover:text-gray-700 dark:hover:text-gray-300"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="p-4"> | |
| <div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-6"> | |
| <div> | |
| <h4 id="results-route" class="text-lg font-bold">JNB → CPT</h4> | |
| <p id="results-dates" class="text-gray-600 dark:text-gray-400">15 Oct - 22 Oct 2023 • 1 Passenger • Economy</p> | |
| </div> | |
| <div class="mt-4 md:mt-0"> | |
| <label for="sort-by" class="mr-2">Sort by:</label> | |
| <select id="sort-by" class="p-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <option value="price">Price (Lowest first)</option> | |
| <option value="duration">Duration (Shortest first)</option> | |
| <option value="departure">Departure Time (Earliest first)</option> | |
| </select> | |
| </div> | |
| </div> | |
| <!-- Filters --> | |
| <div class="bg-gray-100 dark:bg-gray-700 rounded-lg p-4 mb-6"> | |
| <h5 class="font-bold mb-3">Filters</h5> | |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-4"> | |
| <div> | |
| <label class="block mb-1">Airlines</label> | |
| <div class="space-y-2"> | |
| <label class="flex items-center"> | |
| <input type="checkbox" class="rounded text-blue-600" checked> | |
| <span class="ml-2">All Airlines</span> | |
| </label> | |
| <label class="flex items-center"> | |
| <input type="checkbox" class="rounded text-blue-600" checked> | |
| <span class="ml-2">FlySafair</span> | |
| </label> | |
| <label class="flex items-center"> | |
| <input type="checkbox" class="rounded text-blue-600" checked> | |
| <span class="ml-2">SAA</span> | |
| </label> | |
| <label class="flex items-center"> | |
| <input type="checkbox" class="rounded text-blue-600" checked> | |
| <span class="ml-2">British Airways</span> | |
| </label> | |
| </div> | |
| </div> | |
| <div> | |
| <label class="block mb-1">Price Range</label> | |
| <div class="mb-2"> | |
| <input type="range" min="500" max="10000" value="10000" class="w-full"> | |
| </div> | |
| <div class="flex justify-between text-sm"> | |
| <span>R 500</span> | |
| <span>R 10,000</span> | |
| </div> | |
| </div> | |
| <div> | |
| <label class="block mb-1">Departure Time</label> | |
| <div class="space-y-2"> | |
| <label class="flex items-center"> | |
| <input type="checkbox" class="rounded text-blue-600" checked> | |
| <span class="ml-2">Morning (6am - 12pm)</span> | |
| </label> | |
| <label class="flex items-center"> | |
| <input type="checkbox" class="rounded text-blue-600" checked> | |
| <span class="ml-2">Afternoon (12pm - 6pm)</span> | |
| </label> | |
| <label class="flex items-center"> | |
| <input type="checkbox" class="rounded text-blue-600" checked> | |
| <span class="ml-2">Evening (6pm - 12am)</span> | |
| </label> | |
| <label class="flex items-center"> | |
| <input type="checkbox" class="rounded text-blue-600" checked> | |
| <span class="ml-2">Night (12am - 6am)</span> | |
| </label> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Flight Results --> | |
| <div id="flight-results-container" class="space-y-4"> | |
| <!-- Flight cards will be inserted here by JavaScript --> | |
| </div> | |
| <!-- Loading more indicator --> | |
| <div id="loading-more" class="text-center py-8 hidden"> | |
| <div class="inline-block animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-blue-600"></div> | |
| <p class="mt-2">Loading more flights...</p> | |
| </div> | |
| <div class="text-center mt-6"> | |
| <button id="load-more-btn" class="px-6 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg"> | |
| Load More Flights | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // Mock flight data | |
| const mockFlights = [ | |
| { | |
| id: 1, | |
| airline: "FlySafair", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7a/FlySafair_logo.svg/1200px-FlySafair_logo.svg.png", | |
| departureTime: "06:00", | |
| arrivalTime: "08:15", | |
| duration: "2h 15m", | |
| price: 1299, | |
| stops: 0, | |
| departureAirport: "JNB", | |
| arrivalAirport: "CPT" | |
| }, | |
| { | |
| id: 2, | |
| airline: "SAA", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7f/South_African_Airways_logo.svg/1200px-South_African_Airways_logo.svg.png", | |
| departureTime: "07:30", | |
| arrivalTime: "09:40", | |
| duration: "2h 10m", | |
| price: 1450, | |
| stops: 0, | |
| departureAirport: "JNB", | |
| arrivalAirport: "CPT" | |
| }, | |
| { | |
| id: 3, | |
| airline: "British Airways", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/British_Airways_Logo.svg/1200px-British_Airways_Logo.svg.png", | |
| departureTime: "10:15", | |
| arrivalTime: "12:30", | |
| duration: "2h 15m", | |
| price: 1599, | |
| stops: 0, | |
| departureAirport: "JNB", | |
| arrivalAirport: "CPT" | |
| }, | |
| { | |
| id: 4, | |
| airline: "Emirates", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d0/Emirates_logo.svg/1200px-Emirates_logo.svg.png", | |
| departureTime: "14:00", | |
| arrivalTime: "16:10", | |
| duration: "2h 10m", | |
| price: 1899, | |
| stops: 0, | |
| departureAirport: "JNB", | |
| arrivalAirport: "CPT" | |
| }, | |
| { | |
| id: 5, | |
| airline: "Kulula", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Kulula_logo.svg/1200px-Kulula_logo.svg.png", | |
| departureTime: "16:45", | |
| arrivalTime: "19:00", | |
| duration: "2h 15m", | |
| price: 1399, | |
| stops: 0, | |
| departureAirport: "JNB", | |
| arrivalAirport: "CPT" | |
| }, | |
| { | |
| id: 6, | |
| airline: "FlySafair", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7a/FlySafair_logo.svg/1200px-FlySafair_logo.svg.png", | |
| departureTime: "19:30", | |
| arrivalTime: "21:45", | |
| duration: "2h 15m", | |
| price: 1499, | |
| stops: 0, | |
| departureAirport: "JNB", | |
| arrivalAirport: "CPT" | |
| }, | |
| { | |
| id: 7, | |
| airline: "SAA", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7f/South_African_Airways_logo.svg/1200px-South_African_Airways_logo.svg.png", | |
| departureTime: "05:45", | |
| arrivalTime: "08:00", | |
| duration: "2h 15m", | |
| price: 1349, | |
| stops: 0, | |
| departureAirport: "JNB", | |
| arrivalAirport: "CPT" | |
| }, | |
| { | |
| id: 8, | |
| airline: "Lift", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Lift_%28airline%29_logo.svg/1200px-Lift_%28airline%29_logo.svg.png", | |
| departureTime: "09:15", | |
| arrivalTime: "11:25", | |
| duration: "2h 10m", | |
| price: 1199, | |
| stops: 0, | |
| departureAirport: "JNB", | |
| arrivalAirport: "CPT" | |
| }, | |
| { | |
| id: 9, | |
| airline: "FlySafair", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7a/FlySafair_logo.svg/1200px-FlySafair_logo.svg.png", | |
| departureTime: "12:30", | |
| arrivalTime: "14:45", | |
| duration: "2h 15m", | |
| price: 1249, | |
| stops: 0, | |
| departureAirport: "JNB", | |
| arrivalAirport: "CPT" | |
| }, | |
| { | |
| id: 10, | |
| airline: "SAA", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7f/South_African_Airways_logo.svg/1200px-South_African_Airways_logo.svg.png", | |
| departureTime: "15:15", | |
| arrivalTime: "17:25", | |
| duration: "2h 10m", | |
| price: 1420, | |
| stops: 0, | |
| departureAirport: "JNB", | |
| arrivalAirport: "CPT" | |
| } | |
| ]; | |
| // Additional mock data for international flights | |
| const internationalFlights = [ | |
| { | |
| id: 11, | |
| airline: "Emirates", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d0/Emirates_logo.svg/1200px-Emirates_logo.svg.png", | |
| departureTime: "20:30", | |
| arrivalTime: "07:15", | |
| duration: "8h 45m", | |
| price: 6799, | |
| stops: 0, | |
| departureAirport: "JNB", | |
| arrivalAirport: "DXB" | |
| }, | |
| { | |
| id: 12, | |
| airline: "Qatar Airways", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9b/Qatar_Airways_Logo.svg/1200px-Qatar_Airways_Logo.svg.png", | |
| departureTime: "22:15", | |
| arrivalTime: "10:30", | |
| duration: "9h 15m", | |
| price: 7299, | |
| stops: 0, | |
| departureAirport: "JNB", | |
| arrivalAirport: "DXB" | |
| }, | |
| { | |
| id: 13, | |
| airline: "British Airways", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/British_Airways_Logo.svg/1200px-British_Airways_Logo.svg.png", | |
| departureTime: "18:45", | |
| arrivalTime: "06:00", | |
| duration: "10h 15m", | |
| price: 8599, | |
| stops: 1, | |
| departureAirport: "CPT", | |
| arrivalAirport: "LON" | |
| }, | |
| { | |
| id: 14, | |
| airline: "SAA", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7f/South_African_Airways_logo.svg/1200px-South_African_Airways_logo.svg.png", | |
| departureTime: "15:30", | |
| arrivalTime: "05:45", | |
| duration: "11h 15m", | |
| price: 8999, | |
| stops: 1, | |
| departureAirport: "JNB", | |
| arrivalAirport: "NYC" | |
| }, | |
| { | |
| id: 15, | |
| airline: "Air Mauritius", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Air_Mauritius_logo.svg/1200px-Air_Mauritius_logo.svg.png", | |
| departureTime: "09:15", | |
| arrivalTime: "14:30", | |
| duration: "4h 15m", | |
| price: 4299, | |
| stops: 0, | |
| departureAirport: "CPT", | |
| arrivalAirport: "MRU" | |
| }, | |
| { | |
| id: 16, | |
| airline: "Fastjet", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7a/Fastjet_logo.svg/1200px-Fastjet_logo.svg.png", | |
| departureTime: "11:30", | |
| arrivalTime: "13:15", | |
| duration: "1h 45m", | |
| price: 2499, | |
| stops: 0, | |
| departureAirport: "JNB", | |
| arrivalAirport: "HRE" | |
| }, | |
| { | |
| id: 17, | |
| airline: "Proflight Zambia", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7a/Proflight_Zambia_logo.svg/1200px-Proflight_Zambia_logo.svg.png", | |
| departureTime: "08:45", | |
| arrivalTime: "10:30", | |
| duration: "1h 45m", | |
| price: 2899, | |
| stops: 0, | |
| departureAirport: "JNB", | |
| arrivalAirport: "LVI" | |
| }, | |
| { | |
| id: 18, | |
| airline: "Ethiopian Airlines", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8c/Ethiopian_Airlines_Logo.svg/1200px-Ethiopian_Airlines_Logo.svg.png", | |
| departureTime: "07:30", | |
| arrivalTime: "16:45", | |
| duration: "7h 15m", | |
| price: 5899, | |
| stops: 1, | |
| departureAirport: "JNB", | |
| arrivalAirport: "ADD" | |
| }, | |
| { | |
| id: 19, | |
| airline: "Kenya Airways", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7a/Kenya_Airways_logo.svg/1200px-Kenya_Airways_logo.svg.png", | |
| departureTime: "10:15", | |
| arrivalTime: "19:30", | |
| duration: "7h 15m", | |
| price: 5499, | |
| stops: 1, | |
| departureAirport: "CPT", | |
| arrivalAirport: "NBO" | |
| }, | |
| { | |
| id: 20, | |
| airline: "Turkish Airlines", | |
| airlineLogo: "https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/Turkish_Airlines_logo_2019_compact.svg/1200px-Turkish_Airlines_logo_2019_compact.svg.png", | |
| departureTime: "21:45", | |
| arrivalTime: "08:30", | |
| duration: "10h 45m", | |
| price: 7699, | |
| stops: 0, | |
| departureAirport: "JNB", | |
| arrivalAirport: "IST" | |
| } | |
| ]; | |
| // Combine all flights | |
| const allFlights = [...mockFlights, ...internationalFlights]; | |
| // DOM elements | |
| const flightSearchForm = document.getElementById('flight-search-form'); | |
| const originSelect = document.getElementById('origin'); | |
| const destinationSelect = document.getElementById('destination'); | |
| const tripTypeHidden = document.getElementById('trip-type'); | |
| const roundTripBtn = document.getElementById('round-trip-btn'); | |
| const oneWayBtn = document.getElementById('one-way-btn'); | |
| const departureDateInput = document.getElementById('departure-date'); | |
| const returnDateInput = document.getElementById('return-date'); | |
| const returnDateContainer = document.getElementById('return-date-container'); | |
| const passengersSelect = document.getElementById('passengers'); | |
| const cabinClassSelect = document.getElementById('cabin-class'); | |
| const flightResultsModal = document.getElementById('flight-results-modal'); | |
| const closeResultsModal = document.getElementById('close-results-modal'); | |
| const resultsRoute = document.getElementById('results-route'); | |
| const resultsDates = document.getElementById('results-dates'); | |
| const flightResultsContainer = document.getElementById('flight-results-container'); | |
| const sortBySelect = document.getElementById('sort-by'); | |
| const loadMoreBtn = document.getElementById('load-more-btn'); | |
| const loadingMore = document.getElementById('loading-more'); | |
| const themeToggle = document.getElementById('theme-toggle'); | |
| const mobileMenuButton = document.getElementById('mobile-menu-button'); | |
| const mobileMenu = document.getElementById('mobile-menu'); | |
| const contactForm = document.getElementById('contact-form'); | |
| const formSuccess = document.getElementById('form-success'); | |
| // Initialize date pickers | |
| flatpickr(departureDateInput, { | |
| minDate: 'today', | |
| dateFormat: 'd M Y', | |
| defaultDate: new Date().fp_incr(7) | |
| }); | |
| flatpickr(returnDateInput, { | |
| minDate: new Date().fp_incr(14), | |
| dateFormat: 'd M Y', | |
| defaultDate: new Date().fp_incr(14) | |
| }); | |
| // Toggle trip type | |
| roundTripBtn.addEventListener('click', () => { | |
| tripTypeHidden.value = 'round-trip'; | |
| roundTripBtn.classList.add('bg-blue-600', 'text-white'); | |
| oneWayBtn.classList.remove('bg-blue-600', 'text-white'); | |
| returnDateContainer.classList.remove('hidden'); | |
| }); | |
| oneWayBtn.addEventListener('click', () => { | |
| tripTypeHidden.value = 'one-way'; | |
| oneWayBtn.classList.add('bg-blue-600', 'text-white'); | |
| roundTripBtn.classList.remove('bg-blue-600', 'text-white'); | |
| returnDateContainer.classList.add('hidden'); | |
| }); | |
| // Form submission | |
| flightSearchForm.addEventListener('submit', (e) => { | |
| e.preventDefault(); | |
| const origin = originSelect.value; | |
| const destination = destinationSelect.value; | |
| const tripType = tripTypeHidden.value; | |
| const departureDate = departureDateInput.value; | |
| const returnDate = tripType === 'round-trip' ? returnDateInput.value : ''; | |
| const passengers = passengersSelect.value; | |
| const cabinClass = cabinClassSelect.value; | |
| // Basic validation | |
| if (!origin || !destination) { | |
| alert('Please select both origin and destination airports.'); | |
| return; | |
| } | |
| if (origin === destination) { | |
| alert('Origin and destination cannot be the same.'); | |
| return; | |
| } | |
| if (!departureDate) { | |
| alert('Please select a departure date.'); | |
| return; | |
| } | |
| if (tripType === 'round-trip' && !returnDate) { | |
| alert('Please select a return date for round trips.'); | |
| return; | |
| } | |
| // Show results | |
| showFlightResults(origin, destination, tripType, departureDate, returnDate, passengers, cabinClass); | |
| }); | |
| // Show flight results | |
| function showFlightResults(origin, destination, tripType, departureDate, returnDate, passengers, cabinClass) { | |
| // Update results header | |
| resultsRoute.textContent = `${origin} → ${destination}`; | |
| let datesText = departureDate; | |
| if (tripType === 'round-trip') { | |
| datesText += ` - ${returnDate}`; | |
| } | |
| resultsDates.textContent = `${datesText} • ${passengers} ${passengers === '1' ? 'Passenger' : 'Passengers'} • ${cabinClass.charAt(0).toUpperCase() + cabinClass.slice(1)}`; | |
| // Filter flights based on origin and destination | |
| let filteredFlights = allFlights.filter(flight => | |
| flight.departureAirport === origin && flight.arrivalAirport === destination | |
| ); | |
| // If no direct flights found, show some alternatives | |
| if (filteredFlights.length === 0) { | |
| filteredFlights = allFlights.slice(0, 10).map(flight => ({ | |
| ...flight, | |
| departureAirport: origin, | |
| arrivalAirport: destination | |
| })); | |
| } | |
| // Sort by price by default | |
| filteredFlights.sort((a, b) => a.price - b.price); | |
| // Display flights | |
| displayFlights(filteredFlights); | |
| // Show modal | |
| flightResultsModal.classList.remove('hidden'); | |
| document.body.style.overflow = 'hidden'; | |
| } | |
| // Display flights in the results container | |
| function displayFlights(flights) { | |
| flightResultsContainer.innerHTML = ''; | |
| flights.forEach((flight, index) => { | |
| const flightCard = document.createElement('div'); | |
| flightCard.className = `bg-white dark:bg-gray-700 rounded-xl shadow-md p-6 flight-card animate-fade-in`; | |
| flightCard.style.setProperty('--order', index); | |
| flightCard.innerHTML = ` | |
| <div class="flex flex-col md:flex-row justify-between"> | |
| <div class="flex items-center mb-4 md:mb-0"> | |
| <img src="${flight.airlineLogo}" alt="${flight.airline}" class="airline-logo mr-4"> | |
| <div> | |
| <h4 class="font-bold">${flight.airline}</h4> | |
| <p class="text-sm text-gray-600 dark:text-gray-400">${flight.stops === 0 ? 'Direct' : flight.stops + ' stop' + (flight.stops > 1 ? 's' : '')}</p> | |
| </div> | |
| </div> | |
| <div class="flex flex-col md:flex-row md:items-center space-y-4 md:space-y-0 md:space-x-8"> | |
| <div class="text-center"> | |
| <p class="text-xl font-bold">${flight.departureTime}</p> | |
| <p class="text-sm text-gray-600 dark:text-gray-400">${flight.departureAirport}</p> | |
| </div> | |
| <div class="text-center"> | |
| <p class="text-sm text-gray-600 dark:text-gray-400">${flight.duration}</p> | |
| <div class="w-20 h-px bg-gray-300 dark:bg-gray-600 mx-auto my-2"></div> | |
| <p class="text-xs text-gray-500 dark:text-gray-400">${flight.stops === 0 ? 'Non-stop' : flight.stops + ' stop' + (flight.stops > 1 ? 's' : '')}</p> | |
| </div> | |
| <div class="text-center"> | |
| <p class="text-xl font-bold">${flight.arrivalTime}</p> | |
| <p class="text-sm text-gray-600 dark:text-gray-400">${flight.arrivalAirport}</p> | |
| </div> | |
| <div class="text-center md:text-right"> | |
| <p class="text-2xl font-bold text-blue-600 dark:text-blue-400">R ${flight.price.toLocaleString()}</p> | |
| <a href="https://example.com/book?flight_id=${flight.id}" class="inline-block mt-2 px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg text-sm font-medium transition duration-300"> | |
| Book Now | |
| </a> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| flightResultsContainer.appendChild(flightCard); | |
| }); | |
| } | |
| // Close results modal | |
| closeResultsModal.addEventListener('click', () => { | |
| flightResultsModal.classList.add('hidden'); | |
| document.body.style.overflow = 'auto'; | |
| }); | |
| // Sort flights | |
| sortBySelect.addEventListener('change', () => { | |
| const sortBy = sortBySelect.value; | |
| const currentFlights = Array.from(flightResultsContainer.children).map(card => { | |
| const airline = card.querySelector('h4').textContent; | |
| const price = parseInt(card.querySelector('.text-2xl').textContent.replace('R ', '').replace(',', '')); | |
| const duration = card.querySelector('.text-sm').textContent; | |
| const departureTime = card.querySelectorAll('.text-xl')[0].textContent; | |
| return { airline, price, duration, departureTime, element: card }; | |
| }); | |
| currentFlights.sort((a, b) => { | |
| if (sortBy === 'price') { | |
| return a.price - b.price; | |
| } else if (sortBy === 'duration') { | |
| const aHours = parseInt(a.duration.split('h')[0]); | |
| const aMins = parseInt(a.duration.split('h')[1].split('m')[0]); | |
| const bHours = parseInt(b.duration.split('h')[0]); | |
| const bMins = parseInt(b.duration.split('h')[1].split('m')[0]); | |
| return (aHours * 60 + aMins) - (bHours * 60 + bMins); | |
| } else if (sortBy === 'departure') { | |
| return a.departureTime.localeCompare(b.departureTime); | |
| } | |
| return 0; | |
| }); | |
| // Reorder flights in the container | |
| flightResultsContainer.innerHTML = ''; | |
| currentFlights.forEach(flight => { | |
| flightResultsContainer.appendChild(flight.element); | |
| }); | |
| }); | |
| // Load more flights | |
| loadMoreBtn.addEventListener('click', () => { | |
| loadMoreBtn.classList.add('hidden'); | |
| loadingMore.classList.remove('hidden'); | |
| // Simulate loading more data | |
| setTimeout(() => { | |
| const additionalFlights = allFlights.slice(10, 15).map(flight => ({ | |
| ...flight, | |
| price: flight.price + Math.floor(Math.random() * 500) // Add some random variation | |
| })); | |
| displayFlights(additionalFlights); | |
| loadingMore.classList.add('hidden'); | |
| loadMoreBtn.classList.remove('hidden'); | |
| }, 1500); | |
| }); | |
| // Theme toggle | |
| themeToggle.addEventListener('click', () => { | |
| document.documentElement.classList.toggle('dark'); | |
| localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); | |
| }); | |
| // Check for saved theme preference | |
| if (localStorage.getItem('theme') === 'dark' || (!localStorage.getItem('theme') && window.matchMedia('(prefers-color-scheme: dark)').matches)) { | |
| document.documentElement.classList.add('dark'); | |
| } | |
| // Mobile menu toggle | |
| mobileMenuButton.addEventListener('click', () => { | |
| mobileMenu.classList.toggle('hidden'); | |
| }); | |
| // Contact form submission | |
| contactForm.addEventListener('submit', (e) => { | |
| e.preventDefault(); | |
| // Simulate form submission | |
| setTimeout(() => { | |
| contactForm.reset(); | |
| formSuccess.classList.remove('hidden'); | |
| setTimeout(() => { | |
| formSuccess.classList.add('hidden'); | |
| }, 3000); | |
| }, 1000); | |
| }); | |
| // Close mobile menu when clicking a link | |
| document.querySelectorAll('#mobile-menu a').forEach(link => { | |
| link.addEventListener('click', () => { | |
| mobileMenu.classList.add('hidden'); | |
| }); | |
| }); | |
| // Smooth scrolling for anchor links | |
| document.querySelectorAll('a[href^="#"]').forEach(anchor => { | |
| anchor.addEventListener('click', function(e) { | |
| e.preventDefault(); | |
| const targetId = this.getAttribute('href'); | |
| if (targetId === '#') return; | |
| const targetElement = document.querySelector(targetId); | |
| if (targetElement) { | |
| targetElement.scrollIntoView({ | |
| behavior: 'smooth' | |
| }); | |
| } | |
| }); | |
| }); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=pheello/flysaverza" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |