158 lines
5.1 KiB
JavaScript
158 lines
5.1 KiB
JavaScript
import React, { useEffect, useRef } from 'react';
|
|
import { MapContainer, TileLayer, Marker, Polyline, Tooltip } from 'react-leaflet';
|
|
import L from 'leaflet';
|
|
import 'leaflet/dist/leaflet.css';
|
|
import dayjs from 'dayjs';
|
|
import { Badge } from '@astryxdesign/core/Badge';
|
|
import { HStack } from '@astryxdesign/core/HStack';
|
|
import { Text } from '@astryxdesign/core/Text';
|
|
import { IconButton } from '@astryxdesign/core/IconButton';
|
|
import { CloseCircleOutlined } from '@ant-design/icons';
|
|
|
|
import logger from 'utils/logger';
|
|
var utc = require('dayjs/plugin/utc');
|
|
dayjs.extend(utc);
|
|
|
|
// Define custom icon for start and end markers
|
|
const startIcon = new L.Icon({
|
|
iconUrl: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-green.png',
|
|
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png',
|
|
iconSize: [25, 41],
|
|
iconAnchor: [12, 41],
|
|
popupAnchor: [1, -34],
|
|
shadowSize: [41, 41]
|
|
});
|
|
|
|
const endIcon = new L.Icon({
|
|
iconUrl: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png',
|
|
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png',
|
|
iconSize: [25, 41],
|
|
iconAnchor: [12, 41],
|
|
popupAnchor: [1, -34],
|
|
shadowSize: [41, 41]
|
|
});
|
|
|
|
const MapWithRoute = ({ coordinates, additionalProps, order, setMapOpen }) => {
|
|
logger.info('setMapOpen:', typeof setMapOpen);
|
|
logger.info('coordinates', coordinates);
|
|
logger.info(additionalProps.riderStart);
|
|
logger.info(additionalProps.riderEnd);
|
|
logger.info('order', order);
|
|
const mapRef = useRef(null);
|
|
|
|
useEffect(() => {
|
|
if (mapRef.current && coordinates.length > 0) {
|
|
const bounds = calculateBounds(coordinates);
|
|
mapRef.current.fitBounds(bounds);
|
|
}
|
|
}, [coordinates]);
|
|
|
|
const calculateBounds = (coords) => {
|
|
const latitudes = coords.map((coord) => coord.lat);
|
|
const longitudes = coords.map((coord) => coord.lng);
|
|
const minLat = Math.min(...latitudes);
|
|
const maxLat = Math.max(...latitudes);
|
|
const minLng = Math.min(...longitudes);
|
|
const maxLng = Math.max(...longitudes);
|
|
return [
|
|
[minLat, minLng],
|
|
[maxLat, maxLng]
|
|
];
|
|
};
|
|
|
|
const dottedOptions = { color: 'blue', weight: 8, dashArray: '4 4' };
|
|
const length = coordinates.length;
|
|
const midlenght = Math.round(coordinates.length / 2);
|
|
const start = coordinates[0];
|
|
const end = coordinates[length - 1];
|
|
const center = coordinates[midlenght];
|
|
|
|
const showList = (primary, secondary) => {
|
|
return (
|
|
<HStack gap={1} vAlign="center">
|
|
<Text type="strong" style={{ fontSize: 13 }}>
|
|
{primary}:
|
|
</Text>
|
|
<Badge label={secondary || 'N/A'} variant="info" />
|
|
</HStack>
|
|
);
|
|
};
|
|
|
|
return (
|
|
coordinates &&
|
|
coordinates.length > 0 && (
|
|
<div
|
|
id="map"
|
|
style={{
|
|
width: '100%',
|
|
height: '90vh',
|
|
margin: '0 auto',
|
|
position: 'relative'
|
|
}}
|
|
>
|
|
<IconButton
|
|
label="Close"
|
|
icon={<CloseCircleOutlined />}
|
|
variant="primary"
|
|
onClick={() => setMapOpen(false)}
|
|
style={{ position: 'absolute', top: 8, right: 8, zIndex: 1000 }}
|
|
/>
|
|
|
|
{/* Overlay */}
|
|
<HStack
|
|
gap={2}
|
|
wrap="wrap"
|
|
vAlign="center"
|
|
justify="start"
|
|
style={{
|
|
position: 'absolute',
|
|
bottom: 0,
|
|
zIndex: 1000,
|
|
left: 0,
|
|
right: 0,
|
|
padding: '8px 16px',
|
|
backgroundColor: 'rgba(255, 255, 255, 0.95)',
|
|
maxWidth: '100%',
|
|
width: 'auto',
|
|
boxShadow: 'var(--shadow-md)'
|
|
}}
|
|
>
|
|
{showList('Tenant', order?.tenantname)}
|
|
{showList('Rider', order?.ridername)}
|
|
{showList('Pickup', order?.pickupcustomer)}
|
|
{showList('Drop', order?.deliverycustomer)}
|
|
{showList('Kms', order?.kms)}
|
|
{showList('Actual kms', order?.actualkms)}
|
|
{showList('Rider kms', order?.riderkms)}
|
|
</HStack>
|
|
|
|
{/* Map */}
|
|
<MapContainer center={center} zoom={15} scrollWheelZoom={false} style={{ height: '100%', width: '100%' }} ref={mapRef}>
|
|
<TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
|
|
<Marker position={start} icon={startIcon}>
|
|
<Tooltip direction="bottom">
|
|
<span>
|
|
{`Pickup Point: ${dayjs(additionalProps.riderStart).utc().format('DD-MM-YYYY')} (${dayjs(additionalProps.riderStart)
|
|
.utc()
|
|
.format('hh:mm A')})`}
|
|
</span>
|
|
</Tooltip>
|
|
</Marker>
|
|
<Marker position={end} icon={endIcon}>
|
|
<Tooltip direction="bottom">
|
|
<span>
|
|
{`Drop Point: ${dayjs(additionalProps.riderEnd).utc().format('DD-MM-YYYY')} (${dayjs(additionalProps.riderEnd)
|
|
.utc()
|
|
.format('hh:mm A')})`}
|
|
</span>
|
|
</Tooltip>
|
|
</Marker>
|
|
<Polyline pathOptions={dottedOptions} positions={coordinates} />
|
|
</MapContainer>
|
|
</div>
|
|
)
|
|
);
|
|
};
|
|
|
|
export default MapWithRoute;
|