feat: Add MapComponent for displaying location on a map and TrackingPage for tracking shipments
This commit is contained in:
68
components/MapComponent.js
Normal file
68
components/MapComponent.js
Normal file
@@ -0,0 +1,68 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
const MapComponent = ({ latitude, longitude, name, description, officeType }) => {
|
||||
const [mapLoaded, setMapLoaded] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// Load Leaflet on client-side only
|
||||
if (typeof window !== 'undefined' && latitude && longitude) {
|
||||
// Import Leaflet dynamically
|
||||
import('leaflet').then((L) => {
|
||||
// Safety check to see if map element exists
|
||||
const mapElement = document.getElementById('map');
|
||||
if (!mapElement) return;
|
||||
|
||||
// Clean up any existing map instance
|
||||
if (mapElement._leaflet_map) {
|
||||
mapElement._leaflet_map.remove();
|
||||
}
|
||||
|
||||
// Initialize map
|
||||
const map = L.map('map').setView([latitude, longitude], 15);
|
||||
|
||||
// Store the map instance on the DOM element to clean up later
|
||||
mapElement._leaflet_map = map;
|
||||
|
||||
// Add OpenStreetMap tiles
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© OpenStreetMap contributors',
|
||||
maxZoom: 19
|
||||
}).addTo(map);
|
||||
|
||||
// Add marker for post office
|
||||
const marker = L.marker([latitude, longitude])
|
||||
.addTo(map)
|
||||
.bindPopup(`
|
||||
<div style="font-family: 'Segoe UI', sans-serif;">
|
||||
<h4 style="margin: 0 0 8px 0; color: #004d99;">${name}</h4>
|
||||
<p style="margin: 4px 0;"><strong>📍 Adres:</strong><br>${description.street} ${description.houseNumber}<br>${description.zipCode} ${description.city}</p>
|
||||
<p style="margin: 4px 0;"><strong>🏢 Typ:</strong> ${officeType === 'UP' ? 'Urząd Pocztowy' : officeType}</p>
|
||||
</div>
|
||||
`, {
|
||||
maxWidth: 300
|
||||
});
|
||||
|
||||
// Open popup by default
|
||||
marker.openPopup();
|
||||
|
||||
// Make sure map renders correctly
|
||||
setTimeout(() => {
|
||||
map.invalidateSize();
|
||||
setMapLoaded(true);
|
||||
}, 300);
|
||||
});
|
||||
}
|
||||
|
||||
// Clean up function
|
||||
return () => {
|
||||
const mapElement = document.getElementById('map');
|
||||
if (mapElement && mapElement._leaflet_map) {
|
||||
mapElement._leaflet_map.remove();
|
||||
}
|
||||
};
|
||||
}, [latitude, longitude, name, description, officeType]);
|
||||
|
||||
return <div id="map" style={{ height: '400px', borderRadius: '8px' }}></div>;
|
||||
};
|
||||
|
||||
export default MapComponent;
|
||||
@@ -10,13 +10,15 @@ import {
|
||||
Bars3Icon as MenuIcon,
|
||||
XMarkIcon as XIcon,
|
||||
UserIcon,
|
||||
ArrowRightOnRectangleIcon as LogoutIcon
|
||||
ArrowRightOnRectangleIcon as LogoutIcon,
|
||||
TruckIcon
|
||||
} from '@heroicons/react/24/outline';
|
||||
|
||||
const navigationItems = [
|
||||
{ name: 'Przekrój terenu', href: '/', icon: HomeIcon },
|
||||
{ name: 'Siatka', href: '/cross', icon: GridIcon },
|
||||
{ name: 'Uziomy', href: '/uziomy', icon: LightningBoltIcon },
|
||||
{ name: 'Śledzenie przesyłek', href: '/tracking', icon: TruckIcon },
|
||||
];
|
||||
|
||||
export default function Layout({ children, title = 'Wastpol' }) {
|
||||
|
||||
Reference in New Issue
Block a user