import { calculateFare } from "@/lib/pricing"; import type { Driver, MarkerData } from "@/types/type"; const directionsAPI = process.env.EXPO_PUBLIC_GOOGLE_API_KEY; export const generateMarkersFromData = ({ data, userLatitude, userLongitude, }: { data: Driver[]; userLatitude: number; userLongitude: number; }): MarkerData[] => { return data.map((driver, i) => { const latOffset = (Math.random() - 0.5) * 0.01; // Random offset between -0.005 and 0.005 const lngOffset = (Math.random() - 0.5) * 0.01; // Random offset between -0.005 and 0.005 return { id: i, latitude: userLatitude + latOffset, longitude: userLongitude + lngOffset, title: `${driver.first_name} ${driver.last_name}`, ...driver, }; }); }; export const calculateRegion = ({ userLatitude, userLongitude, destinationLatitude, destinationLongitude, }: { userLatitude: number | null; userLongitude: number | null; destinationLatitude?: number | null; destinationLongitude?: number | null; }) => { if (!userLatitude || !userLongitude) { // Default to Beirut, Lebanon. return { latitude: 33.8938, longitude: 35.5018, latitudeDelta: 0.09, longitudeDelta: 0.09, }; } if (!destinationLatitude || !destinationLongitude) { return { latitude: userLatitude, longitude: userLongitude, latitudeDelta: 0.01, longitudeDelta: 0.01, }; } const minLat = Math.min(userLatitude, destinationLatitude); const maxLat = Math.max(userLatitude, destinationLatitude); const minLng = Math.min(userLongitude, destinationLongitude); const maxLng = Math.max(userLongitude, destinationLongitude); const latitudeDelta = (maxLat - minLat) * 1.3; // Adding some padding const longitudeDelta = (maxLng - minLng) * 1.3; // Adding some padding const latitude = (userLatitude + destinationLatitude) / 2; const longitude = (userLongitude + destinationLongitude) / 2; return { latitude, longitude, latitudeDelta, longitudeDelta, }; }; export const calculateDriverTimes = async ({ markers, userLatitude, userLongitude, destinationLatitude, destinationLongitude, }: { markers: MarkerData[]; userLatitude: number | null; userLongitude: number | null; destinationLatitude: number | null; destinationLongitude: number | null; }) => { if ( !userLatitude || !userLongitude || !destinationLatitude || !destinationLongitude ) return; try { const timesPromises = markers.map(async (marker) => { const responseToUser = await fetch( `https://maps.googleapis.com/maps/api/directions/json?origin=${marker.latitude},${marker.longitude}&destination=${userLatitude},${userLongitude}&key=${directionsAPI}`, ); const dataToUser = await responseToUser.json(); const responseToDestination = await fetch( `https://maps.googleapis.com/maps/api/directions/json?origin=${userLatitude},${userLongitude}&destination=${destinationLatitude},${destinationLongitude}&key=${directionsAPI}`, ); const dataToDestination = await responseToDestination.json(); // Google returns no routes when a leg is unreachable (ZERO_RESULTS). const legToUser = dataToUser.routes?.[0]?.legs?.[0]; const legToDestination = dataToDestination.routes?.[0]?.legs?.[0]; if (!legToUser || !legToDestination) { return { ...marker, time: 0, price: "0.00" }; } const timeToUser = legToUser.duration.value; // Pickup ETA in seconds const timeToDestination = legToDestination.duration.value; // Trip duration in seconds // The rider pays for the trip leg only (distance + duration) — // never for the driver's approach. const price = calculateFare({ distanceMeters: legToDestination.distance.value, durationSeconds: timeToDestination, }); const totalTripTime = (timeToUser + timeToDestination) / 60; // Minutes until drop-off return { ...marker, time: totalTripTime, price }; }); return await Promise.all(timesPromises); } catch (error) { console.error("Error calculating driver times:", error); } };