+
Configure radius for geofence
)),
)}
- {!_.isEmpty(props.polygon) && (
+ {!_.isEmpty(polygon) && (
)}
- )),
-);
+ );
+};
export default MapComponent;
diff --git a/src/index.html b/src/index.html
index f3c877dab..e4d9ed843 100644
--- a/src/index.html
+++ b/src/index.html
@@ -4,6 +4,9 @@
+
+
+
{
const location = useLocation();
const theme = useTheme();
const organization = getUser().organization.organization_uuid;
+ const { options: tzOptions } = useTimezoneSelect({ labelStyle: 'original', timezones: allTimezones });
const [locShipmentID, setLocShipmentID] = useState('');
const [shipmentFilter, setShipmentFilter] = useState('Active');
@@ -250,8 +254,8 @@ const Reporting = () => {
}, [selectedShipment, markers, allGraphs, reports]);
const getShipmentValue = (value) => {
- let returnValue;
- if (selectedShipment[value] !== null) {
+ let returnValue = '';
+ if (!_.isEqual(selectedShipment[value], null)) {
if (moment(selectedShipment[value], true).isValid()) {
returnValue = moment(selectedShipment[value])
.tz(timeZone).format(`${dateFormat} ${timeFormat}`);
@@ -265,7 +269,7 @@ const Reporting = () => {
}
}
} else {
- returnValue = 'NA';
+ returnValue = 'N/A';
}
return returnValue;
};
@@ -302,7 +306,8 @@ const Reporting = () => {
if (col.label === 'Date Time') {
const timeArray = _.split(timeFormat, ' ');
const timePeriod = _.size(timeArray) === 1 ? '24-hour' : '12-hour';
- const formattedLabel = `${col.label} (${getTimezone(new Date(), timeZone)}) (${dateFormat} ${timePeriod})`;
+ const filteredTimeZone = _.find(tzOptions, (option) => option.value === timeZone);
+ const formattedLabel = `${col.label} (${filteredTimeZone.abbrev}) (${dateFormat} ${timePeriod})`;
return escapeCSV(formattedLabel);
}
if (col.name === 'temperature') {
@@ -315,24 +320,31 @@ const Reporting = () => {
}).join(',');
const dateTimeColumnIndex = columns.findIndex((col) => col.label === 'Date Time');
- const departureTime = moment(selectedShipment.actual_time_of_departure).unix();
- const arrivalTime = moment(selectedShipment.actual_time_of_arrival).unix();
+ const departureTime = moment(selectedShipment.actual_time_of_departure).tz(timeZone).format(`${dateFormat} ${timeFormat}`);
+ const arrivalTime = moment(selectedShipment.actual_time_of_arrival).isValid()
+ ? moment(selectedShipment.actual_time_of_arrival).tz(timeZone).format(`${dateFormat} ${timeFormat}`)
+ : null;
+ const formattedDepartureTime = moment(departureTime).unix();
+ const formattedArrivalTime = arrivalTime ? moment(arrivalTime).unix() : null;
const rowsWithinTimeRange = rows.filter((row) => {
const dateTimeValue = moment(row[columns[dateTimeColumnIndex].name]).unix();
- return dateTimeValue >= departureTime && dateTimeValue <= arrivalTime;
+ if (formattedArrivalTime) {
+ return dateTimeValue >= formattedDepartureTime && dateTimeValue <= formattedArrivalTime;
+ } else {
+ return dateTimeValue >= formattedDepartureTime;
+ }
});
if (_.size(rowsWithinTimeRange) > 0) {
const firstRowIndex = rows.findIndex((row) => row === rowsWithinTimeRange[0]);
const lastRowIndex = rows.findIndex((row) => row === rowsWithinTimeRange[_.size(rowsWithinTimeRange) - 1]);
- rows[firstRowIndex].allAlerts.push({ title: 'Arrived', color: '#000' });
+ if (formattedArrivalTime) {
+ rows[firstRowIndex].allAlerts.push({ title: 'Arrived', color: '#000' });
+ }
rows[lastRowIndex].allAlerts.push({ title: 'En route', color: '#000' });
}
const csvBody = rows.map((row) => columns.map((col, colIndex) => {
let cell = row[col.name];
- if (col.label === 'Date Time' && !_.isEmpty(cell)) {
- return escapeCSV(moment(cell).tz(timeZone).format(`${dateFormat} ${timeFormat}`));
- }
if (!row.location || row.location === 'Error retrieving address') {
row.location = 'N/A';
}
@@ -554,7 +566,8 @@ const Reporting = () => {
if (col.label === 'Date Time') {
const timeArray = _.split(timeFormat, ' ');
const timePeriod = _.size(timeArray) === 1 ? '24-hour' : '12-hour';
- const formattedLabel = `Date Time (${getTimezone(new Date(), timeZone)}) (${dateFormat} ${timePeriod})`;
+ const filteredTimeZone = _.find(tzOptions, (option) => option.value === timeZone);
+ const formattedLabel = `Date Time (${filteredTimeZone.abbrev}) (${dateFormat} ${timePeriod})`;
return formattedLabel;
}
if (col.name === 'battery') {
@@ -579,8 +592,12 @@ const Reporting = () => {
});
const dateTimeColIndex = columns.findIndex((col) => col.label === 'Date Time') + 1;
- const departureTime = moment(selectedShipment.actual_time_of_departure).unix();
- const arrivalTime = moment(selectedShipment.actual_time_of_arrival).unix();
+ const departureTime = moment(selectedShipment.actual_time_of_departure).tz(timeZone).format(`${dateFormat} ${timeFormat}`);
+ const arrivalTime = moment(selectedShipment.actual_time_of_arrival).isValid()
+ ? moment(selectedShipment.actual_time_of_arrival).tz(timeZone).format(`${dateFormat} ${timeFormat}`)
+ : null;
+ const formattedDepartureTime = moment(departureTime).unix();
+ const formattedArrivalTime = arrivalTime ? moment(arrivalTime).unix() : null;
const greyRows = [];
rows.forEach((row, rowIndex) => {
@@ -733,17 +750,32 @@ const Reporting = () => {
};
const dateValue = moment(row[columns[dateTimeColIndex - 1].name]).unix();
- if (dateValue >= departureTime && dateValue <= arrivalTime) {
- rowRef.eachCell((cell, colNumber) => {
- if (!cell.fill) {
- cell.fill = {
- type: 'pattern',
- pattern: 'solid',
- fgColor: { argb: theme.palette.background.light6.replace('#', '') },
- };
- }
- });
- greyRows.push(rowRef.number);
+ if (formattedArrivalTime) {
+ if (dateValue >= formattedDepartureTime && dateValue <= formattedArrivalTime) {
+ rowRef.eachCell((cell, colNumber) => {
+ if (!cell.fill) {
+ cell.fill = {
+ type: 'pattern',
+ pattern: 'solid',
+ fgColor: { argb: theme.palette.background.light6.replace('#', '') },
+ };
+ }
+ });
+ greyRows.push(rowRef.number);
+ }
+ } else {
+ if (dateValue >= formattedDepartureTime) {
+ rowRef.eachCell((cell, colNumber) => {
+ if (!cell.fill) {
+ cell.fill = {
+ type: 'pattern',
+ pattern: 'solid',
+ fgColor: { argb: theme.palette.background.light6.replace('#', '') },
+ };
+ }
+ });
+ greyRows.push(rowRef.number);
+ }
}
});
@@ -754,18 +786,20 @@ const Reporting = () => {
let firstGreyRowRichText = firstGreyRow.getCell(1).value.richText;
let lastGreyRowRichText = lastGreyRow.getCell(1).value.richText;
- if (_.size(firstGreyRowRichText) > 0) {
- firstGreyRowRichText = [
- ...firstGreyRowRichText,
- {
- text: ', Arrived',
- font: { color: { argb: theme.palette.background.black2.replace('#', '') } },
- },
- ];
- } else {
- firstGreyRowRichText = [
- { text: 'Arrived', font: { color: { argb: theme.palette.background.black2.replace('#', '') } } },
- ];
+ if (formattedArrivalTime) {
+ if (_.size(firstGreyRowRichText) > 0) {
+ firstGreyRowRichText = [
+ ...firstGreyRowRichText,
+ {
+ text: ', Arrived',
+ font: { color: { argb: theme.palette.background.black2.replace('#', '') } },
+ },
+ ];
+ } else {
+ firstGreyRowRichText = [
+ { text: 'Arrived', font: { color: { argb: theme.palette.background.black2.replace('#', '') } } },
+ ];
+ }
}
if (_.size(lastGreyRowRichText) > 0) {
@@ -1002,12 +1036,9 @@ const Reporting = () => {
screenshotMapCenter
noInitialInfo
markers={markers}
- googleMapURL={window.env.MAP_API_URL}
zoom={4}
setSelectedMarker={setSelectedMarker}
- loadingElement={
}
- containerElement={
}
- mapElement={
}
+ containerStyle={{ height: '625px' }}
unitOfMeasure={unitData}
/>
@@ -1072,10 +1103,6 @@ const Reporting = () => {
- }
- containerElement={(
-
- )}
- mapElement={
-
- }
+ containerStyle={{
+ height: '200px',
+ marginTop: isMobile() ? '10px' : '30px',
+ marginBottom: '14px',
+ }}
markers={[
{
lat: last_known_location
diff --git a/src/pages/Shipment/CreateShipment.js b/src/pages/Shipment/CreateShipment.js
index 4a8c8afd2..e1c1f26ae 100644
--- a/src/pages/Shipment/CreateShipment.js
+++ b/src/pages/Shipment/CreateShipment.js
@@ -1181,11 +1181,8 @@ const CreateShipment = ({ history, location }) => {
}
- containerElement={}
- mapElement={}
+ containerStyle={{ height: '300px', marginTop: '10px' }}
markers={[
{
lat: startingLocation && _.includes(startingLocation, ',') && parseFloat(startingLocation.split(',')[0]),
@@ -1255,11 +1252,8 @@ const CreateShipment = ({ history, location }) => {
}
- containerElement={}
- mapElement={}
+ containerStyle={{ height: '300px', marginTop: '10px' }}
markers={[
{
lat: endingLocation && _.includes(endingLocation, ',') && parseFloat(endingLocation.split(',')[0]),
diff --git a/src/pages/Shipment/Shipment.js b/src/pages/Shipment/Shipment.js
index 3cec70ae2..962295071 100644
--- a/src/pages/Shipment/Shipment.js
+++ b/src/pages/Shipment/Shipment.js
@@ -1,3 +1,4 @@
+/* eslint-disable array-callback-return */
/* eslint-disable no-nested-ternary */
import React, { useEffect, useState } from 'react';
import _ from 'lodash';
@@ -41,6 +42,7 @@ import useAlert from '@hooks/useAlert';
import { useStore } from '@zustand/timezone/timezoneStore';
import './ShipmentStyles.css';
import { TIVE_GATEWAY_TIMES } from '@utils/mock';
+import { calculateLatLngBounds } from '@utils/utilMethods';
const Shipment = ({ history }) => {
const muiTheme = useTheme();
@@ -62,6 +64,8 @@ const Shipment = ({ history }) => {
const [expandedRows, setExpandedRows] = useState([]);
const [steps, setSteps] = useState([]);
const [isLoading, setLoading] = useState(false);
+ const [selectedCluster, setSelectedCluster] = useState({});
+ const [zoom, setZoom] = useState(4);
const { data: shipmentData, isLoading: isLoadingShipments, isFetching: isFetchingShipments } = useQuery(
['shipments', shipmentFilter, organization],
@@ -153,11 +157,21 @@ const Shipment = ({ history }) => {
sensorReportData,
);
const filteredRows = _.filter(formattedRows, { type: shipmentFilter });
- setRows(filteredRows);
+ if (_.isEmpty(selectedCluster)) {
+ setRows(filteredRows);
+ }
setAllMarkers(_.map(filteredRows, 'allMarkers'));
}, [shipmentFilter, shipmentData, custodianData, custodyData,
itemData, allGatewayData, sensorAlertData, sensorReportData]);
+ useEffect(() => {
+ if (!_.isEmpty(markers) || !_.isEmpty(selectedCluster)) {
+ setZoom(12);
+ } else {
+ setZoom(4);
+ }
+ }, [markers, selectedCluster]);
+
useEffect(() => {
if (selectedShipment) {
processMarkers(selectedShipment, true);
@@ -176,6 +190,22 @@ const Shipment = ({ history }) => {
}
}, [selectedShipment, expandedRows]);
+ useEffect(() => {
+ if (!_.isEmpty(selectedCluster) && !_.isEmpty(rows)) {
+ const { lat, lng } = selectedCluster;
+ const { radius } = user.organization;
+ const values = calculateLatLngBounds(lat, lng, radius);
+ const filteredRows = rows.filter((obj) => !_.isEmpty(obj.allMarkers));
+ const clusterFilteredRows = filteredRows.filter((obj) => {
+ const firstMarker = _.first(obj.allMarkers);
+ const isLatInRange = firstMarker.lat >= values.minLat && firstMarker.lat <= values.maxLat;
+ const isLngInRange = firstMarker.lng >= values.minLng && firstMarker.lng <= values.maxLng;
+ return isLatInRange && isLngInRange;
+ });
+ setRows(clusterFilteredRows);
+ }
+ }, [selectedCluster]);
+
const processMarkers = (shipment, setExpanded = false) => {
const dateFormat = !_.isEmpty(unitData) && _.find(unitData, (unit) => (_.toLower(unit.unit_of_measure_for) === 'date')).unit_of_measure;
const timeFormat = !_.isEmpty(unitData) && _.find(unitData, (unit) => (_.toLower(unit.unit_of_measure_for) === 'time')).unit_of_measure;
@@ -537,6 +567,7 @@ const Shipment = ({ history }) => {
setSelectedMarker({});
setExpandedRows([]);
setSteps([]);
+ setSelectedCluster({});
};
const renderSensorData = (marker) => {
@@ -673,6 +704,36 @@ const Shipment = ({ history }) => {
+ {!_.isEmpty(selectedCluster) && (
+
+ )}
@@ -687,20 +748,12 @@ const Shipment = ({ history }) => {
isMarkerShown={!_.isEmpty(markers)}
showPath
markers={markers}
- googleMapURL={window.env.MAP_API_URL}
- zoom={_.isEmpty(markers) ? 2.5 : 12}
+ zoom={zoom}
setSelectedMarker={setSelectedMarker}
- loadingElement={
-
- }
- containerElement={
-
- }
- mapElement={
-
- }
- clusterClick={processMarkers}
+ containerStyle={{ height: '600px' }}
unitOfMeasure={unitData}
+ setSelectedCluster={setSelectedCluster}
+ selectedCluster={selectedCluster}
/>
diff --git a/src/pages/Shipment/ShipmentStyles.css b/src/pages/Shipment/ShipmentStyles.css
index da6aa0b70..a1fc7b283 100644
--- a/src/pages/Shipment/ShipmentStyles.css
+++ b/src/pages/Shipment/ShipmentStyles.css
@@ -27,6 +27,17 @@
background-color: var(--color-palette-primary-main);
}
+.shipmentGoBackButton {
+ margin-bottom: 24px;
+ margin-left: 16px;
+ background-color: var(--color-palette-primary-main);
+ color: var(--color-palette-background-default);
+}
+
+.shipmentGoBackButton:hover {
+ background-color: var(--color-palette-primary-main);
+}
+
.shipmentTab {
color: var(--color-palette-background-default);
}
diff --git a/src/utils/utilMethods.js b/src/utils/utilMethods.js
index da90c6e21..3ea82aa1e 100644
--- a/src/utils/utilMethods.js
+++ b/src/utils/utilMethods.js
@@ -93,3 +93,18 @@ export const dateDifference = (initialDate, finalDate) => {
const dateString = `${days} days, ${hours} hrs., ${minutes} min.`;
return dateString;
};
+
+export const calculateLatLngBounds = (lat, lng, miles) => {
+ const milesToLatDegree = miles / 69;
+ const maxLat = lat + milesToLatDegree;
+ const minLat = lat - milesToLatDegree;
+ const milesToLngDegree = miles / (69 * Math.cos(lat * (Math.PI / 180)));
+ const maxLng = lng + milesToLngDegree;
+ const minLng = lng - milesToLngDegree;
+ return {
+ maxLat,
+ minLat,
+ maxLng,
+ minLng,
+ };
+};