Spaces:
Build error
Build error
import { useState } from 'react'; | |
import { Search, MapPin } from 'lucide-react'; | |
interface Location { | |
id: string; | |
name: string; | |
address: string; | |
city: string; | |
state: string; | |
zip: string; | |
hours: string; | |
phone: string; | |
amenities: string[]; | |
coordinates: { | |
lat: number; | |
lng: number; | |
}; | |
} | |
const locations: Location[] = [ | |
{ | |
id: 'sf-downtown', | |
name: 'San Francisco Downtown', | |
address: '123 Market Street', | |
city: 'San Francisco', | |
state: 'CA', | |
zip: '94105', | |
hours: 'Mon-Sun: 7am-10pm', | |
phone: '(415) 555-1234', | |
amenities: ['Tesla Superchargers', 'Waiting Lounge', 'Accessories Shop', 'Restrooms'], | |
coordinates: { | |
lat: 37.7749, | |
lng: -122.4194, | |
}, | |
}, | |
{ | |
id: 'la-century', | |
name: 'Los Angeles Century City', | |
address: '1888 Century Park East', | |
city: 'Los Angeles', | |
state: 'CA', | |
zip: '90067', | |
hours: 'Mon-Sun: 8am-9pm', | |
phone: '(310) 555-6789', | |
amenities: ['Tesla Superchargers', 'Waiting Lounge', 'Car Wash', 'Restrooms'], | |
coordinates: { | |
lat: 34.0522, | |
lng: -118.2437, | |
}, | |
}, | |
{ | |
id: 'nyc-manhattan', | |
name: 'New York - Manhattan', | |
address: '347 West 34th Street', | |
city: 'New York', | |
state: 'NY', | |
zip: '10001', | |
hours: 'Mon-Sun: 9am-8pm', | |
phone: '(212) 555-8901', | |
amenities: ['Tesla Superchargers', 'Waiting Lounge', 'Accessories Shop', 'Coffee Bar'], | |
coordinates: { | |
lat: 40.7128, | |
lng: -74.006, | |
}, | |
}, | |
{ | |
id: 'miami-beach', | |
name: 'Miami Beach', | |
address: '1100 Collins Avenue', | |
city: 'Miami Beach', | |
state: 'FL', | |
zip: '33139', | |
hours: 'Mon-Sun: 8am-10pm', | |
phone: '(305) 555-2345', | |
amenities: ['Tesla Superchargers', 'Waiting Lounge', 'Car Wash', 'Coffee Bar', 'Restrooms'], | |
coordinates: { | |
lat: 25.7617, | |
lng: -80.1918, | |
}, | |
}, | |
{ | |
id: 'chicago-loop', | |
name: 'Chicago - The Loop', | |
address: '333 South Wabash Avenue', | |
city: 'Chicago', | |
state: 'IL', | |
zip: '60604', | |
hours: 'Mon-Sun: 7am-9pm', | |
phone: '(312) 555-3456', | |
amenities: ['Tesla Superchargers', 'Waiting Lounge', 'Restrooms'], | |
coordinates: { | |
lat: 41.8781, | |
lng: -87.6298, | |
}, | |
}, | |
{ | |
id: 'seattle-downtown', | |
name: 'Seattle Downtown', | |
address: '500 Pine Street', | |
city: 'Seattle', | |
state: 'WA', | |
zip: '98101', | |
hours: 'Mon-Sun: 7am-8pm', | |
phone: '(206) 555-4567', | |
amenities: ['Tesla Superchargers', 'Waiting Lounge', 'Accessories Shop', 'Restrooms'], | |
coordinates: { | |
lat: 47.6062, | |
lng: -122.3321, | |
}, | |
}, | |
]; | |
const cities = ['All Cities', 'San Francisco', 'Los Angeles', 'New York', 'Miami Beach', 'Chicago', 'Seattle']; | |
const LocationsPage = () => { | |
const [searchQuery, setSearchQuery] = useState(''); | |
const [selectedCity, setSelectedCity] = useState('All Cities'); | |
const [selectedLocation, setSelectedLocation] = useState<Location | null>(null); | |
const filteredLocations = locations.filter((location) => { | |
const matchesSearch = searchQuery === '' || | |
location.name.toLowerCase().includes(searchQuery.toLowerCase()) || | |
location.address.toLowerCase().includes(searchQuery.toLowerCase()) || | |
location.city.toLowerCase().includes(searchQuery.toLowerCase()) || | |
location.state.toLowerCase().includes(searchQuery.toLowerCase()) || | |
location.zip.toLowerCase().includes(searchQuery.toLowerCase()); | |
const matchesCity = selectedCity === 'All Cities' || location.city === selectedCity; | |
return matchesSearch && matchesCity; | |
}); | |
const handleLocationClick = (location: Location) => { | |
setSelectedLocation(location); | |
}; | |
return ( | |
<div className="bg-[#0a0a0a] text-white min-h-screen"> | |
<div className="container mx-auto px-4 py-12"> | |
{/* Header */} | |
<div className="max-w-3xl mx-auto text-center mb-12"> | |
<h1 className="text-4xl md:text-5xl font-bold mb-4">Our Locations</h1> | |
<p className="text-gray-300 text-lg"> | |
Find the nearest pickup and dropoff location for your electric vehicle rental. | |
</p> | |
</div> | |
{/* Search and Filter */} | |
<div className="mb-8"> | |
<div className="flex flex-col md:flex-row gap-4 mb-4"> | |
<div className="relative flex-1"> | |
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> | |
<Search className="h-5 w-5 text-gray-400" /> | |
</div> | |
<input | |
type="text" | |
placeholder="Search by location name, address, or zip code" | |
className="block w-full pl-10 pr-3 py-3 bg-[#161617] border border-gray-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-transparent text-white" | |
value={searchQuery} | |
onChange={(e) => setSearchQuery(e.target.value)} | |
/> | |
</div> | |
<select | |
value={selectedCity} | |
onChange={(e) => setSelectedCity(e.target.value)} | |
className="bg-[#161617] border border-gray-700 text-white rounded-md py-3 px-4 appearance-none md:max-w-xs focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-transparent" | |
> | |
{cities.map((city) => ( | |
<option key={city} value={city}> | |
{city} | |
</option> | |
))} | |
</select> | |
</div> | |
</div> | |
{/* Main Content */} | |
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6"> | |
{/* Locations List */} | |
<div className="lg:col-span-1"> | |
<div className="bg-[#161617] rounded-lg overflow-hidden border border-gray-800"> | |
<div className="p-4 border-b border-gray-800"> | |
<h3 className="font-medium">{filteredLocations.length} {filteredLocations.length === 1 ? 'Location' : 'Locations'} Found</h3> | |
</div> | |
<div className="divide-y divide-gray-800 max-h-[600px] overflow-y-auto"> | |
{filteredLocations.length > 0 ? ( | |
filteredLocations.map((location) => ( | |
<button | |
key={location.id} | |
onClick={() => handleLocationClick(location)} | |
className={`w-full px-4 py-3 flex items-start text-left transition-colors hover:bg-gray-800 ${ | |
selectedLocation?.id === location.id ? 'bg-gray-800' : '' | |
}`} | |
> | |
<MapPin className="h-5 w-5 text-blue-500 flex-shrink-0 mt-0.5 mr-3" /> | |
<div> | |
<h4 className="font-medium">{location.name}</h4> | |
<p className="text-gray-400 text-sm">{location.address}, {location.city}, {location.state} {location.zip}</p> | |
<p className="text-gray-500 text-xs mt-1">{location.hours}</p> | |
</div> | |
</button> | |
)) | |
) : ( | |
<div className="p-6 text-center"> | |
<p className="text-gray-400">No locations found matching your search criteria.</p> | |
</div> | |
)} | |
</div> | |
</div> | |
</div> | |
{/* Map and Location Details */} | |
<div className="lg:col-span-2"> | |
{selectedLocation ? ( | |
<div className="grid grid-cols-1 gap-6"> | |
{/* Map Placeholder */} | |
<div className="bg-[#161617] rounded-lg overflow-hidden border border-gray-800 h-[300px] flex items-center justify-center"> | |
<div className="text-center px-4"> | |
<p className="text-gray-400 mb-2">Interactive map would be displayed here with location:</p> | |
<p className="font-medium">{selectedLocation.name}</p> | |
<p className="text-sm text-gray-500">Coordinates: {selectedLocation.coordinates.lat}, {selectedLocation.coordinates.lng}</p> | |
</div> | |
</div> | |
{/* Location Details */} | |
<div className="bg-[#161617] rounded-lg overflow-hidden border border-gray-800"> | |
<div className="p-5 border-b border-gray-800"> | |
<h3 className="text-xl font-bold">{selectedLocation.name}</h3> | |
<p className="text-gray-400 mt-1">{selectedLocation.address}, {selectedLocation.city}, {selectedLocation.state} {selectedLocation.zip}</p> | |
</div> | |
<div className="p-5 grid grid-cols-1 md:grid-cols-2 gap-6"> | |
<div> | |
<h4 className="text-lg font-medium mb-3">Hours & Contact</h4> | |
<div className="space-y-3"> | |
<div> | |
<p className="text-gray-400 text-sm">Hours</p> | |
<p>{selectedLocation.hours}</p> | |
</div> | |
<div> | |
<p className="text-gray-400 text-sm">Phone</p> | |
<p>{selectedLocation.phone}</p> | |
</div> | |
</div> | |
</div> | |
<div> | |
<h4 className="text-lg font-medium mb-3">Amenities</h4> | |
<ul className="space-y-2"> | |
{selectedLocation.amenities.map((amenity, index) => ( | |
<li key={index} className="flex items-center gap-2"> | |
<div className="h-2 w-2 rounded-full bg-blue-500"></div> | |
<span>{amenity}</span> | |
</li> | |
))} | |
</ul> | |
</div> | |
</div> | |
<div className="p-5 bg-[#1c1c1e] border-t border-gray-800"> | |
<button className="bg-blue-600 hover:bg-blue-700 text-white font-medium px-4 py-2 rounded-md transition-colors"> | |
Book a Vehicle at This Location | |
</button> | |
</div> | |
</div> | |
</div> | |
) : ( | |
<div className="bg-[#161617] rounded-lg border border-gray-800 h-full flex items-center justify-center p-10"> | |
<div className="text-center max-w-md"> | |
<MapPin className="h-12 w-12 text-blue-500 mb-4 mx-auto" /> | |
<h3 className="text-xl font-bold mb-2">Select a Location</h3> | |
<p className="text-gray-400"> | |
Choose a location from the list to view details and availability information. | |
</p> | |
</div> | |
</div> | |
)} | |
</div> | |
</div> | |
</div> | |
</div> | |
); | |
}; | |
export default LocationsPage; | |