From 89cf46ffb49cab97e7c8f1b1ab1f7d2decf9a767 Mon Sep 17 00:00:00 2001 From: dharaneesh-r Date: Sat, 4 Jul 2026 16:57:39 +0530 Subject: [PATCH] updates on the google change --- src/pages/maintenance/coming-soon.js | 2 +- src/pages/nearle/orders/createorder1.js | 72 +++++--------------- src/pages/nearle/orders/miltiUploadBackup.js | 62 ++--------------- src/pages/nearle/orders/multiOrderBackup.js | 61 ++--------------- src/pages/nearle/orders/multipleOrders.js | 44 +++--------- src/utils/distance.js | 65 ++++++++++++++++++ 6 files changed, 102 insertions(+), 204 deletions(-) create mode 100644 src/utils/distance.js diff --git a/src/pages/maintenance/coming-soon.js b/src/pages/maintenance/coming-soon.js index eddd960..a8c5bdb 100644 --- a/src/pages/maintenance/coming-soon.js +++ b/src/pages/maintenance/coming-soon.js @@ -5,7 +5,7 @@ import { useTheme } from '@mui/material/styles'; import { useMediaQuery, Box, Button, Grid, Stack, TextField, Typography } from '@mui/material'; // third party -import { useTimer } from 'react-timer-hook'; +const { useTimer } = require('react-timer-hook'); // assets import coming from 'assets/images/maintenance/coming-soon.png'; diff --git a/src/pages/nearle/orders/createorder1.js b/src/pages/nearle/orders/createorder1.js index 0e000e1..d45f7bb 100644 --- a/src/pages/nearle/orders/createorder1.js +++ b/src/pages/nearle/orders/createorder1.js @@ -34,6 +34,7 @@ import { FormControlLabel } from '@mui/material'; import CloseIcon from '@mui/icons-material/Close'; +import { calculateDrivingDistance, calculateTotalCharge } from '../../../utils/distance'; import { Empty } from 'antd'; import { FaPhoneAlt } from 'react-icons/fa'; import { GiDoorHandle } from 'react-icons/gi'; @@ -619,66 +620,25 @@ const Createorder1 = () => { }; const calculateDistance = async (pickup, drop) => { - const service = new google.maps.DistanceMatrixService(); - - const getDistanceMatrix = (origins, destinations, travelMode, unitSystem) => { - return new Promise((resolve, reject) => { - service.getDistanceMatrix( - { - origins: [new google.maps.LatLng(origins.latitude, origins.longitude)], - destinations: [new google.maps.LatLng(destinations.latitude, destinations.longitude)], - travelMode: travelMode, - unitSystem: unitSystem - }, - (response, status) => { - if (status === 'OK') { - resolve(response); - } else { - reject(new Error(`Error calculating distance: ${status}`)); - } - } - ); - }); - }; - try { - // Use await to wait for the promise to resolve - const response = await getDistanceMatrix(pickup, drop, 'DRIVING', google.maps.UnitSystem.METRIC); + const roundedDistance = await calculateDrivingDistance(pickup, drop); + console.log('calculated distance in km:', roundedDistance); + setDistance(roundedDistance); - // Handle the response - const results = response.rows[0].elements; - for (let i = 0; i < results.length; i++) { - const element = results[i]; - const distance = element.distance.value; - console.log('distance in m ', distance); - const distanceInKm = (distance / 1000).toFixed(2); - console.log('distance in km ', distanceInKm); - const roundedDistance = Math.round(distanceInKm); - console.log('roundedDistance', roundedDistance); - setDistance(roundedDistance); - if (roundedDistance < minKm) { - setTotalCharge(basePrice); - } else { - console.log('minKm', minKm); - console.log('pricePerKm', pricePerKm); - console.log('basePrice', basePrice); - const total = (roundedDistance - minKm) * pricePerKm + basePrice; - console.log('total', total); - setTotalCharge(total); - } + const total = calculateTotalCharge(roundedDistance, basePrice, pricePerKm, minKm); + console.log('total charge:', total); + setTotalCharge(total); + + setShowDistance(true); + if (roundedDistance > appLocaRadius) { setShowDistance(true); - if (roundedDistance > appLocaRadius) { - setShowDistance(true); - setOpen4(true); - } - - // Extract the numerical value of the duration - const durationMatch = element.duration.text.match(/([\d.]+)/); - const duration = durationMatch ? parseInt(durationMatch[0]) : null; - - // Display only the numerical values - console.log(`Distance: ${roundedDistance}, Duration: ${duration}`); + setOpen4(true); } + + // ⏱️ Approximate duration + const avgSpeed = 40; // km/h (adjust if needed) + const duration = Math.round((roundedDistance / avgSpeed) * 60); // minutes + console.log(`Distance: ${roundedDistance}, Duration: ${duration}`); } catch (error) { console.error('Error calculating distance:', error); } diff --git a/src/pages/nearle/orders/miltiUploadBackup.js b/src/pages/nearle/orders/miltiUploadBackup.js index 64e7852..e9dfb07 100644 --- a/src/pages/nearle/orders/miltiUploadBackup.js +++ b/src/pages/nearle/orders/miltiUploadBackup.js @@ -17,6 +17,7 @@ dayjs.extend(utc); import { enqueueSnackbar } from 'notistack'; import { useNavigate } from 'react-router'; import Papa from 'papaparse'; +import { calculateDrivingDistance, calculateTotalCharge } from '../../../utils/distance'; import * as XLSX from 'xlsx'; import { @@ -375,37 +376,6 @@ const MultipleOrders = () => { // 🔹 Main distance calculation function const calculateDistance = async (customer) => { - const service = new google.maps.DistanceMatrixService(); - - // Helper: safely get distance matrix - const getDistanceMatrix = (origins, destinations) => { - return new Promise((resolve, reject) => { - // 2; - try { - if (!origins || !destinations) { - return reject(new Error('Origin or destination data missing.')); - } - service.getDistanceMatrix( - { - origins: [new google.maps.LatLng(origins.latitude, origins.longitude)], - destinations: [new google.maps.LatLng(destinations.latitude, destinations.longitude)], - travelMode: 'DRIVING', - unitSystem: google.maps.UnitSystem.METRIC - }, - (response, status) => { - if (status === 'OK') { - resolve(response); - } else { - reject(new Error(`Google API error: ${status}`)); - } - } - ); - } catch (err) { - reject(new Error(`Unexpected error inside DistanceMatrixService: ${err.message}`)); - } - }); - }; - try { // --- Input validation --- if (!customer || typeof customer !== 'object') { @@ -416,38 +386,18 @@ const MultipleOrders = () => { throw new Error('Origin (pickCust) data missing or invalid.'); } - // --- Call Google Maps API --- - const response = await getDistanceMatrix(pickCust, customer); - - // --- Validate response structure --- - if (!response.rows?.[0]?.elements?.[0] || !response.rows[0].elements[0].distance?.value) { - throw new Error('Malformed Distance Matrix response: missing distance value.'); - } // --- Compute distance --- - const distanceInMeters = response.rows[0].elements[0].distance.value; - const distanceInKilometers = distanceInMeters / 1000; - const roundedDistance = Math.round(distanceInKilometers); + const roundedDistance = await calculateDrivingDistance(pickCust, customer); // --- Calculate total charge --- - let totalcharge; - if (roundedDistance < minKm) { - totalcharge = basePrice; - } else { - totalcharge = (roundedDistance - minKm) * pricePerKm + basePrice; - } + const totalcharge = calculateTotalCharge(roundedDistance, basePrice, pricePerKm, minKm); return { roundedDistance, totalcharge }; } catch (error) { // --- Categorized smart error handling --- console.log('on calculateDistance', error.message); - if (error.message.includes('Google API')) { - console.log('🚨 Google Maps API Error:', error.message); - OpenToast('Invalid file format, upload valid file', 'error', 5000); - } else if (error.message.includes('Invalid coordinates')) { - console.log('📍 Invalid coordinate format:', error.message, 3000); - OpenToast('Invalid coordinate format. Check location data.', 'warning'), 3000; - } else if (error.message.includes('Malformed Distance Matrix')) { - console.log('⚠️ Unexpected Google response structure:', error.message); - OpenToast('Google Distance Matrix returned invalid data.', 'error', 3000); + if (error.message.includes('Invalid coordinates') || error.message.includes('Invalid coordinate')) { + console.log('📍 Invalid coordinate format:', error.message); + OpenToast('Invalid coordinate format. Check location data.', 'warning', 3000); } else if (error.message.includes('Origin') || error.message.includes('customer')) { console.log('❌ Missing or invalid input data:', error.message); OpenToast('Missing or invalid input data for distance calculation.', 'warning', 3000); diff --git a/src/pages/nearle/orders/multiOrderBackup.js b/src/pages/nearle/orders/multiOrderBackup.js index 0f0ecc7..e57e6d6 100644 --- a/src/pages/nearle/orders/multiOrderBackup.js +++ b/src/pages/nearle/orders/multiOrderBackup.js @@ -16,6 +16,7 @@ var utc = require('dayjs/plugin/utc'); dayjs.extend(utc); import { enqueueSnackbar } from 'notistack'; import { useNavigate } from 'react-router'; +import { calculateDrivingDistance, calculateTotalCharge } from '../../../utils/distance'; import { GoogleMap, LoadScript, Marker } from '@react-google-maps/api'; import { @@ -236,67 +237,13 @@ const MultipleOrders = () => { // ========================================================= || calculateDistance || ========================================================= const calculateDistance = async (customer) => { console.log('Distance calculation starts'); - const service = new google.maps.DistanceMatrixService(); - // Helper function to get the distance matrix - const getDistanceMatrix = async (origins, destinations) => { - console.log('origins', origins); - console.log('destinations', destinations); - return new Promise((resolve, reject) => { - console.log('calculation starts'); - service.getDistanceMatrix( - { - origins: [new google.maps.LatLng(origins.latitude, origins.longitude)], - destinations: [new google.maps.LatLng(destinations.latitude, destinations.longitude)], - travelMode: 'DRIVING', - unitSystem: google.maps.UnitSystem.METRIC // Distances in metric units (km) - }, - (response, status) => { - console.log('cal response', response); - console.log('cal status', status); - if (status === 'OK') { - console.log('calcualtion resolved'); - resolve(response); - } else { - console.log('calcualtion rejected'); - - reject(new Error(`Error calculating distance: ${status}`)); - } - } - ); - }); - }; - try { - // Call getDistanceMatrix and wait for the response - const response = await getDistanceMatrix(pickCust, customer); - - // Extract distance from the first result - const distanceInMeters = response.rows[0].elements[0].distance.value; - - // Convert distance from meters to kilometers - const distanceInKilometers = distanceInMeters / 1000; - - // Round the distance to the nearest integer - const roundedDistance = Math.round(distanceInKilometers); - let totalcharge; - if (roundedDistance < minKm) { - console.log('minKm', minKm); - console.log('pricePerKm', pricePerKm); - console.log('basePrice', basePrice); - totalcharge = basePrice; - } else { - console.log('minKm', minKm); - console.log('pricePerKm', pricePerKm); - console.log('basePrice', basePrice); - totalcharge = (roundedDistance - minKm) * pricePerKm + basePrice; - console.log('totalcharge', totalcharge); - } - - // Return the rounded distance + const roundedDistance = await calculateDrivingDistance(pickCust, customer); + const totalcharge = calculateTotalCharge(roundedDistance, basePrice, pricePerKm, minKm); return { roundedDistance, totalcharge }; } catch (error) { console.error('Error calculating distance:', error); - throw error; // Rethrow the error to be handled by the caller + throw error; } }; diff --git a/src/pages/nearle/orders/multipleOrders.js b/src/pages/nearle/orders/multipleOrders.js index bac520f..c5451dc 100644 --- a/src/pages/nearle/orders/multipleOrders.js +++ b/src/pages/nearle/orders/multipleOrders.js @@ -7,6 +7,7 @@ import { useNavigate } from 'react-router'; import { useTheme } from '@mui/material/styles'; import useMediaQuery from '@mui/material/useMediaQuery'; import { enqueueSnackbar } from 'notistack'; +import { calculateDrivingDistance, calculateTotalCharge } from '../../../utils/distance'; import { FormControl, @@ -238,46 +239,21 @@ const MultipleOrders = () => { }, [dropCust]); // ============================== distance (Google) ============================== + // ============================== distance (OSRM/Haversine) ============================== const calculateDistance = async (customer) => { - if (typeof window === 'undefined' || !window.google?.maps?.DistanceMatrixService) { - throw new Error('Google Maps not loaded'); - } - const service = new window.google.maps.DistanceMatrixService(); - const getDistanceMatrix = (origins, destinations) => - new Promise((resolve, reject) => { - try { - if (!origins || !destinations) return reject(new Error('Origin or destination data missing.')); - service.getDistanceMatrix( - { - origins: [new window.google.maps.LatLng(origins.latitude, origins.longitude)], - destinations: [new window.google.maps.LatLng(destinations.latitude, destinations.longitude)], - travelMode: 'DRIVING', - unitSystem: window.google.maps.UnitSystem.METRIC - }, - (response, status) => { - if (status === 'OK') resolve(response); - else reject(new Error(`Google API error: ${status}`)); - } - ); - } catch (err) { - reject(new Error(`Unexpected error inside DistanceMatrixService: ${err.message}`)); - } - }); - try { if (!customer || typeof customer !== 'object') throw new Error('Invalid customer data.'); if (!pickCust || typeof pickCust !== 'object') throw new Error('Origin (pickCust) data missing or invalid.'); - const response = await getDistanceMatrix(pickCust, customer); - const distVal = response?.rows?.[0]?.elements?.[0]?.distance?.value; - if (distVal == null) throw new Error('Malformed Distance Matrix response: missing distance value.'); - const km = distVal / 1000; - const roundedDistance = Math.round(km); - const totalcharge = roundedDistance < minKm ? basePrice : (roundedDistance - minKm) * pricePerKm + basePrice; + + const roundedDistance = await calculateDrivingDistance(pickCust, customer); + const totalcharge = calculateTotalCharge(roundedDistance, basePrice, pricePerKm, minKm); return { roundedDistance, totalcharge }; } catch (error) { - if (error.message.includes('Google API')) OpenToast('Invalid coordinates or Google API error.', 'error', 3000); - else if (error.message.includes('Malformed')) OpenToast('Google Distance Matrix returned invalid data.', 'error', 3000); - else OpenToast('Unexpected error during distance calculation.', 'error', 3000); + if (error.message.includes('Origin') || error.message.includes('customer') || error.message.includes('coordinates')) { + OpenToast('Missing or invalid input data for distance calculation.', 'warning', 3000); + } else { + OpenToast('Unexpected error during distance calculation.', 'error', 3000); + } throw error; } }; diff --git a/src/utils/distance.js b/src/utils/distance.js new file mode 100644 index 0000000..9f35c2a --- /dev/null +++ b/src/utils/distance.js @@ -0,0 +1,65 @@ +/** + * Calculates distance (in km) between origin and destination. + * Uses OSRM as primary driving distance source, and falls back to Haversine with a 1.3 multiplier. + * + * @param {Object} origin - { latitude, longitude } + * @param {Object} destination - { latitude, longitude } + * @returns {Promise} - Round distance in KM + */ +export const calculateDrivingDistance = async (origin, destination) => { + const lat1 = origin?.latitude; + const lon1 = origin?.longitude; + const lat2 = destination?.latitude; + const lon2 = destination?.longitude; + + if (lat1 == null || lon1 == null || lat2 == null || lon2 == null) { + throw new Error("Invalid coordinates"); + } + + // 1. Try OSRM API (either self-hosted or public demo server for fallback) + const osrmBaseUrl = process.env.REACT_APP_OSRM_URL || "https://router.project-osrm.org"; + try { + const url = `${osrmBaseUrl}/route/v1/driving/${lon1},${lat1};${lon2},${lat2}?overview=false`; + const response = await fetch(url); + if (response.ok) { + const data = await response.json(); + if (data.routes && data.routes.length > 0) { + const distanceInMeters = data.routes[0].distance; + const distanceInKm = distanceInMeters / 1000; + return Math.round(distanceInKm); + } + } + } catch (error) { + console.warn("OSRM API failed, falling back to Haversine math:", error); + } + + // 2. Fallback: Haversine Formula with 1.3x multiplier + const toRad = (val) => (val * Math.PI) / 180; + const R = 6371; // Earth radius in km + const dLat = toRad(lat2 - lat1); + const dLon = toRad(lon2 - lon1); + const a = + Math.sin(dLat / 2) * Math.sin(dLat / 2) + + Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * + Math.sin(dLon / 2) * Math.sin(dLon / 2); + const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + const aerialDistance = R * c; + + return Math.round(aerialDistance * 1.3); +}; + +/** + * Calculates total charge based on distance and pricing tier + * + * @param {number} distanceKm + * @param {number} basePrice + * @param {number} pricePerKm + * @param {number} minKm + * @returns {number} + */ +export const calculateTotalCharge = (distanceKm, basePrice, pricePerKm, minKm) => { + if (distanceKm < minKm) { + return basePrice; + } + return (distanceKm - minKm) * pricePerKm + basePrice; +};