Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>StoreSpotter - Find Our Locations</title> | |
| <link rel="icon" type="image/x-icon" href="/static/favicon.ico"> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://unpkg.com/feather-icons"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> | |
| <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" /> | |
| <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> | |
| <style> | |
| .map-container { | |
| height: 70vh; | |
| border-radius: 1rem; | |
| overflow: hidden; | |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); | |
| } | |
| .leaflet-popup-content-wrapper { | |
| border-radius: 0.5rem ; | |
| padding: 0.5rem ; | |
| } | |
| .leaflet-popup-content { | |
| margin: 0.5rem ; | |
| } | |
| .leaflet-control { | |
| margin-right: 0 ; | |
| margin-bottom: 0 ; | |
| } | |
| .custom-marker { | |
| background-color: #3B82F6; | |
| width: 20px; | |
| height: 20px; | |
| border-radius: 50%; | |
| border: 3px solid white; | |
| } | |
| .user-marker { | |
| background-color: #10B981; | |
| width: 20px; | |
| height: 20px; | |
| border-radius: 50%; | |
| border: 3px solid white; | |
| animation: pulse 2s infinite; | |
| } | |
| @keyframes pulse { | |
| 0% { | |
| transform: scale(0.95); | |
| box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.7); | |
| } | |
| 70% { | |
| transform: scale(1); | |
| box-shadow: 0 0 0 10px rgba(16, 185, 129, 0); | |
| } | |
| 100% { | |
| transform: scale(0.95); | |
| box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50"> | |
| <!-- Navigation --> | |
| <nav class="bg-white shadow-sm"> | |
| <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"> | |
| <i data-feather="map-pin" class="text-blue-500"></i> | |
| <span class="ml-2 text-xl font-bold text-gray-800">StoreSpotter</span> | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| <a href="#" class="text-gray-700 hover:text-blue-600">Home</a> | |
| <a href="#" class="text-gray-700 hover:text-blue-600">Stores</a> | |
| <a href="#" class="text-gray-700 hover:text-blue-600">About</a> | |
| <button class="bg-blue-500 text-white px-4 py-2 rounded-lg hover:bg-blue-600 transition">Contact</button> | |
| </div> | |
| </div> | |
| </div> | |
| </nav> | |
| <!-- Hero Section --> | |
| <div class="relative bg-gradient-to-r from-blue-500 to-blue-600 text-white py-16"> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
| <div class="text-center"> | |
| <h1 class="text-4xl font-bold mb-4">Find Our Stores Near You</h1> | |
| <p class="text-xl mb-8">Discover the closest StoreSpotter locations with real-time distance calculation</p> | |
| <div class="max-w-md mx-auto relative"> | |
| <input type="text" placeholder="Enter your location" class="w-full px-4 py-3 rounded-lg text-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-300"> | |
| <button class="absolute right-2 top-2 bg-blue-600 text-white p-2 rounded-lg hover:bg-blue-700 transition"> | |
| <i data-feather="search"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Main Content --> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12"> | |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-8"> | |
| <!-- Store List --> | |
| <div class="bg-white rounded-xl shadow-md overflow-hidden lg:col-span-1"> | |
| <div class="p-6"> | |
| <h2 class="text-2xl font-bold text-gray-800 mb-6">Our Stores</h2> | |
| <div class="space-y-4 max-h-[500px] overflow-y-auto pr-2"> | |
| <!-- Store Item 1 --> | |
| <div class="border-b pb-4"> | |
| <div class="flex items-start"> | |
| <div class="bg-blue-100 p-3 rounded-lg mr-4"> | |
| <i data-feather="shopping-bag" class="text-blue-600"></i> | |
| </div> | |
| <div> | |
| <h3 class="font-bold text-gray-800">Main Headquarters</h3> | |
| <p class="text-gray-600">123 Business St, District 1</p> | |
| <p class="text-sm text-gray-500">Open: 8AM - 10PM</p> | |
| <p class="text-blue-500 font-medium mt-1">0.8 km away</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Store Item 2 --> | |
| <div class="border-b pb-4"> | |
| <div class="flex items-start"> | |
| <div class="bg-blue-100 p-3 rounded-lg mr-4"> | |
| <i data-feather="shopping-bag" class="text-blue-600"></i> | |
| </div> | |
| <div> | |
| <h3 class="font-bold text-gray-800">Westside Branch</h3> | |
| <p class="text-gray-600">456 Shopping Ave, District 2</p> | |
| <p class="text-sm text-gray-500">Open: 9AM - 9PM</p> | |
| <p class="text-blue-500 font-medium mt-1">2.3 km away</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Store Item 3 --> | |
| <div class="border-b pb-4"> | |
| <div class="flex items-start"> | |
| <div class="bg-blue-100 p-3 rounded-lg mr-4"> | |
| <i data-feather="shopping-bag" class="text-blue-600"></i> | |
| </div> | |
| <div> | |
| <h3 class="font-bold text-gray-800">Downtown Store</h3> | |
| <p class="text-gray-600">789 Central Blvd, District 3</p> | |
| <p class="text-sm text-gray-500">Open: 7AM - 11PM</p> | |
| <p class="text-blue-500 font-medium mt-1">1.5 km away</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Store Item 4 --> | |
| <div class="border-b pb-4"> | |
| <div class="flex items-start"> | |
| <div class="bg-blue-100 p-3 rounded-lg mr-4"> | |
| <i data-feather="shopping-bag" class="text-blue-600"></i> | |
| </div> | |
| <div> | |
| <h3 class="font-bold text-gray-800">Northside Plaza</h3> | |
| <p class="text-gray-600">321 Market St, District 4</p> | |
| <p class="text-sm text-gray-500">Open: 8AM - 10PM</p> | |
| <p class="text-blue-500 font-medium mt-1">3.2 km away</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Store Item 5 --> | |
| <div class="pb-4"> | |
| <div class="flex items-start"> | |
| <div class="bg-blue-100 p-3 rounded-lg mr-4"> | |
| <i data-feather="shopping-bag" class="text-blue-600"></i> | |
| </div> | |
| <div> | |
| <h3 class="font-bold text-gray-800">Riverside Outlet</h3> | |
| <p class="text-gray-600">654 Waterfront Rd, District 5</p> | |
| <p class="text-sm text-gray-500">Open: 10AM - 8PM</p> | |
| <p class="text-blue-500 font-medium mt-1">5.7 km away</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Map Container --> | |
| <div class="lg:col-span-2"> | |
| <div class="map-container" id="map"></div> | |
| <div class="mt-4 flex flex-wrap gap-2"> | |
| <button class="bg-blue-500 text-white px-4 py-2 rounded-lg hover:bg-blue-600 transition flex items-center"> | |
| <i data-feather="navigation" class="mr-2"></i> Get Directions | |
| </button> | |
| <button class="bg-gray-100 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-200 transition flex items-center"> | |
| <i data-feather="list" class="mr-2"></i> View All Stores | |
| </button> | |
| <button class="bg-gray-100 text-gray-700 px-4 py-2 rounded-lg hover:bg-gray-200 transition flex items-center"> | |
| <i data-feather="filter" class="mr-2"></i> Filter | |
| </button> | |
| <button id="locate-me" class="bg-green-500 text-white px-4 py-2 rounded-lg hover:bg-green-600 transition flex items-center ml-auto"> | |
| <i data-feather="target" class="mr-2"></i> Locate Me | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Footer --> | |
| <footer class="bg-gray-800 text-white py-12"> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
| <div class="grid grid-cols-1 md:grid-cols-4 gap-8"> | |
| <div> | |
| <h3 class="text-xl font-bold mb-4">StoreSpotter</h3> | |
| <p class="text-gray-400">Finding your way to our stores since 2023</p> | |
| </div> | |
| <div> | |
| <h4 class="font-bold mb-4">Quick Links</h4> | |
| <ul class="space-y-2"> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Home</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Stores</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">About Us</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Contact</a></li> | |
| </ul> | |
| </div> | |
| <div> | |
| <h4 class="font-bold mb-4">Contact</h4> | |
| <ul class="space-y-2"> | |
| <li class="flex items-center text-gray-400"><i data-feather="mail" class="mr-2"></i> hello@storespotter.com</li> | |
| <li class="flex items-center text-gray-400"><i data-feather="phone" class="mr-2"></i> +123 456 7890</li> | |
| <li class="flex items-center text-gray-400"><i data-feather="map-pin" class="mr-2"></i> 123 Business St, City</li> | |
| </ul> | |
| </div> | |
| <div> | |
| <h4 class="font-bold mb-4">Follow Us</h4> | |
| <div class="flex space-x-4"> | |
| <a href="#" class="text-gray-400 hover:text-white transition"><i data-feather="facebook"></i></a> | |
| <a href="#" class="text-gray-400 hover:text-white transition"><i data-feather="twitter"></i></a> | |
| <a href="#" class="text-gray-400 hover:text-white transition"><i data-feather="instagram"></i></a> | |
| <a href="#" class="text-gray-400 hover:text-white transition"><i data-feather="linkedin"></i></a> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="border-t border-gray-700 mt-8 pt-8 text-center text-gray-400"> | |
| <p>© 2023 StoreSpotter. All rights reserved.</p> | |
| </div> | |
| </div> | |
| </footer> | |
| <script> | |
| // Initialize Leaflet map | |
| const map = L.map('map').setView([10.776888, 106.699992], 12); | |
| // Add OpenStreetMap tiles | |
| L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { | |
| attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' | |
| }).addTo(map); | |
| // Add store markers | |
| const stores = [ | |
| { | |
| name: "Main Headquarters", | |
| address: "123 Business St, District 1", | |
| hours: "8AM - 10PM", | |
| coordinates: [10.778110, 106.704980] | |
| }, | |
| { | |
| name: "Westside Branch", | |
| address: "456 Shopping Ave, District 2", | |
| hours: "9AM - 9PM", | |
| coordinates: [10.787870, 106.732470] | |
| }, | |
| { | |
| name: "Downtown Store", | |
| address: "789 Central Blvd, District 3", | |
| hours: "7AM - 11PM", | |
| coordinates: [10.782790, 106.691240] | |
| }, | |
| { | |
| name: "Northside Plaza", | |
| address: "321 Market St, District 4", | |
| hours: "8AM - 10PM", | |
| coordinates: [10.763380, 106.706990] | |
| }, | |
| { | |
| name: "Riverside Outlet", | |
| address: "654 Waterfront Rd, District 5", | |
| hours: "10AM - 8PM", | |
| coordinates: [10.755430, 106.680520] | |
| } | |
| ]; | |
| const storeIcon = L.divIcon({ | |
| className: 'custom-marker', | |
| iconSize: [20, 20] | |
| }); | |
| stores.forEach(store => { | |
| const marker = L.marker(store.coordinates, { icon: storeIcon }) | |
| .addTo(map) | |
| .bindPopup(` | |
| <div class="font-bold">${store.name}</div> | |
| <div class="text-gray-600">${store.address}</div> | |
| <div class="text-sm text-gray-500">Hours: ${store.hours}</div> | |
| <button class="mt-2 text-sm text-blue-500 hover:underline">Get Directions</button> | |
| `); | |
| }); | |
| // Locate me button functionality | |
| document.getElementById('locate-me').addEventListener('click', () => { | |
| if (navigator.geolocation) { | |
| navigator.geolocation.getCurrentPosition( | |
| position => { | |
| const userLocation = [position.coords.latitude, position.coords.longitude]; | |
| // Remove existing user marker if any | |
| if (window.userMarker) { | |
| map.removeLayer(window.userMarker); | |
| } | |
| // Create user marker | |
| const userIcon = L.divIcon({ | |
| className: 'user-marker', | |
| iconSize: [20, 20] | |
| }); | |
| // Add user marker to map | |
| window.userMarker = L.marker(userLocation, { icon: userIcon }) | |
| .addTo(map) | |
| .bindPopup(` | |
| <div class="font-bold">Your Location</div> | |
| <div class="text-sm text-gray-600">Accuracy: ${position.coords.accuracy.toFixed(0)} meters</div> | |
| `) | |
| .openPopup(); | |
| // Center map on user location | |
| map.flyTo(userLocation, 14); | |
| }, | |
| error => { | |
| alert('Unable to retrieve your location: ' + error.message); | |
| }, | |
| { | |
| enableHighAccuracy: true | |
| } | |
| ); | |
| } else { | |
| alert('Geolocation is not supported by your browser'); | |
| } | |
| }); | |
| // Initialize feather icons | |
| feather.replace(); | |
| </script> | |
| </body> | |
| </html> | |