import L from 'leaflet'; import markerIcon2x from 'leaflet/dist/images/marker-icon-2x.png'; import markerIcon from 'leaflet/dist/images/marker-icon.png'; import markerShadow from 'leaflet/dist/images/marker-shadow.png'; delete L.Icon.Default.prototype._getIconUrl; L.Icon.Default.mergeOptions({ iconUrl: markerIcon, iconRetinaUrl: markerIcon2x, shadowUrl: markerShadow, }); const CLASSIFICATION_COLOURS = { current: '#22c55e', recent: '#64748b', stale: '#f59e0b', outdated: '#ef4444', }; const UK_CENTRE = [54.0, -2.0]; const UK_ZOOM = 6; export function stationMap(results, meta) { return { results, meta, _map: null, _markers: [], init() { this._map = L.map(this.$el, { zoomControl: true }).setView(UK_CENTRE, UK_ZOOM); L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors', maxZoom: 19, }).addTo(this._map); if (this.results && this.results.length > 0) { this._plotMarkers(); } this.$watch('results', () => this._plotMarkers()); }, _clearMarkers() { this._markers.forEach((m) => m.remove()); this._markers = []; }, _plotMarkers() { this._clearMarkers(); if (!this.results || this.results.length === 0) { return; } const bounds = []; this.results.forEach((station) => { const colour = CLASSIFICATION_COLOURS[station.price_classification] ?? '#64748b'; const miles = (station.distance_km * 0.621371).toFixed(1); const supermarketTag = station.is_supermarket ? 'Supermarket' : ''; const popup = `
${station.name}${supermarketTag}
${Number(station.price).toFixed(1)}p
${miles} miles away
${station.address}, ${station.postcode}
`; const marker = L.circleMarker([station.lat, station.lng], { radius: 9, fillColor: colour, color: '#ffffff', weight: 2, opacity: 1, fillOpacity: 0.85, }).bindPopup(popup); marker.addTo(this._map); this._markers.push(marker); bounds.push([station.lat, station.lng]); }); this._map.fitBounds(bounds, { padding: [40, 40], maxZoom: 14 }); }, }; }