map path solve
parent
af0438fa91
commit
3b3b9acefa
|
@ -1,6 +1,7 @@
|
||||||
import { useDriverStore, useLocationStore } from "@/store";
|
import { useDriverStore, useLocationStore } from "@/store";
|
||||||
import { calculateDriverTimes, calculateRegion, generateMarkersFromData } from "@/lib/map";
|
import { calculateDriverTimes, calculateRegion, generateMarkersFromData } from "@/lib/map";
|
||||||
import MapView, { Marker, PROVIDER_DEFAULT } from "react-native-maps";
|
import MapView, { Marker, PROVIDER_DEFAULT } from "react-native-maps";
|
||||||
|
import MapViewDirections from "react-native-maps-directions";
|
||||||
import tw from "twrnc";
|
import tw from "twrnc";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Driver, MarkerData } from "@/types/type";
|
import { Driver, MarkerData } from "@/types/type";
|
||||||
|
@ -9,7 +10,7 @@ import { useFetch } from "@/lib/fetch";
|
||||||
import { ActivityIndicator, Text, View } from "react-native";
|
import { ActivityIndicator, Text, View } from "react-native";
|
||||||
|
|
||||||
const Map = () => {
|
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 { userLongitude, userLatitude, destinationLatitude, destinationLongitude } = useLocationStore();
|
||||||
const { selectedDriver, setDrivers } = useDriverStore();
|
const { selectedDriver, setDrivers } = useDriverStore();
|
||||||
const [markers, setMarkers] = useState<MarkerData[]>([]);
|
const [markers, setMarkers] = useState<MarkerData[]>([]);
|
||||||
|
@ -22,7 +23,7 @@ const Map = () => {
|
||||||
const newMarkers = generateMarkersFromData({ data: drivers, userLatitude, userLongitude, });
|
const newMarkers = generateMarkersFromData({ data: drivers, userLatitude, userLongitude, });
|
||||||
setMarkers(newMarkers);
|
setMarkers(newMarkers);
|
||||||
}
|
}
|
||||||
}, [drivers]);
|
}, [drivers,userLatitude,userLongitude]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (markers.length > 0 && destinationLatitude && destinationLongitude) {
|
if (markers.length > 0 && destinationLatitude && destinationLongitude) {
|
||||||
calculateDriverTimes({ markers, userLongitude, userLatitude, destinationLatitude, destinationLongitude }).then((drivers) => {
|
calculateDriverTimes({ markers, userLongitude, userLatitude, destinationLatitude, destinationLongitude }).then((drivers) => {
|
||||||
|
@ -56,6 +57,12 @@ const Map = () => {
|
||||||
image={selectedDriver === marker.id ? icons.selectedMarker : icons.marker}
|
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>
|
</MapView>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,32 @@
|
||||||
import { Alert, Text, View } from "react-native";
|
import { Alert, Image, Text, View } from "react-native";
|
||||||
import CustomButton from "./CustomButton";
|
import CustomButton from "./CustomButton";
|
||||||
import tw from "twrnc";
|
import tw from "twrnc";
|
||||||
import { PaymentMethod, PaymentSheetError, useStripe } from "@stripe/stripe-react-native";
|
import { useStripe } from "@stripe/stripe-react-native";
|
||||||
import { useState, useEffect } from "react";
|
import { useState } from "react";
|
||||||
import { fetchAPI } from "@/lib/fetch";
|
import { fetchAPI } from "@/lib/fetch";
|
||||||
import { PaymentProps } from "@/types/type";
|
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 Payment = ({fullName,email,amount,driverId,rideTime}:PaymentProps) => {
|
||||||
const [success, setSuccess] = useState(false);
|
const [success, setSuccess] = useState(false);
|
||||||
|
const {userId} =useAuth();
|
||||||
|
const {userAddress,userLatitude,userLongitude,destinationAddress,destinationLatitude,destinationLongitude} = useLocationStore();
|
||||||
|
|
||||||
const { initPaymentSheet, presentPaymentSheet } = useStripe();
|
const { initPaymentSheet, presentPaymentSheet } = useStripe();
|
||||||
const confirmHandler = async (paymentMethod,_, intentCreationCallback) => {
|
|
||||||
const {paymentIntent,customer} = await fetchAPI("/(api)/(stripe)/create",{
|
const initializePaymentSheet = async () => {
|
||||||
|
const { error } = await initPaymentSheet({
|
||||||
|
merchantDisplayName: "Neel,Inc.",
|
||||||
|
intentConfiguration: {
|
||||||
|
mode: {
|
||||||
|
amount: parseInt(amount)*100,
|
||||||
|
currencyCode: "USD",
|
||||||
|
},
|
||||||
|
confirmHandler: async (paymentMethod,_, intentCreationCallback) => {
|
||||||
|
const {paymentIntent,customer} = await fetchAPI("/api/stripe/create",{
|
||||||
method:"POST",
|
method:"POST",
|
||||||
headers:{
|
headers:{
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
@ -23,7 +40,7 @@ const Payment = ({fullName,email,amount,driverId,rideTime}:PaymentProps) => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if(paymentIntent.client_sercet){
|
if(paymentIntent.client_sercet){
|
||||||
const {result} = await fetchAPI ("/(api)/(stripe)/pay",{
|
const {result} = await fetchAPI ("/api/stripe/pay",{
|
||||||
method:"POST",
|
method:"POST",
|
||||||
headers:{
|
headers:{
|
||||||
"Content-Type":"application/json",
|
"Content-Type":"application/json",
|
||||||
|
@ -35,30 +52,37 @@ const Payment = ({fullName,email,amount,driverId,rideTime}:PaymentProps) => {
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
if (result.client_sercet) {
|
if (result.client_sercet) {
|
||||||
//ride/create
|
await fetchAPI("/api/ride/create",{
|
||||||
}
|
method: "POST",
|
||||||
}
|
headers:{
|
||||||
const { clientSercet, error } = await response.json();
|
"Content-Type":"application/json",
|
||||||
if(clientSercet){
|
|
||||||
intentCreationCallback({clientSercet})
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
intentCreationCallback({error})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const initializePaymentSheet = async () => {
|
|
||||||
const { error } = await initPaymentSheet({
|
|
||||||
merchantDisplayName: "Example,Inc.",
|
|
||||||
intentConfiguration: {
|
|
||||||
mode: {
|
|
||||||
amount: 1099,
|
|
||||||
currencyCode: "USD",
|
|
||||||
},
|
},
|
||||||
confirmHandler: confirmHandler
|
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) {
|
if (error) {
|
||||||
//handle error
|
console.log(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const openPaymentSheet = async () => {
|
const openPaymentSheet = async () => {
|
||||||
|
@ -76,6 +100,15 @@ const Payment = ({fullName,email,amount,driverId,rideTime}:PaymentProps) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CustomButton title="Confirm Ride" style={tw`my-10`} onPress={openPaymentSheet} />
|
<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>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,9 +2,9 @@ import {useState, useEffect, useCallback} from "react";
|
||||||
|
|
||||||
const API_BASE_URL = "http://192.168.29.174:3000";
|
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 {
|
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) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
}
|
}
|
||||||
|
|
100
server.js
100
server.js
|
@ -10,6 +10,23 @@ const requestHandler = async (req, res) => {
|
||||||
res.end(JSON.stringify({ message: "GET is working" }));
|
res.end(JSON.stringify({ message: "GET is working" }));
|
||||||
return;
|
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") {
|
if (req.method === "POST" && req.url === "/api/users") {
|
||||||
let body = "";
|
let body = "";
|
||||||
|
|
||||||
|
@ -56,6 +73,89 @@ const requestHandler = async (req, res) => {
|
||||||
|
|
||||||
return;
|
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
|
// Fallback for unrecognized routes
|
||||||
res.writeHead(404, { "Content-Type": "text/plain" });
|
res.writeHead(404, { "Content-Type": "text/plain" });
|
||||||
|
|
|
@ -44,7 +44,7 @@ declare interface Ride {
|
||||||
fare_price: number;
|
fare_price: number;
|
||||||
payment_status: string;
|
payment_status: string;
|
||||||
driver_id: number;
|
driver_id: number;
|
||||||
user_email: string;
|
user_email?: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
driver: {
|
driver: {
|
||||||
first_name: string;
|
first_name: string;
|
||||||
|
|
Loading…
Reference in New Issue