diff --git a/frontend/src/components/HUDleftPoints.jsx b/frontend/src/components/HUDleftPoints.jsx
index 96060f0..8902e64 100644
--- a/frontend/src/components/HUDleftPoints.jsx
+++ b/frontend/src/components/HUDleftPoints.jsx
@@ -444,21 +444,31 @@ function LogoBlock() {
{showSortMenu && (
-
{/* Temperature sorting */}
@@ -636,6 +646,20 @@ function LogoBlock() {
.boxwithpoints div::-webkit-scrollbar {
display: none;
}
+ .sort-menu::-webkit-scrollbar {
+ width: 8px;
+ }
+ .sort-menu::-webkit-scrollbar-track {
+ background: ${theme === 'light' ? 'rgba(0,0,0,0.1)' : 'rgba(255,255,255,0.1)'};
+ border-radius: 10px;
+ }
+ .sort-menu::-webkit-scrollbar-thumb {
+ background: ${theme === 'light' ? 'rgba(0,0,0,0.3)' : 'rgba(255,255,255,0.3)'};
+ border-radius: 10px;
+ }
+ .sort-menu::-webkit-scrollbar-thumb:hover {
+ background: ${theme === 'light' ? 'rgba(0,0,0,0.5)' : 'rgba(255,255,255,0.5)'};
+ }
`
}} />
{filteredList.map((item, index) => (
diff --git a/frontend/src/components/MapComponent.jsx b/frontend/src/components/MapComponent.jsx
index 2099a61..fa4bd95 100644
--- a/frontend/src/components/MapComponent.jsx
+++ b/frontend/src/components/MapComponent.jsx
@@ -298,13 +298,31 @@ export default function MapComponent() {
timeDifferences.push(`${diffHours}h gap`);
}
- // Create graph container
+ // Create graph container with responsive dimensions
const graphContainer = document.createElement('div');
- graphContainer.style.width = '600px';
- graphContainer.style.height = '420px';
- graphContainer.style.padding = '15px';
+ graphContainer.className = 'historical-data-container';
+
+ // Detect mobile viewport
+ const isMobile = window.innerWidth <= 768;
+ const isSmallMobile = window.innerWidth <= 480;
+
+ // Set responsive dimensions
+ if (isSmallMobile) {
+ graphContainer.style.width = '340px';
+ graphContainer.style.height = '300px';
+ graphContainer.style.padding = '8px';
+ } else if (isMobile) {
+ graphContainer.style.width = '450px';
+ graphContainer.style.height = '350px';
+ graphContainer.style.padding = '10px';
+ } else {
+ graphContainer.style.width = '600px';
+ graphContainer.style.height = '420px';
+ graphContainer.style.padding = '15px';
+ }
+
graphContainer.style.backgroundColor = window.globalTheme === 'dark' ? '#1a1a1a' : '#ffffff';
- graphContainer.style.borderRadius = '12px';
+ graphContainer.style.borderRadius = isMobile ? '8px' : '12px';
graphContainer.style.boxShadow = window.globalTheme === 'dark'
? '0 8px 32px rgba(0,0,0,0.5)'
: '0 8px 32px rgba(0,0,0,0.15)';
@@ -313,8 +331,18 @@ export default function MapComponent() {
const canvas = document.createElement('canvas');
canvas.style.width = '100%';
canvas.style.height = 'calc(100% - 40px)';
- canvas.width = 570;
- canvas.height = 380;
+
+ // Set canvas dimensions based on screen size
+ if (isSmallMobile) {
+ canvas.width = 320;
+ canvas.height = 240;
+ } else if (isMobile) {
+ canvas.width = 420;
+ canvas.height = 290;
+ } else {
+ canvas.width = 570;
+ canvas.height = 380;
+ }
graphContainer.appendChild(canvas);
console.log('Creating chart with time-based data:', timeBasedData);
@@ -346,11 +374,11 @@ export default function MapComponent() {
display: true,
text: `Historical Data for ${name}`,
font: {
- size: 18,
+ size: isSmallMobile ? 14 : (isMobile ? 16 : 18),
weight: 'bold'
},
color: window.globalTheme === 'dark' ? '#fff' : '#333',
- padding: 20
+ padding: isSmallMobile ? 10 : (isMobile ? 15 : 20)
},
legend: {
display: false
@@ -385,26 +413,35 @@ export default function MapComponent() {
type: 'linear', // Use linear instead of time to avoid adapter issues
position: 'bottom',
title: {
- display: true,
+ display: !isSmallMobile, // Hide title on very small screens
text: 'Date & Time',
color: window.globalTheme === 'dark' ? '#fff' : '#333',
font: {
- size: 14,
+ size: isSmallMobile ? 10 : (isMobile ? 12 : 14),
weight: 'bold'
}
},
ticks: {
color: window.globalTheme === 'dark' ? '#ccc' : '#666',
- maxRotation: 45,
+ maxRotation: isMobile ? 45 : 45,
font: {
- size: 10
+ size: isSmallMobile ? 8 : (isMobile ? 9 : 10)
},
- maxTicksLimit: 5, // Limit to prevent overcrowding
+ maxTicksLimit: isSmallMobile ? 3 : (isMobile ? 4 : 5), // Fewer ticks on mobile
callback: function(value) {
// The value here is the actual timestamp (milliseconds)
const date = new Date(value);
if (isNaN(date.getTime())) return ''; // Invalid date
- return date.toLocaleDateString() + ' ' + date.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
+
+ // Mobile-friendly date formatting
+ if (isSmallMobile) {
+ return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
+ } else if (isMobile) {
+ return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }) + '\n' +
+ date.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
+ } else {
+ return date.toLocaleDateString() + ' ' + date.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
+ }
}
},
grid: {
@@ -413,18 +450,18 @@ export default function MapComponent() {
},
y: {
title: {
- display: true,
+ display: !isSmallMobile, // Hide title on very small screens
text: `Temperature (°${currentUnit})`,
color: window.globalTheme === 'dark' ? '#fff' : '#333',
font: {
- size: 14,
+ size: isSmallMobile ? 10 : (isMobile ? 12 : 14),
weight: 'bold'
}
},
ticks: {
color: window.globalTheme === 'dark' ? '#ccc' : '#666',
font: {
- size: 11
+ size: isSmallMobile ? 8 : (isMobile ? 9 : 11)
},
callback: function(value) {
return `${value}°${currentUnit}`;
@@ -448,12 +485,14 @@ export default function MapComponent() {
marker.chartData = sortedData;
marker.chartContainer = graphContainer; // Store reference to the container
- // Open popup
+ // Open popup with responsive sizing
const popup = L.popup({
offset: popupOffset,
- maxWidth: 650,
- maxHeight: 470,
- className: 'custom-popup'
+ maxWidth: isSmallMobile ? 360 : (isMobile ? 480 : 650),
+ maxHeight: isSmallMobile ? 320 : (isMobile ? 370 : 470),
+ className: 'custom-popup mobile-optimized-popup',
+ autoPan: true,
+ autoPanPadding: [10, 10]
})
.setLatLng([lat, lon])
.setContent(graphContainer)
@@ -466,6 +505,25 @@ export default function MapComponent() {
console.log('Chart resized');
}
}, 100);
+
+ // Add resize handler for mobile orientation changes
+ const handleResize = () => {
+ if (chart && chart.resize) {
+ setTimeout(() => {
+ chart.resize();
+ console.log('Chart resized after orientation change');
+ }, 200);
+ }
+ };
+
+ window.addEventListener('resize', handleResize);
+ window.addEventListener('orientationchange', handleResize);
+
+ // Store cleanup function for the resize handlers
+ marker._resizeCleanup = () => {
+ window.removeEventListener('resize', handleResize);
+ window.removeEventListener('orientationchange', handleResize);
+ };
});
// Add keyboard accessibility AFTER the click handler
@@ -574,6 +632,10 @@ export default function MapComponent() {
// Clear existing markers before adding new ones
markersRef.current.forEach(({ marker }) => {
+ // Clean up resize handlers if they exist
+ if (marker._resizeCleanup) {
+ marker._resizeCleanup();
+ }
map.removeLayer(marker);
});
markersRef.current = [];
diff --git a/frontend/src/components/TempFilterModal.jsx b/frontend/src/components/TempFilterModal.jsx
index 99daf68..712267d 100644
--- a/frontend/src/components/TempFilterModal.jsx
+++ b/frontend/src/components/TempFilterModal.jsx
@@ -224,7 +224,7 @@ function TempFilterModal({
backgroundColor: theme === 'light' ? '#34c759' : '#30D158',
border: 'none',
borderRadius: '0.35rem',
- color: '#fff',
+ color: 'black',
cursor: 'pointer',
fontSize: '0.85rem',
fontWeight: '600',
diff --git a/frontend/src/styles/MapView.css b/frontend/src/styles/MapView.css
index d524fd8..6b38098 100644
--- a/frontend/src/styles/MapView.css
+++ b/frontend/src/styles/MapView.css
@@ -176,4 +176,107 @@
.temp-label[data-temp-category="hot"] {
border-left: 4px solid #ff3b30 !important;
-}
\ No newline at end of file
+
+}
+
+/* Mobile-optimized popup styles */
+.mobile-optimized-popup .leaflet-popup-content-wrapper {
+ border-radius: 8px !important;
+ overflow: hidden !important;
+}
+
+.mobile-optimized-popup .leaflet-popup-content {
+ margin: 0 !important;
+ padding: 0 !important;
+ width: auto !important;
+ height: auto !important;
+}
+
+.historical-data-container {
+ position: relative !important;
+ overflow: hidden !important;
+ box-sizing: border-box !important;
+}
+
+/* Mobile responsive adjustments */
+@media (max-width: 768px) {
+ .leaflet-popup-content-wrapper {
+ max-width: 95vw !important;
+ max-height: 70vh !important;
+ }
+
+ .mobile-optimized-popup .leaflet-popup-content-wrapper {
+ border-radius: 6px !important;
+ }
+
+ .historical-data-container {
+ min-height: 280px !important;
+ }
+
+
+ /* Adjust popup close button for mobile */
+ .leaflet-popup-close-button {
+ padding: 8px !important;
+ font-size: 18px !important;
+ width: 32px !important;
+ height: 32px !important;
+ line-height: 16px !important;
+ }
+}
+
+@media (max-width: 568px) {
+ /* Move legend further up on small mobile devices */
+ .legend {
+ top: 36% !important;
+ }
+}
+
+@media (max-width: 480px) {
+ .leaflet-popup-content-wrapper {
+ max-width: 98vw !important;
+ max-height: 60vh !important;
+ }
+
+ .mobile-optimized-popup .leaflet-popup-content-wrapper {
+ border-radius: 4px !important;
+ }
+
+ .historical-data-container {
+ min-height: 240px !important;
+ }
+
+
+
+ /* Make popup close button more touch-friendly */
+ .leaflet-popup-close-button {
+ padding: 10px !important;
+ font-size: 20px !important;
+ width: 36px !important;
+ height: 36px !important;
+ line-height: 16px !important;
+ background: rgba(0, 0, 0, 0.1) !important;
+ border-radius: 50% !important;
+ }
+
+ .leaflet-popup-close-button:hover {
+ background: rgba(0, 0, 0, 0.2) !important;
+ }
+}
+
+/* Touch-friendly chart interactions */
+@media (pointer: coarse) {
+ .historical-data-container canvas {
+ touch-action: pan-x pan-y !important;
+ }
+}
+
+/* Landscape orientation adjustments for mobile */
+@media (max-width: 768px) and (orientation: landscape) {
+ .historical-data-container {
+ max-height: 50vh !important;
+ }
+
+ .leaflet-popup-content-wrapper {
+ max-height: 60vh !important;
+ }
+}