diff --git a/app/(auth)/_layout.tsx b/app/(auth)/_layout.tsx
new file mode 100644
index 0000000..9917912
--- /dev/null
+++ b/app/(auth)/_layout.tsx
@@ -0,0 +1,13 @@
+import { Stack } from "expo-router";
+
+const AuthLayout = () => {
+ return (
+
+
+
+
+
+ );
+};
+
+export default AuthLayout;
diff --git a/app/(auth)/sign-in.tsx b/app/(auth)/sign-in.tsx
new file mode 100644
index 0000000..60cae36
--- /dev/null
+++ b/app/(auth)/sign-in.tsx
@@ -0,0 +1,12 @@
+import { Text } from "react-native";
+import { SafeAreaView } from "react-native-safe-area-context";
+
+const SignIn = () => {
+ return (
+
+ SignIn
+
+ );
+};
+
+export default SignIn;
diff --git a/app/(auth)/sign-up.tsx b/app/(auth)/sign-up.tsx
new file mode 100644
index 0000000..be38c49
--- /dev/null
+++ b/app/(auth)/sign-up.tsx
@@ -0,0 +1,12 @@
+import { Text } from "react-native";
+import { SafeAreaView } from "react-native-safe-area-context";
+
+const SignUp = () => {
+ return (
+
+ SignUp
+
+ );
+};
+
+export default SignUp;
diff --git a/app/(auth)/welcome.tsx b/app/(auth)/welcome.tsx
new file mode 100644
index 0000000..72d5f1e
--- /dev/null
+++ b/app/(auth)/welcome.tsx
@@ -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(null);
+ const [activeIndex, setActiveIndex] = useState(0);
+ const isLastSlide = activeIndex === onboarding.length - 1;
+
+ return (
+
+ router.replace("/(auth)/sign-up")}
+ className="w-full flex justify-end items-end p-5"
+ >
+ Skip
+
+
+ }
+ activeDot={}
+ index={activeIndex}
+ onIndexChanged={setActiveIndex}
+ >
+ {onboarding.map((item) => (
+
+
+
+
+
+ {item.title}
+
+
+
+
+ {item.description}
+
+
+ ))}
+
+
+
+ isLastSlide
+ ? router.replace("/(auth)/sign-up")
+ : swiperRef.current?.scrollBy(1)
+ }
+ title={isLastSlide ? "Get Started" : "Next"}
+ className="w-11/12 mt-10"
+ />
+
+ );
+};
+
+export default Welcome;
diff --git a/app/(root)/(tabs)/_layout.tsx b/app/(root)/(tabs)/_layout.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/app/(root)/(tabs)/chat.tsx b/app/(root)/(tabs)/chat.tsx
new file mode 100644
index 0000000..16d0727
--- /dev/null
+++ b/app/(root)/(tabs)/chat.tsx
@@ -0,0 +1,12 @@
+import { Text } from "react-native";
+import { SafeAreaView } from "react-native-safe-area-context";
+
+const Chat = () => {
+ return (
+
+ Chat
+
+ );
+};
+
+export default Chat;
diff --git a/app/(root)/(tabs)/home.tsx b/app/(root)/(tabs)/home.tsx
new file mode 100644
index 0000000..4fe8492
--- /dev/null
+++ b/app/(root)/(tabs)/home.tsx
@@ -0,0 +1,12 @@
+import { Text } from "react-native";
+import { SafeAreaView } from "react-native-safe-area-context";
+
+const Home = () => {
+ return (
+
+ Home
+
+ );
+};
+
+export default Home;
diff --git a/app/(root)/(tabs)/profile.tsx b/app/(root)/(tabs)/profile.tsx
new file mode 100644
index 0000000..4d44dfd
--- /dev/null
+++ b/app/(root)/(tabs)/profile.tsx
@@ -0,0 +1,12 @@
+import { Text } from "react-native";
+import { SafeAreaView } from "react-native-safe-area-context";
+
+const Profile = () => {
+ return (
+
+ Profile
+
+ );
+};
+
+export default Profile;
diff --git a/app/(root)/(tabs)/rides.tsx b/app/(root)/(tabs)/rides.tsx
new file mode 100644
index 0000000..af2a22b
--- /dev/null
+++ b/app/(root)/(tabs)/rides.tsx
@@ -0,0 +1,12 @@
+import { Text } from "react-native";
+import { SafeAreaView } from "react-native-safe-area-context";
+
+const Rides = () => {
+ return (
+
+ Rides
+
+ );
+};
+
+export default Rides;
diff --git a/app/(root)/_layout.tsx b/app/(root)/_layout.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/app/_layout.tsx b/app/_layout.tsx
index ae7f26a..e9ca36f 100644
--- a/app/_layout.tsx
+++ b/app/_layout.tsx
@@ -7,7 +7,7 @@ import "react-native-reanimated";
// Prevent the splash screen from auto-hiding before asset loading is complete.
SplashScreen.preventAutoHideAsync();
-export default function RootLayout() {
+const RootLayout = () => {
const [loaded] = useFonts({
"Jakarta-Bold": require("../assets/fonts/PlusJakartaSans-Bold.ttf"),
"Jakarta-ExtraBold": require("../assets/fonts/PlusJakartaSans-ExtraBold.ttf"),
@@ -31,7 +31,10 @@ export default function RootLayout() {
return (
-
+
+
);
-}
+};
+
+export default RootLayout;
diff --git a/app/index.tsx b/app/index.tsx
index 4fe8492..177abaa 100644
--- a/app/index.tsx
+++ b/app/index.tsx
@@ -1,12 +1,7 @@
-import { Text } from "react-native";
-import { SafeAreaView } from "react-native-safe-area-context";
+import { Redirect } from "expo-router";
-const Home = () => {
- return (
-
- Home
-
- );
+const App = () => {
+ return ;
};
-export default Home;
+export default App;
diff --git a/components/custom-button.tsx b/components/custom-button.tsx
new file mode 100644
index 0000000..698bc0d
--- /dev/null
+++ b/components/custom-button.tsx
@@ -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) => (
+
+ {IconLeft && }
+
+
+ {title}
+
+
+ {IconRight && }
+
+);
diff --git a/constants/index.ts b/constants/index.ts
new file mode 100644
index 0000000..a73b69b
--- /dev/null
+++ b/constants/index.ts
@@ -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,
+};
diff --git a/types/image.d.ts b/types/image.d.ts
new file mode 100644
index 0000000..bb75dcc
--- /dev/null
+++ b/types/image.d.ts
@@ -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;
+}
diff --git a/types/type.d.ts b/types/type.d.ts
new file mode 100644
index 0000000..79b07fd
--- /dev/null
+++ b/types/type.d.ts
@@ -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;
+ iconRight?: React.ComponentType;
+ 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;
+}