updates on the autocomplete in the create order page
This commit is contained in:
@@ -1,50 +1,58 @@
|
||||
/**
|
||||
* 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<number>} - Round distance in KM
|
||||
* Driving Distance, Duration & Route Polyline Calculator for DoorMile
|
||||
* Uses OSRM as primary routing engine with GeoJSON polyline extraction,
|
||||
* and falls back seamlessly to Haversine with a 1.3 road winding multiplier.
|
||||
*/
|
||||
// Duration from the most recent OSRM route, in minutes, or null when the
|
||||
// Haversine fallback was used (a straight-line estimate has no honest
|
||||
// duration — better to show nothing than a made-up ETA).
|
||||
|
||||
let lastRouteDurationMin = null;
|
||||
|
||||
export const getLastRouteDurationMin = () => lastRouteDurationMin;
|
||||
|
||||
export const calculateDrivingDistance = async (origin, destination) => {
|
||||
const lat1 = origin?.latitude;
|
||||
const lon1 = origin?.longitude;
|
||||
const lat2 = destination?.latitude;
|
||||
const lon2 = destination?.longitude;
|
||||
/**
|
||||
* Calculates complete driving route with distance, duration, and road polyline
|
||||
* @param {Object} origin - { latitude, longitude }
|
||||
* @param {Object} destination - { latitude, longitude }
|
||||
* @returns {Promise<{ distance: number, minutes: number, polyline: Array<[number, number]>, resolved: boolean }>}
|
||||
*/
|
||||
export const calculateDrivingRoute = async (origin, destination) => {
|
||||
const lat1 = Number(origin?.latitude);
|
||||
const lon1 = Number(origin?.longitude);
|
||||
const lat2 = Number(destination?.latitude);
|
||||
const lon2 = Number(destination?.longitude);
|
||||
|
||||
if (lat1 == null || lon1 == null || lat2 == null || lon2 == null) {
|
||||
if (!Number.isFinite(lat1) || !Number.isFinite(lon1) || !Number.isFinite(lat2) || !Number.isFinite(lon2)) {
|
||||
throw new Error("Invalid coordinates");
|
||||
}
|
||||
|
||||
// 1. Try OSRM API (either self-hosted or public demo server for fallback)
|
||||
const osrmBaseUrl = import.meta.env.VITE_OSRM_URL || "https://router.project-osrm.org";
|
||||
// 1. Try OSRM API with full GeoJSON geometry for live polyline map preview
|
||||
const osrmBaseUrl =
|
||||
(typeof import.meta !== 'undefined' && import.meta?.env?.VITE_OSRM_URL) ||
|
||||
'https://router.project-osrm.org';
|
||||
try {
|
||||
const url = `${osrmBaseUrl}/route/v1/driving/${lon1},${lat1};${lon2},${lat2}?overview=false`;
|
||||
const url = `${osrmBaseUrl}/route/v1/driving/${lon1},${lat1};${lon2},${lat2}?overview=full&geometries=geojson`;
|
||||
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;
|
||||
// OSRM already returns the driving duration alongside the distance;
|
||||
// it was being discarded. Cached here so callers that want an ETA get
|
||||
// a REAL routed figure instead of dividing km by a guessed speed.
|
||||
lastRouteDurationMin = Number.isFinite(data.routes[0].duration) ? Math.round(data.routes[0].duration / 60) : null;
|
||||
return Math.round(distanceInKm);
|
||||
const route = data.routes[0];
|
||||
const distanceKm = Math.round(route.distance / 1000);
|
||||
const durationMin = Number.isFinite(route.duration) ? Math.round(route.duration / 60) : null;
|
||||
// OSRM geojson coordinates are [lng, lat] -> convert to Leaflet [lat, lng]
|
||||
const polyline = (route.geometry?.coordinates || []).map(([lng, lat]) => [lat, lng]);
|
||||
lastRouteDurationMin = durationMin;
|
||||
return {
|
||||
distance: Math.max(0, distanceKm),
|
||||
minutes: durationMin,
|
||||
polyline: polyline.length > 0 ? polyline : [[lat1, lon1], [lat2, lon2]],
|
||||
resolved: true
|
||||
};
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("OSRM API failed, falling back to Haversine math:", error);
|
||||
}
|
||||
|
||||
// 2. Fallback: Haversine Formula with 1.3x multiplier
|
||||
// 2. Fallback: Haversine Formula with 1.3x road factor
|
||||
const toRad = (val) => (val * Math.PI) / 180;
|
||||
const R = 6371; // Earth radius in km
|
||||
const dLat = toRad(lat2 - lat1);
|
||||
@@ -54,25 +62,36 @@ export const calculateDrivingDistance = async (origin, destination) => {
|
||||
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;
|
||||
const aerialDistance = Math.round(R * c * 1.3);
|
||||
|
||||
// No route was fetched, so there is no honest duration to report.
|
||||
lastRouteDurationMin = null;
|
||||
return Math.round(aerialDistance * 1.3);
|
||||
return {
|
||||
distance: aerialDistance,
|
||||
minutes: null,
|
||||
polyline: [[lat1, lon1], [lat2, lon2]],
|
||||
resolved: true
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates distance (in km) between origin and destination
|
||||
*/
|
||||
export const calculateDrivingDistance = async (origin, destination) => {
|
||||
const res = await calculateDrivingRoute(origin, destination);
|
||||
return res.distance;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
const dist = Number(distanceKm) || 0;
|
||||
const base = Number(basePrice) || 40;
|
||||
const perKm = Number(pricePerKm) || 10;
|
||||
const min = Number(minKm) || 2;
|
||||
|
||||
if (dist <= min) {
|
||||
return base;
|
||||
}
|
||||
return (distanceKm - minKm) * pricePerKm + basePrice;
|
||||
return (dist - min) * perKm + base;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user