diff --git a/frontend/src/components/MapComponent.jsx b/frontend/src/components/MapComponent.jsx index fad9cc3..4e38383 100644 --- a/frontend/src/components/MapComponent.jsx +++ b/frontend/src/components/MapComponent.jsx @@ -185,7 +185,98 @@ export default function MapComponent() { // Update the addMarkers function function addMarkers(items) { - items.forEach((item, i) => { + // First, separate user points from API points + const apiPoints = []; + const userPoints = []; + + items.forEach(item => { + if (item.isUserPoint || (!item.siteName && !item.Label)) { + userPoints.push(item); + } else { + apiPoints.push(item); + } + }); + + // Helper function to calculate distance between two points in kilometers (Haversine formula) + function calculateDistance(lat1, lon1, lat2, lon2) { + const R = 6371; // Radius of the earth in km + const dLat = (lat2 - lat1) * Math.PI / 180; + const dLon = (lon2 - lon1) * Math.PI / 180; + const a = + Math.sin(dLat/2) * Math.sin(dLat/2) + + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * + Math.sin(dLon/2) * Math.sin(dLon/2); + const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); + return R * c; // Distance in km + } + + // Group user points that are within 1km of each other + const groupedUserPoints = []; + + userPoints.forEach(point => { + const lon = point.lng || point.lon || point.Longitude; + const lat = point.lat || point.Latitude; + const timestamp = new Date(point.timestamp || point.createdAt || point.created_at).getTime(); + + // Find if this point belongs to any existing group + let foundGroup = false; + + for (const group of groupedUserPoints) { + const distance = calculateDistance(lat, lon, group.lat, group.lon); + + if (distance <= 1) { // Within 1km + foundGroup = true; + // Add this point to the group's historical points collection + if (!group.historicalPoints) { + group.historicalPoints = []; + } + + // Add this point to the historical collection + group.historicalPoints.push({ + temp: point.temp || point.Result, + timestamp: point.timestamp || point.createdAt || point.created_at + }); + + // Update the main display with the most recent point + const groupTimestamp = new Date(group.timestamp || group.createdAt || group.created_at).getTime(); + + if (!isNaN(timestamp) && !isNaN(groupTimestamp) && timestamp > groupTimestamp) { + // Update the group with this point's data but keep the group's position + group.temp = point.temp || point.Result; + group.timestamp = point.timestamp || point.createdAt || point.created_at; + } + + // Increase the count regardless + group.pointCount = (group.pointCount || 1) + 1; + break; + } + } + + // If no matching group was found, create a new one + if (!foundGroup) { + groupedUserPoints.push({ + ...point, + pointCount: 1, + historicalPoints: [{ + temp: point.temp || point.Result, + timestamp: point.timestamp || point.createdAt || point.created_at + }] + }); + } + }); + + // Add API points (these don't get grouped) + apiPoints.forEach((item, i) => { + addMarkerForItem(item, i); + }); + + // Add the grouped user points + groupedUserPoints.forEach((item, i) => { + addMarkerForItem(item, i, true); + }); + + // Function to add a marker for a single item + function addMarkerForItem(item, i, isGrouped = false) { const lon = item.lng || item.lon || item.Longitude; const lat = item.lat || item.Latitude; const t = item.temp || item.Result; @@ -210,23 +301,34 @@ export default function MapComponent() { const staleFilter = isStale ? 'backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);' : ''; + + // If this is a grouped user point, modify the marker appearance + const groupLabel = isGrouped && item.pointCount > 1 + ? `${item.pointCount}` + : ''; + + const groupStyle = isGrouped && item.pointCount > 1 + ? 'border: 2px solid #fff; transform: scale(1.1);' + : ''; const icon = L.divIcon({ className: 'custom-temp-marker', html: `
No historical data available
-Current temperature: ${formattedTemp} (${tempCategory})
+ ${ + isStale + ? `Last updated at: ${new Date(rawTime).toLocaleString()}
` + : `Current temperature: ${formattedTemp} (${tempCategory})
` + } + ${isGrouped && item.pointCount > 1 ? 'This is a group of multiple user points within 1km radius. The most recent temperature is shown.
' : ''}Not enough data to generate a graph.
+Last updated at: ${new Date(rawTime).toLocaleString()}
+