find ride and book ride page ui created

This commit is contained in:
Sanidhya Kumar Verma
2024-09-04 06:42:36 +00:00
committed by GitHub
parent 78ba198a1f
commit 0b2a3ee944
7 changed files with 252 additions and 10 deletions
+3
View File
@@ -4,6 +4,9 @@ const RootLayout = () => {
return ( return (
<Stack> <Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} /> <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="find-ride" options={{ headerShown: false }} />
<Stack.Screen name="confirm-ride" options={{ headerShown: false }} />
{/* <Stack.Screen name="book-ride" options={{ headerShown: false }} /> */}
</Stack> </Stack>
); );
}; };
+36
View File
@@ -0,0 +1,36 @@
import { FlatList, View } from "react-native";
import { DriverCard } from "@/components/driver-card";
import { RideLayout } from "@/components/ride-layout";
import { CustomButton } from "@/components/custom-button";
import { router } from "expo-router";
import { useDriverStore } from "@/store";
const ConfirmRide = () => {
const { drivers, selectedDriver, setSelectedDriver } = useDriverStore();
return (
<RideLayout title="Choose a Driver" snapPoints={["65%", "85%"]}>
<FlatList
data={drivers}
renderItem={({ item }) => (
<DriverCard
item={item}
selected={selectedDriver ?? 0}
setSelected={() => setSelectedDriver(item.id)}
/>
)}
ListFooterComponent={() => (
<View className="mx-5 mt-10">
<CustomButton
title="Select Ride"
onPress={() => router.replace("/(root)/book-ride")}
/>
</View>
)}
/>
</RideLayout>
);
};
export default ConfirmRide;
+44 -3
View File
@@ -1,10 +1,51 @@
import { CustomButton } from "@/components/custom-button";
import { GoogleTextInput } from "@/components/google-text-input";
import { RideLayout } from "@/components/ride-layout";
import { icons } from "@/constants";
import { useLocationStore } from "@/store";
import { router } from "expo-router";
import { Text, View } from "react-native"; import { Text, View } from "react-native";
const FindRide = () => { const FindRide = () => {
const {
userAddress,
destinationAddress,
setDestinationLocation,
setUserLocation,
} = useLocationStore();
return ( return (
<View> <RideLayout title="Ride" snapPoints={["85%"]}>
<Text>Find Ride</Text> <View className="my-3">
</View> <Text className="text-lg font-JakartaSemiBold mb-3">From</Text>
<GoogleTextInput
icon={icons.target}
initialLocation={userAddress ?? ""}
containerStyles="bg-neutral-100"
textInputBackgroundColor="#F5F5F5"
handlePress={setUserLocation}
/>
</View>
<View className="my-3">
<Text className="text-lg font-JakartaSemiBold mb-3">To</Text>
<GoogleTextInput
icon={icons.map}
initialLocation={destinationAddress ?? ""}
containerStyles="bg-neutral-100"
textInputBackgroundColor="transparent"
handlePress={setDestinationLocation}
/>
</View>
<CustomButton
title="Find now"
onPress={() => router.replace("/(root)/confirm-ride")}
className="mt-5"
/>
</RideLayout>
); );
}; };
+69
View File
@@ -0,0 +1,69 @@
import { Image, Text, TouchableOpacity, View } from "react-native";
import { icons } from "@/constants";
import { formatTime } from "@/lib/utils";
import { DriverCardProps } from "@/types/type";
export const DriverCard = ({
item,
selected,
setSelected,
}: DriverCardProps) => {
return (
<TouchableOpacity
onPress={setSelected}
className={`${
selected === item.id ? "bg-general-600" : "bg-white"
} flex flex-row items-center justify-between py-5 px-3 rounded-xl`}
>
<Image
source={{ uri: item.profile_image_url }}
alt="Driver Avatar"
className="w-14 h-14 rounded-full"
/>
<View className="flex-1 flex flex-col items-start justify-center mx-3">
<View className="flex flex-row items-center justify-start mb-1">
<Text className="text-lg font-JakartaRegular">{item.title}</Text>
<View className="flex flex-row items-center space-x-1 ml-2">
<Image source={icons.star} alt="Star" className="w-3.5 h-3.5" />
<Text className="text-sm font-JakartaRegular">4</Text>
</View>
</View>
<View className="flex flex-row items-center justify-start">
<View className="flex flex-row items-center">
<Image source={icons.dollar} alt="Dollar" className="w-4 h-4" />
<Text className="text-sm font-JakartaRegular ml-1">
${item.price}
</Text>
</View>
<Text className="text-sm font-JakartaRegular text-general-800 mx-1">
|
</Text>
<Text className="text-sm font-JakartaRegular text-general-800">
{formatTime(item.time!)}
</Text>
<Text className="text-sm font-JakartaRegular text-general-800 mx-1">
|
</Text>
<Text className="text-sm font-JakartaRegular text-general-800">
{item.car_seats} seats
</Text>
</View>
</View>
<Image
source={{ uri: item.car_image_url }}
alt="Car"
className="h-14 w-14"
resizeMode="contain"
/>
</TouchableOpacity>
);
};
+12 -3
View File
@@ -1,4 +1,4 @@
import { View, Image } from "react-native"; import { View, Image, TouchableOpacity } from "react-native";
import { GooglePlacesAutocomplete } from "react-native-google-places-autocomplete"; import { GooglePlacesAutocomplete } from "react-native-google-places-autocomplete";
import { icons } from "@/constants"; import { icons } from "@/constants";
@@ -64,13 +64,22 @@ export const GoogleTextInput = ({
language: "en", language: "en",
}} }}
renderLeftButton={() => ( renderLeftButton={() => (
<View className="justify-center items-center w-6 h-6"> <TouchableOpacity
onPress={() => {
handlePress({
latitude: 26.8467,
longitude: 80.9462,
address: "Lucknow, Uttar Pradesh",
});
}}
className="justify-center items-center w-6 h-6"
>
<Image <Image
source={icon ? icon : icons.search} source={icon ? icon : icons.search}
className="w-6 h-6" className="w-6 h-6"
resizeMode="contain" resizeMode="contain"
/> />
</View> </TouchableOpacity>
)} )}
textInputProps={{ textInputProps={{
placeholderTextColor: "gray", placeholderTextColor: "gray",
+26 -4
View File
@@ -8,7 +8,7 @@ import { icons } from "@/constants";
const drivers = [ const drivers = [
{ {
id: "1", id: 1,
driver_id: 1, driver_id: 1,
first_name: "James", first_name: "James",
last_name: "Wilson", last_name: "Wilson",
@@ -18,9 +18,14 @@ const drivers = [
"https://ucarecdn.com/a2dc52b2-8bf7-4e49-9a36-3ffb5229ed02/-/preview/465x466/", "https://ucarecdn.com/a2dc52b2-8bf7-4e49-9a36-3ffb5229ed02/-/preview/465x466/",
car_seats: 4, car_seats: 4,
rating: 4.8, rating: 4.8,
latitude: 0,
longitude: 0,
title: "",
price: "45",
time: 5,
}, },
{ {
id: "2", id: 2,
driver_id: 2, driver_id: 2,
first_name: "David", first_name: "David",
last_name: "Brown", last_name: "Brown",
@@ -30,9 +35,14 @@ const drivers = [
"https://ucarecdn.com/a3872f80-c094-409c-82f8-c9ff38429327/-/preview/930x932/", "https://ucarecdn.com/a3872f80-c094-409c-82f8-c9ff38429327/-/preview/930x932/",
car_seats: 5, car_seats: 5,
rating: 4.6, rating: 4.6,
latitude: 0,
longitude: 0,
title: "",
price: "45",
time: 5,
}, },
{ {
id: "3", id: 3,
driver_id: 3, driver_id: 3,
first_name: "Michael", first_name: "Michael",
last_name: "Johnson", last_name: "Johnson",
@@ -42,9 +52,14 @@ const drivers = [
"https://ucarecdn.com/289764fb-55b6-4427-b1d1-f655987b4a14/-/preview/930x932/", "https://ucarecdn.com/289764fb-55b6-4427-b1d1-f655987b4a14/-/preview/930x932/",
car_seats: 4, car_seats: 4,
rating: 4.7, rating: 4.7,
latitude: 0,
longitude: 0,
title: "",
price: "45",
time: 5,
}, },
{ {
id: "4", id: 4,
driver_id: 4, driver_id: 4,
first_name: "Robert", first_name: "Robert",
last_name: "Green", last_name: "Green",
@@ -54,6 +69,11 @@ const drivers = [
"https://ucarecdn.com/b6fb3b55-7676-4ff3-8484-fb115e268d32/-/preview/930x932/", "https://ucarecdn.com/b6fb3b55-7676-4ff3-8484-fb115e268d32/-/preview/930x932/",
car_seats: 4, car_seats: 4,
rating: 4.9, rating: 4.9,
latitude: 0,
longitude: 0,
title: "",
price: "45",
time: 5,
}, },
]; ];
@@ -76,6 +96,8 @@ export const Map = () => {
useEffect(() => { useEffect(() => {
if (Array.isArray(drivers)) { if (Array.isArray(drivers)) {
setDrivers(drivers);
if (!userLatitude || !userLongitude) return; if (!userLatitude || !userLongitude) return;
const newMarkers = generateMarkersFromData({ const newMarkers = generateMarkersFromData({
+62
View File
@@ -0,0 +1,62 @@
import BottomSheet, { BottomSheetView } from "@gorhom/bottom-sheet";
import { router } from "expo-router";
import { useRef, type PropsWithChildren } from "react";
import { Image, Text, TouchableOpacity, View } from "react-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { icons } from "@/constants";
import { Map } from "./map";
type RideLayoutProps = {
title?: string;
snapPoints?: string[];
};
export const RideLayout = ({
title = "Go Back",
snapPoints,
children,
}: PropsWithChildren<RideLayoutProps>) => {
const bottomSheetRef = useRef<BottomSheet>(null);
return (
<GestureHandlerRootView>
<View className="flex-1 bg-white">
<View className="flex flex-col h-screen bg-blue-500">
<View className="flex flex-row absolute z-10 top-16 items-center justify-start px-5">
<TouchableOpacity onPress={() => router.back()}>
<View className="w-10 h-10 bg-white rounded-full items-center justify-center">
<Image
source={icons.backArrow}
resizeMode="contain"
className="w-6 h-6"
/>
</View>
</TouchableOpacity>
<Text className="text-xl font-JakartaSemiBold ml-5">{title}</Text>
</View>
<Map />
</View>
<BottomSheet
keyboardBehavior="extend"
ref={bottomSheetRef}
snapPoints={snapPoints ?? ["40%", "85%"]}
index={0}
>
<BottomSheetView
style={{
flex: 1,
padding: 20,
}}
>
{children}
</BottomSheetView>
</BottomSheet>
</View>
</GestureHandlerRootView>
);
};