Spaces:
Running
Running
| // Mock data for rides | |
| const mockRides = [ | |
| { | |
| id: 1, | |
| from: "San Francisco, CA", | |
| to: "Los Angeles, CA", | |
| date: "2024-01-20", | |
| time: "08:00 AM", | |
| price: 45, | |
| seats: 3, | |
| driver: "Sarah M.", | |
| driverImage: "http://static.photos/people/200x200/1", | |
| rating: 4.8, | |
| car: "Tesla Model 3", | |
| features: ["AC", "WiFi", "Pets OK"] | |
| }, | |
| { | |
| id: 2, | |
| from: "New York, NY", | |
| to: "Boston, MA", | |
| date: "2024-01-21", | |
| time: "09:30 AM", | |
| price: 35, | |
| seats: 2, | |
| driver: "Mike R.", | |
| driverImage: "http://static.photos/people/200x200/2", | |
| rating: 4.9, | |
| car: "Honda Civic", | |
| features: ["AC", "Music"] | |
| }, | |
| { | |
| id: 3, | |
| from: "Chicago, IL", | |
| to: "Detroit, MI", | |
| date: "2024-01-22", | |
| time: "07:00 AM", | |
| price: 40, | |
| seats: 4, | |
| driver: "Emma L.", | |
| driverImage: "http://static.photos/people/200x200/3", | |
| rating: 4.7, | |
| car: "Toyota Camry", | |
| features: ["AC", "Luggage Space"] | |
| }, | |
| { | |
| id: 4, | |
| from: "Seattle, WA", | |
| to: "Portland, OR", | |
| date: "2024-01-20", | |
| time: "02:00 PM", | |
| price: 25, | |
| seats: 3, | |
| driver: "John D.", | |
| driverImage: "http://static.photos/people/200x200/4", | |
| rating: 5.0, | |
| car: "Subaru Outback", | |
| features: ["Bike Rack", "Pets OK"] | |
| }, | |
| { | |
| id: 5, | |
| from: "Austin, TX", | |
| to: "Dallas, TX", | |
| date: "2024-01-23", | |
| time: "10:00 AM", | |
| price: 30, | |
| seats: 2, | |
| driver: "Lisa K.", | |
| driverImage: "http://static.photos/people/200x200/5", | |
| rating: 4.6, | |
| car: "BMW X3", | |
| features: ["AC", "WiFi", "Leather Seats"] | |
| }, | |
| { | |
| id: 6, | |
| from: "Miami, FL", | |
| to: "Orlando, FL", | |
| date: "2024-01-21", | |
| time: "11:00 AM", | |
| price: 28, | |
| seats: 3, | |
| driver: "Carlos G.", | |
| driverImage: "http://static.photos/people/200x200/6", | |
| rating: 4.9, | |
| car: "Ford Mustang", | |
| features: ["Music", "Snacks"] | |
| } | |
| ]; | |
| // Theme toggle functionality | |
| function initTheme() { | |
| if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) { | |
| document.documentElement.classList.add('dark'); | |
| } else { | |
| document.documentElement.classList.remove('dark'); | |
| } | |
| } | |
| function toggleTheme() { | |
| if (document.documentElement.classList.contains('dark')) { | |
| document.documentElement.classList.remove('dark'); | |
| localStorage.theme = 'light'; | |
| } else { | |
| document.documentElement.classList.add('dark'); | |
| localStorage.theme = 'dark'; | |
| } | |
| } | |
| // Navigation | |
| function showSection(sectionId) { | |
| // Hide all sections | |
| const sections = ['hero', 'rides', 'how-it-works', 'offer-ride']; | |
| sections.forEach(id => { | |
| const el = document.getElementById(id); | |
| if (el) { | |
| if (id === sectionId) { | |
| el.classList.remove('hidden'); | |
| el.scrollIntoView({ behavior: 'smooth', block: 'start' }); | |
| } else { | |
| el.classList.add('hidden'); | |
| } | |
| } | |
| }); | |
| // Special handling for hero to show it properly | |
| if (sectionId === 'hero') { | |
| document.getElementById('hero').classList.remove('hidden'); | |
| window.scrollTo({ top: 0, behavior: 'smooth' }); | |
| } | |
| } | |
| // Search functionality | |
| function searchRides() { | |
| const from = document.getElementById('search-from').value; | |
| const to = document.getElementById('search-to').value; | |
| const date = document.getElementById('search-date').value; | |
| // Show loading state | |
| const ridesContainer = document.getElementById('rides-container'); | |
| ridesContainer.innerHTML = '<div class="col-span-full text-center py-12"><div class="shimmer h-32 w-full rounded-xl"></div></div>'; | |
| // Simulate API call | |
| setTimeout(() => { | |
| displayRides(mockRides, from, to); | |
| showSection('rides'); | |
| // Update search results text | |
| const resultsText = document.getElementById('search-results-text'); | |
| if (from && to) { | |
| resultsText.textContent = `Rides from ${from} to ${to}${date ? ' on ' + date : ''}`; | |
| } else { | |
| resultsText.textContent = 'Showing all available rides'; | |
| } | |
| }, 800); | |
| } | |
| function displayRides(rides, filterFrom = '', filterTo = '') { | |
| const container = document.getElementById('rides-container'); | |
| container.innerHTML = ''; | |
| // Filter rides (case insensitive partial match) | |
| const filteredRides = rides.filter(ride => { | |
| const matchFrom = !filterFrom || ride.from.toLowerCase().includes(filterFrom.toLowerCase()); | |
| const matchTo = !filterTo || ride.to.toLowerCase().includes(filterTo.toLowerCase()); | |
| return matchFrom && matchTo; | |
| }); | |
| if (filteredRides.length === 0) { | |
| container.innerHTML = ` | |
| <div class="col-span-full text-center py-12"> | |
| <div class="inline-block p-4 rounded-full bg-gray-100 dark:bg-slate-700 mb-4"> | |
| <i data-feather="inbox" class="w-8 h-8 text-gray-400"></i> | |
| </div> | |
| <p class="text-gray-600 dark:text-gray-400">No rides found matching your criteria.</p> | |
| <button onclick="displayRides(mockRides)" class="mt-4 text-primary-600 hover:text-primary-700 font-medium">Show all rides</button> | |
| </div> | |
| `; | |
| feather.replace(); | |
| return; | |
| } | |
| filteredRides.forEach(ride => { | |
| const card = document.createElement('ride-card'); | |
| card.ride = ride; | |
| container.appendChild(card); | |
| }); | |
| feather.replace(); | |
| } | |
| // Offer ride form | |
| function offerRide(event) { | |
| event.preventDefault(); | |
| // Show success message | |
| const btn = event.target.querySelector('button[type="submit"]'); | |
| const originalText = btn.textContent; | |
| btn.textContent = 'Publishing...'; | |
| btn.disabled = true; | |
| setTimeout(() => { | |
| btn.textContent = 'β Ride Published!'; | |
| btn.classList.remove('from-secondary-500', 'to-secondary-600'); | |
| btn.classList.add('from-primary-500', 'to-primary-600'); | |
| setTimeout(() => { | |
| showSection('rides'); | |
| // Reset form | |
| event.target.reset(); | |
| btn.textContent = originalText; | |
| btn.disabled = false; | |
| btn.classList.remove('from-primary-500', 'to-primary-600'); | |
| btn.classList.add('from-secondary-500', 'to-secondary-600'); | |
| // Add the new ride to mock data (in real app, this would be an API call) | |
| const newRide = { | |
| id: mockRides.length + 1, | |
| from: "Your Location", | |
| to: "Destination", | |
| date: new Date().toISOString().split('T')[0], | |
| time: "09:00 AM", | |
| price: 30, | |
| seats: 3, | |
| driver: "You", | |
| driverImage: "http://static.photos/people/200x200/99", | |
| rating: 5.0, | |
| car: "Your Car", | |
| features: ["AC"] | |
| }; | |
| mockRides.unshift(newRide); | |
| displayRides(mockRides); | |
| }, 1500); | |
| }, 1000); | |
| } | |
| // Initialize | |
| document.addEventListener('DOMContentLoaded', () => { | |
| initTheme(); | |
| // Set today's date as min for date inputs | |
| const today = new Date().toISOString().split('T')[0]; | |
| document.querySelectorAll('input[type="date"]').forEach(input => { | |
| input.min = today; | |
| }); | |
| // Check URL hash for direct navigation | |
| const hash = window.location.hash.replace('#', ''); | |
| if (hash && ['rides', 'how-it-works', 'offer-ride'].includes(hash)) { | |
| showSection(hash); | |
| } | |
| }); | |
| // Export functions for global access | |
| window.toggleTheme = toggleTheme; | |
| window.showSection = showSection; | |
| window.searchRides = searchRides; | |
| window.offerRide = offerRide; |