basic layout created and welcome onboarding screen implemented
This commit is contained in:
committed by
GitHub
parent
a72a83ebe3
commit
77030fd4c2
@@ -0,0 +1,13 @@
|
|||||||
|
import { Stack } from "expo-router";
|
||||||
|
|
||||||
|
const AuthLayout = () => {
|
||||||
|
return (
|
||||||
|
<Stack>
|
||||||
|
<Stack.Screen name="welcome" options={{ headerShown: false }} />
|
||||||
|
<Stack.Screen name="sign-up" options={{ headerShown: false }} />
|
||||||
|
<Stack.Screen name="sign-in" options={{ headerShown: false }} />
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AuthLayout;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { Text } from "react-native";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
|
||||||
|
const SignIn = () => {
|
||||||
|
return (
|
||||||
|
<SafeAreaView>
|
||||||
|
<Text>SignIn</Text>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SignIn;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { Text } from "react-native";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
|
||||||
|
const SignUp = () => {
|
||||||
|
return (
|
||||||
|
<SafeAreaView>
|
||||||
|
<Text>SignUp</Text>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SignUp;
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
import { CustomButton } from "@/components/custom-button";
|
||||||
|
import { onboarding } from "@/constants";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import { useRef, useState } from "react";
|
||||||
|
import { Image, Text, TouchableOpacity, View } from "react-native";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
import Swiper from "react-native-swiper";
|
||||||
|
|
||||||
|
const Welcome = () => {
|
||||||
|
const swiperRef = useRef<Swiper>(null);
|
||||||
|
const [activeIndex, setActiveIndex] = useState(0);
|
||||||
|
const isLastSlide = activeIndex === onboarding.length - 1;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView className="flex h-full items-center justify-between bg-white">
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => router.replace("/(auth)/sign-up")}
|
||||||
|
className="w-full flex justify-end items-end p-5"
|
||||||
|
>
|
||||||
|
<Text className="text-black text-base font-JakartaBold">Skip</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<Swiper
|
||||||
|
ref={swiperRef}
|
||||||
|
loop={false}
|
||||||
|
dot={<View className="w-8 h-1 mx-1 bg-[#E2E8F0] rounded-full" />}
|
||||||
|
activeDot={<View className="w-8 h-1 mx-1 bg-[#0286FF] rounded-full" />}
|
||||||
|
index={activeIndex}
|
||||||
|
onIndexChanged={setActiveIndex}
|
||||||
|
>
|
||||||
|
{onboarding.map((item) => (
|
||||||
|
<View key={item.id} className="flex items-center justify-center p-5">
|
||||||
|
<Image
|
||||||
|
source={item.image}
|
||||||
|
className="w-full h-[300px]"
|
||||||
|
resizeMode="contain"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<View className="flex flex-row items-center justify-center w-full mt-10">
|
||||||
|
<Text className="text-black text-3xl font-bold mx-10 text-center">
|
||||||
|
{item.title}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text className="text-base font-JakartaSemiBold text-center text-[#858585] mx-10 mt-3">
|
||||||
|
{item.description}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</Swiper>
|
||||||
|
|
||||||
|
<CustomButton
|
||||||
|
onPress={() =>
|
||||||
|
isLastSlide
|
||||||
|
? router.replace("/(auth)/sign-up")
|
||||||
|
: swiperRef.current?.scrollBy(1)
|
||||||
|
}
|
||||||
|
title={isLastSlide ? "Get Started" : "Next"}
|
||||||
|
className="w-11/12 mt-10"
|
||||||
|
/>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Welcome;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { Text } from "react-native";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
|
||||||
|
const Chat = () => {
|
||||||
|
return (
|
||||||
|
<SafeAreaView>
|
||||||
|
<Text>Chat</Text>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Chat;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { Text } from "react-native";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
|
||||||
|
const Home = () => {
|
||||||
|
return (
|
||||||
|
<SafeAreaView>
|
||||||
|
<Text>Home</Text>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Home;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { Text } from "react-native";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
|
||||||
|
const Profile = () => {
|
||||||
|
return (
|
||||||
|
<SafeAreaView>
|
||||||
|
<Text>Profile</Text>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Profile;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { Text } from "react-native";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
|
||||||
|
const Rides = () => {
|
||||||
|
return (
|
||||||
|
<SafeAreaView>
|
||||||
|
<Text>Rides</Text>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Rides;
|
||||||
+6
-3
@@ -7,7 +7,7 @@ import "react-native-reanimated";
|
|||||||
// Prevent the splash screen from auto-hiding before asset loading is complete.
|
// Prevent the splash screen from auto-hiding before asset loading is complete.
|
||||||
SplashScreen.preventAutoHideAsync();
|
SplashScreen.preventAutoHideAsync();
|
||||||
|
|
||||||
export default function RootLayout() {
|
const RootLayout = () => {
|
||||||
const [loaded] = useFonts({
|
const [loaded] = useFonts({
|
||||||
"Jakarta-Bold": require("../assets/fonts/PlusJakartaSans-Bold.ttf"),
|
"Jakarta-Bold": require("../assets/fonts/PlusJakartaSans-Bold.ttf"),
|
||||||
"Jakarta-ExtraBold": require("../assets/fonts/PlusJakartaSans-ExtraBold.ttf"),
|
"Jakarta-ExtraBold": require("../assets/fonts/PlusJakartaSans-ExtraBold.ttf"),
|
||||||
@@ -31,7 +31,10 @@ export default function RootLayout() {
|
|||||||
return (
|
return (
|
||||||
<Stack>
|
<Stack>
|
||||||
<Stack.Screen name="index" options={{ headerShown: false }} />
|
<Stack.Screen name="index" options={{ headerShown: false }} />
|
||||||
<Stack.Screen name="+not-found" />
|
<Stack.Screen name="(root)" options={{ headerShown: false }} />
|
||||||
|
<Stack.Screen name="(auth)" options={{ headerShown: false }} />
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default RootLayout;
|
||||||
|
|||||||
+4
-9
@@ -1,12 +1,7 @@
|
|||||||
import { Text } from "react-native";
|
import { Redirect } from "expo-router";
|
||||||
import { SafeAreaView } from "react-native-safe-area-context";
|
|
||||||
|
|
||||||
const Home = () => {
|
const App = () => {
|
||||||
return (
|
return <Redirect href="/(auth)/welcome" />;
|
||||||
<SafeAreaView>
|
|
||||||
<Text>Home</Text>
|
|
||||||
</SafeAreaView>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Home;
|
export default App;
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import { ButtonProps } from "@/types/type";
|
||||||
|
import React from "react";
|
||||||
|
import { Text, TouchableOpacity } from "react-native";
|
||||||
|
|
||||||
|
const getBgVariantStyle = (variant: ButtonProps["bgVariant"]) => {
|
||||||
|
switch (variant) {
|
||||||
|
case "secondary":
|
||||||
|
return "bg-gray-500";
|
||||||
|
case "danger":
|
||||||
|
return "bg-rose-500";
|
||||||
|
case "success":
|
||||||
|
return "bg-emerald-500";
|
||||||
|
case "outline":
|
||||||
|
return "bg-transparent-500 border-neutral-300 border-[0.5px]";
|
||||||
|
default:
|
||||||
|
return "bg-[#0286ff]";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTextVariantStyle = (variant: ButtonProps["textVariant"]) => {
|
||||||
|
switch (variant) {
|
||||||
|
case "primary":
|
||||||
|
return "text-black";
|
||||||
|
case "secondary":
|
||||||
|
return "text-gray-100";
|
||||||
|
case "danger":
|
||||||
|
return "text-rose-100";
|
||||||
|
case "success":
|
||||||
|
return "text-emerald-100";
|
||||||
|
default:
|
||||||
|
return "text-white";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CustomButton = ({
|
||||||
|
onPress,
|
||||||
|
title,
|
||||||
|
bgVariant = "primary",
|
||||||
|
textVariant = "default",
|
||||||
|
iconLeft: IconLeft,
|
||||||
|
iconRight: IconRight,
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: ButtonProps) => (
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={onPress}
|
||||||
|
className={`w-full rounded-full p-3 flex flex-row justify-center items-center shadow-md shadow-neutral-400/70 ${getBgVariantStyle(bgVariant)} ${className}`}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{IconLeft && <IconLeft />}
|
||||||
|
|
||||||
|
<Text className={`text-lg font-bold ${getTextVariantStyle(textVariant)}`}>
|
||||||
|
{title}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
{IconRight && <IconRight />}
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
import arrowDown from "@/assets/icons/arrow-down.png";
|
||||||
|
import arrowUp from "@/assets/icons/arrow-up.png";
|
||||||
|
import backArrow from "@/assets/icons/back-arrow.png";
|
||||||
|
import chat from "@/assets/icons/chat.png";
|
||||||
|
import checkmark from "@/assets/icons/check.png";
|
||||||
|
import close from "@/assets/icons/close.png";
|
||||||
|
import dollar from "@/assets/icons/dollar.png";
|
||||||
|
import email from "@/assets/icons/email.png";
|
||||||
|
import eyecross from "@/assets/icons/eyecross.png";
|
||||||
|
import google from "@/assets/icons/google.png";
|
||||||
|
import home from "@/assets/icons/home.png";
|
||||||
|
import list from "@/assets/icons/list.png";
|
||||||
|
import lock from "@/assets/icons/lock.png";
|
||||||
|
import map from "@/assets/icons/map.png";
|
||||||
|
import marker from "@/assets/icons/marker.png";
|
||||||
|
import out from "@/assets/icons/out.png";
|
||||||
|
import person from "@/assets/icons/person.png";
|
||||||
|
import pin from "@/assets/icons/pin.png";
|
||||||
|
import point from "@/assets/icons/point.png";
|
||||||
|
import profile from "@/assets/icons/profile.png";
|
||||||
|
import search from "@/assets/icons/search.png";
|
||||||
|
import selectedMarker from "@/assets/icons/selected-marker.png";
|
||||||
|
import star from "@/assets/icons/star.png";
|
||||||
|
import target from "@/assets/icons/target.png";
|
||||||
|
import to from "@/assets/icons/to.png";
|
||||||
|
import check from "@/assets/images/check.png";
|
||||||
|
import getStarted from "@/assets/images/get-started.png";
|
||||||
|
import message from "@/assets/images/message.png";
|
||||||
|
import noResult from "@/assets/images/no-result.png";
|
||||||
|
import onboarding1 from "@/assets/images/onboarding1.png";
|
||||||
|
import onboarding2 from "@/assets/images/onboarding2.png";
|
||||||
|
import onboarding3 from "@/assets/images/onboarding3.png";
|
||||||
|
import signUpCar from "@/assets/images/signup-car.png";
|
||||||
|
|
||||||
|
export const images = {
|
||||||
|
onboarding1,
|
||||||
|
onboarding2,
|
||||||
|
onboarding3,
|
||||||
|
getStarted,
|
||||||
|
signUpCar,
|
||||||
|
check,
|
||||||
|
noResult,
|
||||||
|
message,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const icons = {
|
||||||
|
arrowDown,
|
||||||
|
arrowUp,
|
||||||
|
backArrow,
|
||||||
|
chat,
|
||||||
|
checkmark,
|
||||||
|
close,
|
||||||
|
dollar,
|
||||||
|
email,
|
||||||
|
eyecross,
|
||||||
|
google,
|
||||||
|
home,
|
||||||
|
list,
|
||||||
|
lock,
|
||||||
|
map,
|
||||||
|
marker,
|
||||||
|
out,
|
||||||
|
person,
|
||||||
|
pin,
|
||||||
|
point,
|
||||||
|
profile,
|
||||||
|
search,
|
||||||
|
selectedMarker,
|
||||||
|
star,
|
||||||
|
target,
|
||||||
|
to,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const onboarding = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "The perfect ride is just a tap away!",
|
||||||
|
description:
|
||||||
|
"Your journey begins with Ryde. Find your ideal ride effortlessly.",
|
||||||
|
image: images.onboarding1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: "Best car in your hands with Ryde",
|
||||||
|
description:
|
||||||
|
"Discover the convenience of finding your perfect ride with Ryde",
|
||||||
|
image: images.onboarding2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: "Your ride, your way. Let's go!",
|
||||||
|
description:
|
||||||
|
"Enter your destination, sit back, and let us take care of the rest.",
|
||||||
|
image: images.onboarding3,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const data = {
|
||||||
|
onboarding,
|
||||||
|
};
|
||||||
Vendored
+24
@@ -0,0 +1,24 @@
|
|||||||
|
declare module "*.png" {
|
||||||
|
const value: any;
|
||||||
|
export default value;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module "*.jpg" {
|
||||||
|
const value: any;
|
||||||
|
export default value;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module "*.jpeg" {
|
||||||
|
const value: any;
|
||||||
|
export default value;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module "*.gif" {
|
||||||
|
const value: any;
|
||||||
|
export default value;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module "*.svg" {
|
||||||
|
const value: any;
|
||||||
|
export default value;
|
||||||
|
}
|
||||||
Vendored
+139
@@ -0,0 +1,139 @@
|
|||||||
|
import { TextInputProps, TouchableOpacityProps } from "react-native";
|
||||||
|
|
||||||
|
declare interface Driver {
|
||||||
|
driver_id: number;
|
||||||
|
first_name: string;
|
||||||
|
last_name: string;
|
||||||
|
profile_image_url: string;
|
||||||
|
car_image_url: string;
|
||||||
|
car_seats: number;
|
||||||
|
rating: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare interface MarkerData {
|
||||||
|
latitude: number;
|
||||||
|
longitude: number;
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
profile_image_url: string;
|
||||||
|
car_image_url: string;
|
||||||
|
car_seats: number;
|
||||||
|
rating: number;
|
||||||
|
first_name: string;
|
||||||
|
last_name: string;
|
||||||
|
time?: number;
|
||||||
|
price?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare interface MapProps {
|
||||||
|
destinationLatitude?: number;
|
||||||
|
destinationLongitude?: number;
|
||||||
|
onDriverTimesCalculated?: (driversWithTimes: MarkerData[]) => void;
|
||||||
|
selectedDriver?: number | null;
|
||||||
|
onMapReady?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare interface Ride {
|
||||||
|
origin_address: string;
|
||||||
|
destination_address: string;
|
||||||
|
origin_latitude: number;
|
||||||
|
origin_longitude: number;
|
||||||
|
destination_latitude: number;
|
||||||
|
destination_longitude: number;
|
||||||
|
ride_time: number;
|
||||||
|
fare_price: number;
|
||||||
|
payment_status: string;
|
||||||
|
driver_id: number;
|
||||||
|
user_email: string;
|
||||||
|
created_at: string;
|
||||||
|
driver: {
|
||||||
|
first_name: string;
|
||||||
|
last_name: string;
|
||||||
|
car_seats: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
declare interface ButtonProps extends TouchableOpacityProps {
|
||||||
|
title: string;
|
||||||
|
bgVariant?: "primary" | "secondary" | "danger" | "outline" | "success";
|
||||||
|
textVariant?: "primary" | "default" | "secondary" | "danger" | "success";
|
||||||
|
iconLeft?: React.ComponentType<any>;
|
||||||
|
iconRight?: React.ComponentType<any>;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare interface GoogleInputProps {
|
||||||
|
icon?: string;
|
||||||
|
initialLocation?: string;
|
||||||
|
containerStyle?: string;
|
||||||
|
textInputBackgroundColor?: string;
|
||||||
|
handlePress: ({
|
||||||
|
latitude,
|
||||||
|
longitude,
|
||||||
|
address,
|
||||||
|
}: {
|
||||||
|
latitude: number;
|
||||||
|
longitude: number;
|
||||||
|
address: string;
|
||||||
|
}) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare interface InputFieldProps extends TextInputProps {
|
||||||
|
label: string;
|
||||||
|
icon?: any;
|
||||||
|
secureTextEntry?: boolean;
|
||||||
|
labelStyle?: string;
|
||||||
|
containerStyle?: string;
|
||||||
|
inputStyle?: string;
|
||||||
|
iconStyle?: string;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare interface PaymentProps {
|
||||||
|
fullName: string;
|
||||||
|
email: string;
|
||||||
|
amount: string;
|
||||||
|
driverId: number;
|
||||||
|
rideTime: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare interface LocationStore {
|
||||||
|
userLatitude: number | null;
|
||||||
|
userLongitude: number | null;
|
||||||
|
userAddress: string | null;
|
||||||
|
destinationLatitude: number | null;
|
||||||
|
destinationLongitude: number | null;
|
||||||
|
destinationAddress: string | null;
|
||||||
|
setUserLocation: ({
|
||||||
|
latitude,
|
||||||
|
longitude,
|
||||||
|
address,
|
||||||
|
}: {
|
||||||
|
latitude: number;
|
||||||
|
longitude: number;
|
||||||
|
address: string;
|
||||||
|
}) => void;
|
||||||
|
setDestinationLocation: ({
|
||||||
|
latitude,
|
||||||
|
longitude,
|
||||||
|
address,
|
||||||
|
}: {
|
||||||
|
latitude: number;
|
||||||
|
longitude: number;
|
||||||
|
address: string;
|
||||||
|
}) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare interface DriverStore {
|
||||||
|
drivers: MarkerData[];
|
||||||
|
selectedDriver: number | null;
|
||||||
|
setSelectedDriver: (driverId: number) => void;
|
||||||
|
setDrivers: (drivers: MarkerData[]) => void;
|
||||||
|
clearSelectedDriver: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare interface DriverCardProps {
|
||||||
|
item: MarkerData;
|
||||||
|
selected: number;
|
||||||
|
setSelected: () => void;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user