map path solve

master
neel 2025-04-11 15:57:48 +05:30
parent af0438fa91
commit 3b3b9acefa
5 changed files with 192 additions and 52 deletions

View File

@ -1,6 +1,7 @@
import { useDriverStore, useLocationStore } from "@/store";
import { calculateDriverTimes, calculateRegion, generateMarkersFromData } from "@/lib/map";
import MapView, { Marker, PROVIDER_DEFAULT } from "react-native-maps";
import MapViewDirections from "react-native-maps-directions";
import tw from "twrnc";
import { useEffect, useState } from "react";
import { Driver, MarkerData } from "@/types/type";
@ -9,7 +10,7 @@ import { useFetch } from "@/lib/fetch";
import { ActivityIndicator, Text, View } from "react-native";
const Map = () => {
const { data: drivers, loading, error } = useFetch<Driver[]>("/(api)/driver");
const { data: drivers, loading, error } = useFetch<Driver[]>("/api/driver");
const { userLongitude, userLatitude, destinationLatitude, destinationLongitude } = useLocationStore();
const { selectedDriver, setDrivers } = useDriverStore();
const [markers, setMarkers] = useState<MarkerData[]>([]);
@ -22,7 +23,7 @@ const Map = () => {
const newMarkers = generateMarkersFromData({ data: drivers, userLatitude, userLongitude, });
setMarkers(newMarkers);
}
}, [drivers]);
}, [drivers,userLatitude,userLongitude]);
useEffect(() => {
if (markers.length > 0 && destinationLatitude && destinationLongitude) {
calculateDriverTimes({ markers, userLongitude, userLatitude, destinationLatitude, destinationLongitude }).then((drivers) => {
@ -56,6 +57,12 @@ const Map = () => {
image={selectedDriver === marker.id ? icons.selectedMarker : icons.marker}
/>
))}
{destinationLatitude && destinationLongitude && (
<>
<Marker key="destination" coordinate={{latitude:destinationLatitude,longitude:destinationLongitude}} title="Destination" image={icons.pin} />
<MapViewDirections origin={{latitude:userLatitude!,longitude:userLongitude!,}} destination={{latitude:destinationLatitude,longitude:destinationLongitude,}} apikey={process.env.EXPO_PUBLIC_GOOGLE_API_KEY} strokeColor="#0286ff" strokeWidth={2} />
</>
)}
</MapView>
)
}

View File

@ -1,64 +1,88 @@
import { Alert, Text, View } from "react-native";
import { Alert, Image, Text, View } from "react-native";
import CustomButton from "./CustomButton";
import tw from "twrnc";
import { PaymentMethod, PaymentSheetError, useStripe } from "@stripe/stripe-react-native";
import { useState, useEffect } from "react";
import { useStripe } from "@stripe/stripe-react-native";
import { useState } from "react";
import { fetchAPI } from "@/lib/fetch";
import { PaymentProps } from "@/types/type";
import { useLocationStore } from "@/store";
import { useAuth } from "@clerk/clerk-expo";
import ReactNativeModal from "react-native-modal";
import { images } from "@/constants";
import { router } from "expo-router";
const Payment = ({fullName,email,amount,driverId,rideTime}:PaymentProps) => {
const [success, setSuccess] = useState(false);
const {userId} =useAuth();
const {userAddress,userLatitude,userLongitude,destinationAddress,destinationLatitude,destinationLongitude} = useLocationStore();
const { initPaymentSheet, presentPaymentSheet } = useStripe();
const confirmHandler = async (paymentMethod,_, intentCreationCallback) => {
const {paymentIntent,customer} = await fetchAPI("/(api)/(stripe)/create",{
method:"POST",
headers:{
"Content-Type": "application/json",
},
body:JSON.stringify({
name:fullName || email.split("@")[0],
email: email,
amount: amount,
paymentMethodId : paymentMethod.id,
}),
},
);
if(paymentIntent.client_sercet){
const {result} = await fetchAPI ("/(api)/(stripe)/pay",{
method:"POST",
headers:{
"Content-Type":"application/json",
},
body: JSON.stringify({
payment_method_id:paymentMethod.id,
payment_intent_id:paymentIntent.id,
customer_id:customer,
}),
});
if (result.client_sercet) {
//ride/create
}
}
const { clientSercet, error } = await response.json();
if(clientSercet){
intentCreationCallback({clientSercet})
}
else{
intentCreationCallback({error})
}
}
const initializePaymentSheet = async () => {
const { error } = await initPaymentSheet({
merchantDisplayName: "Example,Inc.",
merchantDisplayName: "Neel,Inc.",
intentConfiguration: {
mode: {
amount: 1099,
amount: parseInt(amount)*100,
currencyCode: "USD",
},
confirmHandler: confirmHandler
}
confirmHandler: async (paymentMethod,_, intentCreationCallback) => {
const {paymentIntent,customer} = await fetchAPI("/api/stripe/create",{
method:"POST",
headers:{
"Content-Type": "application/json",
},
body:JSON.stringify({
name:fullName || email.split("@")[0],
email: email,
amount: amount,
paymentMethodId : paymentMethod.id,
}),
},
);
if(paymentIntent.client_sercet){
const {result} = await fetchAPI ("/api/stripe/pay",{
method:"POST",
headers:{
"Content-Type":"application/json",
},
body: JSON.stringify({
payment_method_id:paymentMethod.id,
payment_intent_id:paymentIntent.id,
customer_id:customer,
}),
});
if (result.client_sercet) {
await fetchAPI("/api/ride/create",{
method: "POST",
headers:{
"Content-Type":"application/json",
},
body:JSON.stringify({
origin_address:userAddress,
destination_address:destinationAddress,
origin_latitude:userLatitude,
origin_longitude:userLongitude,
destination_latitude:destinationLatitude,
destination_longitude:destinationLongitude,
ride_time:rideTime.toFixed(0),
fare_price:parseInt(amount)*100,
payment_status:"paid",
driver_id:driverId,
user_id:userId,
}),
});
intentCreationCallback({
clientSercet:result.client_secert,
})
}
}
}
},
returnURL:'myapp"//book-ride',
});
if (error) {
//handle error
console.log(error);
}
};
const openPaymentSheet = async () => {
@ -76,6 +100,15 @@ const Payment = ({fullName,email,amount,driverId,rideTime}:PaymentProps) => {
return (
<>
<CustomButton title="Confirm Ride" style={tw`my-10`} onPress={openPaymentSheet} />
<ReactNativeModal isVisible={success} onBackButtonPress={()=>setSuccess(false)} >
<View style={tw`flex flex-col items-center justify-center bg-white p-7 rounded-2xl`} >
<Image source={images.check} style={tw`w-28 h-28 mt-5`} />
<Text style={tw`text-2xl text-center font-JakartaBold mt-5`}>Ride Booked!</Text>
<Text style={tw`text-md text-general-200 f0nt-JakartaMedium`} >Thank you for your booking. Your reservation has been placed. Please proceed with your trip! </Text>
<CustomButton title="Back Home" onPress={()=>{setSuccess(false)
router.push("/(root)/(tabs)/home")}} style={tw`mt-5`} />
</View>
</ReactNativeModal>
</>
)
};

View File

@ -2,9 +2,9 @@ import {useState, useEffect, useCallback} from "react";
const API_BASE_URL = "http://192.168.29.174:3000";
export const fetchAPI = async (endpoint: string, options?: RequestInit) => {
export const fetchAPI = async (url: string, options?: RequestInit) => {
try {
const response = await fetch(`${API_BASE_URL}${endpoint}`, options);
const response = await fetch(`${process.env.EXPO_PUBLIC_API_URL}${url}`, options);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

102
server.js
View File

@ -9,7 +9,24 @@ const requestHandler = async (req, res) => {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ message: "GET is working" }));
return;
}
if (req.method === "GET" && req.url === "/api/ride/create") {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ message: "GET is working" }));
return;
}
if (req.method === "GET" && req.url === "/api/driver") {
try {
const drivers = await sql`SELECT * FROM drivers`; // Adjust table name
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ data: drivers }));
} catch (err) {
console.error("❌ Error fetching drivers:", err);
res.writeHead(500, { "Content-Type": "application/json" });
res.end(JSON.stringify({ error: "Error fetching drivers" }));
}
return;
}
if (req.method === "POST" && req.url === "/api/users") {
let body = "";
@ -56,7 +73,90 @@ const requestHandler = async (req, res) => {
return;
}
if (req.method === "POST" && req.url === "/api/ride/rides") {
let body = "";
req.on("data", (chunk) => {
body += chunk.toString();
});
req.on("end", async () => {
try {
const {
origin_address,
destination_address,
origin_latitude,
origin_longitude,
destination_latitude,
destination_longitude,
ride_time,
fare_price,
payment_status,
driver_id,
user_id,
} = JSON.parse(body);
if (
!origin_address ||
!destination_address ||
!origin_latitude ||
!origin_longitude ||
!destination_latitude ||
!destination_longitude ||
!ride_time ||
!fare_price ||
!payment_status ||
!driver_id ||
!user_id
) {
res.writeHead(400, { "Content-Type": "application/json" });
res.end(JSON.stringify({ error: "Missing required fields" }));
return;
}
const sql = neon(`${process.env.DATABASE_URL}`);
const response = await sql`
INSERT INTO rides (
origin_address,
destination_address,
origin_latitude,
origin_longitude,
destination_latitude,
destination_longitude,
ride_time,
fare_price,
payment_status,
driver_id,
user_id
) VALUES (
${origin_address},
${destination_address},
${origin_latitude},
${origin_longitude},
${destination_latitude},
${destination_longitude},
${ride_time},
${fare_price},
${payment_status},
${driver_id},
${user_id}
)
RETURNING *;
`;
res.writeHead(201, { "Content-Type": "application/json" });
res.end(JSON.stringify({ data: response[0] }));
} catch (error) {
console.error("Error inserting data into recent_rides:", error);
res.writeHead(500, { "Content-Type": "application/json" });
res.end(JSON.stringify({ error: "Internal Server Error" }));
}
});
return;
}
// Fallback for unrecognized routes
res.writeHead(404, { "Content-Type": "text/plain" });
res.end("Not Found");

2
types/type.d.ts vendored
View File

@ -44,7 +44,7 @@ declare interface Ride {
fare_price: number;
payment_status: string;
driver_id: number;
user_email: string;
user_email?: string;
created_at: string;
driver: {
first_name: string;