Build a Full Stack React Native App with Payments | PostgreSQL, TypeScript, Stripe, Tailwind — Transcript
Full transcript
- 0:00do you want to create feature full Stack
- 0:02mobile applications that push the
- 0:04boundaries of what's possible leave a
- 0:06lasting impression and set you aart if
- 0:08so you're in the right place hi there
- 0:11and welcome to a highly anticipated
- 0:13course where you'll build a full stack
- 0:15Uber clone and no this won't be your
- 0:18average app showing a map on a screen
- 0:20I'm talking about a 15 screen
- 0:23state-of-the-art application that uses
- 0:25expo's latest features such as Expo
- 0:27router API routes Expo location
- 0:30Lightning Fast EDG ready postgress
- 0:32database Global State Management with
- 0:35zest stand and many others after taking
- 0:37this course you can build any mobile app
- 0:39you can imagine why because I didn't cut
- 0:42any Corners when making it I decided to
- 0:44include screens that appear on all of
- 0:46the most popular apps in the world
- 0:48you'll learn how to make splash screens
- 0:50and onboarding flows add authentication
- 0:52access device sensors integrate Maps
- 0:55build custom tabs navigation models
- 0:57bottom sheets success screens and even
- 1:00integrate payments using stripe there
- 1:02are also some Uber specific features
- 1:04you'll Implement such as live Google
- 1:06location with Google maps showing nearby
- 1:08rides search relocations using Google
- 1:10Places choose a destination driver and
- 1:13book a ride get directions and estimated
- 1:16time see all booked rides and your
- 1:19profile details alongside this video in
- 1:21the description below I've also prepared
- 1:23the ultimate react native guide that
- 1:25covers everything you need to know to
- 1:27become a fantastic developer the guide
- 1:29covers the complete react native Road
- 1:31mapap prerequisites and essential react
- 1:34native Concepts and project ideas you
- 1:36can build and deploy to get a job you
- 1:38can download the guide and use it as a
- 1:40reference whenever you're unsure what to
- 1:42do next of course the guide is
- 1:44completely free and once again the link
- 1:46is in the description alongside that in
- 1:48this video I'll teach you react native
- 1:50fundamentals Expo router for file-based
- 1:53navigation zustand for Global State
- 1:55Management native wind for styling Expo
- 1:58API routes stripe payments data fetching
- 2:01with custom hooks reusable Advanced
- 2:03components with best practices
- 2:05typescript for writing types safe code
- 2:07es length and preder for organizing the
- 2:09code authentication with email
- 2:12verification using Clerk and even
- 2:14postgress using neon a serverless fully
- 2:17managed postgress database that
- 2:18automatically scales resources and lets
- 2:21you write native SQL queries it is so
- 2:24good that even versell uses it behind
- 2:26the scenes for their versell postgress
- 2:28service now with even better teaching
- 2:30methods you'll get an open source
- 2:32codebase a custom figma design and a
- 2:34Discord server with a dedicated Uber
- 2:36channel to resolve bugs if you get stuck
- 2:39all those things are free so grab those
- 2:41from the links below while I continue
- 2:42telling you more about the project a
- 2:45basic to medium understanding of react
- 2:47native is needed so if you're not quite
- 2:49there yet check out the react native
- 2:51crash course and come right back and
- 2:53we're also working on the ultimate react
- 2:55native course to learn more about it
- 2:57check out the first page in the guide
- 2:59that I mentioned before in this course
- 3:01though I'll also teach you how to set up
- 3:03an IDE you didn't know you needed
- 3:05webstorm is a professional JavaScript
- 3:07and typescript IDE that will make you so
- 3:09efficient you'll wonder what you were
- 3:11doing all this time Jed brains reached
- 3:13out to sponsor this video and initially
- 3:15I was skeptical about switching from the
- 3:17code editor I've been so used to so I
- 3:20used it for over 3 months to test it for
- 3:21myself and oh boy is it powerful I can't
- 3:25wait to share everything it can do I'll
- 3:26do it later on while we're developing
- 3:28the application but just to say it
- 3:30quickly it has smart terminal with auto
- 3:32suggestions typescript type suggestions
- 3:34code completion automatic bug fixes
- 3:37oneclick refactoring speed search and an
- 3:40integrated git and GitHub system and
- 3:42here's the best part clicking the link
- 3:43in the description will give you a free
- 3:4590-day access plus if you're a student
- 3:48it'll remain free download it while I
- 3:50continue telling you more about the app
- 3:51will build today when you first launch
- 3:53the app a custom splash screen will
- 3:55appear for a few seconds you'll then go
- 3:58through a smooth onboarding process
- 3:59process highlighting the app's main
- 4:01features after that you'll see a sign up
- 4:04off screen where you can create a new
- 4:06account or log in if we go to create a
- 4:08new account it'll ask you for your email
- 4:11and password but this time I decided to
- 4:13teach you how to implement email
- 4:15verification too after you enter your
- 4:17details the app will request a code sent
- 4:19to your email hold on okay here it is if
- 4:23you try to enter anything else of course
- 4:25it won't work enter the right code and
- 4:27voila your account is successfully
- 4:29verified you can also choose to
- 4:31authenticate using Google which works
- 4:33smoothly and logs you in within seconds
- 4:35now we are redirected to the homepage
- 4:37you'll first notice a popup asking for
- 4:39location access once you grant
- 4:41permission your location will
- 4:43immediately appear on the map you'll
- 4:45also see the nearby drivers if you click
- 4:47on them their names will be displayed
- 4:49below is a list of all rides I've booked
- 4:51so far and at the top a Google
- 4:53autocomplete search bar will suggest
- 4:55locations as you type pretty cool right
- 4:57once we select a location we're taking
- 4:59to the ride finding screen where you can
- 5:01enter your destination and see the
- 5:03location on the map through this smooth
- 5:05bottom sheet which we can expand or
- 5:07collaps you can also change your
- 5:09location and choose where you want to
- 5:11start by selecting places in
- 5:12autocompletion next we move to choose a
- 5:15writer screen where you can pick your
- 5:17preferred writer at a fair price then
- 5:19you'll be directed to the confirmation
- 5:21screen where you can review the details
- 5:23one last time before giving any money
- 5:25thanks to stripe we can select from
- 5:27various payment methods I'll enter some
- 5:29dummy details hit pay and watch it go
- 5:32through successfully you'll see this
- 5:33cool model with a smooth animation popup
- 5:36specifying that the booking is
- 5:37successful we click back home to return
- 5:40to the home screen to see the new ride
- 5:41we just booked you can also see the
- 5:43complete list of rides in the history
- 5:44screen plus there's also a well-designed
- 5:47profile screen with all of your details
- 5:49it is fully responsive and provides
- 5:52consistent results across all types of
- 5:54devices it is such a large feature reach
- 5:57application isn't it and you'll learn
- 5:58how to build it to today so what are you
- 6:01waiting for let's Dive Right In before
- 6:04we begin developing our app I want to
- 6:06show you how you can set up a new IDE
- 6:09that I tried and loved so much that I
- 6:11decided to use it to replace my vs code
- 6:14I know making a switch is not easy but
- 6:17just try it and you won't be
- 6:19disappointed Jed brain's tools are
- 6:21trusted by Google Tesla Visa Shopify
- 6:25City Bank and even NASA so they'll suit
- 6:28us just fine the link in the description
- 6:30will give you a free 90-day webstorm
- 6:33license so you have nothing to lose open
- 6:35it fill in your information click redeem
- 6:38and follow the instructions in the email
- 6:40once you click the link you got in your
- 6:42email you'll be redirected to your
- 6:43account dashboard and just click
- 6:45download then select your operating
- 6:48system and click download keep in mind
- 6:50this is a full IDE and not just a code
- 6:53editor so it's going to take some time
- 6:55to download let's leave it B and I'll be
- 6:57right back and if you're not ready to
- 6:59choose webstorm yet that's totally okay
- 7:02you can still follow along with the
- 7:03entire video without any problems I just
- 7:06want to say that I've been trying it on
- 7:08our internal projects for the last
- 7:10couple of months and found it to be the
- 7:12perfect IDE for web and mobile
- 7:15applications I'm still discovering new
- 7:17features as I go but I'm already so
- 7:19impressed that I won't be going back to
- 7:21vs code anytime soon once you install it
- 7:23it's going to ask you whether you want
- 7:25to import your settings from vs code so
- 7:27you can do that or start completely from
- 7:29SC scratch in this case I will import
- 7:31the settings you can choose the theme
- 7:33the key maps plugins and even the recent
- 7:35projects this was super quick and now we
- 7:39can create a new project it can be just
- 7:41an empty project which we can create on
- 7:43our
- 7:44desktop under SL Uber dclone and click
- 7:50create once you're in there it'll look
- 7:53something like this but of course we can
- 7:54fully customize it and what's the one
- 7:57thing that developers first change when
- 7:59they download a new IDE it's got to be
- 8:02the theme so press control or command
- 8:05shift p and it'll open up this search
- 8:08context where you can search for theme
- 8:11press enter and then select one of the
- 8:13predefined themes but of course you can
- 8:15press get more themes and very easily
- 8:18install any theme you want in this case
- 8:21I'll proceed with one dark theme and
- 8:23press
- 8:24accept and immediately it got applied
- 8:28another thing I'll do just so you can
- 8:29follow along more easily is increase the
- 8:31font size so I'll use the command shift
- 8:34p to go to settings select font and I
- 8:39will increase it to about 18 and enable
- 8:43ligatures this should allow you to see
- 8:45much better what I'm working on I think
- 8:48this is more than enough to get us going
- 8:50as we develop the application we can
- 8:51continue customizing the IDE to make it
- 8:54more your own and I'll be pointing out
- 8:56to all the cool details that webstorm
- 8:58does for us so with that said let's get
- 9:00started with a project setup to develop
- 9:03our mobile application of course we'll
- 9:05be using react native a platform that
- 9:08allows us to learn a technology such as
- 9:10react once and then write code anywhere
- 9:14be that Android iOS or web so as we
- 9:17click get started we'll be redirected to
- 9:20the getting started guide and I want to
- 9:22point your attention to
- 9:23something they say right here that you
- 9:26can use react native without a framework
- 9:29however they've found that most
- 9:31developers benefit from using a react
- 9:33framework like Expo providing you with
- 9:35features such as file based routing
- 9:37highquality Universal libraries and the
- 9:40ability to write plugins that modify
- 9:42native code without having to manage
- 9:44native files so we'll use the
- 9:46recommended approach and we'll start a
- 9:48new react native project with Expo we
- 9:51can do that by quickly navigating over
- 9:53to their page and going to the docs to
- 9:56get started with it there's only one
- 9:58command we need to run MPX create xfo
- 10:00app at latest so if we copy it and go
- 10:04back to our code editor you can open up
- 10:06the terminal by holding the control and
- 10:08then the key left of the one key on your
- 10:10keyboard and yeah terminal is a whole
- 10:12other beast in webstorm as we write
- 10:15commands I'll point out some cool
- 10:16features that it has so right here we
- 10:19can run MPX create Expo app at latest
- 10:22and then add the dot slash at the end to
- 10:24create it in the current Uber clone
- 10:26repository let's press enter and and
- 10:29press y to install the following
- 10:31packages let's give it a moment until it
- 10:33does its thing and while the packages
- 10:35are getting installed let's set up the
- 10:37database which we'll use to make our
- 10:39entire Uber application possible we need
- 10:42to have a place to store user accounts
- 10:44the writers the drivers and the rides
- 10:47themselves so click the neon link down
- 10:49in the description to be able to follow
- 10:51along and see exactly what I'm seeing
- 10:54next click get started and sign up I'll
- 10:57continue with Google for this project
- 10:59we're not using any thirdparty libraries
- 11:02for our database management you'll be
- 11:04working with a native postgress database
- 11:06and will write real SQL queries here you
- 11:10can enter your project name started with
- 11:12JSM uncore and then you can enter your
- 11:14project name you can do ride or Uber or
- 11:17whatever you prefer and same thing for
- 11:19the database name I'll do JSM ride you
- 11:22can choose the region that is closest to
- 11:24you and click create project and there
- 11:27we go we are redirected to this
- 11:29beautiful dashboard which will put to
- 11:31full use soon enough there we go it took
- 11:34some time but it finally worked your
- 11:36project is ready and now we can either
- 11:39run Android iOS or web before we do that
- 11:42you can press these three dots here and
- 11:44enable the new terminal which is in
- 11:46better right now and soon you'll see
- 11:48some of the new functionalities that it
- 11:50brings to the table for now let's just
- 11:53type mpm start and press enter you will
- 11:56see some warnings right here but that's
- 11:58not a big deal because below that you
- 12:01will see a QR code that you can scan
- 12:03with your phone and this QR code is very
- 12:06important for the whole Expo react
- 12:09native environment if you don't want to
- 12:11use it there's some different
- 12:13alternative options that we can use such
- 12:15as pressing a to open up Android Studio
- 12:17or the letter i to open up the iOS
- 12:20simulator but for all of these things
- 12:22you have to have heavy software we all
- 12:26know those stories where you open up
- 12:27Android studio and your device starts
- 12:30heating up and explodes and for the iOS
- 12:33it doesn't explode but you have to have
- 12:35very expensive devices what Expo allows
- 12:38us to do is to use the Expo go
- 12:40application to run our application on
- 12:43our phone in real time and see exactly
- 12:46what we're developing and we can even
- 12:48play with it and touch the app in real
- 12:50time that is super cool so let's go back
- 12:53to this QR code and if you're an iOS
- 12:56you'll have to scan it with your camera
- 12:58and before to scan it you'll have to go
- 13:00to your app store or Google Play store
- 13:02and just download the Expo go
- 13:05Application it should look something
- 13:06like this on your phone so I think this
- 13:08is the perfect time that I brought my
- 13:10phone preview on the right side of the
- 13:12screen so at all times while watching
- 13:14this video you'll be able to see exactly
- 13:17what I'm seeing on my phone screen so
- 13:19once you download it simply click open
- 13:22and you'll also have to create your Expo
- 13:25account by logging in if you're an
- 13:27Android you can open up the Expo Go app
- 13:29and scan the code from there and if
- 13:31you're an iOS you can scan it directly
- 13:34from your native camera app and on both
- 13:36systems make sure that you're connected
- 13:38to the same Wi-Fi network where you're
- 13:41running the code so both the phone and
- 13:43the device have to be on the same
- 13:44network and on iOS you'll also have to
- 13:47go to your phone settings expoo app and
- 13:50turn on the local network and also turn
- 13:53the VPN status off to not connect it
- 13:57this is necessary for Expo to connect
- 13:59properly then open up your phone camera
- 14:02point it at your QR code and click open
- 14:05in expoo but it seems like there's an
- 14:08error here it says too many open files
- 14:11error node Watcher broke and then it
- 14:14exited so we of course cannot test our
- 14:16application if we're no longer running
- 14:18the Expo server since it points to the
- 14:20node Watcher instance I think our node
- 14:23version might have something to do with
- 14:25this so let's just go to the node.js
- 14:27website and click download node.js
- 14:30LTS this is the long-term support
- 14:33version once it gets downloaded simply
- 14:35follow the steps to install it to check
- 14:38whether our newly installed version of
- 14:39node applied we can type node DV and
- 14:43unfortunately it's still using a newer
- 14:46experimental node version for me and for
- 14:48you it might be something else but maybe
- 14:50not the one that we just installed for
- 14:52that reason we can use a package called
- 14:54NVM that is a version manager for
- 14:57node.js there's a handy the GitHub repo
- 15:00that allows us to install it and update
- 15:02it with one script command you can use
- 15:04Curl on Mac OS or W get on windows so
- 15:09let's copy the command for your own
- 15:10operating system and paste it in the
- 15:13terminal it'll quickly install NVM and
- 15:15you need to close and reopen your
- 15:17terminal so let's close this one and
- 15:19reopen it to verify the installation you
- 15:21can run
- 15:23command-v MVM which should output MVM if
- 15:27the installation was successful and now
- 15:29you can install a specific version of
- 15:30node I believe the active version at the
- 15:32time of the recording of this video is
- 15:35version 2016 so we can say NVM install
- 15:39206 0 and press enter there we go and
- 15:43now we can type node DV to check your
- 15:46current node version now let's rerun mpm
- 15:49start to see whether now node Watcher
- 15:53will properly watch over our Expo
- 15:55application I'll scan the code one more
- 15:57time with my device
- 16:00and open in Expo go it seems like the
- 16:02application is building you can see that
- 16:04right here iOS has been bundled and we
- 16:07can see the welcome screen success so
- 16:10now we know that we might want to use
- 16:12these stable versions of node when
- 16:13running your Expo applications great but
- 16:16with that said I mean just just look at
- 16:18this we have successfully set up a react
- 16:20native application and right now I have
- 16:23my phone in my hand and I can swipe
- 16:26around move through different screens
- 16:28and even open up some toggles that tell
- 16:30me a bit more about the Expos
- 16:32functionalities we already have a
- 16:35working Expo application but of course
- 16:37today you will turn what you see on the
- 16:39screen right now and what you're holding
- 16:41in your hand into what I believe is one
- 16:44of the most popular mobile apps of all
- 16:47time Uber so let's continue with doing
- 16:51just that and since this will be a
- 16:53pretty big application you know that
- 16:55every big app needs to have a proper
- 16:58setup
- 16:59we need to ensure that the app is
- 17:01scalable and the code is readable so for
- 17:04that reason let's go ahead and set up a
- 17:06couple of things that will make our
- 17:08development experience so much better
- 17:10first we'll install native wind native
- 17:13wind is a react native version of
- 17:15Tailwind CSS that allows us to very
- 17:18quickly write Styles within our mobile
- 17:21applications so let's just head over to
- 17:23the Expo quick start and install native
- 17:26Wind by running mpm install native wind
- 17:29and then installing Tailwind CSS as well
- 17:32we can copy this command go back to
- 17:34webstorm and run this command now we can
- 17:37see that our terminal is currently
- 17:38running the expoo application so we can
- 17:41just open up a new one right here and
- 17:44paste these commands we can quickly head
- 17:46over to our package.json I used a
- 17:49command P shortcut to quickly open up my
- 17:53file manager and we can scroll down to
- 17:55dependencies and search for Tailwind CSS
- 17:57as a Dev dependency as well as a native
- 18:00wind installed right here as a regular
- 18:03dependency next we need to set up
- 18:05Tailwind CSS by running MPX tailin CSS
- 18:08in nit so let's open up the terminal and
- 18:10paste this command here by the way I
- 18:12want to point your attention to how
- 18:14webstorm terminal dynamically separates
- 18:18each command from each other so you know
- 18:20exactly what you're working on here we
- 18:22have the one that we just ran and Below
- 18:24we can run a new one there we go this
- 18:27just created a new file and it's asking
- 18:29us whether we want to automatically add
- 18:31it to G sure we can add it and now we
- 18:35can check out our new tailwind config.js
- 18:38and we can copy this code from the
- 18:40Native width installation and paste it
- 18:42right here but of course we'll have to
- 18:44modify it to make sure the content is
- 18:47all right there we go step three is to
- 18:50add the native wind Babble plugin under
- 18:52Babel config JS so let's navigate over
- 18:55to Babel config JS one more time I am
- 18:58using the command or control P to open
- 19:01up the file explorer which is the
- 19:03quickest way to move over the files but
- 19:05of course you can just open up the
- 19:06project by pressing the command shift
- 19:09and e or clicking right here and then
- 19:12finding the babble config now I will add
- 19:15the plugins native wind
- 19:18Babble and that's it we can start
- 19:20writing code before we test it out we
- 19:22need to do one more thing and that is
- 19:24make typescript work with our native
- 19:27wind so the only thing we have to do do
- 19:29is create a new native wind- env. D.S
- 19:33file in the root of our directory so we
- 19:36can do that right here by creating a new
- 19:39file and pasting this
- 19:41name and then we can add this reference
- 19:44right within it and now typescript will
- 19:46know exactly what we're doing with the
- 19:48styles to test it out we can copy this
- 19:50view right here from the example code
- 19:53and go to our app tabs and then index.
- 19:56TSX as you can see here right now it
- 19:59says welcome and all of this other text
- 20:01we don't necessarily need that we just
- 20:04need one single view to start
- 20:06understanding how we can modify the code
- 20:08that has been provided to us so I'll
- 20:10just use one single view by the way a
- 20:13view in react native is similar to a div
- 20:17in web development so let's import this
- 20:19view from react native at the top by
- 20:21saying import
- 20:24view as well as a text and a status bar
- 20:28for from react native and we don't need
- 20:31any of the other Imports we can also
- 20:33remove all the other styles that we had
- 20:35in there now to test whether it works we
- 20:38have to position our text to appear in
- 20:40the middle of the screen and in react
- 20:43native we do that with something called
- 20:45a safe area View and there's an
- 20:47additional package that we can install
- 20:49that provides that component right out
- 20:51of the box so we can run mpm
- 20:55install
- 20:56react-native DS safe - area- context and
- 21:01press
- 21:02enter as soon as it installs and it'll
- 21:05do so quickly because it's a very small
- 21:07package we can now import something
- 21:09known as a safe area view coming from
- 21:13react safe area context and instead of
- 21:16using the regular view we can wrap her
- 21:19app with a safe area view now you can
- 21:22see that the text fits nicely at the top
- 21:24of the screen now even though the text
- 21:26is in view the styles are still not
- 21:28getting applied and we can see that
- 21:30because the text should be centered but
- 21:32it's still appearing at the top so we
- 21:34can go over our Tailwind that config.js
- 21:37and we can quickly modify the content we
- 21:40need to tell it where what will be
- 21:41writing styles so that it starts
- 21:44understanding them so instead of a
- 21:46capital A for app we can say
- 21:49slapp slash asterisk asterisk meaning
- 21:52everything in those folders within the
- 21:54app SL asterisk Dot and then we have
- 21:58those files extensions and here instead
- 22:00of a custom directory we have to modify
- 22:02this to
- 22:04say/
- 22:07components SL asterisk asterisk SL
- 22:10asterisk and now if we go back you'll
- 22:13see that the text is centered we can
- 22:15also give it a class name equal to
- 22:18something like text- r-500 to see that
- 22:22it changes color now it is highly likely
- 22:25that this will not be working for you
- 22:27immediately there's just just one a bit
- 22:29of an annoying thing that we sometimes
- 22:31have to do with Expo applications
- 22:33whenever we make any big changes such as
- 22:36install native wind or any other major
- 22:38packages and that is clear the cach okay
- 22:42remember this clear cash if something
- 22:45doesn't work so for you what you can do
- 22:49is stop the serve from running clear it
- 22:51and then run MPX
- 22:54Expo
- 22:56start- C this run it with a cleared
- 23:00cache so if you rerun the project you
- 23:02can see it right here it says bundler
- 23:05cache is empty rebuilding and then you
- 23:07can press R while in terminal to reload
- 23:10your application after you do this I'm
- 23:13pretty positive that it should work and
- 23:16there we go our text is in the middle
- 23:19and we can say something like uber clone
- 23:22we're getting ready to start building it
- 23:24now Uber is a big application and as
- 23:27I've told you already when you're
- 23:29starting to develop big applications
- 23:31there is a bit of a setup work that you
- 23:32have to do to make sure that the rest of
- 23:35the building process flows smoothly and
- 23:38one of the things that is very important
- 23:39to set up in big projects is a linter in
- 23:43our case we'll use expo's recommended es
- 23:46length and preder configuration so let's
- 23:48just follow the steps we can run MPX
- 23:51Expo lint I'll do it in our second
- 23:54terminal not to disturb our application
- 23:56it's going to ask us a couple of
- 23:57questions such as says do you want to
- 23:59install eslint in this project and I'm
- 24:01going to say why for yes let's give it
- 24:03some time and I'll be right back there
- 24:05we go eslint has been configured we also
- 24:08need to install prettier so let's scroll
- 24:11down and I think somewhere here we can
- 24:12see the installation command so let's
- 24:15copy it and paste it in the terminal
- 24:18that was simple and now we have to
- 24:20update our eslint RC file with the
- 24:23following code so let's head over to
- 24:26eslint rc. Js and paste this code right
- 24:30in now eslint and prier will be watching
- 24:33over our changes and make sure that we
- 24:35write quality code in webstorm there's
- 24:38one additional thing that we have to do
- 24:39to properly set up eslint so press
- 24:42command shift b or control shift B and
- 24:45type eslint open up its preferences and
- 24:49head over to manual es lint
- 24:51configuration click on this Arrow right
- 24:54here and then choose the es lint for our
- 24:56specific Uber project and select run es
- 24:59lint fix on Save click apply and also
- 25:03head to tools actions on Save and make
- 25:06sure that it is turned on we can repeat
- 25:09the same thing with prier by going to
- 25:11settings manual preder configuration and
- 25:13then choosing our own config right here
- 25:16and run on Save apply and okay that's it
- 25:20you can see how immediately pretty a
- 25:22changes our configuration to be easier
- 25:25on the eyes and it works so seamlessly
- 25:27with storm and if you're using some
- 25:29other code editor here's the settings
- 25:31that Json file which you can put in
- 25:33there to also make it work there the
- 25:35code available to copy is in the GitHub
- 25:37readme linked below and now that we have
- 25:39linting set up let's customize webstorm
- 25:42even further to make it truly our own
- 25:45I'm going to press command shift b or
- 25:47control shift B on Windows and I'll go
- 25:50ahead and change the theme you can
- 25:51scroll down and go to get more themes
- 25:54and many of you have been asking me what
- 25:56theme do I use and now I can finally
- 25:59tell you it's going to be a cat pin
- 26:02theme you can type it like this and you
- 26:05can just go to search in the marketplace
- 26:07it's spelled with a double p and Double
- 26:09C you can install it and once you do you
- 26:12can go to theme and change it to kuchin
- 26:16and then choose the flavor you prefer
- 26:18macchiato or
- 26:20mocha once you have that I'm going to
- 26:22also do another thing and that is change
- 26:24the font family so you can search for
- 26:27font
- 26:28go to preferences and then go to General
- 26:31editor settings font and here I chose F
- 26:35code this is the font that I've been
- 26:37using for a long time you can also
- 26:39choose that one and you can install it
- 26:41by simply downloading the font to your
- 26:43device another thing I want to focus on
- 26:45is to turn on something called Soft wrap
- 26:49so go to configure soft wraps make sure
- 26:52to add the asterisk.svg
- 26:58so that it wraps for those files and
- 27:00turn off the used the original line
- 27:02indent for wrap fragments that's going
- 27:05to allow us to WRA specific files it
- 27:08should look something like this so that
- 27:10once the text goes beyond the line you
- 27:13can still see it on the screen right
- 27:14here to make it easier for you to follow
- 27:16what I'm doing and another thing we can
- 27:18do is install a material theme for our
- 27:21icons and folders to make them look just
- 27:24a bit better so once again command shift
- 27:26p search for
- 27:29plugins go to Marketplace and search for
- 27:32icons you can choose the atom material
- 27:35icons or anything else that you prefer
- 27:38in this case I'll go with adom click
- 27:40install apply and okay and we do need to
- 27:44restart our IDE for the changes to be
- 27:46applied once you're restarted you can
- 27:48notice that now all of the folders have
- 27:50their corresponding icons which makes it
- 27:53look so much better also you can see
- 27:55that the colors change for some of the
- 27:57icons on the side for now what I want to
- 27:59do is clean up this environment a bit so
- 28:02we can just hide some of the things
- 28:04right here that we don't need to create
- 28:06a bit more space for us we can customize
- 28:08the toolbar remove the part from the
- 28:10center and also remove some of the parts
- 28:13from the right as we don't necessarily
- 28:14need to play with a toolbar play with a
- 28:17code with me we don't need anything on
- 28:19the right so I will remove that as well
- 28:21and this will clean it up just a bit you
- 28:23can do the same thing for the things at
- 28:24the bottom that you don't necessarily
- 28:26need and there we go I went went ahead
- 28:28and I hided some of the things from the
- 28:30screen now we have a cleaner working
- 28:33environment with that said we can now
- 28:35proceed with cleaning up our file and
- 28:37folder structure now that we can see it
- 28:39a bit clearer when we initially set up
- 28:41our react native export application it
- 28:43came with a lot of different things the
- 28:46file and folder structure already set up
- 28:48two different pages there's a lot of
- 28:50stuff that we don't necessarily need and
- 28:53that will just complicate your
- 28:55understanding of our react native
- 28:56application so I want to make sure to
- 28:58take a second to delete all of the
- 29:00things that we don't need to focus on
- 29:02creating everything from
- 29:05scratch right now our application is not
- 29:07running and maybe for the better that's
- 29:10because we are going to do a whole
- 29:12cleanup and then we're going to run it
- 29:13together later on so first things first
- 29:16let's delete the things that we don't
- 29:17need I'll begin with deleting the tabs
- 29:20route Group by simply clicking delete or
- 29:23pressing the backspace key and pressing
- 29:26delete next I'll delete the hooks folder
- 29:28as we don't need it I'll also delete the
- 29:30constants folder and the components
- 29:32folder as well as the assets folder so
- 29:35we're going to clean our entire
- 29:37application up we only have our HTML
- 29:40index DSX and you might be wondering
- 29:42what is this HTML file well Expo allows
- 29:45you to run your applications in the
- 29:47browser as well but that's not what we
- 29:49need to be concerned with at this point
- 29:50in time there's also a 404 page that can
- 29:54show up if we are on a not found screen
- 29:57but again not something that is super
- 29:59important right now what we do want to
- 30:01focus on instead is the layout. TSX file
- 30:06we want to update it a bit to suit our
- 30:08very minimalistic app right now that
- 30:10doesn't have any additional files inside
- 30:12of here you'll notice we have a theme
- 30:14provider for now I will go ahead and
- 30:16delete it and the only thing we'll have
- 30:18is the stack a stack of different
- 30:21screens the name of her first screen
- 30:24will be just index it's her home and
- 30:27under options will run Heather shown as
- 30:29false we also have a screen for the not
- 30:33found and this is the only thing we want
- 30:34to have for now just an empty screen
- 30:37next we can create that index screen
- 30:40right here in the root of our directory
- 30:42so let's go to app and let's create a
- 30:45new file called index. TSX within it we
- 30:49can create a new homepage by saying
- 30:51const home is equal to and we're going
- 30:54to create a new Arrow function component
- 30:57and let's not forget to to export
- 30:59default that home component at the
- 31:01bottom within it we can return something
- 31:04within it we can import a view which is
- 31:07going to come from react
- 31:10native and we can show a text also
- 31:14coming from react native and it can say
- 31:17something like home for now you can
- 31:19notice that webstorm sometimes adds
- 31:21these additional inlay hints that allow
- 31:24us to see where we're using specific
- 31:26instances of our code
- 31:28um they're going to be super useful
- 31:30later on when they tell you more
- 31:32information about different parameters
- 31:34within the functions but in this case I
- 31:36don't need them to show the usages I can
- 31:38hide code Vision usages in line hence
- 31:41not all and this is just going to
- 31:42provide us with a bit of a cleaner
- 31:44working environment now is the time that
- 31:47we reopen our terminal and rerun mpm
- 31:51start just to see if our application
- 31:53still works after making all of those
- 31:55changes we can press R to reload our
- 31:59application and you'll see that we have
- 32:01an issue in our not found. TSX which
- 32:04makes sense because we change so many
- 32:06things I pressed command P or control P
- 32:09to open up the file search and if I
- 32:12start typing you can very quickly just
- 32:14press enter and navigate to that
- 32:16different file here you can see that we
- 32:18used two different components which we
- 32:21no longer have so we can just remove
- 32:23their Imports and we can also just
- 32:26instead of a themed view just say view
- 32:28coming from react native and instead of
- 32:31theme text we can just say text coming
- 32:33from react native as
- 32:36well there we go if we save it we should
- 32:39have no more issues with the code but
- 32:43our app still doesn't seem to be there
- 32:45well that's because this view doesn't
- 32:47have any Styles and most likely the text
- 32:49is being pushed above our application so
- 32:52we can use a safe area
- 32:55view coming from react native or in this
- 32:58case we have a special package react
- 33:00native safe area context as well but
- 33:03it's still not showing so if I open up
- 33:06my terminal we can see that the iOS
- 33:07bundling failed and it's still
- 33:09complaining about the components themed
- 33:11text even though we deleted it from the
- 33:13not found screen so what we can do is
- 33:16press R once again to reload our
- 33:18application once
- 33:19more now it's complaining about hooks
- 33:22use color scheme from App layout so we
- 33:25can go within it we can remove
- 33:27everything that we're no longer using
- 33:28just to simplify it alongside the used
- 33:31color context and we can also remove
- 33:33this color scheme from here and if we
- 33:36scroll down we can see that the stack
- 33:38screen is okay and we're not using
- 33:40anything regarding what we just deleted
- 33:42so I think we're good now I'll just
- 33:44reload one more time and now it's
- 33:47complaining about a splash screen okay
- 33:50in the app that config.js because we
- 33:52removed our assets this is completely
- 33:54normal we removed a lot of code so we
- 33:56have to make sure that it all
- 33:58works so in this case I'll provide you
- 34:02with the full assets for this entire
- 34:04project in the description down below
- 34:06you can find an Uber repository with the
- 34:09entire codebase for this project but
- 34:12what's even more important is that right
- 34:14there you can find the entire readme for
- 34:17this project and one of the things in
- 34:19the readme are the Snippets and the
- 34:21Assets in this case you can download the
- 34:24assets for this project this includes
- 34:26the illustrations the the icons and all
- 34:29the little images that we'll be showing
- 34:30on the app to make the development of
- 34:32our app easier so let's click here and
- 34:36you can just press the download button
- 34:38once you download them simply unzip them
- 34:40and then drag and drop them to the
- 34:42folder where you have your app for us
- 34:44it's on desktop and it's within the Uber
- 34:46clone so now if we go here you can see
- 34:49the full assets of our application
- 34:51webstorm also ask me whether I want to
- 34:53add it to G so we can say sure and here
- 34:56we have all of the IM
- 34:58so that means that now we can go to the
- 35:00app. Json and we can modify some
- 35:04important information about our app for
- 35:06example we can choose the name as Uber
- 35:09with a capital u and a slug of uber here
- 35:13it's taking the icon directly from the
- 35:15assets images icon.png and it's taking a
- 35:18splash screen directly from our assets
- 35:21as well we can leave the rest as it is
- 35:24now if we try to reload our application
- 35:26once more you you can see that a new
- 35:28splash screen that says ride appears
- 35:31right here so if we reload it once more
- 35:33you can see how nice it looks like a
- 35:35splash screen on mobile devices is a
- 35:37screen that appears before your
- 35:39application loads it gives the user
- 35:41something to look at while it's loading
- 35:43now we have issues with the fonts
- 35:45because we won't be using the regular
- 35:47space mono font rather we'll be using a
- 35:50different one we'll be using plus
- 35:52Jakarta Sans so we can head over to our
- 35:56app and then head over over to layout.
- 35:58TSX to modify the fonts we're
- 36:01using these fonts just need to be copied
- 36:04and you can find them under the Snippets
- 36:06in this GitHub repo you can find root
- 36:08layout fonts copy this block of code go
- 36:12back here and then simply paste them
- 36:14I'll Zoom this out a bit so you can see
- 36:16it better make sure that it is formatted
- 36:19well I believe it already should be for
- 36:21you if you still see some issues in your
- 36:23terminal you might want to press contrl
- 36:26C to exit and then you can run mpm start
- 36:29once again and then it should build it
- 36:31properly after pressing the r key on
- 36:34your keyboard you can see the splash
- 36:35screen while it's loading and then after
- 36:37that you can just see the home and that
- 36:40home is exactly what we have crafted in
- 36:42our index. TSX so this is perfect now we
- 36:47have a structure that we're starting to
- 36:50understand we have an app where we have
- 36:52a not found page we have a layout and an
- 36:54index and we have also learned how to
- 36:57add a splash screen to our react
- 36:59application through app. Json it is as
- 37:03simple as pointing to an image that you
- 37:05want to show so let me show you it's
- 37:07assets images Splash if we go to assets
- 37:10images and then splash this image is
- 37:14right here perfect with that in mind we
- 37:17are ready to set up the styling for our
- 37:19application that we'll use throughout
- 37:21this project we can start by navigating
- 37:24over to Tailwind doc config.js
- 37:28in that same GitHub repo you can find
- 37:30the modified Tailwind config JS that
- 37:32extends all of these fonts and ensures
- 37:35we can very easily use them so just
- 37:37override the existing tailin config
- 37:40you'll notice that here we also import
- 37:43some of the different variants of colors
- 37:45such as primary secondary success danger
- 37:48and warning so that we can use them
- 37:50within our application nothing more
- 37:53nothing less so what do you say with all
- 37:55of that setup out of the way our you're
- 37:57ready to start creating the onboarding
- 37:59screens of our application finally some
- 38:02real code right we already have this
- 38:04splash screen and now we're starting
- 38:06with the first out of three onboarding
- 38:08screens and I would highly recommend
- 38:10that you replicate this figma design as
- 38:12well the link is going to be down in the
- 38:13description you can easily get it and
- 38:16that way at every point in time you will
- 38:18know exactly what we're building so get
- 38:21that figma design and let's start by
- 38:22creating our first onboarding screen
- 38:25within the app folder we'll create a new
- 38:28route Group by creating a new directory
- 38:32and I'll call it rout within parentheses
- 38:36like this within the root we'll create a
- 38:39new underscore layout yes each route
- 38:43group will have its own layout depending
- 38:45on what is it showing on the screen
- 38:48because our onboarding screens won't
- 38:49have the Bottom bar which means that we
- 38:51have to have a separate layout from the
- 38:53rest of the screens then within the root
- 38:56we can create another another directory
- 38:58which will be called tabs so these are
- 39:01the tabs that we can switch between and
- 39:03here we're going to have some of the
- 39:05primary pages of our application it'll
- 39:08also have its own uncore layout. DSX and
- 39:12it'll have a few other files such as the
- 39:15homepage the profile and more so what do
- 39:18you say that we create them right away
- 39:19by creating like a home. TSX file and
- 39:23within it we can just create a simple
- 39:26react a function component const home is
- 39:30equal to basically an aror function
- 39:33component that returns a view with a
- 39:35text we already have that right it is
- 39:37currently within the primary index. TSX
- 39:40so let's copy it and paste it into home
- 39:43we can now copy this and create a few
- 39:45other files as well within the tabs
- 39:48folder it'll be a new profile. TSX where
- 39:52we can paste everything we have here and
- 39:55rename home to profile we can do the
- 39:58same thing for chat.
- 40:01TSX and rename it to chat and we can do
- 40:05the same thing for history so this is
- 40:07going to be a history of a r that we
- 40:10have history. DSX we can paste it and
- 40:15call it history I think we can rename it
- 40:18to something like rides it would make a
- 40:20bit more sense so let's just do rides.
- 40:24TSX and there we go it automatically
- 40:28renamed it here as well perfect so now
- 40:31we can start seeing how our application
- 40:33will look like and it's very important
- 40:35to mention here that what you're seeing
- 40:37right now is Expo router it is a file
- 40:41based router for react native
- 40:43applications allowing you to manage the
- 40:45navigation between the screens in your
- 40:47application so you can move seamlessly
- 40:49between different parts of your apps UI
- 40:52using the same components on multiple
- 40:53platforms what I love about it is that
- 40:56it's using the same file based routing
- 40:58concept from web specifically nextjs so
- 41:02if you've done some nextjs apps it's
- 41:04going to feel like home so how exactly
- 41:06does it work well Expo router uses links
- 41:09to move between pages in the app it's
- 41:12similar to an anchor tag or href
- 41:14attribute or you have an app you have an
- 41:16index page about page and you can have
- 41:18subpages or even Dynamic pages and then
- 41:21you can use links to move to different
- 41:23pages or use buttons we can also use the
- 41:26navigate functionality which behaves
- 41:28similarly to modifying the URL in the
- 41:30browser and the primary way of
- 41:32navigating in Expo applications is the
- 41:34stack Navigator it is like a navigation
- 41:37bar in the browser you first need to
- 41:39create a file-based routing structure
- 41:42like with an app a layout and then some
- 41:44additional routes and then in the layout
- 41:47you can create something known as a
- 41:49stack a stack of screens each screen can
- 41:53decide to show or hide the header Styles
- 41:56can have different colors and more and
- 41:58then you can configure how do you get to
- 42:00each one of these screens by giving them
- 42:03a name so let's create a stack of our
- 42:05own we use the stack to modify how a
- 42:08specific route behaves so if we go right
- 42:11here to our root layout you can see that
- 42:13we have this index route which is our
- 42:15homepage and there we have added an
- 42:18option of header shown to false if we
- 42:20remove that option you'll be able to see
- 42:22the name of the route which typically
- 42:24you don't want to show so that's the
- 42:27reason why we have to add all of these
- 42:28stack screens only so we can add options
- 42:31header shown is set to false and we're
- 42:34going to repeat this process for all the
- 42:36other routes and Route groups so we're
- 42:39going to do the same for the root so
- 42:42that's the root route group Heather
- 42:44shown false and we're going to do the
- 42:46same for o this is a second group of
- 42:49routes which will'll show so let's go
- 42:51here and next to root which is going to
- 42:54be the primary part of our application
- 42:56where we're going to have all the routes
- 42:57we're going to have something that
- 42:58happens before we enter the main
- 43:01application which is the onboarding and
- 43:03the off so let's create a new directory
- 43:06called off in parenthesis there we can
- 43:09also create a newor layout. TSX and
- 43:13within it we can duplicate the main
- 43:15layout we have right now but we'll
- 43:18remove some of the things regarding the
- 43:19fonts we're loading the fonts once we
- 43:22don't need to load them anymore so it's
- 43:24going to be much much simpler it's going
- 43:26to look something like this import stack
- 43:29from Expo router then we can declare a
- 43:32layout and a simpler way to do it is
- 43:34const
- 43:36layout is equal to an arrow
- 43:39function and then we can just export
- 43:41default it at the bottom by saying
- 43:43export default
- 43:45layout and here we have different stacks
- 43:47of screens for that route group so no
- 43:50longer do we have to have the index or
- 43:52the root or the KN found rather we're
- 43:55just going to have the welcome which is
- 43:57going to be the primary screen and then
- 43:59we're going to have sign up and finally
- 44:02we're going to have the sign in and we
- 44:04want to hide the headers in all
- 44:06places so that means that we have to
- 44:08create these additional off Pages such
- 44:11as welcome sign in and sign up let's
- 44:15create all three I'll create a new file
- 44:18called
- 44:19sign-in. TSX and within it we can paste
- 44:23just the basic component which we
- 44:24created in our index. TSX so that's just
- 44:27going to be a basic view safe area view
- 44:31with a text that's going to say sign in
- 44:34we can duplicate that once more by
- 44:36creating a second file in the oth group
- 44:40which is going to be called sign Dash
- 44:43up. DSX and we can rename that to sign
- 44:47up we can also rename the actual
- 44:50component name sign up single word and
- 44:54we can do the same thing for the sign in
- 44:56since I forgot to do it there sign in
- 45:00and finally we need to create one last
- 45:03off page which is going to be the first
- 45:05one we'll start to work on and that is
- 45:07the welcome onboarding so welcome. TSX
- 45:10where we can paste it and say
- 45:14onboarding great so now the question is
- 45:17how can we navigate to this page right
- 45:19here right now our app is saying home
- 45:22because we have this index. TSX that is
- 45:25rendering the home well in here will do
- 45:27a simple redirect in case we're logged
- 45:30in so the return will do only one thing
- 45:33and that's going to be call to a
- 45:36redirect
- 45:37component coming from Expo router with
- 45:40an hre of forward slash route group of O
- 45:45SL welcome now as soon as somebody opens
- 45:48up the application we'll be redirected
- 45:50to oops the screen doesn't exist okay we
- 45:53know that at least the 404 is working as
- 45:57well let me do a Reload by pressing R
- 45:59right here and you can see that now it
- 46:01worked sometimes while developing react
- 46:03native applications you'll have to
- 46:06reload your application often and now we
- 46:08are on the onboarding screen we also
- 46:11have a warning right here at the bottom
- 46:12but you can just collapse it to close it
- 46:14right now we can close all of the
- 46:16currently open files and just head over
- 46:19to our welcome screen which is really an
- 46:22onboarding and the pages for the
- 46:24onboarding are going to look like this
- 46:26it's going to be a three page or
- 46:28three-step onboarding process where
- 46:31we'll have some nice illustration a
- 46:33title description tabs that move as we
- 46:36move to the second screen and then the
- 46:38button that says next so let's get
- 46:41started with creating our first real
- 46:43piece of user interface in a large react
- 46:46native application there's one small
- 46:48thing that I can see here and that is
- 46:50that we have one week warning pointed
- 46:52out by our webstorm in this case this is
- 46:54not a real warning because if you think
- 46:57about it it says unused default export
- 47:00but we're actually using a file based
- 47:02routing system so we never actually have
- 47:04to import the onboarding it is just
- 47:06being used by default once we go to that
- 47:09page so to hide this error you can press
- 47:12command or control shift B and type
- 47:15inspections and then search for unused
- 47:18Global symbol and tick it off click okay
- 47:21and then close and reopen your webstorm
- 47:24if you do that you can run mpm start one
- 47:26more time
- 47:27and the error will be gone great another
- 47:30thing you can do to clean up your
- 47:31workspace is go to toolbar and then
- 47:34toggle it off um I don't think I need
- 47:36all that info at the top and this just
- 47:38makes it so much easier for you to
- 47:40follow along and with that in mind we
- 47:42can now dive right into the onboarding
- 47:45I'll press R to bundle our app one more
- 47:47time so press this warning and we can
- 47:50get started everything is already
- 47:52wrapped in a safe area view coming from
- 47:54react native safe area context which is
- 47:57why we can see the onboarding text right
- 47:59within our screen next we can give our
- 48:01safier view some class names such as a
- 48:04class name is equal to flex h- full to
- 48:08give it a full height items D Center
- 48:11justifi Das between and BG - white so
- 48:16now this will Center the text
- 48:17horizontally next instead of this text
- 48:20right within the safe area view we'll
- 48:22create our first touchable opacity and
- 48:26we'll UT Ed from react native in the
- 48:29react native or mobile World a touchable
- 48:32opacity is basically just a button you
- 48:35know how on web you have a button here
- 48:38on mobile you have a touchable opacity
- 48:41within which we will render a text
- 48:43coming from react native and this text
- 48:46will say something like skip so in case
- 48:48we want to skip this on boarding we can
- 48:51do that what's going to happen if we
- 48:53decide to skip it well instead of
- 48:55onclick here we have an onpress activity
- 48:59and on press we can call a callback
- 49:02function and say something like router.
- 49:05replace and we want to go over to for SL
- 49:10off SL
- 49:12sign-up just like this and this router
- 49:16will be coming from Expo router so we
- 49:18can say import router coming from Expo
- 49:22router great now we can also give a
- 49:26class name to this touchable opacity and
- 49:28that's going to be a w full so full
- 49:31width Flex justify Dash and items Dash
- 49:36end in the padding of five so we show it
- 49:40a little button at the top right we can
- 49:42also style this text element by giving
- 49:45it a class name which is equal to let's
- 49:49do um text- Black text- MD for medium
- 49:54and font D Jakarta bold so this is one
- 49:57of the fonts that we imported it didn't
- 50:00seem to apply the Bold style so I think
- 50:02we should use the capital J there we go
- 50:04Jakarta bold this now works great now
- 50:08let's go below this touchable opacity
- 50:10and let's create a component that allows
- 50:12us to swipe left and right like we're in
- 50:15Tinder but we're not swiping different
- 50:17dates we're swiping the onboarding cards
- 50:21almost as exciting right so for that
- 50:23we'll install a new component in the new
- 50:27terminal mpm install
- 50:29react-native D
- 50:31swiper and we can use it right below the
- 50:34touchable opacity by saying swiper and
- 50:37we can import it at the top by saying
- 50:39import swiper coming from
- 50:43react-native D swiper currently this
- 50:46will break our application because
- 50:47swiper expects to have some things
- 50:49within it so let's add it first of all
- 50:53we have to create a new reference to
- 50:55this swiper so so that we can control it
- 50:58we can do that by saying con swiper ref
- 51:01is equal to use ref of a type swiper and
- 51:06at the start it can be set to null next
- 51:09we can just say ref is equal to swiper
- 51:12ref on this swiper we can also give it a
- 51:16couple of other properties such as a
- 51:18loop in this case we don't want to Loop
- 51:21over the swiper we just want it to come
- 51:23to the end after the three so we'll set
- 51:25the loop property to false it also
- 51:28allows us to change how the dots look
- 51:30like uh so the dot for the first swipe
- 51:33second and the third so we can say dot
- 51:35is equal to a view which remember is a
- 51:39div in a mobile world and we can make it
- 51:41self closing and give it a class name
- 51:46equal to w-32 pixels within square
- 51:49brackets h-4 pixels margin X of one and
- 51:55BG of a very light variant of a white
- 51:59color so that's going to be E2 E8 F0 and
- 52:03we of course have to import the view
- 52:06from react native and we also have to
- 52:08import use ref inside of square brackets
- 52:12from react now this is a very cool thing
- 52:15about webstorm as soon as we imported
- 52:17this use ref we no longer have to hover
- 52:19over it to see what it does you can see
- 52:22that it understood that this n that we
- 52:24passed is a property that that specifies
- 52:27the initial value similar thing here it
- 52:30recognized that the first prop or the
- 52:32first parameter to this function that
- 52:33we're passing is corresponding to an hre
- 52:37property so now as you're typing you can
- 52:39immediately know what you need to pass
- 52:41in it sure you could hover over it and
- 52:43see what it is but it is so convenient
- 52:45to just start typing something and then
- 52:48immediately know that that's
- 52:49corresponding to an hre in that specific
- 52:52method great so now we created this
- 52:54swiper and explained how a DOT should
- 52:56look like we can also duplicate this Dot
- 52:59and change it to an active dot so
- 53:03depending on which screen we're
- 53:04currently on and here we're going to
- 53:06change the BG color to something like
- 53:11028 6 FF and we're going to make it
- 53:15rounded by saying rounded Das full as a
- 53:18matter of fact we can do that for the
- 53:20dot regular dot as well great and
- 53:23somehow we have to keep track of the
- 53:25indexes that we're switching from and to
- 53:28so we can create a new use State call it
- 53:32active index set active index at the
- 53:35start set to zero and then we can handle
- 53:38that with the on index changed property
- 53:41which will accept a callback function
- 53:43with the new index and we can simply set
- 53:45active index to be equal to the index
- 53:48that we have right here finally we can
- 53:50show something within that swiper and
- 53:52sure what you could do is create an
- 53:54array of things right here that's going
- 53:56to have different objects where each
- 53:59object will have something like a title
- 54:02it'll have an image and description and
- 54:04if you did this quickly your jsx file or
- 54:08in this case TSX would grew and then you
- 54:10would have to map over them but
- 54:12typically you don't want to combine the
- 54:15presentation which is the jsx or the TSX
- 54:17in this case with the data so the data
- 54:20of what we will be showing so for that
- 54:23reason it's always good to separate some
- 54:25of these pieces
- 54:26in specialized files in this case I'll
- 54:29create a new directory or folder called
- 54:33constants and within it I'll create a
- 54:36new file called
- 54:39index.ts here we can create a new
- 54:41onboarding array which will contain
- 54:44three different objects for three
- 54:46different screens that we have each one
- 54:48will have an ID it'll also have a title
- 54:51something like the perfect ride is just
- 54:55a tab
- 54:57away and we can also have a
- 55:00description something like the
- 55:03Journey Begins With
- 55:08ride and we need an image to show so for
- 55:11now I'll leave image to null and now we
- 55:13can do the same thing for all of the
- 55:15other onboarding fields and of course
- 55:17let's just export this as well by saying
- 55:19export con onboarding now within here we
- 55:22can use this onboarding coming from the
- 55:24index. DSX file and map over it by
- 55:27saying map where we get each individual
- 55:30item and for each one of those items we
- 55:32want to render a new view for now let's
- 55:36simply show the item. tile and it's
- 55:39pretty cool how it immediately knows how
- 55:41these properties look like so we can
- 55:44just say this and it's not showing on
- 55:46the screen right now and that's because
- 55:49we cannot just showed a text inside of a
- 55:51view in react native in react native you
- 55:54have to wrap it in a text prop prop y so
- 55:56let's import text from react native and
- 55:59also close it up with a text property if
- 56:02we save this you can see the perfect
- 56:04ride is just a tap away and soon enough
- 56:07we'll be able to swipe that left and
- 56:09right to move to the next screen and if
- 56:11you accidentally go to sign up you can
- 56:13just press R to reload and rebundle the
- 56:16application great now alongside this we
- 56:19want to show an image from figma and
- 56:21sure you could go here and download it
- 56:24but thankfully we already have it in the
- 56:26app assets so the only thing you have to
- 56:27do here in the constants is refer to
- 56:31images. onboarding one but of course we
- 56:34have to have the path to that image so
- 56:37we'll have to do something like import
- 56:40onboarding
- 56:41one from add SL assets SL images SL
- 56:48onboarding
- 56:49one.png and now we'll have this
- 56:51onboarding one image that we can show
- 56:54but we'll have to do this for import
- 56:56recoring every single image every single
- 56:58icon and everything else so for that
- 57:01reason just to simplify the procedure a
- 57:03bit more I have added the entire
- 57:05constants index.ts where I'm simply
- 57:08importing all of those images and then
- 57:11exporting them where we need them that
- 57:13way it's going to be much simpler to
- 57:15just continue with development when our
- 57:17data is nicely structured and we can
- 57:19easily import it so copy this file and
- 57:22then override the entire index.ts of
- 57:25constants
- 57:27you'll notice that here we have the
- 57:28entire on boarding we have some icons
- 57:31and we have all of these assets it's
- 57:33currently saying that it cannot find the
- 57:35type declarations for these things so we
- 57:37have to add the type declarations for
- 57:39these images just so that it recognizes
- 57:42it so copy this first file and create a
- 57:46new types type D.S that's going to be in
- 57:49the root of the
- 57:50directory new folder called
- 57:54types and then within it we can create a
- 57:57new file called type.
- 58:02D.S and we need another one which is
- 58:04type image. D.S where we can paste this
- 58:09so create a new file image. D.S and
- 58:13paste the Declarations for the images
- 58:16now if we go back it's no longer
- 58:18complaining great and now if you just
- 58:20reload one more time you can still see
- 58:22the perfect ride is just a type away but
- 58:25now you can move move between different
- 58:27onboarding profiles that is perfect and
- 58:31of course if you want to you can
- 58:32completely change the titles for each
- 58:34one for now just the images are changing
- 58:37which is great so let's show that image
- 58:40so we can actually see the difference
- 58:42and swipe between these three different
- 58:44screens to this view I'll provide a
- 58:48class name equal to flex items D Center
- 58:52justify Das Center and the padding of
- 58:55five
- 58:56since we're mapping over it I'll also
- 58:58give it a key equal to item. ID and
- 59:01right within the view above the text
- 59:03we'll render an image coming from react
- 59:07native it'll be a self-closing component
- 59:10with a source equal to item. image so
- 59:14it's coming from constants a class name
- 59:17equal to
- 59:18w-o and
- 59:20h-300 pixels and we'll also give it a
- 59:22resize mode equal to contain so now you
- 59:27can see how we have this nice looking
- 59:28image and we can swipe between these
- 59:30three images this is super cool because
- 59:33swiping is not something you can do on
- 59:35desktop devices but in Mobile It Feels
- 59:38So natural to move it with your finger
- 59:41right below this image we can render a
- 59:44view once again it's like a div in react
- 59:48this view can have a class name equal to
- 59:50flex Flex D row items D Center justify
- 59:55Das Center w- full and a margin top of
- 59:5910 so we're just centering everything
- 1:00:02within it we can render a text element
- 1:00:05that'll have a class name equal to text-
- 1:00:08Black text- 3 Excel to make it very
- 1:00:11large font Das bold margin X of 10 and
- 1:00:16text- Center within it we can simply
- 1:00:19render the item. title the perfect ride
- 1:00:22is just a step away we can go below this
- 1:00:24View and below the text and create
- 1:00:27another text this text will render the
- 1:00:30description so we can immediately say
- 1:00:32item. description and we can give it a
- 1:00:35class name equal to text- MD font
- 1:00:40djakarta semi bold text- Center
- 1:00:45text-
- 1:00:46hash
- 1:00:488585 85 margin X of 10 to divide it from
- 1:00:52the left and right side and a margin top
- 1:00:54of three to divide it from the
- 1:00:56and there we go your perfect ride is
- 1:00:58just one step away in this case we can
- 1:01:01make this text- LG just so it's a bit
- 1:01:04larger there we go and we can finally
- 1:01:07create a custom button that should go
- 1:01:09below here that says next sure we can
- 1:01:12swipe but if the user is not used to the
- 1:01:14swiper we can also have just a button so
- 1:01:17let's create our first custom component
- 1:01:19of the day we're going to create a new
- 1:01:21components folder right here in the Uber
- 1:01:24clone called component components and
- 1:01:27I'll create a new file called custom
- 1:01:31button. TSX here we can create a const
- 1:01:35custom button which is going to be a
- 1:01:38react Arrow function component and it'll
- 1:01:41have an immediate return so we can just
- 1:01:43wrap it in parenthesis and at the bottom
- 1:01:46we can export default the custom button
- 1:01:50so this custom button will of course
- 1:01:52return the touchable opacity because the
- 1:01:55touchable opacity is a button in react
- 1:01:58native every touchable opacity needs to
- 1:02:00have an on press functionality and in
- 1:02:03this case since it's a custom button
- 1:02:05what this button will be doing will be
- 1:02:07coming through props so we can simply
- 1:02:10pass the onpress from props and then
- 1:02:13call it right here it'll also have many
- 1:02:15other things in the props so let's
- 1:02:16destructure them we'll have a dynamic
- 1:02:19title we have a BG variant which by
- 1:02:22default can be set to primary we'll also
- 1:02:24have a text variant
- 1:02:26of the button which by default can be
- 1:02:28set to default we're going to have an
- 1:02:31icon left with a capital I and then icon
- 1:02:34right if we need to provide it to the
- 1:02:36button we're also going to have some
- 1:02:38custom class names and finally we can
- 1:02:40spread all the other props in case we
- 1:02:42need to share it with the button and you
- 1:02:44can see how convenient this is right now
- 1:02:47that prer and Es length automatically
- 1:02:49reformed my application so we can better
- 1:02:51see what's happening within this
- 1:02:53touchable opacity I'll say if there is
- 1:02:55is an icon left then we can render that
- 1:02:59icon left component just like so I'll
- 1:03:03repeat that at the bottom and say if
- 1:03:05there is an icon right we'll render the
- 1:03:08icon
- 1:03:09right and make sure to say left right
- 1:03:12here in the middle will show the actual
- 1:03:15text of the button so this is a text
- 1:03:17coming from react native and it'll
- 1:03:20render the title that we're passing as a
- 1:03:22prop to this button now let's import
- 1:03:25this custom button
- 1:03:26at the bottom of the swiper we can do
- 1:03:28that by declaring a custom button it'll
- 1:03:31be a self-closing component and we need
- 1:03:33to pass some of these props such as a
- 1:03:36title and the title will say something
- 1:03:38like next we want to go to the next
- 1:03:41screen immediately you can see the next
- 1:03:43key appear right below the swiper we can
- 1:03:46also give it some class names such as w
- 1:03:5011 out of 12 and margin top of 10 and
- 1:03:53now we can dive into the button and
- 1:03:55style it further by giving this
- 1:03:57touchable opacity a class name which
- 1:03:59will be a dynamic template string of
- 1:04:03w-o rounded Das full Flex Flex D row
- 1:04:09justify Das center items Das Center
- 1:04:14Shadow
- 1:04:15DMD Shadow D neutral d400
- 1:04:20over7 and we can then dynamically call
- 1:04:23get BG VAR
- 1:04:26style and to it we can pass the BG
- 1:04:29variant just like
- 1:04:31so and finally we can render the class
- 1:04:34name dynamically right here as well but
- 1:04:37what is this get BG variant style well
- 1:04:40it's a utility function which we can
- 1:04:42create right here above by saying const
- 1:04:45get BG variant style is equal to it
- 1:04:50obviously accepts a variant which is of
- 1:04:53a type button props which we can import
- 1:04:56from types of a BG variant so it can
- 1:04:59either be primary or secondary and we'll
- 1:05:03open up a switch
- 1:05:05statement where we'll look into the
- 1:05:07variant of that button and depending on
- 1:05:10the variant if the case is for example
- 1:05:13secondary will apply a specific color
- 1:05:17such as return BG gray 500 and now we
- 1:05:23can cover it for all other cases so I'll
- 1:05:26duplicate this a couple more times and
- 1:05:28say if Case is danger then the color
- 1:05:31will obviously be red 500 if it's
- 1:05:35success then it'll be green
- 1:05:39500 and if it is
- 1:05:43outline then we'll make it transparent
- 1:05:46by saying BG
- 1:05:48transparent border Das neutral D300 and
- 1:05:53Border Das 0.5 5
- 1:05:57pixels and we can close it finally if
- 1:06:01the case is the default case so we can
- 1:06:04say default then I'll return a BG of
- 1:06:07hash
- 1:06:090286 FF which is some kind of a basic
- 1:06:13button color great so now we can see
- 1:06:15that this button is taking a b variant
- 1:06:17of primary in this case and I believe
- 1:06:20that is the default color here in this
- 1:06:23case it looks like it's complaining a
- 1:06:25bit
- 1:06:26it says that the BG variant needs to be
- 1:06:28of one of these types and what are we
- 1:06:30passing it's BG variant
- 1:06:33primary and here we're not passing
- 1:06:35anything as the BG variant so I do
- 1:06:38believe that we should be good but it
- 1:06:40thinks that it is just a string and we
- 1:06:42know that it's always going to be of one
- 1:06:44of these types so we can say here that a
- 1:06:48BG variant will be of a type button
- 1:06:51props coming from the types declaration
- 1:06:54this way we're importing this
- 1:06:55declaration where we say that the B
- 1:06:57variant will always be of one of these
- 1:06:59types great so now we can also style the
- 1:07:03text by giving it a class name equal to
- 1:07:08text- LG font Das bold and we'll also do
- 1:07:12a very similar thing that we have done
- 1:07:14with the backgrounds so I will make this
- 1:07:16a template
- 1:07:18string and instead of saying get BG
- 1:07:21variant I'll say Dynamic get text
- 1:07:26variant style and then to it I'll pass
- 1:07:29the text variant so now we have to
- 1:07:32declare this function right above and
- 1:07:34I'll do it by duplicating the get BG
- 1:07:37variant and I'll say get text variant
- 1:07:43style and it's going to be of text
- 1:07:47variant right here we have the primary
- 1:07:50which will just make the text black so
- 1:07:52we can say text- black
- 1:07:55next we can move this outline a bit
- 1:07:58above below the primary and we'll call
- 1:08:01that a secondary and this one we'll
- 1:08:04simply say
- 1:08:06text-
- 1:08:09gr-100 next we have danger which is
- 1:08:11going to be a
- 1:08:13text-
- 1:08:16r-100 and finally success is going to be
- 1:08:19a text of green 100 and the default will
- 1:08:23be a text of white so now we have those
- 1:08:26two helper functions that are going to
- 1:08:28help us determine what kind of variant
- 1:08:30Styles we want for our button and of
- 1:08:33course all of this in order to make it
- 1:08:35easier to add new buttons in the future
- 1:08:39we did some heavy lifting to make this
- 1:08:40button fully customizable but now the
- 1:08:43next time that we use it it's going to
- 1:08:44be super simple now let's make that
- 1:08:47button do something first we have to
- 1:08:50figure out if we're on the last slide or
- 1:08:53not if we're not on the last slide we
- 1:08:55simply want to move to the next screen
- 1:08:57once we click it so right at the top
- 1:09:00let's use the active index to figure out
- 1:09:02on which screen we're on we can create a
- 1:09:05new variable called is last slide and
- 1:09:08say if active index is triple equal to
- 1:09:12onboarding length minus one so if we're
- 1:09:15on the last screen that must mean that
- 1:09:17we're on the last slide depending on
- 1:09:20that we can change some different things
- 1:09:23such as we can change the title we we
- 1:09:25can say if is last slide say get started
- 1:09:30else say next similarly we can change
- 1:09:33the onpress button action by creating a
- 1:09:36new callback function and checking if is
- 1:09:40last slide is true then call the router
- 1:09:45replace and point
- 1:09:47two forward SL off sign up just like
- 1:09:53this else if it's not the last step then
- 1:09:56use the swiper ref. current question
- 1:10:01mark. scroll by one so this is how you
- 1:10:05scroll to the next screen so you can
- 1:10:07swipe but you can also click next and
- 1:10:10now it will navigate to the next screen
- 1:10:12and if you get to the last one it'll
- 1:10:14actually move you over to the sign up so
- 1:10:17now let's reload the screen to go
- 1:10:19back finally let's see why this button
- 1:10:23is so slim we need to make it have a bit
- 1:10:25more height so let's navigate over to
- 1:10:27the custom button and let's give it a
- 1:10:30padding of three there we go that's
- 1:10:32better and to this touchable opacity we
- 1:10:35also want to spread all of the other
- 1:10:37props so we can do do do dot props that
- 1:10:41means that whatever we pass right here
- 1:10:43as a class name or as anything else
- 1:10:46we're immediately also transferring to
- 1:10:48this touchable opacity in this case it
- 1:10:50is a custom width and a margin top and
- 1:10:53this is making it look so nice ni and it
- 1:10:56makes it super
- 1:10:58customizable with that in mind our
- 1:11:00welcome screens are now complete we can
- 1:11:03nicely scroll between them you know how
- 1:11:05you can change the title in the
- 1:11:06description if you want to you can
- 1:11:08navigate over with the buttons you can
- 1:11:10press the skip at the top right or you
- 1:11:12can just come to the end of the
- 1:11:14onboarding and press get started an
- 1:11:16onboarding sequence is something that
- 1:11:19every single mobile application has so
- 1:11:22now you know how to do it too and moving
- 1:11:24forward we'll focus on the sign up and
- 1:11:28signin screens so let's do that next by
- 1:11:31heading over to sign Dash up our signup
- 1:11:35page will have a bit more height than
- 1:11:38what some of the devices can fit on one
- 1:11:40screen so instead of a safe area view
- 1:11:43we'll render a scroll view coming from
- 1:11:47react native so let's imported scroll
- 1:11:50View and text coming from react native
- 1:11:53to that scroll View we can give a class
- 1:11:56name equal to flex D1 as well as a
- 1:11:59background of white within it we can
- 1:12:02render a regular view which we also need
- 1:12:05to import from react native so let's do
- 1:12:09just that and let's give it a class name
- 1:12:13equal to flex D1 and BG White Once Again
- 1:12:18within that view we'll render one more
- 1:12:20view within which we'll render an image
- 1:12:23so let's render that image image right
- 1:12:25here and that image once again will come
- 1:12:28from react native it'll have a source
- 1:12:32equal to images which we can import from
- 1:12:36constants do signup car with a class
- 1:12:41name equal to Z of0 w- full for full
- 1:12:45width and
- 1:12:47h-250 pixels for the full height and
- 1:12:50take a look at this nice image at the
- 1:12:52top let's also style this view by giving
- 1:12:56it a class name equal to
- 1:12:58relative w-o and
- 1:13:02h-250 pixels as well below the image we
- 1:13:05can render a text and that text will say
- 1:13:10create your
- 1:13:13account and we can style it a bit by
- 1:13:15giving it a class name of text- 2XL
- 1:13:19text- black font D Jakarta semi bold and
- 1:13:26absolute with a bottom five and left
- 1:13:29five so now we're absolutely positioning
- 1:13:32it just at the bottom of this image but
- 1:13:35it's going a bit within it since we have
- 1:13:37a white gradient appearing right here we
- 1:13:41can go below this view that's below the
- 1:13:43text and we can create another view
- 1:13:46right here this view will have a class
- 1:13:50name equal to padding of five and within
- 1:13:54it we can render a custom component of
- 1:13:57input field so similar to what we have
- 1:14:01done before with a custom button we want
- 1:14:03to create a new custom component called
- 1:14:07input field. TSX we can declare this new
- 1:14:12component input field which is going to
- 1:14:14be just an immediate return function
- 1:14:18where we'll return something very soon
- 1:14:20and then we can do export default input
- 1:14:23field now let's immediately import it
- 1:14:26right here so import input field coming
- 1:14:30from components input field and this
- 1:14:32input field will be within a special
- 1:14:35view a view called keyboard avoiding
- 1:14:39view pretty interesting once you have
- 1:14:41this view your keyboard will not be able
- 1:14:43to go into it because if it did how
- 1:14:45would you type into it okay so that's
- 1:14:49why we have this keyboard avoiding View
- 1:14:51and within it we can also have a
- 1:14:53touchable
- 1:14:56without feedback so this is similar to a
- 1:14:59button but this time we don't really
- 1:15:01want to make it seem like we're clicking
- 1:15:03it and we can import this from react
- 1:15:06native within it we can render a view
- 1:15:09with a class name equal to margin y of 2
- 1:15:14and W of full and within it we can
- 1:15:17render a piece of text that'll have a
- 1:15:20class name it'll be template string of
- 1:15:23text- LG font Das Jakarta semi bold and
- 1:15:28margin bottom of three and we can also
- 1:15:30render the label style which will pass
- 1:15:33through props as well as a label itself
- 1:15:37so now we already know that in the props
- 1:15:39we have to get some things like the
- 1:15:41label we have to get the label style and
- 1:15:45later on much more so now let's pass
- 1:15:50those props while we're calling the
- 1:15:52input field from the signup component we
- 1:15:55can pass things such as a label equal to
- 1:15:58name we can pass a placeholder equal to
- 1:16:01enter name or enter your name we can
- 1:16:06pass an icon equal to icons which we can
- 1:16:10import from icons.
- 1:16:12person a value will be equal to a form
- 1:16:16value so right at the top of this file
- 1:16:18we can declare a form for the signup by
- 1:16:21saying use state is equal to form
- 1:16:25set form at the start equal to an object
- 1:16:28that has a name equal to an empty string
- 1:16:31it has an email equal to an empty string
- 1:16:34as well and it has a password equal to
- 1:16:37an empty string and now we can use that
- 1:16:40value right within this first input
- 1:16:43field by saying form. name and below it
- 1:16:47we can call the on change Handler so on
- 1:16:50change text will be equal to where we
- 1:16:53get the value and then we need to set up
- 1:16:56the form by saying set form and first we
- 1:17:00have to spread the existing values of
- 1:17:02the form by saying do do do form and
- 1:17:05then update this specific Field's value
- 1:17:08so the value of this specific field is
- 1:17:11name and we can set that over to be
- 1:17:13equal to Value I think I can expand this
- 1:17:15in a few lines just so you can quickly
- 1:17:17see what's happening so we're setting
- 1:17:19the form by first spreading all of the
- 1:17:21other fields and then updating
- 1:17:23specifically the name field with the
- 1:17:26name value if I zoom out a bit we can
- 1:17:28see it in one line and that now allows
- 1:17:30us to go into the input field and accept
- 1:17:33all of these props so alongside the
- 1:17:36label and the label style we also have
- 1:17:39things like the icon the secure text
- 1:17:43entry so if this is true that means that
- 1:17:45we're typing in a password and by
- 1:17:47default it will be set to false we have
- 1:17:49the container style the input style the
- 1:17:54icon sty style the class name and
- 1:17:57finally we can spread all of the other
- 1:18:00props that we have so now we can
- 1:18:02continue with creating this field
- 1:18:04because right now we're just showing the
- 1:18:06label and nothing more so let's go below
- 1:18:10this text and let's create a new view
- 1:18:12inside of which we can create the icon
- 1:18:15and the input this view will have a
- 1:18:18class name equal to it'll be a dynamic
- 1:18:22property of flex Flex D
- 1:18:26row justify Das start items D Center
- 1:18:31relative BG Das neutral of 100 rounded
- 1:18:35Das full border border neutral of 100
- 1:18:41and on Focus border Das primary of 500
- 1:18:45and dynamic property of container style
- 1:18:51if we decide to pass any additional
- 1:18:52properties and now we're slowly starting
- 1:18:55to create this specific input within it
- 1:18:58we can check if we have the icon so if
- 1:19:01icon exists then we can render an image
- 1:19:05which we of course have to import from
- 1:19:07react native we can do that right at the
- 1:19:10top by getting the image from react
- 1:19:13native this image will have of course a
- 1:19:16source equal to Icon and a class name of
- 1:19:21it will be dynamic w6h
- 1:19:25six margin left of four and dynamic
- 1:19:29property of Icon style so now we can see
- 1:19:32this icon and what is soon going to
- 1:19:34become an input field below the icon we
- 1:19:37can render a text input which is a react
- 1:19:40native component so we have to import it
- 1:19:42from react native it will also have a
- 1:19:45class name which will be dynamic it'll
- 1:19:48be rounded Das
- 1:19:51full padding of four F of Jakarta semi
- 1:19:56bold text of 15 pixels Flex
- 1:20:00one and it'll have Dynamic Property of
- 1:20:04input style as well as text Dash left
- 1:20:07it'll also have a property of secure
- 1:20:09text entry equal to secure text entry
- 1:20:13and we can spread all of the other props
- 1:20:15that we decide to share with this input
- 1:20:17so now you can slowly start seeing this
- 1:20:19input appear on the screen enter your
- 1:20:21name we can style this input a bit
- 1:20:23further by modifying the keyboard
- 1:20:26avoiding View and we can change the
- 1:20:28behavior of this view depending on the
- 1:20:31platform we're on so we can use the
- 1:20:33special platform feature coming from
- 1:20:35react native by saying platform which we
- 1:20:38can import from react
- 1:20:40native. and if the OS is equal to iOS
- 1:20:44then we can do padding else we can do
- 1:20:47height I learned that this makes it work
- 1:20:49better on those specific devices to
- 1:20:52touchable without feedback we can
- 1:20:54provide an on press and here we can run
- 1:20:58the keyboard coming from react native.
- 1:21:02dismiss which means that if we click
- 1:21:04outside or if we click within this
- 1:21:06touchable opacity or touchable without
- 1:21:08feedback we will close the keyboard
- 1:21:11check this out I click it I click
- 1:21:14outside it closes great and now we have
- 1:21:17a single input field we can also specify
- 1:21:20the types of those props which are equal
- 1:21:23to input field props coming from types
- 1:21:26and now that we have created this
- 1:21:28structure for input Fields it is super
- 1:21:30simple to just duplicate them below one
- 1:21:33two
- 1:21:34more the one below will have a label of
- 1:21:38email it'll say enter email or enter
- 1:21:42your email the icon will be icons. email
- 1:21:47it'll say form. email and under form we
- 1:21:51will set the email right here and for
- 1:21:54the third one we can say password so
- 1:21:57password enter your password icons will
- 1:22:00be icons. loock and here we'll pass the
- 1:22:03special secure text entry equal to True
- 1:22:08Value is form. password and finally we
- 1:22:11can set the password here as well and
- 1:22:15now we can see three fields and how
- 1:22:17simple it was to create them below those
- 1:22:20three we can do something even simpler
- 1:22:23and that is call our custom button we
- 1:22:27can provide it a title of sign up we can
- 1:22:31give it an on press which we'll call a
- 1:22:34special function called on signup
- 1:22:38press and we can give it a class name
- 1:22:41equal to margin top of six so before we
- 1:22:46save this we just have to create this on
- 1:22:48signup press functionality so let me
- 1:22:51just add it right here above const
- 1:22:55on signup press is equal to an
- 1:22:58async arrow
- 1:23:00function which we'll create later on but
- 1:23:02for now you can see how simple it was to
- 1:23:05duplicate these three inputs and create
- 1:23:07a custom button right below right below
- 1:23:11this custom button soon enough we'll
- 1:23:13create our oo meaning a special button
- 1:23:17that will allow us to log in with Google
- 1:23:20and Below oo will show just a regular
- 1:23:23link coming coming from react
- 1:23:26native that will point to for SL sign-
- 1:23:30in and it'll have a text property of
- 1:23:33something like already have an account
- 1:23:37question mark and then we can render
- 1:23:39another text right below and say
- 1:23:41something like log in but this one will
- 1:23:45have a class name equal to text- primary
- 1:23:49d500 okay let's style this link just a
- 1:23:53bit more by giving giving it a class
- 1:23:56name equal to text-
- 1:23:59LG text- Center text- general of 200 and
- 1:24:05a margin top of 10 we can also create an
- 1:24:08empty space right here after the
- 1:24:10question mark like this and this is now
- 1:24:12looking so much better below this link
- 1:24:15and below the view later on we'll create
- 1:24:18a model for the verification so I can
- 1:24:20say verification model right here so now
- 1:24:24let's add this oo button to which we can
- 1:24:26add the functionality very soon I'll
- 1:24:28create a new custom component called
- 1:24:32oo which typically stands for social
- 1:24:35authentication here we can create a new
- 1:24:37component const oo is equal to a
- 1:24:41functional component and we can just
- 1:24:43export default ooth within there we can
- 1:24:46automatically return a view within that
- 1:24:49view we'll have another smaller view
- 1:24:52that will have a class name equal to
- 1:24:55flex Flex Das row justify Das center
- 1:25:01items Das Center margin top of four and
- 1:25:06a gap X of three within it we can render
- 1:25:10one self-closing view that'll have a
- 1:25:13class name equal to flex of
- 1:25:17one h of one pixel so height of only one
- 1:25:20pixel and a BG General of 100 below that
- 1:25:26one dot we'll also have a text which we
- 1:25:29need to import from react
- 1:25:32native and this text will have a class
- 1:25:35name equal to text- LG and it'll say or
- 1:25:40and then right below that we can
- 1:25:42duplicate this View and show it here so
- 1:25:45this is going to look something like
- 1:25:48this even though we cannot see it yet it
- 1:25:50will be there soon once we call the O
- 1:25:53off component which we just created so
- 1:25:57all off and we can import it
- 1:25:59automatically right here I'm going to
- 1:26:02skip the on boarding and it should
- 1:26:04appear just above the already have an
- 1:26:07account thing but we cannot see it yet
- 1:26:09so to make it a bit more visible we can
- 1:26:11go below this inner View and create a
- 1:26:15custom button it'll look something like
- 1:26:18this and it'll have quite a few props a
- 1:26:21title equal to log in
- 1:26:25with Google there we go now we can see
- 1:26:28it we can also give it a class name
- 1:26:31equal to margin top w- full and Shadow
- 1:26:39dnone we can also give it an icon left
- 1:26:42which is going to be equal to a callback
- 1:26:45function that automatically returns an
- 1:26:48image and this image will have a source
- 1:26:52equal to icons .
- 1:26:55Google a resize mode equal to contain
- 1:27:00and a class name equal to w-5
- 1:27:05h-5 and margin X off two and of course
- 1:27:09we need to import these icons at the top
- 1:27:12by saying
- 1:27:13import icons coming from add for slash
- 1:27:18constants slash nothing because the
- 1:27:22icons are exported from there now if we
- 1:27:25head over to our sign up you can see a
- 1:27:28button that says login with Google let's
- 1:27:32also give it an additional property of
- 1:27:36BG variant is equal to outline because
- 1:27:40typically Google buttons don't have a
- 1:27:42color typically they're white and the
- 1:27:45text variant will be set to
- 1:27:48primary like this there we go that's a
- 1:27:51Google button and finally we can say on
- 1:27:53press
- 1:27:54and that'll be equal to a function
- 1:27:56called to handle Google sign in so this
- 1:28:00is a function which we can declare right
- 1:28:02here above it'll have to be within the
- 1:28:04function so it cannot be an instant
- 1:28:06return rather we have to say return
- 1:28:10here close it properly indent it and now
- 1:28:14we can declare the function const handle
- 1:28:17Google signin which will be equal to an
- 1:28:19async function to which we can add the
- 1:28:21logic very soon so now we have the
- 1:28:24Google sign-in button and the regular
- 1:28:26sign up and we can click on the login to
- 1:28:29navigate over to a log in screen so if
- 1:28:32we click it right now it'll be empty and
- 1:28:35how will our login screen look like well
- 1:28:38if we check out our design you can see
- 1:28:39that it is basically almost the same as
- 1:28:42the signup it just doesn't have the name
- 1:28:44field because we already have our name
- 1:28:47so for that reason to create our sign in
- 1:28:50I will duplicate the signup head over to
- 1:28:53sign in
- 1:28:54and just override everything we have
- 1:28:56here while I rename it to sign in so
- 1:29:00let's do that here and here and Skip and
- 1:29:06head over to login and there we go we
- 1:29:08can see the same signup screen here but
- 1:29:11in this case we'll make some changes so
- 1:29:13let's go down we'll keep the same sign
- 1:29:15up image but instead create your account
- 1:29:18we'll say something like welcome and we
- 1:29:21can also do an emoji of wave right here
- 1:29:24you can find it on Google and copy it in
- 1:29:26this case as I told you we won't have
- 1:29:28the input field off name rather we'll
- 1:29:30just have input fields for email and
- 1:29:34password the button will say sign in of
- 1:29:38course and instead of on signup press
- 1:29:41here we'll have on sign in press
- 1:29:44functionality so that's going to be on
- 1:29:46sign
- 1:29:48in and we can use it here at the same
- 1:29:52time the form will only have the email
- 1:29:54Emil and password it won't have a name
- 1:29:56so we can delete it from here the link
- 1:29:59will also have a reverse logic right
- 1:30:01here instead of saying already have an
- 1:30:03account we'll say something like don't
- 1:30:07have an account and then we can say sign
- 1:30:11up there we go so now we have enabled
- 1:30:14switching between the sign in and the
- 1:30:16sign up after we modify the H right here
- 1:30:21I click sign up it goes there sign in
- 1:30:24goes here and now we can nicely move
- 1:30:26between the different screens this is
- 1:30:29great The Next Step will of course be to
- 1:30:32implement the functionality of
- 1:30:34registering our account we'll first
- 1:30:36start by implementing the functionality
- 1:30:38of registering through the email and the
- 1:30:41password and then later on we'll make
- 1:30:43the oo work as well for authentication
- 1:30:47will of course be using clerk it is more
- 1:30:49than just a signup box it allows you to
- 1:30:52very quickly implement
- 1:30:54and super functional and secure
- 1:30:56authentication flows and if you checked
- 1:30:58out a couple of my other videos you know
- 1:31:00that it's completely free for up to
- 1:31:0310,000 not just users but monthly active
- 1:31:07users it is super hard to ever cross
- 1:31:09this number but if you do then you can
- 1:31:11start paying or make a switch but if you
- 1:31:14never reach that number it is completely
- 1:31:16free and here's the best part clerk
- 1:31:19created a phenomenal Expo quick start
- 1:31:22making it work so seamlessly ly with
- 1:31:24Mobile Expo applications the first step
- 1:31:27we have already done we have installed
- 1:31:29all the necessary things and created an
- 1:31:31expo app but we just have to install the
- 1:31:35Expo Metro runtime as well so let's just
- 1:31:38copy the second part of this first
- 1:31:40terminal command we can open up a new
- 1:31:42terminal and paste it right here MPX XO
- 1:31:46stall and then couple of these
- 1:31:48dependencies we can continue following
- 1:31:50the other steps such as installing the
- 1:31:52clerk and the clerk Expo package by
- 1:31:56pasting the command after that we'll
- 1:31:58have to set up our environment variables
- 1:32:00and in this case it looks like I'm
- 1:32:02already logged in if you're not logged
- 1:32:04in click the link in the description
- 1:32:07which will allow you to follow along and
- 1:32:09see exactly what I'm seeing and now I
- 1:32:11can see that this is not the right key
- 1:32:12for me either because I have to create a
- 1:32:14new project so let's head over to the
- 1:32:17dashboard and as you can see I already
- 1:32:19created many clerk applications but now
- 1:32:22we'll create a new one I'll call it
- 1:32:25JSM Uber you can give it some other name
- 1:32:29I think you can do something like ride
- 1:32:30as well but make sure to start with
- 1:32:32JSM we'll choose email signin option as
- 1:32:36well as Google and click create
- 1:32:39application you can see that they have
- 1:32:40the Expo setup right here so we can
- 1:32:43continue following right from
- 1:32:45here here we have our environment test
- 1:32:48variable so let's copy it and add it to
- 1:32:50our envs I'll create a new file in the
- 1:32:53root of our directory ctory called
- 1:32:56EnV and just paste this environment
- 1:32:59variable here webstorm asks me if I want
- 1:33:02to install the EnV file support plugin
- 1:33:05which I will install now we can continue
- 1:33:08to the next step and that is adding the
- 1:33:10clerk provider to our root layout so
- 1:33:13let's copy this entire file head over to
- 1:33:17layout and paste it right here at the
- 1:33:19top you'll notice that we have some
- 1:33:22imports we're getting that environment
- 1:33:24key and we have a check if we don't have
- 1:33:27a key after that we need to wrap our
- 1:33:29entire application with the clerk
- 1:33:31provider and the clerk loaded wrappers
- 1:33:34so let's copy them delete this and wrap
- 1:33:38our stack with the clerk provider and
- 1:33:41clerk loaded and close one by
- 1:33:44one I indented everything nicely and it
- 1:33:48looks great we can add this if no
- 1:33:50publishable key right within the root
- 1:33:53layout
- 1:33:54below the fonts loaded now let's go to
- 1:33:57the next step and that is to configure
- 1:34:00the token cache with Expo for that we
- 1:34:03need to install the new package Expo
- 1:34:06secure store so let's simply open up a
- 1:34:09new terminal and copy and paste the
- 1:34:11command the next step is to copy this
- 1:34:14token cache so let's copy it and instead
- 1:34:17of cluttering the layout file with all
- 1:34:19of the authentication logic we can put
- 1:34:22all authentication logic in another file
- 1:34:25that can be within Uber clone and we can
- 1:34:27create a new
- 1:34:29folder called lib as in library and
- 1:34:32within the library we can create a new
- 1:34:34file called
- 1:34:36O.S inside of which we can post this
- 1:34:40token cache interface and here we can
- 1:34:42also copy the token cache part of this
- 1:34:45next code block we're not going to put
- 1:34:47it within the layout which is going to
- 1:34:49take the token cache so let's paste it
- 1:34:51here and let's make sure to get the
- 1:34:54secure store from Expo secure store and
- 1:34:58all the other Imports that we need so
- 1:35:00I'll paste it at the top of this file
- 1:35:03right here we just need that and I don't
- 1:35:06even believe we'll need the token cache
- 1:35:08interface we can add it later on if it's
- 1:35:10needed and since we'll use token cache
- 1:35:12somewhere else for now I'll just say
- 1:35:14export const token cache now let's go
- 1:35:17down and the next thing is to create a
- 1:35:21Home Route group layout I believe we
- 1:35:24call this root and we already have it
- 1:35:26the next step is to conditionally render
- 1:35:29the content depending whether we're
- 1:35:30signed in or not we don't have to do
- 1:35:33this yet we're going to do it on the
- 1:35:34homepage remember we haven't yet signed
- 1:35:37in so we cannot even see the homepage
- 1:35:39but maybe it will be good to see this
- 1:35:41once we're actually logged in to see at
- 1:35:44least something to see a successful
- 1:35:46authentication state so let's actually
- 1:35:48copy everything that is on here that is
- 1:35:51indeed the index TSX of the home page so
- 1:35:54we can override what we currently have
- 1:35:56in our app Root tabs and then home and
- 1:36:01here we can paste what we just copied if
- 1:36:04we do authenticate successfully we
- 1:36:06should be redirected to this page and we
- 1:36:08should be able to see our email address
- 1:36:11next we need to protect our o routes in
- 1:36:14the layout by creating a new route group
- 1:36:16O which we already have done with the
- 1:36:19underscore layout file and now we can do
- 1:36:21a redirect there so let's copy this if
- 1:36:25statement and the use o and we can head
- 1:36:28over to index. DSX which is our homepage
- 1:36:33and here we can paste if signed in use o
- 1:36:37and that's coming from clerk Expo we can
- 1:36:39also imported so if we're signed in then
- 1:36:42redirect to home else redirect to O
- 1:36:47welcome in our case the home will be
- 1:36:50under a bit of a different route it's
- 1:36:52not going to be just for slash it'll be
- 1:36:57slash
- 1:36:59root slash
- 1:37:02tabs
- 1:37:04slome okay I hope that makes sense that
- 1:37:08is the home page that we just added
- 1:37:10these clerk functionalities too great so
- 1:37:13far we're just following the steps the
- 1:37:15next thing that it says is to add the
- 1:37:17sign up page we already have the signup
- 1:37:20page thankfully uh but we can copy this
- 1:37:23on signup press function and on press
- 1:37:27verify function so let's copy them head
- 1:37:31over to sign up where we left off and
- 1:37:34override the on signup press with these
- 1:37:37new functions which we have just copied
- 1:37:39with them we most likely also have to
- 1:37:41get some of the states or we'll have to
- 1:37:43make some of the modifications I think
- 1:37:45we can add all of that on our own the
- 1:37:47only thing we need is the call to the
- 1:37:49use signup hook right here at the top
- 1:37:52coming from Clerk Expo so let's call
- 1:37:55this hook at the top use sign up and
- 1:37:59this is coming from clerk Expo so we can
- 1:38:02say import use sign up coming from clerk
- 1:38:08at clerk clerk Expo we already have the
- 1:38:12form that is good but we also need the
- 1:38:14verification because for clerk to work
- 1:38:17with react native applications via email
- 1:38:19we need to verify our user login or sign
- 1:38:22up by email and this will be just a
- 1:38:25state so we can use the use State
- 1:38:27snippet
- 1:38:29verification set verification at the
- 1:38:32start equal to an object containing the
- 1:38:34state equal to
- 1:38:36default the error code if there is one
- 1:38:40at the start equal to an empty string
- 1:38:42and the code the user is trying to enter
- 1:38:45to verify their credentials that's also
- 1:38:48going to be an empty string at the start
- 1:38:50next our email address and password are
- 1:38:53coming from a form so we have to say
- 1:38:56email address and password are equal to
- 1:38:58form. email and form that password next
- 1:39:03we can leave this as it is and instead
- 1:39:05of set pending verification to true we
- 1:39:07can say set verification where we can
- 1:39:10say dot do dot verification to spread
- 1:39:13all the existing information about the
- 1:39:15verification but we can set the state to
- 1:39:18pending if we get an error we'll simply
- 1:39:20conso log that error and that's it for
- 1:39:23the signup but we have to figure out
- 1:39:25what happens on the verification the
- 1:39:28verification is the second part of the
- 1:39:30authentication it's when we get the
- 1:39:31email with the code that's asking us to
- 1:39:34verify whether it's us who's trying to
- 1:39:36sign up with our email account so we can
- 1:39:38say if not loaded then return nothing
- 1:39:42meaning exit out of the function else we
- 1:39:45can try to complete the signup the code
- 1:39:48in this case will be equal to
- 1:39:50verification. code because that's where
- 1:39:52we put it within that specific State
- 1:39:54field if complete signup do status is
- 1:39:58equal to complete then we want to set
- 1:40:01active the session of the complete
- 1:40:03signup that created session ID and we
- 1:40:06also want to modify the verification
- 1:40:08state to say do do do verification where
- 1:40:12we spread everything but then we also
- 1:40:14want to set the state to be equal to
- 1:40:16success else if it doesn't succeed we
- 1:40:19want to set the verification to state is
- 1:40:23equal to failed and then we can add the
- 1:40:26error message equal to
- 1:40:29verification failed and finally on the
- 1:40:32big catch we can also set the
- 1:40:35verification error right here but this
- 1:40:37time the error can be equal to error.
- 1:40:40errors
- 1:40:41z. long message so this will tell us a
- 1:40:44bit more information about why the error
- 1:40:47happened finally there's something that
- 1:40:49aite hasn't done here and that is create
- 1:40:52a new user in our own database once a
- 1:40:55clerk user gets created and that's what
- 1:40:58we want to do right here so I'll say to
- 1:41:00do create a
- 1:41:03database
- 1:41:05user so here later on we'll make a
- 1:41:07database call to create a user in our
- 1:41:09database Beyond just being a clerk user
- 1:41:13but for the time being we've been
- 1:41:14looking at this create your account
- 1:41:16screen for far too long and I would just
- 1:41:18want to see something change so let's
- 1:41:21try to authenticate with Clerk first but
- 1:41:24of course to be able to do that we have
- 1:41:26to create a model that would allow us to
- 1:41:29type in the code that we got via email
- 1:41:33so let's create a new model right here
- 1:41:36below everything that we have
- 1:41:38verification model it is waiting for us
- 1:41:41to create this model we'll install a new
- 1:41:43package mpm install
- 1:41:46react-native Das model it's a very handy
- 1:41:50package that basically screams don't
- 1:41:53reinvent the wheel somebody else needed
- 1:41:56a model before they created it it is
- 1:41:58used by tens of thousands of people if
- 1:42:01not more and we're going to make use of
- 1:42:03that model in here as well but of course
- 1:42:06we'll style it to match our own
- 1:42:07application so to start creating it we
- 1:42:10can use it by importing it by saying
- 1:42:13react native
- 1:42:15model which Imports it from react-native
- 1:42:18D model and it accepts an is visible
- 1:42:22prop and it'll only be visible if the
- 1:42:26verification. state is triple equal to
- 1:42:30success next within it we can show a
- 1:42:33view and that view will have a class
- 1:42:36name equal to BG dwh padding X of s
- 1:42:41padding y of 9 rounded -2 XL and m-
- 1:42:47h-300 pixels inside of square
- 1:42:50brackets within it we can also render an
- 1:42:53image with a source equal to images.
- 1:42:58check and a class name equal to
- 1:43:02w-10 pixels for the width h- 110 pixels
- 1:43:07for the height and margin X of Auto and
- 1:43:11margin y of
- 1:43:13five if we save it we cannot see
- 1:43:16anything yet because we haven't yet
- 1:43:18modified the verification status by
- 1:43:20entering our details but thank
- 1:43:23thankfully we can mock that verification
- 1:43:25status by changing the default State
- 1:43:28variable to success and let's reload our
- 1:43:32application just to see the latest
- 1:43:34changes I think sometimes it does get
- 1:43:37stuck oh this time we have an error
- 1:43:39saying module Expo local
- 1:43:42authentication could not be found within
- 1:43:44the project directory this error seems
- 1:43:47pretty self-explanatory it's saying that
- 1:43:49it's unable to resolve this package from
- 1:43:52Clerk Expo so that might mean that we
- 1:43:55just need to install it manually so
- 1:43:58let's copy the name let's say mpm
- 1:44:01install and then say Expo local
- 1:44:04authentication make sure to spell it
- 1:44:06properly I often misspell authentication
- 1:44:09and press
- 1:44:11enter once it gets installed we can try
- 1:44:14to reload our application and see if
- 1:44:16that fixes it indeed it got bundled we
- 1:44:20are back on our onboarding which is
- 1:44:23looking great and it looks like we're
- 1:44:25still having this console warning from
- 1:44:27the root but we're going to fix that
- 1:44:29very soon for now I will dismiss it and
- 1:44:32we can see our beautiful
- 1:44:34model let's continue creating it below
- 1:44:37the image I'll show a text element with
- 1:44:41a class name equal to text- 3XL font D
- 1:44:46Jakarta
- 1:44:48bold and text Dash Center within it we
- 1:44:52can say some something like verified
- 1:44:55right below we can do another text that
- 1:44:57will have a class name equal to
- 1:45:01text-base text- gray- 400 font D Jakarta
- 1:45:07text- Center and margin top of two and
- 1:45:11we can say something like you have
- 1:45:13successfully verified your account and
- 1:45:16finally below the text we can have
- 1:45:19another custom button with a title of
- 1:45:23browse Home on press we can have a
- 1:45:26callback function that calls the
- 1:45:28router from Expo router and replaces our
- 1:45:33URL to a string of SL root which is in
- 1:45:39parentheses slash tabs in parentheses
- 1:45:44slome and it's going to have a class
- 1:45:46name of margin top of
- 1:45:50five there we go verified browse home
- 1:45:54now we won't click it just yet as it'll
- 1:45:56most likely break our
- 1:45:58application but what we can do is
- 1:46:01actually test out the full
- 1:46:03functionalities of our authentication we
- 1:46:06have added a lot of code I'm not saying
- 1:46:08everything will work right of the bad
- 1:46:11but we can give it a shot I will bring
- 1:46:14back the default state of the
- 1:46:16verification to default so it'll get
- 1:46:19hidden and now that I think about it
- 1:46:21instead of changing it to default we're
- 1:46:23going to change it to pending because
- 1:46:25that's the state that has to happen
- 1:46:27before success so that means that we can
- 1:46:30go down where we have created our react
- 1:46:34native model and now we'll have to
- 1:46:36create yet another react native model
- 1:46:39with a status of
- 1:46:42pending so let's copy
- 1:46:45it and I'll put it right here on
- 1:46:48top react native model with a status of
- 1:46:51pending another property we can add to
- 1:46:54this react native model is on modal hide
- 1:46:58and on modal hide in this case we can
- 1:47:01create a callback
- 1:47:03function and we can set
- 1:47:06verification by spreading the
- 1:47:08verification properties and then
- 1:47:11changing the state to
- 1:47:13success and now we can go inside of that
- 1:47:16model and craft it by crafting a view
- 1:47:20that view will have a class name equal
- 1:47:22to BG - wi padding X of 7 padding y of 9
- 1:47:28we already know the drill rounded -2
- 1:47:30Excel and m-h of 300 pixels there we go
- 1:47:36that's our model within it we can render
- 1:47:39a piece of text that'll have a class
- 1:47:42name of text- 2XL font
- 1:47:46djakarta extra bold and margin bottom of
- 1:47:51two that's going to say something like
- 1:47:53verification below that text we can have
- 1:47:56another piece of text with a class name
- 1:48:00equal to font D
- 1:48:03Jakarta and margin bottom of
- 1:48:06five and it can say we've sent a
- 1:48:10verification code to form. mail so this
- 1:48:14is the email you entered during the form
- 1:48:17below this text we can create an input
- 1:48:20field again it is Super Con venient Now
- 1:48:23to create it because we have already
- 1:48:25created this input field component uh
- 1:48:28that's going to have a label equal to
- 1:48:30code icon equal to icons. loock
- 1:48:36placeholder equal to 1 2 3 4
- 1:48:405 value equal to
- 1:48:43verification. code keyboard type this is
- 1:48:48something pretty interesting numeric in
- 1:48:51web applications you cannot change your
- 1:48:53physical keyboard but here you can um
- 1:48:56next we can also have the onchange
- 1:49:00text which will request a callback
- 1:49:03function with the code you're typing in
- 1:49:06and we can set verification to be equal
- 1:49:10to where we spread verification and then
- 1:49:12update the code that's going to look
- 1:49:15something like
- 1:49:16this finally if there is a verification
- 1:49:19error we can show it so if verification
- 1:49:24error then we can render another piece
- 1:49:27of
- 1:49:28text that's going to render the
- 1:49:30verification. error of course that text
- 1:49:33will be red in color so we can give it a
- 1:49:36class name equal to text-
- 1:49:39r-500 and text- smm as well as margin
- 1:49:43top of one and below that we need to
- 1:49:46have a custom
- 1:49:48button of course that we'll use to
- 1:49:50submit it so we can say VAR ify email
- 1:49:55onpress here we're actually calling the
- 1:49:57onpress verify which is the function
- 1:49:59that we coded above with a class name of
- 1:50:03margin top of five and BG success of 500
- 1:50:07there we go that's looking good so what
- 1:50:11do you say that we give it a shot I'll
- 1:50:14change the default state to
- 1:50:18default to CR form and now I'll start
- 1:50:22typing my
- 1:50:24name it's Adrien the email is contact at
- 1:50:30JS mastery.
- 1:50:32proo and we can choose a password Here
- 1:50:36we have very strict clerk rules I
- 1:50:38believe so if I enter
- 1:50:40123123 and click sign up we have an
- 1:50:43error it seems like we cannot expand it
- 1:50:45right now but of course we want to show
- 1:50:47that error in some kind of a better
- 1:50:50place and that's where react native
- 1:50:53alerts come in so we can scroll down to
- 1:50:56this catch where we just consel log the
- 1:50:58error and instead of a conso log we can
- 1:51:01actually alert it by using the alert
- 1:51:05functionality from react native. alert
- 1:51:09of a type error and we can enter a
- 1:51:12message of
- 1:51:13er. Errors z. long
- 1:51:18message now if we save this and try to
- 1:51:22sign up with a basic password one more
- 1:51:24time we got a nice error saying
- 1:51:27passwords must be eight characters or
- 1:51:30more even though you cannot see it on
- 1:51:32the screen I think my phone recording
- 1:51:34software is hiding it I do indeed see
- 1:51:37six password dots on my screen now I
- 1:51:40will change it to 123123123 to pass over
- 1:51:45the8 character minimum limit and I'll
- 1:51:47click sign
- 1:51:49up now it says password has been found
- 1:51:52in an online data breach for account
- 1:51:54safety please use a different password
- 1:51:56very interesting so it looks like we'll
- 1:51:59have to choose a real password I'll
- 1:52:02enter something specific I'll pause the
- 1:52:05video and enter a strong password and
- 1:52:08press sign
- 1:52:10up this time a verification model
- 1:52:14appeared which is a good sign and would
- 1:52:17you look at that JSM ride verification
- 1:52:20code just arrived in Mya email so let's
- 1:52:24copy the code or should I say type it in
- 1:52:28623
- 1:52:30263 and click verify
- 1:52:34email and nothing where is our success
- 1:52:38screen why didn't we get renav to the
- 1:52:41home are we signed in or are we not or
- 1:52:44should I say was the account created or
- 1:52:47was it not the best way to find out is
- 1:52:49to go to Clerk's dashboard under users
- 1:52:53and here you can indeed see a new user
- 1:52:56that got
- 1:52:57created but for some reason the success
- 1:53:00model didn't show that's totally okay
- 1:53:03let's delete the user and let's give it
- 1:53:05another shot in react native you can
- 1:53:08never show two models at the same time
- 1:53:11and if you scroll down you can see that
- 1:53:13we're using the same state to go from
- 1:53:15pending and then to success we have to
- 1:53:19use two different states to make that
- 1:53:21happen so let's scroll up and let's
- 1:53:24create a new state use State
- 1:53:30snippet called show success model set
- 1:53:35show success model at the start set to
- 1:53:37false now we can scroll down and on our
- 1:53:41pending model instead of setting the
- 1:53:43verification state to success we can do
- 1:53:46something else we can say if
- 1:53:50verification. state
- 1:53:53is triple equal to success then we can
- 1:53:56set show success model to True let's
- 1:54:02just turn this into a function and
- 1:54:04properly close it and now when we
- 1:54:07activate this second model for success
- 1:54:10we're not going to activate it by the
- 1:54:11verification that state rather we'll
- 1:54:14activate it by this new show success
- 1:54:16modal state so let's give it another
- 1:54:19shot let's create a new account I again
- 1:54:22pause the video enter my details and
- 1:54:25press sign up we get this new
- 1:54:28verification model which is great send
- 1:54:30to contact jm.pro indeed we get back a
- 1:54:34new code which I can enter on my phone
- 1:54:37this feels so good it feels like I'm
- 1:54:40trying to install or sign up for a
- 1:54:42completely new mobile application
- 1:54:475982 verify email and verified there we
- 1:54:51go I love how nicely it's slided from
- 1:54:54the bottom to the center of the screen
- 1:54:55and now we can click browse home and it
- 1:54:59broke my application let's try to reopen
- 1:55:02it once again by the way we have to fix
- 1:55:04the borders here of the splash screen so
- 1:55:07let's fix that right away I think the
- 1:55:09fixes in the app. Json where we have the
- 1:55:12splash screen right here we have to
- 1:55:14change the background color to match the
- 1:55:16blue color of the application so that's
- 1:55:202f8 e
- 1:55:23if we save it and reload our entire
- 1:55:26splash screen you can see that now it
- 1:55:28appears perfectly on the screen and the
- 1:55:30blue covers the entire thing now we can
- 1:55:33skip the onboarding and try to sign up
- 1:55:36one more time but I think the issue was
- 1:55:39with this router. replace thing right
- 1:55:42here instead of router replace let's try
- 1:55:45to use a router. push there are minor
- 1:55:48differences between the two but this
- 1:55:50might just do it so one more time you'll
- 1:55:53have to reload your clerk dashboard and
- 1:55:56delete this user in case you want to use
- 1:55:58the same email address I'll pause the
- 1:56:00video and type in my credentials I'll
- 1:56:03click sign
- 1:56:05up enter my code click verify and browse
- 1:56:10Home there we go it almost worked we
- 1:56:13just have to hide the actual model the
- 1:56:16only thing we have to do to fix this is
- 1:56:19expand this router. push and add
- 1:56:21something to it and that something is
- 1:56:24set show success model and reset it back
- 1:56:27to false because then once we rigate it
- 1:56:30will no longer be showing great so if I
- 1:56:34click it as you can see it works great
- 1:56:38so now we can see our homepage and we
- 1:56:41can get rid of this ugly top bar we can
- 1:56:45do that easily by finding the layout
- 1:56:47that is close to our home which is this
- 1:56:50layout right here and we need to copy
- 1:56:53one of the previous layouts that we've
- 1:56:55had maybe this one right here we had in
- 1:56:58the O we can copy it and head over to
- 1:57:02the layout next to the tabs not the one
- 1:57:05inside it but rather next to the tabs
- 1:57:09and paste it
- 1:57:11here here we can just say name tabs in
- 1:57:15parenthesis Heather shown is set to
- 1:57:18false and for now we can remove these
- 1:57:20other routes and just leave the tabs
- 1:57:22route group I'll also open up the app
- 1:57:25once again and actually now might be a
- 1:57:28good idea to implement the
- 1:57:30authentication session to check whether
- 1:57:32our user has already authenticated so we
- 1:57:34can automatically skip the onboarding
- 1:57:37and skip the welcome screen and skip the
- 1:57:39authentication screens and go straight
- 1:57:42to the home I mean think about it that's
- 1:57:44the typical app experience you're not
- 1:57:46going to sign in for the app or go
- 1:57:48through the onboarding every time you
- 1:57:49open the app on your phone you're going
- 1:57:51to go Direct ly to the homepage of that
- 1:57:53app so let's do that next I think it's
- 1:57:56going to be an easy fix and it's not
- 1:57:58working right now because I accidentally
- 1:58:00skipped one of the steps in the Expo
- 1:58:02clerk setup and that is if you go to
- 1:58:05this app layout remember when I told you
- 1:58:08that we will take apart this o TS token
- 1:58:11cache just to not clutter the layout
- 1:58:14well I exported it but I forgot to use
- 1:58:17it so we have to pass this clerk token
- 1:58:21cache
- 1:58:22equal to token cache coming from lib o
- 1:58:26right here once you pass it it should
- 1:58:29have access to the current user session
- 1:58:31it is still not redirecting me back to
- 1:58:33home though which is okay for now we can
- 1:58:36retest it once again later once we
- 1:58:38implement the login functionality
- 1:58:40because right now we just have the
- 1:58:42registration so even if we did want it
- 1:58:44to login again with the same account we
- 1:58:46cannot do that right now so let's head
- 1:58:49over to the sign in component or the
- 1:58:53page and head over to this function
- 1:58:56called on signin press if you head over
- 1:58:59to the clerk Expo setup if you scroll
- 1:59:02down there's going to be the sign in
- 1:59:04page here as well just below the signup
- 1:59:08there we go signin page and it includes
- 1:59:11the on signin press you can get to this
- 1:59:14documentation Page by googleing for Expo
- 1:59:18clerk quick start now I will override
- 1:59:21this function and we'll of course have
- 1:59:23to do some additional fixes such as
- 1:59:25importing this use signin functionality
- 1:59:28alongside the router so we can paste
- 1:59:30that right here at the top and we need
- 1:59:33to import the use sign
- 1:59:36in coming from at clerk SL clerk Expo
- 1:59:43and we also need to import the used
- 1:59:44router so let's do just that use router
- 1:59:49from Expo router in here they're using
- 1:59:52the Ed call back so that means that we
- 1:59:54need to import the use call back from
- 1:59:57react and as email address that's just
- 2:00:00going to be form. email and password
- 2:00:03will be equal to form. password other
- 2:00:06than that I think we just need to fix it
- 2:00:09in one more place form. email and form.
- 2:00:13password right here in the dependency
- 2:00:16array and we have no more errors now we
- 2:00:20can try to sign in
- 2:00:22let's skip the onboarding we've seen it
- 2:00:24quite a few times let's head over to
- 2:00:26login and enter the email and password
- 2:00:29you signed up with I have stored it in
- 2:00:32my Apple passwords and here's a cool
- 2:00:34thing I can now just press password for
- 2:00:36Expo Dev scan my face and it
- 2:00:39automatically entered my email and
- 2:00:41password and I can click sign in and
- 2:00:44there we go I got redirected straight to
- 2:00:47the tabs home this is amazing now we can
- 2:00:52fix some of these routing issues that we
- 2:00:54have with the warnings at the bottom for
- 2:00:57example it is say that no route name
- 2:00:59tabs exists in nested children tabs chat
- 2:01:02tabs home and tabs profile so let's
- 2:01:05first check our layout next to the tabs
- 2:01:10and here we have added a name of tabs
- 2:01:12Heather shown false but it looks like
- 2:01:15we're missing the navigation to point to
- 2:01:17the other screens on our main
- 2:01:19application such as chat home profile
- 2:01:22and rides and we'll create the knv bar
- 2:01:25or should I say the Bottom bar for your
- 2:01:27thumb right within tabs and then the
- 2:01:30layout and then we'll be able to
- 2:01:32navigate to all of these other screens
- 2:01:34so let's do that next to get started
- 2:01:37with creating our tabs let's first
- 2:01:40declare the layout by saying const
- 2:01:43layout is equal to just a regular
- 2:01:46function and it can be an instant return
- 2:01:49where we'll render the tabs coming from
- 2:01:52Expo router and then we can export
- 2:01:55default the layout so what are tabs well
- 2:01:59tabs is like a navigation bar in web
- 2:02:01applications it allows us to quickly
- 2:02:04switch over to other screens this tab
- 2:02:07will have an initial route name which
- 2:02:10will be equal to index in this case and
- 2:02:13we can also provide a couple of
- 2:02:15different screen options to it the
- 2:02:18screen options will be an object to
- 2:02:20which we can provide things like tab bar
- 2:02:23active tint color equal to White there's
- 2:02:27many many other things that we can
- 2:02:29provide to it for now I will just leave
- 2:02:31this here within the tabs we also can
- 2:02:35create different tabs. screens our first
- 2:02:39Tab screen will be a self-closing
- 2:02:41component with a name equal to home and
- 2:02:45options where we can render the title
- 2:02:48equal to home as well
- 2:02:52header shown will be set to false and we
- 2:02:55can even modify the tab bar icon which
- 2:02:58is going to be a callback function that
- 2:03:01returns a tab icon and this tab icon
- 2:03:05will be a custom component which we can
- 2:03:07declare right here const tab
- 2:03:11icon is just an immediate return
- 2:03:14function that for now just returns a
- 2:03:18view within the view we can have another
- 2:03:21smaller View coming from react native
- 2:03:23and within it we can render an image
- 2:03:26with this icon so we can import the
- 2:03:28image and render it right here I just
- 2:03:31noticed that my iPhone simulator is no
- 2:03:33longer running so let me hook it up and
- 2:03:36now we can get into our application and
- 2:03:39now if we fix this typo right here we
- 2:03:43should be able to get into our
- 2:03:44application I'll just reloaded for good
- 2:03:46measure and you can see that we're in it
- 2:03:49says contact adjs master at the top
- 2:03:53that's because we have said Heather
- 2:03:54shown to false otherwise it would be
- 2:03:56here so let's remove it and let's
- 2:03:59continue working on the tabs you can
- 2:04:01also start seeing the tabs appear on the
- 2:04:03bottom and as we switch between them
- 2:04:05we're actually going to different routes
- 2:04:08pretty cool we have those routes as
- 2:04:10they're dynamically taken from these
- 2:04:13files we have created because each file
- 2:04:16corresponds to a screen great so why are
- 2:04:20we even adding these tab screens here
- 2:04:22well to further modify how this Bottom
- 2:04:24bar will look like and primarily to
- 2:04:27change the icon so here we can take the
- 2:04:30focused state of this icon and if it's
- 2:04:33focused we can pass it as focused is
- 2:04:37equal to focus and we can pass a source
- 2:04:39equal to icons coming from index home
- 2:04:44and now you'll be able to see that this
- 2:04:46one the home should have an icon at
- 2:04:48least it will have it once we add it
- 2:04:50within this image we can also duplicate
- 2:04:52this Tab screen three more times 1 2 3
- 2:04:57the first time it'll be for home the
- 2:05:00second time it will be for rides uh
- 2:05:02rather the history of rides so we can
- 2:05:04say rides and the title will be rides
- 2:05:08and the icon will be
- 2:05:11list the next one will be chat chat with
- 2:05:15a Capital C and it's going to be icons.
- 2:05:19chat and then the last one will be
- 2:05:22profile title will be
- 2:05:25profile and the icons will be profile as
- 2:05:30well if we save it it's good they're
- 2:05:32back but now we can further style how
- 2:05:35each one of these looks like or at least
- 2:05:38it's tab icon so let's give this first
- 2:05:41view a class name equal to
- 2:05:45flex Flex Das row justify Das Center I
- 2:05:51items D
- 2:05:53Center rounded D full and if it's
- 2:05:56focused then we can give it a BG general
- 2:06:00of 300 else we can give it nothing but
- 2:06:04of course for this to work we have to
- 2:06:05make it a template string so let's do
- 2:06:08just that there we go that's good and
- 2:06:12this Focus state is coming from props so
- 2:06:14we can say source is for the image and
- 2:06:17focus is for the focus State and we can
- 2:06:19declare the types source is of a Type
- 2:06:22image source prop type and focused will
- 2:06:27simply be a Boolean the interview can be
- 2:06:31styled in a similar manner it can have a
- 2:06:34class name which will be a dynamic
- 2:06:35template string of rounded D full W of
- 2:06:4012 h of 12 items D Center justify Das
- 2:06:45Center and if it is focused then we can
- 2:06:49give it a BG of General
- 2:06:53400 and otherwise it's going to be just
- 2:06:56an empty string now you can see that we
- 2:06:58have this green selector icon and for
- 2:07:01the image itself let's give it a source
- 2:07:03equal to
- 2:07:04Source a tint color equal to White a
- 2:07:10resize mode equal to
- 2:07:13contain and finally a class name equal
- 2:07:17to W of 7 and H of 7 as well and and now
- 2:07:21we can see a nice looking home icon but
- 2:07:25it still doesn't look that good and
- 2:07:26that's because we haven't modified the
- 2:07:29actual tabs options so we have many many
- 2:07:32more options to choose how our tab will
- 2:07:36look like tab bar active tint color is
- 2:07:39just one of the options we can also say
- 2:07:41tab bar inactive tint color and we can
- 2:07:45also set that to White next we have tab
- 2:07:49bar show label we're going to set that
- 2:07:51to false that's because we have a nice
- 2:07:53looking icon next we have a tab bar
- 2:07:57style which will be equal to an object
- 2:08:01that's going to have a background color
- 2:08:03equal to Hash 333 333 and if we save
- 2:08:08this you can now see this nice looking
- 2:08:10background and finally this is starting
- 2:08:12to look more like a real mobile app we
- 2:08:15can give it a border radius of about
- 2:08:19let's do 50 let's give it a a padding
- 2:08:22bottom of zero an overflow of hidden a
- 2:08:27margin horizontal equal to about 20 a
- 2:08:31margin bottom equal to 20 as well height
- 2:08:35of 78 display equal to flex justify
- 2:08:40content equal to space between align
- 2:08:44items equal to Center let's fix this
- 2:08:48space between let's give it a flex
- 2:08:51direction of
- 2:08:53row and finally a position of absolute
- 2:08:57so this way it will always appear on top
- 2:08:59of other content and take a look at this
- 2:09:02we have a beautiful bottom navigation
- 2:09:05bar with nice looking icons and activity
- 2:09:08status that allows us to switch between
- 2:09:11all of our four apps screens and now we
- 2:09:14can go back to our homepage so that's
- 2:09:16going to be home and we can put this
- 2:09:18within a safe area
- 2:09:22view which is coming from react native
- 2:09:24safe area context now we can actually
- 2:09:27see Hello contact adjs Mastery Pro and
- 2:09:30now if we reload our application by
- 2:09:33shaking it a bit and pressing reload you
- 2:09:36can notice that we are automatically
- 2:09:37brought to our home screen which means
- 2:09:40that we no longer have to go through
- 2:09:42that entire welcome onboarding and off
- 2:09:45process that's great we have a clean
- 2:09:48slate to continue working on our
- 2:09:50homepage so let's clean it up a bit and
- 2:09:53sure we could start adding more UI but
- 2:09:56what's UI good for if we don't have it
- 2:09:59stored as real data that we're showing
- 2:10:01in our app we want to make our apps
- 2:10:03truly functional and use databases to
- 2:10:06store users data and then present it to
- 2:10:08them in a nice looking UI for that
- 2:10:11reason now is the perfect time to
- 2:10:13implement a database and in this video
- 2:10:15we won't be using any backend as a
- 2:10:17service tools we'll be using a native
- 2:10:21postgress database and will even write
- 2:10:24real SQL queries we'll do that with neon
- 2:10:27the database platform which I think is
- 2:10:29the best one so far and even versell
- 2:10:32builds their postr databases on top of
- 2:10:35them so if you haven't already created
- 2:10:36an account at the start of the video
- 2:10:38click the link in the description to
- 2:10:40follow along and see exactly what I'm
- 2:10:42seeing and create an account right now
- 2:10:45once you do that you'll be redirected to
- 2:10:47your neon dashboard let me show it to
- 2:10:50you how simple it is to set it up in
- 2:10:53this case we'll be using the neon driver
- 2:10:55so let's copy this block of code and add
- 2:10:58it to our code just to keep our code
- 2:11:00clean I'll put it in a new file and this
- 2:11:02time it has to be added to a special
- 2:11:05file in Expo we have the possibility to
- 2:11:08create APA routes does it sound familiar
- 2:11:11it's because it's coming from nextjs so
- 2:11:14we can create in parentheses an API
- 2:11:17folder and then within it we can create
- 2:11:20a new route for for our users's API so
- 2:11:23let's say new file user Plus api. Ts
- 2:11:29it's not dashes it's not square brackets
- 2:11:32Expo uses pluses in between so user plus
- 2:11:36API and here we can paste what we just
- 2:11:39copied you'll quickly notice that we
- 2:11:40don't have this package installed so
- 2:11:42just copy it open up the second terminal
- 2:11:45and run mpm install and install the neon
- 2:11:48database serverless once you do that we
- 2:11:51can store this database URL within our
- 2:11:53environment variables so let's copy it
- 2:11:57head over to
- 2:11:59ourv and add it as a database undor URL
- 2:12:04is equal to to the key that you just
- 2:12:06copied you don't have to keep the string
- 2:12:08signs so make sure to remove them now we
- 2:12:11can go back in here and just use the
- 2:12:14process. EnV right here so neon process.
- 2:12:19EnV do
- 2:12:22database uncore
- 2:12:24URL and we might need to wrap it in a
- 2:12:27template string because this needs to be
- 2:12:30a string great and this exposes the SQL
- 2:12:34neon querying function allowing us to
- 2:12:36query anything we want from our database
- 2:12:39we won't be querying it just here rather
- 2:12:41we'll be using expose API routes
- 2:12:44functionality that we can call from I
- 2:12:47wanted to say front end but it's really
- 2:12:49from mobile screens so let me show you
- 2:12:51how that works the only thing you have
- 2:12:53to do is export a new async function
- 2:12:57declare whether it's post or get or
- 2:12:59something else you get a request as the
- 2:13:02first and only parameter and you open it
- 2:13:05up in here you have a try and catch
- 2:13:07block and you can do all the server
- 2:13:10logic right here but let me explain this
- 2:13:12by referring to the documentation as
- 2:13:14well what are API routes they are
- 2:13:17functions that are executed when a route
- 2:13:20is matched
- 2:13:22they can be used to handle sensitive
- 2:13:23data such as API keys or Implement
- 2:13:26custom server logic they're created by
- 2:13:29creating files in the app directory with
- 2:13:31the Plus api. Ts extension for example
- 2:13:34the following route Handler is executed
- 2:13:37when for/ Hello is matched to create an
- 2:13:40API route you just need to export a new
- 2:13:43function either say get or post and then
- 2:13:46return a response. Json that's it
- 2:13:49similar to nextjs and when it comes to
- 2:13:52how we can use the neon serverless
- 2:13:54driver well it's pretty simple you can
- 2:13:57use raw SQL queries or use tools like
- 2:14:00drizzle or something else to fetch data
- 2:14:03in this application we'll be using
- 2:14:05native SQL queries but if you want me to
- 2:14:08use some kind of an orm like Prisma or
- 2:14:10drizzle just let me know and this is it
- 2:14:13take a look you just declare a new SQL
- 2:14:16instance by declaring neon from neon
- 2:14:19database serverless and you Prov provide
- 2:14:21your database URL and you can
- 2:14:23immediately start querying it pretty
- 2:14:26cool right if you're not familiar with
- 2:14:28SQL syntax I'll give you a phenomenal
- 2:14:31resource you can refer to very soon but
- 2:14:34with that in mind let's create our first
- 2:14:35post request that would create a user we
- 2:14:37can move this SQL neon thing right
- 2:14:40within our post request because we have
- 2:14:42to declare it every time we make a new
- 2:14:44request then we can destructure some
- 2:14:46things that we're passing into the
- 2:14:48request such as the name email and clerk
- 2:14:51ID and that's going to be equal to await
- 2:14:55request. Json we're not passing those
- 2:14:58yet but we'll pass it soon once we try
- 2:15:01to make a call to this API route next
- 2:15:03we're going to check if we don't have
- 2:15:05access to the name or email or clerk ID
- 2:15:09we're just going to return a
- 2:15:12response.
- 2:15:14Json where the first parameter is an
- 2:15:16error where we can say missing required
- 2:15:20fields and the second parameter is the
- 2:15:23inid where we can send the status of 400
- 2:15:27and it looks like I'm missing an equal
- 2:15:29sign right here there we go now it
- 2:15:31nicely structures it for me but if we do
- 2:15:34have all of these fields then we can
- 2:15:36form a new response that we're getting
- 2:15:38from the database by saying const
- 2:15:41response is equal to await SQL and now
- 2:15:46here we dive into the magic of SQL
- 2:15:49syntax the most most powerful way to
- 2:15:52talk to a postgress or mySQL database
- 2:15:55you just open up template strings you
- 2:15:58expand it into multiple lines and you
- 2:16:00can tell your database to do whatever
- 2:16:03you want it to do the syntax and a bit
- 2:16:06on the longer side as opposed to using
- 2:16:08an orm but you have the full flexibility
- 2:16:12so if you wanted to create a user no
- 2:16:14longer is it just users. create or
- 2:16:17something like that with SQL you can say
- 2:16:20insert
- 2:16:21into
- 2:16:23users and then you can choose what you
- 2:16:25want to insert into it in this case
- 2:16:28it'll be name email and clerk ID and
- 2:16:34then you can Define which values are you
- 2:16:36passing into these fields that you are
- 2:16:40inserting so the values will be a
- 2:16:43template string of name a template
- 2:16:46string of email and a template string of
- 2:16:49clerk ID that's going to look something
- 2:16:52like this and even though this SQL query
- 2:16:55is quite simple soon enough we'll dive
- 2:16:58into more complex SQL queries so I want
- 2:17:01to share with you a course that I
- 2:17:03created which will most likely be a paid
- 2:17:05course later on but for now I will give
- 2:17:07it to you for free so you can practice
- 2:17:09your SQL knowledge before continuing
- 2:17:12with the rest of this project if you
- 2:17:14need it the course is called database
- 2:17:17Mastery and it starts with pure SQL it
- 2:17:21is currently available on our platform
- 2:17:24and as I said soon enough it will become
- 2:17:26paid but for now I can give you free
- 2:17:30access there we dive into database
- 2:17:32introductions introduction to SQL how to
- 2:17:36create tables and insert data and Main
- 2:17:39SQL parameters you can access it by
- 2:17:42clicking the databases link down in the
- 2:17:44description we'll revisit the course
- 2:17:46later on once we start writing more
- 2:17:48complex SQL queries for now we can can
- 2:17:51proceed with the rest of this API call
- 2:17:53we can return a new response and we can
- 2:17:57say json.
- 2:17:59stringify to which we can pass an object
- 2:18:01of data which can be equal to the
- 2:18:04response and as the second parameter to
- 2:18:06the response we can pass a status of
- 2:18:092011 and I just noticed that all of this
- 2:18:12should have been within a try so I have
- 2:18:14to put this Tri block all the way above
- 2:18:18there we go and then we finally have a
- 2:18:21catch so if we have an error we want a
- 2:18:23console. log. error and we can also
- 2:18:27return a response. Json with the error
- 2:18:31and a status code of
- 2:18:35500 great and this is our Expo API route
- 2:18:41inside of which we're calling serverless
- 2:18:43neon database so how can we actually
- 2:18:46trigger this API route well I've told
- 2:18:49you a bit about that when reading the
- 2:18:51documentation but let me show it to you
- 2:18:54one thing I'll do first is go to the lib
- 2:18:57and create a new file called fetch. TS
- 2:19:02and inside of here I prepared for you a
- 2:19:05helper function that will make it easier
- 2:19:07for us to continually make fetch calls
- 2:19:10without writing so much code so if you
- 2:19:13go to the read me of this video go to
- 2:19:15Snippets you'll be able to find a lib
- 2:19:17fetch. TS file so copy it and P pasted
- 2:19:21right here you'll notice it has two
- 2:19:23functions one is a hook use fetch which
- 2:19:27will allow us to Simply fetch the data
- 2:19:29and it already has built-in loading and
- 2:19:32error handling right here so when we
- 2:19:34fetch the data we can make sure that
- 2:19:36it's either there it's either loading or
- 2:19:39it aired out and here's the part that
- 2:19:41actually helps us make the request it is
- 2:19:45just a regular function that accepts the
- 2:19:47URL and the options and it just calls
- 2:19:50the regular Fetch with that URL and with
- 2:19:53those options if the response is not
- 2:19:55okay we throw an error else we forward
- 2:19:58the response from that API call so
- 2:20:00instead of writing this entire code
- 2:20:03every time now we can just call the
- 2:20:05fetch API functionality so let's call it
- 2:20:08within signup we can navigate over to
- 2:20:11sign up and remember where we have a
- 2:20:13to-do right here create a database user
- 2:20:17this is exactly what we want to do right
- 2:20:19now so we can say AIT
- 2:20:21and we can call this fetch API to which
- 2:20:24we can pass first of all the URL SL API
- 2:20:29SL
- 2:20:30user why is it that well because it is
- 2:20:34API user plus API so it means it's an
- 2:20:37API route and as the second parameter we
- 2:20:40can provide all the options such as a
- 2:20:43method of post and then a body which
- 2:20:46will be Json stringify to which we can
- 2:20:49pass an object of name is equal to
- 2:20:53formname email is equal to form. mail
- 2:20:57and clerk ID is equal to complete signup
- 2:21:01doc created
- 2:21:04user ID like this and now you know where
- 2:21:08these are coming from name email and
- 2:21:09clerk ID correspond to our API
- 2:21:15route and they correspond to these
- 2:21:18request Json data variables name name
- 2:21:20email and clerk we make this call from
- 2:21:24when we sign up the user we call our
- 2:21:26Expo API routes we insert that data into
- 2:21:30the neon DB database at the same time we
- 2:21:33create and connect the clerk user and
- 2:21:36set it to the session so if we have done
- 2:21:39everything correctly we should be able
- 2:21:41to go to the neon DV database and go to
- 2:21:45the SQL editor inside of here we can run
- 2:21:48some SQL commands and with this GitHub
- 2:21:51repost Snippets I prepared for you one
- 2:21:53command that we need to run it is under
- 2:21:56create users table SQL so you can copy
- 2:22:00it go back to the neon DB console paste
- 2:22:03it right here and we can read it
- 2:22:05together it says create table users it's
- 2:22:08going to have an ID which is going to be
- 2:22:10a Serial primary key with a name email
- 2:22:14and clerk ID and we can run this it
- 2:22:17looks like we got an error and if I run
- 2:22:19it again it's it says statement executed
- 2:22:22successfully it looks like there was an
- 2:22:24issue with the c character in the clerk
- 2:22:26ID so just delete it and type it again
- 2:22:29and try to rerun it I think it should
- 2:22:31work maybe GitHub MDX added some special
- 2:22:34characters here either way the table has
- 2:22:37been created and we can head over to
- 2:22:39Branch tables which is a new feature on
- 2:22:41neon
- 2:22:42DB this is pretty cool because we can
- 2:22:44immediately see the users table appear
- 2:22:47which means that we are ready to test
- 2:22:49everything out and alongside a new user
- 2:22:51appearing on clerk now a new user should
- 2:22:54appear on neon DB as well so going back
- 2:22:57to Clerk's dashboard for one last time I
- 2:23:00will delete this user because now as
- 2:23:03soon as we create a new one hopefully it
- 2:23:05will appear on both sides so let's
- 2:23:08reload our application clerk session
- 2:23:11died which is great because that means
- 2:23:13that we have deleted our user and now
- 2:23:15before we go ahead and create a new
- 2:23:17account there's just one more thing we
- 2:23:18have to do and that is within the app.
- 2:23:21Json if we want to use expose server
- 2:23:24functionalities we have to go under web
- 2:23:27output and change this into server
- 2:23:30that's going to enable us to do APA
- 2:23:32routes and alongside that we also have
- 2:23:35to add a settings object into plugins
- 2:23:39right here for the Expo router and we
- 2:23:41can do that by adding the origin and
- 2:23:44here we can have any kind of a mock URL
- 2:23:47for our server at least it can be a mock
- 2:23:49URL for development purposes and in this
- 2:23:52case we can do something like a string
- 2:23:54of https col sl/ uber.com and since we
- 2:24:00have expanded this Expo router with
- 2:24:02additional options we have to wrap it in
- 2:24:04an array so now we'll have an array
- 2:24:07where the name of the plugin will be
- 2:24:09Expo router and then we're showing the
- 2:24:11options as the second parameter so
- 2:24:13that's going to look something like this
- 2:24:16I think we can even put it all in one
- 2:24:18line so it makes more sense
- 2:24:21there we go perfect and now that we have
- 2:24:25added this URL we also have to add it to
- 2:24:28our environment variables that's going
- 2:24:30to look something like this go to
- 2:24:33EnV call it Expo corpore server URL and
- 2:24:39make it equal to to this URL that we
- 2:24:42have right here I think we need to end
- 2:24:45it with a forward slash so we can do
- 2:24:47that here and here now we can close
- 2:24:51these files open up the terminal stop it
- 2:24:54from running and run MPX Expo start- C
- 2:24:59to rerun our application with cach
- 2:25:02cleared and you'll notice that now it'll
- 2:25:05take a bit of a longer time to bundle
- 2:25:07which is a good thing because it means
- 2:25:08that our app now has more things within
- 2:25:10it so let's wait until it bundles there
- 2:25:14we go soon enough we'll remove this
- 2:25:16clerk warning from the bottom and now we
- 2:25:18can try to register one more more time
- 2:25:21make sure to delete your existing clerk
- 2:25:23account I'll enter my name and I'll also
- 2:25:27enter my email and password and I'll
- 2:25:30click sign up here we get our
- 2:25:33verification code
- 2:25:3686437 and we can verify our email there
- 2:25:40we go verified browse home we got
- 2:25:43redirected to home but that's nothing
- 2:25:45new we also get a new clerk user but
- 2:25:48that's also nothing new the most
- 2:25:50important thing is that if you go to
- 2:25:52your neon console and go to table check
- 2:25:55out the users table and here our new
- 2:25:58user will be created so soon enough
- 2:26:01we'll be able to create additional
- 2:26:03tables for writers and drivers and we
- 2:26:06can make a connection between all of
- 2:26:08that to store it in our database and
- 2:26:10displayed within our app great work so
- 2:26:13far moving forward we can finally start
- 2:26:16creating some of the UI for our homepage
- 2:26:18so let's navigate to our home and let's
- 2:26:21Dive Right In to get started with
- 2:26:24creating our homepage we can wrap
- 2:26:26everything in a safe area View and give
- 2:26:28it a class name equal to BG General 500
- 2:26:33that's going to give it a nice looking
- 2:26:34grayish background now for the first
- 2:26:36time in this course we'll use something
- 2:26:39known as a flat list coming from react
- 2:26:42native a flat list in react native is a
- 2:26:46performant interface for rendering basic
- 2:26:49flat lists supporting things like
- 2:26:51horizontal mode header support footer
- 2:26:54separators pull to refresh scroll
- 2:26:56loadings it's basically a UL an
- 2:26:59unordered list but with some additional
- 2:27:01functionalities for mobile devices where
- 2:27:04you can pull to refresh you can scroll
- 2:27:06horizontally and they all nicely appear
- 2:27:09it is also completely customizable so
- 2:27:11you can choose exactly how each one of
- 2:27:13these elements looks like but the gist
- 2:27:15is you get some data and then you decide
- 2:27:18how each one of these list items looks
- 2:27:20like and finally you render it within a
- 2:27:23flat list I'll show all of that to you
- 2:27:25right now so for the flat list to work
- 2:27:28we of course have to have some data so
- 2:27:30we can have a data object and for now I
- 2:27:32can make that an array of different
- 2:27:35rides so how will each one of our rides
- 2:27:38look like well it's going to have an
- 2:27:41origin address a destination address
- 2:27:44different map information a screenshot
- 2:27:46of the map driver first name last name
- 2:27:48and more so we could go ahead and create
- 2:27:51some kind of a mock list of rides right
- 2:27:53here and that's exactly what I've done
- 2:27:56under these code Snippets just to make
- 2:27:58your life a bit easier so if you scroll
- 2:28:00all the way to the bottom you can see
- 2:28:02that we have mock rides and this is
- 2:28:05simply an array with a couple of objects
- 2:28:08that allow us to mock four different
- 2:28:10rides just so we can create their UI
- 2:28:12first and then implement the
- 2:28:13functionality later so let's go ahead
- 2:28:16and copy this code snippet and we can
- 2:28:19put it right here above our page const
- 2:28:22recent rides is equal to and then we can
- 2:28:26paste this entire array right here what
- 2:28:29we can do is just collapse it that way
- 2:28:31we don't have to keep looking at this
- 2:28:32huge array but we can now use it within
- 2:28:35the data so let's just say data is equal
- 2:28:38to recent rides I think I misspelled it
- 2:28:42there we go recent rides and we can
- 2:28:45slice only the first five characters so
- 2:28:48from zero to five
- 2:28:50question mark. slice just to make sure
- 2:28:52that we actually do have them now that
- 2:28:55we have the data we also have to have
- 2:28:57something else to figure out how we will
- 2:28:59render each ride or should I say how we
- 2:29:02should render each item within the list
- 2:29:05and for that we can use a prop called
- 2:29:07render item that allows us to specify
- 2:29:11how each one of these items will be
- 2:29:14rendered so first make sure to create a
- 2:29:16callback function that looks like this
- 2:29:19you can D structure the item data like
- 2:29:21this and then for each one we can return
- 2:29:24a ride card which is a self closing
- 2:29:28component to which we can pass the
- 2:29:30entire ride which is equal to the item
- 2:29:33of course this ride card is another
- 2:29:35custom component that we have to create
- 2:29:38so let's go to our components folder and
- 2:29:42create a new component called ride card.
- 2:29:47TSX here we can of course create a new
- 2:29:50con ride card and we can export default
- 2:29:54that ride
- 2:29:55card and you already know that it's
- 2:29:57going to accept only one prop so we can
- 2:29:59destructure the prop of ride which is
- 2:30:02going to be of a type ride is of a type
- 2:30:06ride coming from the types and here for
- 2:30:09now we can just return a view and within
- 2:30:11the view for now we can render a text
- 2:30:14and that text can render the ride.
- 2:30:17driver. first uncore name just so we can
- 2:30:21see who is the driver and don't forget
- 2:30:23to import The View as well as the text
- 2:30:27from react native there we go now we can
- 2:30:30go back to home and we can import the
- 2:30:33right card coming from components right
- 2:30:36card and right at the top I'm not sure
- 2:30:39if you can see it as it's very very
- 2:30:40small we have four different names of
- 2:30:43writers we can make that a bit larger by
- 2:30:45giving it a class name equal to text- 3
- 2:30:49XL
- 2:30:51and there we go we can see David James
- 2:30:53James and Michael that is great so now
- 2:30:56our flat list has the data that it wants
- 2:30:59to render and it also has a render item
- 2:31:02function that tells it how each piece of
- 2:31:05data should look like so now we can go
- 2:31:07into the right card and start developing
- 2:31:10it first things first we'll have to
- 2:31:12mention ride. driver Ride die
- 2:31:15geolocation Ride die destination many
- 2:31:18many times as we have too many any
- 2:31:20properties on this ride so what we could
- 2:31:22do is just destructure those properties
- 2:31:25at the top so we don't have to repeat
- 2:31:26ourselves you do that by saying ride and
- 2:31:29then you destructure it within a new
- 2:31:31object we can destructure something like
- 2:31:33a destination longitude we can
- 2:31:36destructure the destination latitude as
- 2:31:39well let's also destructure the origin
- 2:31:42address we can destructure the
- 2:31:44destination
- 2:31:46address I think we'll need a created app
- 2:31:50so when was the ride created at as well
- 2:31:52as the ride time how much time does it
- 2:31:55take we can then destructure the driver
- 2:31:58and we can destructure the payment
- 2:32:00uncore status I think this is going to
- 2:32:02be enough for now so instead of saying
- 2:32:04ride. driver now we can just say driver.
- 2:32:07first name great so let's start turning
- 2:32:10this ugly list of names into something
- 2:32:13that looks like this each one of the
- 2:32:14cards will have the pickup location
- 2:32:17destination location a photo of that
- 2:32:19entire path and many more pieces of
- 2:32:22information quite exciting and a bit
- 2:32:24easier than what we have done so far in
- 2:32:26our application this is mainly just the
- 2:32:28UI so let's give this view some class
- 2:32:30names I'll give it a class name of flex
- 2:32:33Flex D row items Das Center justify Das
- 2:32:38Center BG of white to differentiate it
- 2:32:41from that gray background rounded dlg to
- 2:32:44give it that organic look Shadow
- 2:32:48DSM Shadow Das neutral
- 2:32:52D300 margin bottom of three so now this
- 2:32:56will create this card like feel you can
- 2:32:59see it on the right side or on your
- 2:33:00phone and you can see how nice this list
- 2:33:02behaves on your phone next we can move
- 2:33:05this text a bit below and we can create
- 2:33:07a second view right here this view will
- 2:33:10have a class name equal to flex Flex D
- 2:33:14row items Das Center justify Dash
- 2:33:18between and a padding of three within it
- 2:33:22we'll have one more view which we'll use
- 2:33:24to enclose the image so we can give it a
- 2:33:27class name of flex Flex D row items Das
- 2:33:32Center and justify Dash
- 2:33:35between within it we can render a react
- 2:33:38native image so import it and give it a
- 2:33:43source this time we'll refer to the
- 2:33:45source by the URI which is going to be a
- 2:33:49template string of
- 2:33:54https maps. gapy and this go apify is
- 2:33:59going to be such a cool API which will
- 2:34:02use to transform the coordinates into an
- 2:34:05image where it shows a map and the start
- 2:34:08and two locations with the entire path
- 2:34:10outlined within it so we'll have to head
- 2:34:12over to gy.com as you can see it is
- 2:34:15completely free for up to 3,000 credits
- 2:34:18per day which is more than enough enough
- 2:34:20and we can click get started the only
- 2:34:22thing we have to do is basically create
- 2:34:24an account which is free and no credit
- 2:34:26card is required so simply continue with
- 2:34:29Google create a project I'll name it JSM
- 2:34:34ride choose the API I believe we're
- 2:34:37using the static map API and it's going
- 2:34:40to give you an API key which we can
- 2:34:42store into our envs what you also get is
- 2:34:45a complete API URL example so let's copy
- 2:34:48that and let let's paste it right here
- 2:34:50instead of this URI you can see it is
- 2:34:53very very long right now but we can cut
- 2:34:56it right here after lawn and lat as
- 2:34:59we'll be providing our own longitude and
- 2:35:02latitude and we don't need any of these
- 2:35:04additional properties so we can remove
- 2:35:07that and we also need to grab our API
- 2:35:09key so copy it head over to our
- 2:35:13envs and add a new one Expo public go
- 2:35:18apy API I key is equal to this number
- 2:35:22right here now if we go back we can
- 2:35:24structure this better by saying maps.
- 2:35:27gy.com V1 static map style is osm bright
- 2:35:32so we don't need this smooth width is
- 2:35:35600 height is 400 Center lawn lad and
- 2:35:40now we can add a column and then we can
- 2:35:43add a dynamic property of destination
- 2:35:47longitude comma and then we can do
- 2:35:50another property of destination latitude
- 2:35:53we can add the end sign outside and say
- 2:35:58Zoom is equal to 14 and finally we have
- 2:36:01to provide the API key which is equal to
- 2:36:05process. EnV
- 2:36:07dot Expo
- 2:36:09undoru uncore
- 2:36:13gapore API uncore key make sure that
- 2:36:16everything is spelled properly right
- 2:36:18here and that this Expo public key is
- 2:36:21the same one that you have right here in
- 2:36:23your envs we can also provide this image
- 2:36:26with a class name of a w of 80 pixels h
- 2:36:33of 90
- 2:36:36pixels rounded dlg still not there so
- 2:36:40maybe I can reload my
- 2:36:43application sometimes that helps once we
- 2:36:45update our envs and there we go the maps
- 2:36:48are appearing you can see we have David
- 2:36:51James and Michael and even though
- 2:36:53they're very very small right now it's
- 2:36:55going to be so interesting to see once
- 2:36:57we put it in a better looking UI of
- 2:37:00course I'm talking about something like
- 2:37:02this so now let's continue with the rest
- 2:37:04of the UI we can go below this image and
- 2:37:07still within the same view we can create
- 2:37:10another
- 2:37:11view with a class name equal to flex
- 2:37:17flex-all margin X of five
- 2:37:20Gap y of five and flex of one within it
- 2:37:25we'll have another view to contain our
- 2:37:27icon that'll have a class name equal to
- 2:37:32flex Flex D row items Das Center and the
- 2:37:36Gap X off
- 2:37:39two and within it we can render an image
- 2:37:43with a source equal to icons which we
- 2:37:46need to import do two so which
- 2:37:50destination are we going to with a class
- 2:37:52name of w of 5 which is about 20 pixels
- 2:37:56and an H of five there we go now we can
- 2:37:59see this two icon and below it we can
- 2:38:02render a text that'll spell out the
- 2:38:05origin address so now we can give it a
- 2:38:08class name equal to text- MD and font
- 2:38:13Das Jakarta medium there we go and now
- 2:38:17we can duplicate this view one more time
- 2:38:20below for the from
- 2:38:23destination or no should they say to
- 2:38:25destination this was the origin address
- 2:38:27so in the second one we can say icons.
- 2:38:30point and I can change it to
- 2:38:34destination address and to both of these
- 2:38:36texts we need to add a special property
- 2:38:39of number of lines is equal to one
- 2:38:44because we don't want it to go over one
- 2:38:46line there we go now we can see some
- 2:38:48different locations at this point it's
- 2:38:50safe to remove this driver first name as
- 2:38:53it's messing with our view so if we do
- 2:38:55that it's looking great now we can go
- 2:38:58below this text and Below one two three
- 2:39:02more views so only two are left at the
- 2:39:05bottom there we can create a view that
- 2:39:07will wrap the bottom part of our
- 2:39:09card this view will have a class name
- 2:39:13equal to flex
- 2:39:15flex-all w- full margin top of five
- 2:39:19BG general of 500 rounded
- 2:39:24dlg padding of three items Das start and
- 2:39:28justify Dash center for the time being
- 2:39:32this messed up our UI but don't you
- 2:39:34worry about that we can add another view
- 2:39:36right here with a class name equal to
- 2:39:40flex Flex D row items Das Center w- full
- 2:39:46justify Dash
- 2:39:47between notice times we're playing with
- 2:39:50flex properties and margin bottom of
- 2:39:53five within it we can render a piece of
- 2:39:56text that'll just say date and
- 2:40:00time and we can give it a class name of
- 2:40:04text- MD font D Jakarta medium and text-
- 2:40:11gray- 500 right below we can duplicate
- 2:40:15this same
- 2:40:17text and instead of in of saying date
- 2:40:20and time we can render real date and
- 2:40:22time by saying format date which we can
- 2:40:25import and give it a created add
- 2:40:29property then we can do a comma and once
- 2:40:32again call the format date function and
- 2:40:36this time pass it the ride time and this
- 2:40:39format date is one of the utility
- 2:40:41functions that we can create so let's
- 2:40:44quickly head over to our lib and let's
- 2:40:47create a new file called
- 2:40:50U.S this stands for utility functions
- 2:40:54one of these functions can be export
- 2:40:56const format date that takes in a date
- 2:41:01string which is a string and returns a
- 2:41:05string so that's going to look something
- 2:41:07like this this is the perfect type of
- 2:41:10function that you would use chat GPT for
- 2:41:13it is pretty simple not that complex and
- 2:41:16it just gets the job done so if you go
- 2:41:19to GitHub Snippets you'll see that I
- 2:41:21provided you with this lib utils file
- 2:41:24which you can copy and override this
- 2:41:27utils you'll notice that here we have
- 2:41:29this format date that basically takes a
- 2:41:32date turns it into a new date gets the
- 2:41:35month names and then returns it in a
- 2:41:38nice human readable format we also have
- 2:41:41a couple of other functions right here
- 2:41:43all created by Chad GPT now we need to
- 2:41:46import this format date function from
- 2:41:49from
- 2:41:50utils so let's do that at the top format
- 2:41:54date at SL SL
- 2:41:57utils and we cannot see that yet right
- 2:42:00now because the layout is broken I think
- 2:42:03everything is going in a row instead of
- 2:42:04a column so let me scroll up and let's
- 2:42:08look into some of these views right here
- 2:42:11oh yeah this second view should have
- 2:42:13been a
- 2:42:16flex-all as in column item start justify
- 2:42:20Center
- 2:42:21here and a padding of three if you do
- 2:42:25this check this out now everything folds
- 2:42:28nicely and this date and time are also
- 2:42:31appearing right here with the correct
- 2:42:33information oh no it's taking the date
- 2:42:35from the right time this right here
- 2:42:37should have been a format time
- 2:42:40function and we have to import it from
- 2:42:42lib utils there we go 12th of August
- 2:42:462024 8 hours this ride took eight hours
- 2:42:50interesting now let's go one text and
- 2:42:53one view down and create a new view
- 2:42:56inside of which will show the driver
- 2:42:58information so let's create its
- 2:43:00container by giving it a class name of
- 2:43:03flex
- 2:43:05flex-r items Das Center w-o for full
- 2:43:10width justify Das between to stay
- 2:43:13consistent with the layout and margin
- 2:43:15bottom of five to divide it from the
- 2:43:17next section within here here we can
- 2:43:19create a
- 2:43:21text that text will say driver so let's
- 2:43:24save it there we go now you can see the
- 2:43:26driver and if you pay close attention
- 2:43:29and if I zoom it out just a bit you'll
- 2:43:31notice that this view right here is
- 2:43:33exactly the same as this view so what we
- 2:43:35can do is just duplicate this view
- 2:43:39talking about the date and
- 2:43:41time and put it right below next we can
- 2:43:45change the date and time to driver and
- 2:43:48we can change the information about the
- 2:43:49date and time to driver. first name and
- 2:43:55driver. last
- 2:43:57name and take a look that looks great we
- 2:44:01can duplicate it a few more times I'll
- 2:44:03do it once more for now and this time
- 2:44:06we'll talk about the car seats so how
- 2:44:10many seats does this driver's car have
- 2:44:13so we can get to that by rendering the
- 2:44:16driver. carore seats
- 2:44:19there we go that looks great some have
- 2:44:21five some have four and finally we can
- 2:44:24duplicate it once more to talk about the
- 2:44:27payment so right here we can say
- 2:44:31payment status and we can render a
- 2:44:34payment status you can see that it all
- 2:44:37says paid right now but we can change
- 2:44:40the class names if it's paid to be green
- 2:44:42and if it's not paid to be red so let's
- 2:44:45turn this class name into a dynamic
- 2:44:47template string and we can say if
- 2:44:50payment status is triple equal to paid
- 2:44:54then we can add an additional style of
- 2:44:56text- green 500 else we can add a text
- 2:45:00to Red
- 2:45:02500 let's make sure to close this
- 2:45:04properly we start with a question mark
- 2:45:07end it here and close it right here
- 2:45:12there we go this is
- 2:45:14good now we can see that it all says
- 2:45:17green we can also cap capitalize it so
- 2:45:20here we can add capitalize so the paid
- 2:45:23is capitalized with letter P you can see
- 2:45:26how nice this form is like we can move
- 2:45:29it up and down we can scroll it it is
- 2:45:31absolutely amazing and with that we have
- 2:45:34just developed our ride card it is
- 2:45:37looking great so let's go back to home
- 2:45:41and now that we have this ride card I
- 2:45:43can show you the other properties of the
- 2:45:46flat list that allow us to further
- 2:45:48modify the look of that list such as a
- 2:45:51class name where we can provide it a
- 2:45:54padding X of five just to create some
- 2:45:56more space there we go that's nice we
- 2:45:59can also add a keyboard should persist
- 2:46:03Taps and here we can say handled so now
- 2:46:07if you tap on it the tabs should persist
- 2:46:10this is preferred with flat lists we can
- 2:46:13also add a Content container
- 2:46:17style which can be a a padding bottom of
- 2:46:21100 so now we'll have a bit more padding
- 2:46:23at the bottom so we have space for our
- 2:46:26bottom navigation now here's another
- 2:46:28pretty cool thing this flat list
- 2:46:31automatically allows you to Define how
- 2:46:33an empty list component should look like
- 2:46:36you just create a callback function and
- 2:46:39return a new view that defines what's
- 2:46:42going to happen if it is empty so let me
- 2:46:46create a text first and say something
- 2:46:49like empty of course we have to import
- 2:46:52The View and the text at the top coming
- 2:46:54from react
- 2:46:58native and now if instead of these
- 2:47:01recent rides I render an empty array you
- 2:47:05can see empty at the top that means that
- 2:47:07it gives us the possibility to style it
- 2:47:09somehow differently so let's do just
- 2:47:12that we can give this view a class name
- 2:47:16equal to flex flex-all
- 2:47:19items Das Center and justify Dash
- 2:47:22Center next we need to check whether
- 2:47:24we're currently loading or not it is
- 2:47:27highly likely that sometimes we might be
- 2:47:29loading so that's the reason why we
- 2:47:31don't have any elements so for now I'll
- 2:47:34just create a mock loading property and
- 2:47:37set it to false later on this will come
- 2:47:39from real Dynamic data So within this
- 2:47:42view we can check if we're not
- 2:47:46loading then we can render an empty
- 2:47:49react fragment within which we'll have
- 2:47:51an image that's another react native
- 2:47:53component we have to
- 2:47:55import and that image will have a source
- 2:47:58equal to images make sure to import that
- 2:48:02do no result if we save this it's going
- 2:48:05to break because we have to have a
- 2:48:07second part of the tary operator so if
- 2:48:10we are loading for now we can just show
- 2:48:12a
- 2:48:14text that says
- 2:48:17loading there we go now this is a huge
- 2:48:20no results image so let's style it a bit
- 2:48:23by giving it a class name of w40
- 2:48:27h40 let's also give it an Al tag of no
- 2:48:30recent rides
- 2:48:33found and let's give it a resize mode of
- 2:48:37contain there we go we can also give it
- 2:48:41a piece of text right below it's going
- 2:48:44to have a class name of text- smm and
- 2:48:47it'll say no recent rides found there we
- 2:48:52go as simple as that now if we are
- 2:48:57loading we can show something else not
- 2:49:00just a boring empty loader we can render
- 2:49:03an activity indicator and that is coming
- 2:49:06directly from react native it's going to
- 2:49:09be a self-closing component called
- 2:49:12activity
- 2:49:14indicator and we can give it a size is
- 2:49:17equal to small and a color of hash
- 2:49:220000 there we go so now you can see a
- 2:49:24very small activity indicator while it
- 2:49:27is loading great let's collab this list
- 2:49:31empty component and we can now bring
- 2:49:33back the real data because we don't want
- 2:49:35to be looking at an empty list and this
- 2:49:37flat list is so versatile as you can see
- 2:49:40we just defined how it would look empty
- 2:49:42without using a turn operator on the
- 2:49:44entire list they just provided a handy
- 2:49:47prop another thing that the flat list
- 2:49:49component provides is the list header
- 2:49:51component allowing you to Define how a
- 2:49:54header should look like let's make it
- 2:49:56into a react fragment that's going to
- 2:49:58render a view this view will have a
- 2:50:01class name all Flex Flex Das row items
- 2:50:06Das Center justify Dash between and
- 2:50:10margin y of five within it we can render
- 2:50:13a piece of text that says welcome and
- 2:50:17then we can render the user question
- 2:50:18mark. first name and we can even choose
- 2:50:22to add a wave
- 2:50:24Emoji you can go to Google and quickly
- 2:50:27copy it welcome and now we have to get
- 2:50:30the user's first name let's see where
- 2:50:32this user is coming from going to the
- 2:50:35top and collapsing the recent rides we
- 2:50:37can see that the user is coming from the
- 2:50:39hook of use user which is coming from
- 2:50:42clerk Expo let's console. log. user to
- 2:50:45see what data do we get in there there
- 2:50:47we go take a look look at this there's a
- 2:50:50lot of data but in this case the first
- 2:50:52name and the full name are false I
- 2:50:56believe that's because we haven't used
- 2:50:57the Google authentication so far we have
- 2:51:00just used the email o so maybe if we
- 2:51:03don't have the first name we can render
- 2:51:06something else maybe user question mark.
- 2:51:10email addresses zero I believe that
- 2:51:13should be the email address no it's
- 2:51:15email address is zero. email address
- 2:51:18there we go so now it says welcome
- 2:51:21contact adjs mastery. proo it'll look
- 2:51:23better once we authenticate using Google
- 2:51:26let's style this text just a bit by
- 2:51:28giving it a class name equal to text-
- 2:51:312XL and font D jaarda extra bold okay so
- 2:51:37maybe one Excel will be good now below
- 2:51:39that text we can also render a touchable
- 2:51:43opacity what is that that's a button so
- 2:51:47what will this touchable opacity do well
- 2:51:49it'll render an
- 2:51:51image that has a source equal to
- 2:51:55icons.
- 2:51:57out and it'll have a class name of W4
- 2:52:00and
- 2:52:01H4 so that is this little button at the
- 2:52:04top right that allows us to log out so
- 2:52:07let's create a function right here
- 2:52:11const handle sign out which is going to
- 2:52:15be equal to an arrow function and now we
- 2:52:18can add it as an onpress functionality
- 2:52:21on this touchable opacity so on press we
- 2:52:24can handle sign out and we can also give
- 2:52:27it some additional class names such as
- 2:52:30justify Das
- 2:52:32center items Das Center W of 10 h of
- 2:52:3810 rounded Das full and BG of
- 2:52:42wide there we go so now it looks great
- 2:52:46and I don't quite like that we have the
- 2:52:47email address here so what do you say
- 2:52:50that we split it and we split it by the
- 2:52:55add sign because most people have their
- 2:52:57name in the first place and then we take
- 2:53:00the first part of that email right here
- 2:53:02by doing this so now it's going to say
- 2:53:04welcome contact because I signed up with
- 2:53:06contact at JS Mastery Pro but for you
- 2:53:09most likely this will be your name or
- 2:53:11let me know in the comments down below
- 2:53:13if it's something else we can also add
- 2:53:15the capitalize right here so that now it
- 2:53:18says welcome we can add a comma right
- 2:53:22here contact much better or it's going
- 2:53:25to be a first name once we do Google off
- 2:53:28great and now I think we can make it a
- 2:53:30bit bigger with 2XL moving down below
- 2:53:33the touchable opacity and Below one more
- 2:53:36view we can render one of the most
- 2:53:38important parts of our application and
- 2:53:40that's going to be a
- 2:53:43Google text input that's going to be a
- 2:53:46custom input which we'll create so let's
- 2:53:49turn it into a component by going over
- 2:53:51to the components folder and creating a
- 2:53:54new Google text input. TSX you know the
- 2:53:59drill it is const Google text
- 2:54:04input which is equal
- 2:54:06to an immediate returning function where
- 2:54:09we export default Google text
- 2:54:13input it's going to return a view and
- 2:54:16within it we can have a text
- 2:54:19that'll say search make sure to import
- 2:54:22The View and the text from react
- 2:54:25native so going back we can now render
- 2:54:28this as a self-closing
- 2:54:30component of course don't forget to
- 2:54:33import it from Google text input and to
- 2:54:36it we can pass some props such as icon
- 2:54:39is equal to icons.
- 2:54:42search we can pass it some container
- 2:54:45style equal to BG White
- 2:54:49Shadow MD and
- 2:54:51Shadow
- 2:54:54neutral
- 2:54:56300 and we can provide a handle press so
- 2:54:59what happens once we press it we want to
- 2:55:01handle destination press and this is yet
- 2:55:05another function which we can Define
- 2:55:08right here at the top for which soon
- 2:55:10enough we'll add the logic now we can
- 2:55:12head into the Google text input to
- 2:55:14accept all of these great props it's
- 2:55:17going to be an icon
- 2:55:19maybe later on we'll pass an initial
- 2:55:21location as well it's going to be a
- 2:55:24container style which we defined later
- 2:55:27on we might want to change the input
- 2:55:29background color so we can say text
- 2:55:32input background color and finally the
- 2:55:36handle
- 2:55:38press and all of these will be of a type
- 2:55:41Google Input props coming from types so
- 2:55:45now we can style this view a bit by
- 2:55:47giving it a class name of a template
- 2:55:49string of flex Flex D row items Das
- 2:55:54Center justify Das Center relative Z50
- 2:56:00so it appears on top of other elements
- 2:56:02rounded Das Excel and finally we can
- 2:56:06spread all of the other container
- 2:56:08Styles so now we can see the search
- 2:56:10appear right here at the top and for now
- 2:56:13we can give it just something like
- 2:56:14margin bottom of five there we go so now
- 2:56:18we can see a nice looking search or at
- 2:56:20least what is soon going to become a
- 2:56:22beautiful Google input from which you'll
- 2:56:25be able to select all of the different
- 2:56:27places in the world starting from the
- 2:56:29places near you so it's going to be very
- 2:56:31smart before we go ahead and create that
- 2:56:34Google text input let's go a bit below
- 2:56:37and create another react fragment inside
- 2:56:39of which we can render a text that tells
- 2:56:42us our current location so we can say
- 2:56:45text your current location we can give
- 2:56:48it a class name equal to text- excl font
- 2:56:53djakarta bold and margin top of five as
- 2:56:57well as a margin bottom of three below
- 2:56:59it we can render a view that'll have a
- 2:57:03class name equal to
- 2:57:05flex Flex Das row items Das
- 2:57:09Center BG of transparent and H of 300
- 2:57:14pixels and within it we'll render maybe
- 2:57:16the most important component of our
- 2:57:18application and that is the map so let's
- 2:57:21create a new file called map.
- 2:57:24TSX you know the drill create a new map
- 2:57:29which is equal to an arrow function
- 2:57:31where we can export default that map and
- 2:57:34for now we can just return a view so
- 2:57:37let's say return a view coming from
- 2:57:40react native and a text within it
- 2:57:42that'll say map
- 2:57:45beautiful so now we can render this map
- 2:57:48right right here within it coming from
- 2:57:49components map and you can see how it
- 2:57:52says map right here so now we're getting
- 2:57:54much much closer to this view right here
- 2:57:56where it says welcome John we have a
- 2:57:59sign out button a beautiful Google
- 2:58:01autocomplete search your current
- 2:58:03location and then the recent rides at
- 2:58:05the bottom so while we're here let's go
- 2:58:08below this react fragment and create one
- 2:58:11final text which is going to be similar
- 2:58:14to this your current location text so
- 2:58:16let's copy it and it'll say
- 2:58:19recent
- 2:58:21rides there we go so we have recent
- 2:58:23rides your current location and then
- 2:58:26finally a greatl looking search input so
- 2:58:29now we only have one question and that
- 2:58:31is what do you want to do first since
- 2:58:34you cannot talk to me right now and I
- 2:58:36can only imagine what you're saying I'll
- 2:58:38have to make a decision and I really
- 2:58:40don't like this big hole in the center
- 2:58:43of our application right now so let's do
- 2:58:45the map first and then we can focus on
- 2:58:47the Google autocomplete later on so I'll
- 2:58:50close the home and the Google text input
- 2:58:53leaving us with the map but of course
- 2:58:55for that we'll have to add a lot of
- 2:58:57functionalities integrating with
- 2:58:59Google's apis to integrate Google's
- 2:59:02Services you'll have to head over to
- 2:59:04Google Cloud console that is console.
- 2:59:07cloud.google.com
- 2:59:09next you can create a new project so
- 2:59:12just click new project at the top right
- 2:59:14I'll call it JSM
- 2:59:16dride and I'll put it under no
- 2:59:19organizations choose where I want to put
- 2:59:21it it looks like I have to choose an
- 2:59:24organization and then click create I
- 2:59:26think it takes about a minute for your
- 2:59:28project to be created there we go it was
- 2:59:31actually 5 Seconds let's select our
- 2:59:33project and head over to apis and
- 2:59:36services next click enable apis and
- 2:59:40services and search for apis and
- 2:59:42services we can search for places and
- 2:59:46select the places API new new there we
- 2:59:49go this is the one they even refresh the
- 2:59:51icon and click enable it looks like the
- 2:59:55place's API new requires a project with
- 2:59:57a building account so let me try to
- 3:00:00cancel this and go back and search for
- 3:00:03just places API and choose this one it
- 3:00:07seems like we can enable the places API
- 3:00:09the original one not the new one without
- 3:00:12entering the credit card details so just
- 3:00:14go ahead and click enable here it might
- 3:00:17ask you something else later on but then
- 3:00:19just exit and it will be enabled let's
- 3:00:22go back and let's enable the second API
- 3:00:24we'll need which is the directions
- 3:00:27API go to it and click enable great it
- 3:00:32looks like it's enabling it right away
- 3:00:34it did redirect me to this page where we
- 3:00:36need to verify our card to get started
- 3:00:39which is totally okay because they're
- 3:00:40not going to charge us anything but for
- 3:00:42now I'll try to exit out of that and
- 3:00:44just go a page back hopefully we can do
- 3:00:46it without entering any details but if
- 3:00:48we need to we'll have to do that later
- 3:00:50on now let's head over to our
- 3:00:53dashboard and go to enabled apis and
- 3:00:56services then click credentials and then
- 3:01:00press create credentials and choose API
- 3:01:03key there we go we just got our API key
- 3:01:06so let's copy it head over to our EnV
- 3:01:11and type Expo public Google API key and
- 3:01:18paste the key that you just copied I
- 3:01:20think this should be enough and it
- 3:01:22should work if Google doesn't mess with
- 3:01:24us further we'll see if it will work
- 3:01:26soon enough now we can go back to the
- 3:01:28map to start implementing it we'll have
- 3:01:31to install two new packages so let's
- 3:01:34type mpm install
- 3:01:38react-native-maps as well as
- 3:01:42react-native-maps DD directions and
- 3:01:45press
- 3:01:46enter as soon as they in sold we'll be
- 3:01:49able to use a map view sounds convenient
- 3:01:52right map view coming from react native
- 3:01:56Maps next we can start passing it props
- 3:01:59that'll make it work so let's give it a
- 3:02:02provider prop which is equal to provider
- 3:02:06uncore default which is coming from
- 3:02:09react native Maps that's going to be
- 3:02:11Google most likely next we can give it a
- 3:02:14class name equal to w-o for full width
- 3:02:18H full so it takes the full height of
- 3:02:20the container and round it Dash to excel
- 3:02:23to make the borders a bit
- 3:02:26organic and would you look at that the
- 3:02:29map is here currently for me it shows
- 3:02:33the country of Croatia with its very
- 3:02:35interesting shape as this is where I'm
- 3:02:38based at for you it's going to show
- 3:02:40something else and you can see how fluid
- 3:02:43it is I can zoom in zoom out and move it
- 3:02:46around and it just works so seamlessly
- 3:02:50great so with that in mind let's
- 3:02:52continue modifying this map to make it
- 3:02:54soothe the needs of our application I'll
- 3:02:57give it a tint color equal to black as
- 3:03:01well as a map type equal to muted
- 3:03:04standard this will make it just a bit
- 3:03:07muted so it fits the theme of our
- 3:03:09application better and it allows us to
- 3:03:12better show the routes from and to
- 3:03:14different locations in this case we're
- 3:03:16not interested in seeing all the rivers
- 3:03:18and lakes and mountains what we're
- 3:03:21interested in are the roads let's also
- 3:03:23turn off show points of interest by
- 3:03:26saying show points of interest is equal
- 3:03:29to
- 3:03:30false now how can we change the initial
- 3:03:33region that it points to well here we
- 3:03:36can say const region is equal to an
- 3:03:39object where we need to provide
- 3:03:41different things such as the latitude
- 3:03:43longitude and more very soon we'll
- 3:03:46calculate this dynamically
- 3:03:48so we'll be able to pass it as initial
- 3:03:51region is equal to and then we can pass
- 3:03:55the region right here but for now let's
- 3:03:57leave it as it is we can also say shows
- 3:04:01user location and set that to true as
- 3:04:05well and finally we can make the user
- 3:04:07interface style light as our application
- 3:04:10is in light mode and I just noticed
- 3:04:13something I mean look at the bottom left
- 3:04:15corner of this map it says Apple Maps so
- 3:04:20it's not Google the default in this case
- 3:04:23actually is Apple because I'm on an
- 3:04:25iPhone if you're using some kind of a
- 3:04:27different operating system you might get
- 3:04:29different map presented to you coming
- 3:04:32from map view from react native maps how
- 3:04:35convenient but we still needed to get
- 3:04:37that Google API key which we'll test
- 3:04:39later on for the places and directions
- 3:04:43and you might have noticed how it found
- 3:04:45your location but it didn't specifically
- 3:04:49pinpoint to where you are on the map
- 3:04:51that's because if you don't Grant your
- 3:04:54device location permissions then it
- 3:04:56cannot know where you are which might be
- 3:04:59good or not depending on how much
- 3:05:00privacy you want but all of the great
- 3:05:03applications to work properly need to
- 3:05:05have your correct location imagine if
- 3:05:08Uber didn't have your exact location how
- 3:05:10would drivers nowhere to find you so how
- 3:05:13do we implement the functionality of
- 3:05:16getting your exact Lo
- 3:05:18well let me show you we'll install a
- 3:05:21package called zustand so mpm install
- 3:05:25zustand and no zustand doesn't have
- 3:05:28anything to do with knowing your
- 3:05:30location but it has Bare Necessities for
- 3:05:34State Management in react and react
- 3:05:36native so it is a state management
- 3:05:38Library you can think of it like react
- 3:05:40context it allows you to create a store
- 3:05:43of some information and then you can use
- 3:05:46an update that information across your
- 3:05:49entire application so let's do just that
- 3:05:53going back to our code we can create a
- 3:05:55new folder in the root of our directory
- 3:05:58and we can call it store within the
- 3:06:00store we can create an index.ts
- 3:06:04file there we can import the create
- 3:06:08functionality from zand once we have the
- 3:06:11create function it allows us to create a
- 3:06:13store and we can do that by saying const
- 3:06:17use location store is equal to
- 3:06:21create that function takes in one
- 3:06:24parameter which is the state Creator so
- 3:06:26it is a callback function with an
- 3:06:29immediate return of an object so it
- 3:06:31looks like this you open up a callback
- 3:06:34function and then you immediately write
- 3:06:37parentheses and then braces this means
- 3:06:39that you're immediately returning an
- 3:06:41object here as the first parameter of
- 3:06:43the Callback function we get a set
- 3:06:46function that allows us to set the state
- 3:06:49now we want to export this Ed location
- 3:06:52store because once we create it zustand
- 3:06:55allows us to call it from any file also
- 3:06:58we can Define the type of that store in
- 3:07:00this case it'll be a location store
- 3:07:03coming from
- 3:07:04types it'll have things like the user
- 3:07:08address which at the start will be set
- 3:07:10to null we can also give it a user
- 3:07:13longitude set to null by default next
- 3:07:16we're going to have a user
- 3:07:18address which is also going to be set to
- 3:07:20null destination longitude set to null
- 3:07:24destination latitude set to null
- 3:07:27destination address set to null by
- 3:07:30default as well and then we have to have
- 3:07:33a Setter function set user
- 3:07:36location which will take in a latitude
- 3:07:40longitude and the address and we have to
- 3:07:43Define the types of these so that's
- 3:07:45going to be latitude
- 3:07:47is a number longitude is a number and
- 3:07:52address is a string and this entire
- 3:07:55thing returns a function or rather it's
- 3:07:58a function block so let's type it out
- 3:08:01properly looks like I have a typo
- 3:08:03somewhere or maybe not maybe it's good
- 3:08:06but the prettier is not formatting it
- 3:08:08yet because we're missing some things
- 3:08:09still we'll fix it as we go in this
- 3:08:12function block where we're passing the
- 3:08:14latitude longitude and the address we
- 3:08:16can now use this Setter function given
- 3:08:19to us by zest end to now actually set
- 3:08:22those values so remember what I said
- 3:08:24immediate return of an object that is
- 3:08:26parentheses and then curly braces where
- 3:08:30we set the user latitude to be equal to
- 3:08:33Latitude we said the user
- 3:08:36longitude to be equal to longitude and
- 3:08:39we set the user address to be equal to
- 3:08:42address I think I have a typo here
- 3:08:44that's why it's not fixing it so if I
- 3:08:46fix the typo
- 3:08:48there we go this is better but it's
- 3:08:50still complaining about something it's
- 3:08:52saying that it's missing the user
- 3:08:53latitude so let's make sure to fix that
- 3:08:56user latitude yeah indeed it is missing
- 3:08:59I have user address two times and it's
- 3:09:02missing one more thing and that is the
- 3:09:04set destination location so that's going
- 3:09:07to be a second Setter function set
- 3:09:10destination location which will be
- 3:09:12almost exactly the same as set user
- 3:09:15location so let's just duplicate it
- 3:09:18it'll also accept the latitude longitude
- 3:09:20and the
- 3:09:22address and this time instead of saying
- 3:09:24user latitude longitude and address
- 3:09:26we'll say
- 3:09:28destination latitude longitude and
- 3:09:31address there we go now it nicely saves
- 3:09:34it and we have to rename it to set
- 3:09:37destination location now we can see our
- 3:09:40tab script and pror or an esent nobody's
- 3:09:42complaining anymore and that's why I
- 3:09:45love typescript so much B Bas on this
- 3:09:47location store where we said how
- 3:09:49everything should look like it is now
- 3:09:51saving your ass from making stupid
- 3:09:53mistakes and typos as I have typed user
- 3:09:56address two times maybe you didn't good
- 3:09:59for you but now now that we have no red
- 3:10:02squiggly lines hopefully this makes a
- 3:10:04bit more sense we have some values and
- 3:10:08we have some Setters for those values
- 3:10:10where we set the user location and where
- 3:10:13we set the destination location great so
- 3:10:16this is called a dtin store and now we
- 3:10:19have access to this use location store
- 3:10:21hook which we can call where are we
- 3:10:24going to call it for the first time well
- 3:10:26it's going to be within our homepage the
- 3:10:29first time we open up our application
- 3:10:32and log our user in right here we can
- 3:10:35say const and we can get the set user
- 3:10:39location as well as set destination
- 3:10:44location and that's going to be equal to
- 3:10:46you use location store coming from store
- 3:10:51alongside getting these Setters from the
- 3:10:53store we also need one more thing and
- 3:10:55that is a use State for the permissions
- 3:10:59whether we have given permissions for
- 3:11:01our location so we can say has
- 3:11:04permissions and set has permissions at
- 3:11:07the start set to false and now we can
- 3:11:11create a new use effect
- 3:11:14hook that's going to take in a callback
- 3:11:16function
- 3:11:18and also a dependency array also see how
- 3:11:20webstorm adds this inlay hints about
- 3:11:24what each one of these parameters is
- 3:11:26first is the actual effect and then the
- 3:11:28dependency array for now we'll keep the
- 3:11:30dependency array empty and within it
- 3:11:33we'll create a new async function called
- 3:11:36request
- 3:11:37location const
- 3:11:40request location is equal to an async
- 3:11:45function and we can call it immediately
- 3:11:48so just right here request location
- 3:11:51within it we can get the status of a
- 3:11:53request for a location by destructuring
- 3:11:56the status by saying await location
- 3:12:00coming from react native do
- 3:12:04request
- 3:12:06foreground
- 3:12:09permission async and this location is
- 3:12:12coming at the top from react native and
- 3:12:14you can see that right now it's having
- 3:12:16trouble getting this method from the
- 3:12:18location object and that's because the
- 3:12:21location is coming from a new package
- 3:12:23called Expo location so let's install it
- 3:12:27mpm install Expo Das location once it
- 3:12:31installs we can just import it at the
- 3:12:33top by saying
- 3:12:35import asterisk meaning everything as
- 3:12:39location from Expo
- 3:12:43location and it looks like I have a typo
- 3:12:45right here it's per perms plural now
- 3:12:49it's okay and it knows exactly what this
- 3:12:51function is about asks the user to Grant
- 3:12:54permissions for location while the app
- 3:12:56is in the foreground next we can check
- 3:12:58if the status is not equal to Granite
- 3:13:02then we can set has permissions to false
- 3:13:07and exit out of the function but if we
- 3:13:09did get the permissions we can get
- 3:13:11access to a location by saying lead
- 3:13:13location is equal to a weight location
- 3:13:17dot get current positions async next we
- 3:13:23can extract the address from the
- 3:13:24location by saying const address is
- 3:13:27equal to await location. reverse geocode
- 3:13:32async to which we pass the
- 3:13:35latitude equal to
- 3:13:37location. cords question mark. latitude
- 3:13:41and we can add the exclamation mark at
- 3:13:43the end because we know it'll be there
- 3:13:45just for tab script to know and we can
- 3:13:47repeat the same thing for the
- 3:13:50longitude once we have that here's the
- 3:13:53keyp part we can call the set user
- 3:13:56location which is coming from our store
- 3:13:59and now we can update the latitude to be
- 3:14:01equal to
- 3:14:03location. chords.
- 3:14:06Latitude we can do the same thing for
- 3:14:08the
- 3:14:09longitude and we can also store the
- 3:14:12address which is going to be a template
- 3:14:13string of
- 3:14:15address Z
- 3:14:18.name comma address 0. region and you
- 3:14:23can notice that here it's complaining
- 3:14:24about the await all of this has to be
- 3:14:27within the request location function
- 3:14:29which is async so let's put it there and
- 3:14:33close the function right here now this
- 3:14:35will request location access and then
- 3:14:38set it to the store which means that
- 3:14:39we'll be able to use it from anywhere
- 3:14:41else in our application okay so if we
- 3:14:44have done everything correctly a new
- 3:14:45popup asking your location permission
- 3:14:48should have appeared for you you cannot
- 3:14:50see it here on my computer screen but on
- 3:14:52my phone I can see allow Expo go to use
- 3:14:55your
- 3:14:56location and I'll click allow while
- 3:14:58using the app in case you gave access to
- 3:15:01expoo to your location before then it'll
- 3:15:05already have it but you can then switch
- 3:15:07it by going to settings and then say ask
- 3:15:09next time or when I share so this time
- 3:15:12it's always going to ask you for the
- 3:15:13location great so now that we're getting
- 3:15:16this location
- 3:15:17we're actually not only getting it but
- 3:15:19we're also setting it to the store which
- 3:15:22means that we can now go back to the map
- 3:15:24and we have all the necessary
- 3:15:26information to figure out where our user
- 3:15:28is on the map so let's extract that
- 3:15:32information by saying const and these
- 3:15:35structure the user longitude user
- 3:15:38latitude destination
- 3:15:42latitude and
- 3:15:44destination longitude and that's going
- 3:15:47to be equal to use location store and
- 3:15:51now that we have that we can figure out
- 3:15:53our region and what is a region well
- 3:15:56region is a circle around you with a
- 3:16:00specified radius from within which we
- 3:16:02can search for
- 3:16:04drivers and we can get the region by
- 3:16:07calling a special method called
- 3:16:10calculate
- 3:16:12region to which we then need to provide
- 3:16:15all of this information such as the user
- 3:16:17longitude latitude destination longitude
- 3:16:20and latitude and that's it but what is
- 3:16:23this calculate region well it's one of
- 3:16:25the utility functions that you can get
- 3:16:28in the Snippets down below if you search
- 3:16:30for lib map. DS copy this and create a
- 3:16:35new file in the lip called map. TS here
- 3:16:41we'll put all the utility functions for
- 3:16:43the map it seems like a lot but it's
- 3:16:47really not we have three different
- 3:16:49functions here we have the calculate
- 3:16:51driver's time which we can nicely
- 3:16:54collapse right here we also have
- 3:16:57calculate region which is the one which
- 3:16:59we want to work on right now and we also
- 3:17:02have generate markers from data this is
- 3:17:06a function that takes in the drivers and
- 3:17:08marks their locations around our Circle
- 3:17:11but later on once we have real drivers
- 3:17:13you can just get their coordinates and
- 3:17:15then use the same function to generate
- 3:17:17markers with slight modifications don't
- 3:17:20worry I'll explain every one of these
- 3:17:22functions as we use them so first let's
- 3:17:24import the use calculate region within
- 3:17:27our map it's going to come from the map
- 3:17:30utils and now we can see what do we have
- 3:17:32to pass to it if there is no user
- 3:17:35longitude and latitude it'll set some
- 3:17:37fake values right here and if there's no
- 3:17:40destination longitude and latitude it'll
- 3:17:42just take a Delta meaning a difference
- 3:17:45from our current user location and and
- 3:17:47just in my specific case I'll take these
- 3:17:49mock values I'll go to home and when
- 3:17:53we're setting the user location I will
- 3:17:56set them to these mock values just so I
- 3:17:59don't have to allow for relocation every
- 3:18:01time now if I go back to the map you can
- 3:18:05see that we're getting the minimum
- 3:18:06latitude and maximum
- 3:18:08latitude based on the user latitude and
- 3:18:11the destination latitude once we have
- 3:18:13that we add some padding meaning we
- 3:18:16spread the circle around our user and we
- 3:18:20further calculate
- 3:18:21it as I said before Chad GPT is perfect
- 3:18:25for these types of functions but it's
- 3:18:27going to make much more sense once we
- 3:18:29actually put it to action so let me go
- 3:18:32back right here and let's put this
- 3:18:33region to use I'll say initial region is
- 3:18:37equal to region and I'll turn on the
- 3:18:39show user location in my case it is
- 3:18:42using this specific location I provided
- 3:18:45which is right here in San
- 3:18:48Francisco so the next thing we can focus
- 3:18:51on is showing some drivers nearby our
- 3:18:54location and we can do that by going
- 3:18:56back to our store and creating a second
- 3:19:00store which will be called use driver
- 3:19:03store here we can export const use
- 3:19:07driver store you know the drill and then
- 3:19:10we can say create with a type of driver
- 3:19:14store and we get this Setter
- 3:19:16functionality it right here make sure to
- 3:19:19import the driver store from the types
- 3:19:21and within here we can set the drivers
- 3:19:24at the start equal to an empty array as
- 3:19:27marker data coming from types it's going
- 3:19:31to be an array of marker data and later
- 3:19:34on we'll have a selected driver which at
- 3:19:36the start can be set to null we have to
- 3:19:39have a set select the driver which is
- 3:19:42going to be equal to a callback function
- 3:19:45that takes in a drive of a type number
- 3:19:48and then calls the set functionality
- 3:19:51with its own callback function where we
- 3:19:53can set the select a
- 3:19:55driver to be equal to driver ID right
- 3:19:59below that we have the set drivers
- 3:20:01functionality to set all the
- 3:20:04drivers which takes in drivers as an
- 3:20:07array of marker data and again calls the
- 3:20:10set functionality where it sets drivers
- 3:20:13to drivers and finally we can clear
- 3:20:16select the driver which is just going to
- 3:20:18call a set functionality and set a
- 3:20:21selected driver to null and it looks
- 3:20:23like I misspelled the driver ID and in
- 3:20:26this case there's so many different
- 3:20:27parentheses and braces and things to
- 3:20:30mess up so what I'll do is I'll provide
- 3:20:33this index.ts of store in the code
- 3:20:36Snippets in the GitHub readme so if you
- 3:20:38mess something up you can copy and paste
- 3:20:40it from there now that we have that used
- 3:20:43driver store we can make use of it in
- 3:20:45the map by getting the selected driver
- 3:20:49as well as the set
- 3:20:51drivers by saying is equal to use driver
- 3:20:55store and now the question is where are
- 3:20:58we going to get the drivers from of
- 3:21:00course they're going to come from our
- 3:21:01neon DB post girl database but for the
- 3:21:04time being let's mock some drivers like
- 3:21:07we mocked our recent rides just so we
- 3:21:09can see it on the screen in the GitHub
- 3:21:11read me you can see a little toggle with
- 3:21:14Moog drivers so copy it and paste it at
- 3:21:18the top of the map file cons drivers is
- 3:21:22equal to this array make sure to
- 3:21:25collapse
- 3:21:26it once you have the drivers we can
- 3:21:29create a new use
- 3:21:31effect it has a callback function and it
- 3:21:35also has a dependency array that changes
- 3:21:38whenever the drivers change in here we
- 3:21:40want to check if the drivers exist and
- 3:21:42whether they're an array so we can say
- 3:21:44if array that do is array to which we
- 3:21:48can pass the drivers and if we have the
- 3:21:51drivers but if we don't have the user so
- 3:21:53if no user latitude or no user
- 3:21:58longitude in that case we want to exit
- 3:22:00out of this but if we do have the user
- 3:22:03location and if we have the drivers we
- 3:22:06want to create markers on the map so we
- 3:22:09can say const new
- 3:22:11markers and that's equal to generate
- 3:22:14markers from data so this is this is a
- 3:22:16function that we created in the map
- 3:22:19utils to which we can pass the data
- 3:22:21equal to drivers and we can pass the
- 3:22:24user latitude and the user longitude and
- 3:22:28that'll generate the markers this is not
- 3:22:30too big of a deal right now because we
- 3:22:32have mock drivers later on once we have
- 3:22:34the real ones from the database it'll be
- 3:22:37okay so now that we have these new
- 3:22:39markers we can set them to the state so
- 3:22:41let's create a new used State and let's
- 3:22:45call it
- 3:22:47markers and set markers at the start
- 3:22:50equal to an empty array and they'll be
- 3:22:52of a type marker
- 3:22:55data and specifically an array of marker
- 3:22:59datas and after we create these new
- 3:23:01markers we can simply set markers to be
- 3:23:05equal to new
- 3:23:08markers and just to go to the map utils
- 3:23:11I can explain how the generate markers
- 3:23:13from data Works basically it's it's
- 3:23:16getting the information about our user
- 3:23:18latitude and longitude so where are we
- 3:23:21right now and it's adding a random
- 3:23:24offset to mock the driver's locations so
- 3:23:27that it seems like they're next to us
- 3:23:29once you implement the real geolocation
- 3:23:31for the drivers you won't have to do
- 3:23:33this you'll be able to just show a
- 3:23:35couple of the drivers that are most
- 3:23:37nearby to the
- 3:23:39user but now the question is where do we
- 3:23:42show these markers and how do we show
- 3:23:44them within the map let me show you
- 3:23:48we can go to the map and specifically
- 3:23:50inside of the map and here we can map
- 3:23:53over the markers by saying markers. map
- 3:23:58where we get each individual marker and
- 3:24:01for each marker we can automatically
- 3:24:03return a new marker this marker is
- 3:24:06coming from react native Maps so let's
- 3:24:10look into it react native Maps we have a
- 3:24:13map view and then before the provider
- 3:24:15default inside of the curly braces we
- 3:24:18can import the marker but of course the
- 3:24:21marker needs to have some
- 3:24:23information so what we can do is give it
- 3:24:26a key equal to marker. ID give it
- 3:24:30coordinates which are going to be equal
- 3:24:32to an object of
- 3:24:34latitude equal to marker.
- 3:24:38latitude longitude equal to marker.
- 3:24:43longitude we can give that specific
- 3:24:46marker a title equal to marker. tile and
- 3:24:51we can also give it an image equal to if
- 3:24:54selected driver is triple equal to
- 3:24:58marker. ID then we can render the icons
- 3:25:01coming from constants do selected marker
- 3:25:06else we can just render a marker icon
- 3:25:09depending on which marker is selected
- 3:25:12and would you look at that we have four
- 3:25:14cars appearing next to our current
- 3:25:16location for me there is no pin about
- 3:25:19the where I'm at right now but for you
- 3:25:22there should be one so it's looking even
- 3:25:24better now we have our current location
- 3:25:27showing on the map we see the recent
- 3:25:29rides and we see the drivers near by us
- 3:25:32that can drive us somewhere but the
- 3:25:35question is where are we going to go and
- 3:25:37how can we tell that to our Uber
- 3:25:39application to implement that we'll have
- 3:25:41to focus on the second biggest part of
- 3:25:44our homepage and that my friend is our
- 3:25:48Google text input finally we'll be able
- 3:25:51to type something in and get the path
- 3:25:54drawn out from our current location to
- 3:25:57our destination location so let's dive
- 3:26:00right into the Google text input and
- 3:26:02let's start implementing it first things
- 3:26:05first we have to install a package for
- 3:26:07the react native Google Places
- 3:26:09autocomplete and its name is exactly
- 3:26:12that mpm install
- 3:26:15react-native -
- 3:26:17google-places D Auto
- 3:26:22Complete we have a view right here and
- 3:26:25directly within the view where currently
- 3:26:27it says search will render the
- 3:26:29self-closing Google Places autocomplete
- 3:26:34and we have to import it right at the
- 3:26:35top from the react native Google Places
- 3:26:38autocomplete that's a mou full and
- 3:26:41immediately you can see a nice looking
- 3:26:43input appear and if you click into it
- 3:26:45you can start typing tying
- 3:26:47something but it's still not showing any
- 3:26:50information so let's continue styling it
- 3:26:52further and passing other props to it
- 3:26:55that it expects such as fetch details
- 3:26:58which can be set to true we can also
- 3:27:01pass it a placeholder equal to search or
- 3:27:05maybe something like where you want to
- 3:27:08go next we can give it a debounce this
- 3:27:11means that it's only going to make a
- 3:27:13request every 200 milliseconds if if it
- 3:27:16was going to make a request every key
- 3:27:18press that would be too many requests
- 3:27:21and we can also give it some Styles so
- 3:27:24let's create a large object of styles
- 3:27:27we're writing CSS injs here and first we
- 3:27:31can style different things such as the
- 3:27:33text input
- 3:27:34container so we can create that as
- 3:27:36another object that's going to look like
- 3:27:39this and we can say align items is equal
- 3:27:42to Center we can also say justify
- 3:27:45content is equal to Center as well we
- 3:27:48can give it a border
- 3:27:51radius equal to
- 3:27:5320 a margin horizontal equal to 20 as
- 3:27:57well you can see how it's moving it and
- 3:28:00a position set to
- 3:28:02relative and also a shadow
- 3:28:06color equal to Hash D4 D4 D4 next we can
- 3:28:12style the text input so let's go outside
- 3:28:16inside of this and say text
- 3:28:18input we can give it a background color
- 3:28:22which is going to be equal to either the
- 3:28:25text input background color or the color
- 3:28:29white so this is the one we're passing
- 3:28:31through props text input background
- 3:28:34color let's properly close this it's
- 3:28:37also going to have a font size of 16 a
- 3:28:41font weight of 600 a margin top of 5 and
- 3:28:47a width of 100% finally a border radius
- 3:28:52of 200 to make it not have such rough
- 3:28:56Corners finally once we can see some
- 3:28:58elements on the screen we can style how
- 3:29:01they look like by modifying the list
- 3:29:04view Styles we can say that the
- 3:29:07background color of the list view will
- 3:29:09be equal to text input background color
- 3:29:12if it exists or else it'll be set to
- 3:29:16white we can also give it a position
- 3:29:19equal to
- 3:29:20relative we can give it a top position
- 3:29:24equal to zero a width equal to
- 3:29:27100% a border radius set to 10 a shadow
- 3:29:33color equal to D4 D4 D4 and a zindex of
- 3:29:3999 so it appears on top of other
- 3:29:42elements great so now our input is
- 3:29:45looking
- 3:29:46great but as we type nothing is
- 3:29:49happening yet so let's give it some
- 3:29:51additional properties as well such as
- 3:29:55the onpress functionality once we press
- 3:29:57it what do we want to happen well first
- 3:30:01once we press it we can get some
- 3:30:03information from the press such as the
- 3:30:05data and the details which is at the
- 3:30:08start set to null and then we can call
- 3:30:10the function and call a handle press
- 3:30:13function and this function is coming
- 3:30:15through props to it we need to pass the
- 3:30:18latitude longitude and the address so
- 3:30:20let's do just that Latitude will be
- 3:30:23equal to details question mark.
- 3:30:26geometry.
- 3:30:28location. latitude or lat
- 3:30:31L and we can add an exclamation mark
- 3:30:34because we know it's there we can repeat
- 3:30:36the same thing with the longitude but
- 3:30:38it's going to be LNG at the end and
- 3:30:41finally the address will be equal to
- 3:30:44data do description next to the on press
- 3:30:47we also have to Define our query so this
- 3:30:50is the search query and the key here is
- 3:30:53going to be equal to the Google Places
- 3:30:55API so this is something we can Define
- 3:30:57right here at the top by saying const
- 3:31:01Google Places API key let's make sure to
- 3:31:06spell it properly is equal to process.
- 3:31:10env. Expo
- 3:31:13corpu gooogle AP apore key and we can
- 3:31:17now use this Google Places API key as
- 3:31:20the key in the query and we can set the
- 3:31:24language equal to any language in the
- 3:31:27world I use en n for English we can also
- 3:31:30choose to render a left button so that's
- 3:31:33how customizable it is render left
- 3:31:36button which will be equal to a callback
- 3:31:39function where we return a view that has
- 3:31:42a class name equal to justify i- center
- 3:31:47items Das Center and a w of 6 and an H
- 3:31:51of
- 3:31:52six within it we can render an image
- 3:31:56coming from react native with a source
- 3:32:00and if an icon exists then we return an
- 3:32:03icon else we tap into the icons from
- 3:32:07constants do search so you can see a big
- 3:32:09search icon on the right right now we
- 3:32:11can style it by giving it a class name
- 3:32:14equal to w ofc 6 and H of 6 with a
- 3:32:18resize mode equal to
- 3:32:21contain there we go that's much better
- 3:32:24finally we can have one last property
- 3:32:28called text input props which will
- 3:32:32accept a placeholder text color which
- 3:32:35will set to be equal to Gray and a
- 3:32:38placeholder will be equal to either the
- 3:32:41initial location so this is if we
- 3:32:43already have a location from before or
- 3:32:46double question mark this is to make
- 3:32:48sure that if we don't have the initial
- 3:32:50location we can show something else and
- 3:32:52that else is where do you want to
- 3:32:57go great so now if I clear it you can
- 3:33:00see where do you want to go and if we
- 3:33:02start typing something like let's see
- 3:33:06Zagreb is the capital of
- 3:33:08Croatia nothing shows up or whatever you
- 3:33:11start typing most likely nothing is
- 3:33:14showing up either
- 3:33:16and the main point of this Google
- 3:33:19autocomplete is for it to autocomplete
- 3:33:21exciting locations and cities near our
- 3:33:25location so why is it not working well
- 3:33:27when Google gave us our API key I
- 3:33:30thought that they're going to let it
- 3:33:31work but it looks like if we go to
- 3:33:34enable apis and services and then search
- 3:33:37for directions API and then even though
- 3:33:40it is enabled we have to go to manage
- 3:33:43and then we have to go through this
- 3:33:44verification process process where the
- 3:33:46use our card to verify that we're not a
- 3:33:49robot they won't charge us absolutely
- 3:33:53anything until we manually decide to
- 3:33:55upgrade to a paid account so this is
- 3:33:57just a strict verification to make sure
- 3:33:59that we're not a
- 3:34:01robot so I'll click agree and continue
- 3:34:04you'll have to enter some additional
- 3:34:05information and then proceed further in
- 3:34:08a matter of seconds my account was
- 3:34:10verified and now you need to answer a
- 3:34:12couple more
- 3:34:14questions you you can say what you want
- 3:34:16to
- 3:34:18build say what you're
- 3:34:20doing choose the
- 3:34:24platform and select the framework once
- 3:34:27you do that it'll give you a new API key
- 3:34:29which you can copy take on enable all
- 3:34:32Google Maps apis for this project and
- 3:34:34create a budget alert to help you stay
- 3:34:37on top of your spending so you don't get
- 3:34:39charged more but that's almost
- 3:34:41impossible to reach given that I believe
- 3:34:43you would need to have millions and
- 3:34:45millions of calls to reach that amount
- 3:34:48so you can think of it as completely
- 3:34:50free and then go to Google Maps platform
- 3:34:53now I'm fully aware that some of you
- 3:34:56might not have a credit card and that's
- 3:34:59totally okay some subscribers have told
- 3:35:01me in the comments of a previous video
- 3:35:03that for India specifically there's also
- 3:35:05Ola Maps which is completely free and
- 3:35:08you can get it without a credit card so
- 3:35:10that's another thing that you can try
- 3:35:11out if Google is not an option or maybe
- 3:35:14other people in the comments will be
- 3:35:16able to tell you some alternative
- 3:35:17Solutions if you really cannot use
- 3:35:19Google but in this case I'll be
- 3:35:21proceeding with Google so it created a
- 3:35:24new project for me and I do believe that
- 3:35:26the services are automatically enabled
- 3:35:28for Google Maps so we can just use this
- 3:35:31new API key that has been provided to us
- 3:35:34and I can paste it right here once you
- 3:35:37do that and whenever you make some
- 3:35:38changes you'll have to reload your
- 3:35:41application so stop it from running and
- 3:35:44then run MPX Expos start- C to clear
- 3:35:48your cache now if you open up the search
- 3:35:51once again and start typing something
- 3:35:53you'll see powered by Google and you'll
- 3:35:56be able to see some great locations
- 3:35:57appear on your screen you'll be able to
- 3:36:00select from many of them and the next
- 3:36:02step we'll have to do is to open up a
- 3:36:04new screen that will allow us to verify
- 3:36:07your current location your destination
- 3:36:09location and then we'll be able to
- 3:36:11create a trip which is a handshake
- 3:36:14between you and and the driver so to
- 3:36:17make that happen we have to make sure
- 3:36:19that something happens once we press or
- 3:36:21choose a specific location and that is
- 3:36:25coming through props from the homepage
- 3:36:28so if we go to home you can see that
- 3:36:30we're passing handle destination press
- 3:36:32which is currently completely empty once
- 3:36:35we press it it's going to give us access
- 3:36:37to a location that contains three
- 3:36:40different things a Latitude which is a
- 3:36:43number a longitude which is is also a
- 3:36:46number and then an address which is a
- 3:36:50string what do we do with those well we
- 3:36:53can call the set destination location to
- 3:36:56which we can pass this newly selected
- 3:36:59location destination once we do that we
- 3:37:02can use the router. push functionality
- 3:37:05to go to the second screen forward slash
- 3:37:09in parentheses root and then find Dash
- 3:37:13Ride Now check this out even typescript
- 3:37:17didn't save me when I was setting up the
- 3:37:20name of the type within this
- 3:37:22location it was okay with launch titude
- 3:37:26but in this case webstorm spellchecking
- 3:37:30found the mistake here it was supposed
- 3:37:32to be
- 3:37:33longitude so this was super useful next
- 3:37:37we have to import the
- 3:37:39router from Expo router so let's do just
- 3:37:42that
- 3:37:49and in this case Expo is also pretty
- 3:37:52smart because it tells us right now that
- 3:37:55there's no such screen find ride so
- 3:37:58let's go ahead and create it we can go
- 3:38:01to our file
- 3:38:02explorer go to app rout and then right
- 3:38:07here next to tabs we can create a new
- 3:38:10file directly in the root we can call it
- 3:38:13find- rde
- 3:38:16TSX there we can say const find ride is
- 3:38:20equal to a react error function where we
- 3:38:24can run export default find ride you
- 3:38:28know the drill we can there return a
- 3:38:32view coming from react native and we can
- 3:38:36return a text element for now saying
- 3:38:39find right just so we know if we have
- 3:38:42reached that screen
- 3:38:44properly now if we go back to home from
- 3:38:47where we were redirecting you can see
- 3:38:49that it's no longer complaining and
- 3:38:52thanks to zustand and our store before
- 3:38:55we change the screen we're also setting
- 3:38:57our destination location right here to
- 3:38:59the store so that even on the next
- 3:39:01screen we know where we want to go so
- 3:39:04let's give it a shot I'll type
- 3:39:07Sacramento right here in California USA
- 3:39:10and it navigates me over to find ride
- 3:39:14and just so I can prove prove to you
- 3:39:16that we actually know where we want to
- 3:39:17go we can make use of the used location
- 3:39:20store so let's head over to find
- 3:39:24ride use the use location store by
- 3:39:28saying const something is equal to use
- 3:39:31location
- 3:39:32store and here we can destructure the
- 3:39:35user address which is our current
- 3:39:37address and the destination address and
- 3:39:41we can also get the set destination
- 3:39:42address and set user location
- 3:39:46in case we decide to change it you know
- 3:39:47how in Uber you can change your current
- 3:39:49location in case you will be somewhere
- 3:39:51else once the driver picks you up so now
- 3:39:55here in the text I can give it a class
- 3:39:57name equal to text-
- 3:40:012XL and I can say you are here and I can
- 3:40:06render the user address I can duplicate
- 3:40:09it and say you are going to and here we
- 3:40:13can say destination address
- 3:40:15and now if I save this you can see you
- 3:40:18are here San Francisco you're going to
- 3:40:21Sacramento wonderful this is working
- 3:40:25like a charm and we can even go back and
- 3:40:28if we want to go somewhere else let's
- 3:40:30say Pao
- 3:40:32Alto we can also go right here so let's
- 3:40:36do that next as you can notice the next
- 3:40:39three screens have a very similar layout
- 3:40:41they have a map at the top here here and
- 3:40:45here they have some kind of a widget
- 3:40:48that appears at the bottom which is this
- 3:40:50form right here here and here and then
- 3:40:54you can slide it above to cover the map
- 3:40:57so for that reason I'll teach you how to
- 3:40:59create something very cool and that is a
- 3:41:01layout component so that we can reuse a
- 3:41:04very similar layout but then change
- 3:41:06what's shown within it so let's go to
- 3:41:09components and create a new file called
- 3:41:12ride layout. TSX
- 3:41:15it'll be a component like any other
- 3:41:18starting with con ride layout which is a
- 3:41:22react functional
- 3:41:24component we can export default. ride
- 3:41:27layout and then we can return some kind
- 3:41:30of a view right within
- 3:41:32it the difference between a regular
- 3:41:35component and a layout component is that
- 3:41:38layouts typically accept children as
- 3:41:41props so we can Define children right
- 3:41:43here and it'll be of a type children is
- 3:41:46a react node what does having children
- 3:41:49allow us to do well first of all we can
- 3:41:52have some kind of a text that allows us
- 3:41:54to say top of the layout and we can
- 3:41:58duplicate that to say bottom of the
- 3:42:00layout but then in the middle we can
- 3:42:03render whatever we show in the children
- 3:42:06so if I do this we can now go back to
- 3:42:09find ride and I'll wrap my entire
- 3:42:12application with the ride layout of
- 3:42:15course make sure to import it from
- 3:42:17components and check what happens now we
- 3:42:20have top of the layout bottom of the
- 3:42:22layout and then in the middle we have
- 3:42:25whatever we have right here for now we
- 3:42:27can leave that just to be a text that
- 3:42:30says something like find ride because
- 3:42:33this is the screen that we're currently
- 3:42:34on now later on we'll be able to reuse
- 3:42:37this layout on other screens as well
- 3:42:39screens such as these ones right here in
- 3:42:43the root layout first we have the find
- 3:42:47ride so we can also hide the header on
- 3:42:50it later on we'll also have a
- 3:42:54confirm ride and finally we'll have a
- 3:42:58book ride and we want to hide headers
- 3:43:00from all of them as you can see our
- 3:43:03layout is now complaining about too many
- 3:43:05screens defined so for now I will
- 3:43:08comment out the bottom twoo and let's
- 3:43:10continue working on our right layout
- 3:43:13instead of having a top and bottom
- 3:43:15bottom text we'll do something different
- 3:43:17I'll wrap everything in a gesture handle
- 3:43:21root view like this and that's going to
- 3:43:24come from a new package so let's install
- 3:43:27it by running mpm install
- 3:43:31react-native-gesture-handler
- 3:43:34once it installs we'll be able to just
- 3:43:37import it from there this will allow us
- 3:43:40to swipe our screen and then show
- 3:43:42something underneath it before rendering
- 3:43:44children let's render some other stuff
- 3:43:46here like another view with a class name
- 3:43:50equal to flex D1 and BG DWI within it we
- 3:43:55can render yet another view with a class
- 3:43:59name equal to flex
- 3:44:03flex-all h- screen for full height and
- 3:44:07BG
- 3:44:09dl-500 I'll go back to my screen and now
- 3:44:13we can see that the entire screen is
- 3:44:14blue
- 3:44:16we can show another view right below it
- 3:44:18or right within it with a class name
- 3:44:21equal to flex Flex Das row absolute Z of
- 3:44:2710 top of
- 3:44:2916 items Das Center justify Das start
- 3:44:34and padding
- 3:44:36xl5 nothing will show yet because we
- 3:44:38have to put something within it and that
- 3:44:41something will be a touchable opacity
- 3:44:43which is basically a button on press of
- 3:44:46this touchable opacity we'll call a
- 3:44:48callback function that'll call the
- 3:44:50router
- 3:44:52doback so we can just go to a page back
- 3:44:55and within it we can render a view
- 3:44:58that'll render an image with a source
- 3:45:01equal to icons coming from constants
- 3:45:04doback
- 3:45:05arrow with a resize mode of
- 3:45:10contain and a class name equal to W6 h
- 3:45:15six now you can see a little back arrow
- 3:45:18right here on top left we can also style
- 3:45:21it further by giving this view a class
- 3:45:23name of W10 h10 BG white round the- full
- 3:45:31and we can also give it items Das Center
- 3:45:34and justify Das Center to put it in the
- 3:45:37middle great so now we're starting to
- 3:45:40create this backdrop right below the
- 3:45:42touchable opacity we can also render a
- 3:45:45piece of text that will say either a
- 3:45:48title so it will render a title that we
- 3:45:51pass through props so alongside children
- 3:45:54we can also get the title and the title
- 3:45:57will be of a type
- 3:45:59string if we don't have a title then we
- 3:46:02can render a piece of text that will say
- 3:46:05something like go back let's style this
- 3:46:08a bit by giving it a class name equal to
- 3:46:11text- excl font djar PARTA semi bold and
- 3:46:17margin left of five right below that
- 3:46:19view will render a
- 3:46:22map coming from components
- 3:46:25map thankfully we have already crafted
- 3:46:28this
- 3:46:29component and that's going to go below
- 3:46:31the view not below the
- 3:46:34text there we go so now this makes much
- 3:46:36more sense for the first time ever we
- 3:46:39can see a map right here on our entire
- 3:46:43screen how nice nice is that but here's
- 3:46:46the key part going below this map and
- 3:46:49below the view we'll create something
- 3:46:52known as a bottom sheet and this bottom
- 3:46:55sheet is coming from another custom
- 3:46:58package it has more than 300,000 weekly
- 3:47:01downloads and it provides this nice
- 3:47:03bottom sheet that you can swipe up and
- 3:47:05you can see the perfect use case is Maps
- 3:47:09so let's copy this installation code
- 3:47:12open up the terminal and run mpmi at
- 3:47:15gorom SL bottom Das
- 3:47:19sheet and now we can very easily import
- 3:47:22it from there this bottom sheet also
- 3:47:25requires a ref so we can say const
- 3:47:28bottom sheet ref is equal to use ref
- 3:47:33coming from
- 3:47:34react of a type bottom sheet at the
- 3:47:38start set to null now we can provide
- 3:47:41this ref to this bottom sheet by saying
- 3:47:43ref is equal to to bottom sheet ref we
- 3:47:47can also give it snap points so these
- 3:47:50are the two different points at which
- 3:47:53the sheet will stop so we can put that
- 3:47:56as an array and it can be equal to let's
- 3:48:00do something like 40% and then the
- 3:48:02second one can be about maybe
- 3:48:0685% like
- 3:48:08this and then we can also give an index
- 3:48:11of zero to this bottom sheet
- 3:48:15within the bottom sheet we can render
- 3:48:17the
- 3:48:19bottom sheet scroll
- 3:48:23view that'll have a style equal to flex
- 3:48:28of one and a padding of
- 3:48:3120 and within it we can render the
- 3:48:34children so this is where the magic
- 3:48:37happens if I now go back right here to
- 3:48:41search you can see that now there's a
- 3:48:43find r text and if I scroll up and down
- 3:48:48it gets stuck at 40 and 85%
- 3:48:51respectively but again the key part is
- 3:48:54that whatever is right in here what
- 3:48:56we're wrapping with the ride layout
- 3:48:58shows directly within this little view
- 3:49:01that you can then move up and down but
- 3:49:03the map remains right on top of it this
- 3:49:07is such a beautiful user interface so
- 3:49:10now the layout is mostly done and if we
- 3:49:13go back to our final ride we can start
- 3:49:16implementing whatever is supposed to be
- 3:49:18within it let's first give it a title
- 3:49:20equal to ride and let's create a view
- 3:49:24right within
- 3:49:26it this view will have a class name
- 3:49:30equal to margin y of
- 3:49:32three and within it we can render a text
- 3:49:35element that will say from so where are
- 3:49:38you coming from it'll have a class name
- 3:49:42equal to text- LG font D Jakarta semi
- 3:49:47bold and a margin bottom of
- 3:49:49three right below it we can render a
- 3:49:53reusable component which we have already
- 3:49:54created called a Google text input of
- 3:49:58course we have to pass a couple of props
- 3:50:00to it so let's do just that we can pass
- 3:50:02it the icon equal to
- 3:50:05icons coming from constants do Target in
- 3:50:09this case we already have an initial
- 3:50:11location as well equal to user
- 3:50:15address so now you can see we already
- 3:50:18know where we're coming from because
- 3:50:20it's taking it from a user address
- 3:50:22location next we can provide some
- 3:50:25container style equal to BG neutral
- 3:50:30100 and we can also provide a text input
- 3:50:35background color of hash F5 F5
- 3:50:41F5 and then what happens on the handle
- 3:50:43press well we can call a call function
- 3:50:47where we get the
- 3:50:48location and we simply set user location
- 3:50:52to a new location that a user has
- 3:50:56chosen in this case it's complaining a
- 3:50:58bit about the initial location maybe
- 3:51:01there's a type mismatch I'll just add an
- 3:51:03exclamation mark at the end because we
- 3:51:05know it'll be in the right format we can
- 3:51:07end this view right here and check this
- 3:51:10out I will simply duplicate this view
- 3:51:13below and say not from but rather to
- 3:51:18change the icons to map change the
- 3:51:22address to destination address you can
- 3:51:25disregard my low battery sign I'll go
- 3:51:27ahead and go charge it soon and we can
- 3:51:30also change the text input background
- 3:51:32color to transparent here instead of set
- 3:51:35user location we'll set the destination
- 3:51:39location I'll close my battery warning
- 3:51:42and would you look at this we have two
- 3:51:44different inputs from and to and we can
- 3:51:47change both of them by typing once again
- 3:51:50so in San Francisco I can type and go
- 3:51:53from let's say somewhere else here we go
- 3:51:56but I do get a warning here saying that
- 3:51:58virtualized lists should never be nested
- 3:52:02and if we close this I'm guessing a
- 3:52:05similar thing will happen right here yep
- 3:52:07you can see virtualized lists should
- 3:52:09never be nested we'll fix that very soon
- 3:52:12but before we do that let's quickly add
- 3:52:14a new custom button right here below
- 3:52:17it's going to say find now remember
- 3:52:20we're trying to find
- 3:52:21drivers and what are we going to do on
- 3:52:24press well on press we will use the
- 3:52:28router coming from Expo router to push
- 3:52:32over to forward slash root in
- 3:52:35parenthesis forward slash confirm Das
- 3:52:39ride and we can give this button a class
- 3:52:42name equal to margin top of
- 3:52:46five there we go this is looking much
- 3:52:49better of course we have to actually
- 3:52:51create this route so let's add a new
- 3:52:55stack screen that's going to say confirm
- 3:52:58ride and let's create a new file in the
- 3:53:01app rout and it'll be
- 3:53:04called
- 3:53:06confirm ride. TSX where we can create a
- 3:53:11new con confirm ride
- 3:53:15and then we can export default that
- 3:53:18confirm ride that'll for now return a
- 3:53:22view and a
- 3:53:25text saying confirm ride one thing that
- 3:53:29could be the issue here is if we go to
- 3:53:32the ride layout remember it's mentioning
- 3:53:35something about scroll views so what if
- 3:53:38we just use a bottom sheet view right
- 3:53:40here and not a bottom scroll sheet view
- 3:53:44we can import it remove the other one
- 3:53:48and give that a shot we don't need a
- 3:53:50scroll within a scroll I think that's
- 3:53:52why it's complaining about so if one
- 3:53:54more time we go
- 3:53:56into
- 3:53:58here and we need to bring it a bit up
- 3:54:02and enter something like
- 3:54:04Switzerland now it works perfect there's
- 3:54:08one thing we could try though and that
- 3:54:10is coming directly from the keyboard
- 3:54:13behavior of the bottom sheet component
- 3:54:17they say that we can Define the keyboard
- 3:54:18appearance behavior and we can use the
- 3:54:21extend or interactive to offset the
- 3:54:24sheet by the size of the keyboard so by
- 3:54:27default it is interactive so we can
- 3:54:29switch it to maybe extend we can do that
- 3:54:31by giving this bottom sheet a keyboard
- 3:54:34Behavior equal to
- 3:54:37extend but even if I try that it doesn't
- 3:54:40seem to do the trick maybe on Android it
- 3:54:43works so so we can leave it as it is
- 3:54:45because by default it is indeed
- 3:54:47interactive but we'll have to figure out
- 3:54:49something else for iOS maybe we'll have
- 3:54:52to pass custom snap points to this ride
- 3:54:55layout by saying snap points is equal to
- 3:54:58and it can be an array of something like
- 3:55:0285% so now if I go to the ride layout
- 3:55:06and accept those snap points which will
- 3:55:08be an array of strings so we can say
- 3:55:11snap points is optional and it is an
- 3:55:13array of strings we can now either
- 3:55:16render 4085 by default or if we have the
- 3:55:19snap points we can then render it by
- 3:55:21snap points so what this is going to do
- 3:55:24is every time that you're here it's
- 3:55:26always going to be opened at least
- 3:55:2985% this way you can see the from and
- 3:55:33two locations very nicely on the screen
- 3:55:35here and on this screen you're not
- 3:55:36supposed to be looking at the map anyway
- 3:55:38you're supposed to be checking whether
- 3:55:40the from and two are correct so with
- 3:55:42that in mind we got that fix so let's
- 3:55:45click find now which is going to
- 3:55:46redirect us to confirm ride this is the
- 3:55:51second page where we'll reuse the ride
- 3:55:54layout so I'll show you how convenient
- 3:55:56that is check this out instead of a view
- 3:56:00I'll use the right layout coming from
- 3:56:03components I'll give it a title which is
- 3:56:06going to be choose a
- 3:56:09driver and I'll give it snap points
- 3:56:12which are going to be custom of about
- 3:56:1565% for the first one and we can do
- 3:56:1985% for the second one within it we can
- 3:56:23render a flat list the data for the flat
- 3:56:26list will be the drivers that we can
- 3:56:28choose from and I do believe that we
- 3:56:31already have some fake drivers I think
- 3:56:33it was maybe in home let's see here we
- 3:56:36have recent rides maybe it was in the
- 3:56:39map yes right here at the top of the map
- 3:56:41we have the mock drivers for now let's
- 3:56:44simply copy them and add them at the top
- 3:56:46of the confirm ride I promise soon
- 3:56:49enough we'll make this Dynamic but for
- 3:56:51now for the flat list data will be equal
- 3:56:54to drivers next we can choose how we
- 3:56:57want to render that item so we can say
- 3:57:00render item we have a callback function
- 3:57:03where we get access to that item and for
- 3:57:06each one we return a driver card so this
- 3:57:10is another component which we can create
- 3:57:12in the components folder
- 3:57:15let's create it by saying a driver card.
- 3:57:19DSX you know the drill const driver card
- 3:57:24is equal to a simple immediate return
- 3:57:27component where we render a view with a
- 3:57:31text that says something like driver and
- 3:57:35we can immediately export default that
- 3:57:38card going back we can import this card
- 3:57:42and if we render it we'll have to go
- 3:57:43back back let's go to Scranton
- 3:57:46Pennsylvania and click find now and we
- 3:57:48can see four different drivers to each
- 3:57:51one of these drivers we can pass the
- 3:57:53item which is basically the entire
- 3:57:56information about a specific driver of
- 3:57:58course in the driver card we'll have to
- 3:58:00accept that prop so let's do that right
- 3:58:03away it'll accept the item of a type
- 3:58:07writer card props and basically what
- 3:58:11we're developing here is this card where
- 3:58:14where we show a profile photo of the
- 3:58:15driver their name their rating how much
- 3:58:18they cost how much it would take for
- 3:58:21them to get to us and how many seats
- 3:58:23their car has as well as their car photo
- 3:58:26to speed up our workflow just a tiny bit
- 3:58:28you can find it right here in the
- 3:58:30Snippets copy it and paste it here
- 3:58:33you'll notice that it is nothing more
- 3:58:35than a touchable opacity basically a
- 3:58:37button that you can click that has an
- 3:58:40image and then with some repeated pieces
- 3:58:42of text that that is it we can nicely
- 3:58:45scroll through it we can click on them
- 3:58:47this is looking great the only thing
- 3:58:50we're missing back at confirm ride is
- 3:58:53going to be this time not a header but a
- 3:58:57list footer
- 3:58:59component where we can define a callback
- 3:59:02function and then Define a
- 3:59:06view which we can
- 3:59:08close that will have a class name equal
- 3:59:12to margin X of five and margin top of
- 3:59:1610 and within it we can render a custom
- 3:59:19button with a title select ride and on
- 3:59:23press we can run the Callback function
- 3:59:27that calls the
- 3:59:29router. push to slash in parentheses
- 3:59:34root slash book- R so right now it is
- 3:59:39red because we don't yet have that route
- 3:59:42but soon enough it'll be there before we
- 3:59:44go ahead and create it there's one more
- 3:59:46thing we have to do and that is create a
- 3:59:48completely new store so right now we
- 3:59:52have the store for the location but
- 3:59:55right below it there's a store for the
- 3:59:57drivers where we're keeping track of all
- 4:00:00of the active drivers and we're keeping
- 4:00:02track of which driver has our user
- 4:00:04selected so we can access that store
- 4:00:08like we're used to so far by saying
- 4:00:10const something is equal to use driver
- 4:00:15store and from it we can extract the
- 4:00:18drivers we can extract the selected
- 4:00:21driver as well as set the selected
- 4:00:24driver to the one that we click so to
- 4:00:27the driver card we can pass the selected
- 4:00:30equal to selected driver and we can add
- 4:00:34the exclamation mark at the end because
- 4:00:36we know it exists and then we can call
- 4:00:38the set selected where we have a
- 4:00:41callback function where we can call the
- 4:00:43set selected driver and to it we can
- 4:00:46pass the item. ID basically the ID of
- 4:00:50the driver we're selecting and in this
- 4:00:53case the drivers here override the
- 4:00:56drivers above which is okay because we
- 4:00:58don't need to Define them to times
- 4:01:01rather I'll remove the drivers from here
- 4:01:04and back on the map where we use the
- 4:01:06drivers for the first time we can call
- 4:01:08the set drivers go into the use effect
- 4:01:12and right here at the top of it we can
- 4:01:14say set drivers and pass our current
- 4:01:17fake drivers that we have at the top
- 4:01:19there's going to be a type mismatch but
- 4:01:21don't worry too much about that this
- 4:01:23will have to be removed anyway very soon
- 4:01:25as soon as we add real drivers so now
- 4:01:28let's create the last screen in our flow
- 4:01:31which is going to be book ride we can do
- 4:01:34that by going to root and creating a new
- 4:01:37file called book ride. DSX it's going to
- 4:01:41be a const book ride ride
- 4:01:44component and we can run export default
- 4:01:48book ride while we return a
- 4:01:52view with a
- 4:01:54text that's going to say book ride in
- 4:01:58the layout we can also add book ride
- 4:02:01back just so we can remove the
- 4:02:04header now let's go through our entire
- 4:02:07process one more time to test it out of
- 4:02:10course the last screen being the book
- 4:02:12ride oh and don't forget to add a return
- 4:02:15statement right here before so that
- 4:02:17everything works so if I do this and if
- 4:02:21I go visit Michael from the office to
- 4:02:24Scranton
- 4:02:26Pennsylvania I'll click find now we can
- 4:02:29see different drivers soon enough we'll
- 4:02:31be able to select only one right now
- 4:02:33we're selecting all of them and we can
- 4:02:36click select ride and that's going to
- 4:02:38lead us to the last screen in this ride
- 4:02:41selection sequence where we can find
- 4:02:43finally confirm that this is our driver
- 4:02:46and we are ready to book a ride with
- 4:02:48them and in terms of actual design this
- 4:02:51is the page we'll develop next as you
- 4:02:54can see it is very similar to previous
- 4:02:57Pages we're still using the ride layout
- 4:03:00and then we show something in the bottom
- 4:03:02sheet we're so close to getting to the
- 4:03:05payments part and we've already done a
- 4:03:08lot of UI I really want to focus on the
- 4:03:10functionality we've been using fake
- 4:03:13drivers and fake rides right here on the
- 4:03:15homepage so it's about time to turn all
- 4:03:18of that into real data and real
- 4:03:21databased
- 4:03:22interactions so just so we can do that
- 4:03:24very quickly I just provided you with
- 4:03:26the UI for the root book ride which you
- 4:03:30can copy here and just paste in this
- 4:03:32book ride page just make sure to fix
- 4:03:35this import where it's going to say ride
- 4:03:39layout and there we go now we have the
- 4:03:42ride information but it seems that it's
- 4:03:45not properly picking up the driver
- 4:03:47information I think I know why in the
- 4:03:50map we're using fake
- 4:03:52drivers and their IDs are
- 4:03:56strings so when we're confirming the
- 4:03:58selected driver we have to turn it into
- 4:04:01a number so we can wrap it just like
- 4:04:04this into a
- 4:04:06number and back in the book ride we can
- 4:04:09now consol log both the
- 4:04:12drivers as well as has the selected
- 4:04:14driver so we can do it just like so and
- 4:04:18save
- 4:04:19it we can see that selected driver is a
- 4:04:22string of
- 4:04:24one and we can see all drivers and there
- 4:04:27should be one with the ID of one so now
- 4:04:30it's just comparing the driver. ID which
- 4:04:33is turned into a number format which is
- 4:04:36equal to the selected driver ID so if I
- 4:04:39go back choose one of these there we go
- 4:04:43we can see the right information and
- 4:04:45just the pickup time is not good so
- 4:04:48right here for the pickup time we can
- 4:04:50check if there is driver details time or
- 4:04:54we can say something like 5 minutes this
- 4:04:57is going to be fixed once we have the
- 4:04:58real data but right now this is looking
- 4:05:02great the only thing that is missing on
- 4:05:04this screen is the confirm ride button
- 4:05:07but that won't be just a simple button
- 4:05:09it'll open up the entire stripe payment
- 4:05:12window where will be be able to choose
- 4:05:14from many different payment options and
- 4:05:16issue a payment after which we'll be
- 4:05:19redirected to the success model screen
- 4:05:21so for the next step we can scroll all
- 4:05:24the way down below this View and we can
- 4:05:27render a new component which we can
- 4:05:29create under the components folder and
- 4:05:32we can call it payment.
- 4:05:35TSX it'll be a react functional
- 4:05:37component called
- 4:05:39payment we don't have any props for now
- 4:05:43but you know the drill it will return a
- 4:05:46view that will have a
- 4:05:49text that'll say payment and we can do
- 4:05:53export
- 4:05:55default payment right here at the bottom
- 4:05:58now back in the book ride we can now
- 4:06:01import the
- 4:06:03payment and you can see it right here at
- 4:06:06the bottom the payment itself will
- 4:06:09simply be a react fragment that'll load
- 4:06:12a custom button so here we can say
- 4:06:15custom
- 4:06:17button with a title equal to confirm
- 4:06:21ride a class name equal to margin y of
- 4:06:2510 to divide it a bit from the top and
- 4:06:27bottom and on press we want to call a
- 4:06:30function called open payment sheet this
- 4:06:34is coming from stripe so we can declare
- 4:06:37this function right here const open
- 4:06:40payment sheet is equal to an AS Arrow
- 4:06:44function which for now we can leave
- 4:06:47blank so if we quickly go back to that
- 4:06:51last screen that we had you can see that
- 4:06:54now there is a confirm ride button which
- 4:06:57means that we can focus on implementing
- 4:06:59the payments big step ahead so let's
- 4:07:02dive right into it great job when coming
- 4:07:05this far for payments will of course use
- 4:07:08stripe one of the largest
- 4:07:10infrastructures for accepting any kind
- 4:07:12of payments online online so head to
- 4:07:15stripe.com and start now you can create
- 4:07:18a new account or sign in once you sign
- 4:07:21in you can turn on the test mode and
- 4:07:24that'll make sure that all the
- 4:07:25information that you can see here is
- 4:07:27test data so no real transactions will
- 4:07:30be processed here then you can go to
- 4:07:33developers and API keys and here you
- 4:07:36should have some of the standard keys or
- 4:07:38if you don't have them already you can
- 4:07:40just create them so I'll copy my
- 4:07:42publishable key and I'll head to
- 4:07:45myv and add a new Expo
- 4:07:49undoru stripe uncore publishable
- 4:07:53underscore key and make it equal to the
- 4:07:55key that I just copied we'll also need
- 4:07:57our secret key so let's copy it and add
- 4:08:01a new stripe secretor key we don't have
- 4:08:06to add Expo public before because we'll
- 4:08:08use this only within the API routes so
- 4:08:11it is truly secure now that we have our
- 4:08:13keys let's open up the documentation
- 4:08:15page thankfully Stripes docs are one of
- 4:08:18the best documentations out there in the
- 4:08:21development industry period so I'll link
- 4:08:24this documentation page down in the
- 4:08:25description where you can collect
- 4:08:28payment details before creating a
- 4:08:30payment intent and thankfully they have
- 4:08:32guides for web iOS Android and react
- 4:08:35native so we can just follow the steps
- 4:08:38first we have to install and set up
- 4:08:41stripe we can install stripe as well as
- 4:08:44stripe react native so let's copy this
- 4:08:46and paste it in our terminal and
- 4:08:49alongside that I'll also copy this other
- 4:08:51part using mpm the first one is serverid
- 4:08:55stripe and the second one is stripe for
- 4:08:57react native s DEC once we do that we
- 4:09:00want to initialize stripe by using the
- 4:09:03init method and this is within the
- 4:09:05stripe provider and do you know where
- 4:09:08we'll use this well we'll only wrap our
- 4:09:11book ride page with this
- 4:09:13so let's go ahead and copy this entire
- 4:09:15file close all of the currently open
- 4:09:18files and just open up the book ride I
- 4:09:22can zoom this out just so we can see
- 4:09:23what's happening a bit better and I'll
- 4:09:26paste it right here at the top we'll
- 4:09:29have to make some modifications for
- 4:09:31example we won't be needing this entire
- 4:09:34new functional
- 4:09:36component next we'll have some use
- 4:09:39effects functions as well as use States
- 4:09:43that we can copy and move into our book
- 4:09:46ride function and finally we have the
- 4:09:48stripe provider itself which we can
- 4:09:51copy and wrap our entire ride layout
- 4:09:56with and finally we can close this
- 4:09:59stripe
- 4:10:01layout or rather should they say stripe
- 4:10:04provider so I'm going to do it just like
- 4:10:09this and
- 4:10:11save as you can see now we have copied
- 4:10:14over the logic for stripe with that we
- 4:10:17have to import use state from react as
- 4:10:21well as import use effect from react as
- 4:10:25well next we need this fetch key
- 4:10:27functionality and this is going to be a
- 4:10:30call to our own server from which we can
- 4:10:32fetch our secure stripe key to make sure
- 4:10:35that we really want to process that
- 4:10:37payment for now I will comment this part
- 4:10:40out next we can scroll down and we need
- 4:10:43to to enable different payment methods
- 4:10:45that's in the payment method settings so
- 4:10:48if you follow that link you'll see many
- 4:10:50many different options that'll be
- 4:10:51enabled depending on where you're at but
- 4:10:54for now I'm okay with Apple and Google
- 4:10:56pay as well as cards so I'll leave it as
- 4:10:59it is and we can collapse the first two
- 4:11:01steps entirely the third step is to set
- 4:11:04up a return URL on the client side and
- 4:11:08they say that we can put this within the
- 4:11:10app. DSX we can skip this part because
- 4:11:13if you're using Expo it says to set up
- 4:11:15your scheme in ab. Json and that has
- 4:11:17already been set up for us so thankfully
- 4:11:19we can skip setting up the return URL
- 4:11:23next we can collect the payment details
- 4:11:25on the client side so we need to
- 4:11:27initialize a payment sheet we can copy
- 4:11:30this entire part of the code and this
- 4:11:32will go on the checkout screen in our
- 4:11:34case that'll be the payment screen so we
- 4:11:37can go over to payment and we can paste
- 4:11:41it right here at the top
- 4:11:44you'll notice that we'll have to remove
- 4:11:45the closing function block and remove
- 4:11:49the export default checkout screen
- 4:11:50because we already have our own payment
- 4:11:52screen let's save it let's move the
- 4:11:56import a bit
- 4:11:58up and now this is starting to make a
- 4:12:00bit more sense I will collapse
- 4:12:02everything just so you can see what's
- 4:12:04happening and we also need to move just
- 4:12:06a few things from the book ride it's
- 4:12:09going to be the publishable key fetch
- 4:12:11publishable key and the use effect we
- 4:12:13can move those things over to the
- 4:12:14payment as well just to have everything
- 4:12:17in one place I'll paste it right
- 4:12:20here we can move the states to the top
- 4:12:24right here and the only thing we have to
- 4:12:26change is now that we have moved the
- 4:12:28publishable key we have to actually
- 4:12:30fetch it from environment variables in
- 4:12:32the book ride so we can say process.
- 4:12:35env. xoor public stripe
- 4:12:41publishable key and I'm going to add an
- 4:12:44exclamation mark because we know that
- 4:12:46it'll be
- 4:12:47there and we can move the Imports for
- 4:12:50the used State and use effect over to
- 4:12:52the payment oh we already have it great
- 4:12:55so now let me Zoom this out a bit so you
- 4:12:58can better see it and let's see what we
- 4:13:00have so far in the payment we have this
- 4:13:03publishable key which we won't really
- 4:13:04need because it's going to be coming
- 4:13:06from environment variables so we can
- 4:13:08delete that we have the init payment
- 4:13:10sheet and present payment sheet so we
- 4:13:13first have to initialize it and then we
- 4:13:16can present it we have a function called
- 4:13:18initialize payment sheet which will call
- 4:13:21when we want to initialize it and we
- 4:13:23have a confirm Handler which they put
- 4:13:25here for us and it'll be explained later
- 4:13:28and in our case we don't need this
- 4:13:29function to fetch the publishable key
- 4:13:31we'll just use our own API calls to
- 4:13:33fetch it so I can remove the use effect
- 4:13:36as well just to make it a bit simpler
- 4:13:38there we go now it's pretty simple we
- 4:13:41have a function to initialize it a
- 4:13:42function open it and our own onpress
- 4:13:45function that should actually call these
- 4:13:47functions and make the magic happen and
- 4:13:50that's exactly what happens in The Next
- 4:13:51Step where we decide to present the
- 4:13:53payment sheet so we don't need to copy
- 4:13:56this entire function block we can just
- 4:13:58copy what's in it so the const error and
- 4:14:02then ifs and elses and we can paste it
- 4:14:05within the open payment sheet here we
- 4:14:08also need to import the payment sheet
- 4:14:10error and before we present the payment
- 4:14:13sheet as I told you we first need to
- 4:14:15initialize that payment sheet so right
- 4:14:18here at the top I can say a
- 4:14:22wait initialize payment sheet which we
- 4:14:26call as a function once we initialize it
- 4:14:29we can check if there are any errors and
- 4:14:31if so we can just let people know that
- 4:14:33there are errors by using the react
- 4:14:36natives alert functionality so alert.
- 4:14:39alert make sure to import it we can say
- 4:14:42error code
- 4:14:44code is error. code and we can also
- 4:14:48render the error message there we go
- 4:14:52else if there's no error we can set a
- 4:14:54new state of success so let's define
- 4:14:58that new state right here at the top by
- 4:15:00saying use
- 4:15:02State I'll call it success and set
- 4:15:05success at the start set to
- 4:15:08false and then in the else right here we
- 4:15:11can set success
- 4:15:13equal to true and we don't actually need
- 4:15:16this secondary if and else we just need
- 4:15:19the inner one so if there is an error we
- 4:15:22show this and then else we can set the
- 4:15:26success
- 4:15:28great so this is a function for opening
- 4:15:31a payment sheet let's see what else do
- 4:15:33we have to do finally we have to confirm
- 4:15:36the payment but we haven't even tested
- 4:15:38whether everything works so far for us
- 4:15:41so before we can confirm the payment
- 4:15:43let's go back and try to actually open
- 4:15:45up the payment sheet okay so we can go
- 4:15:48to any kind of
- 4:15:51location find choose a
- 4:15:55driver and click
- 4:15:57confirm this time we get an error saying
- 4:16:00you did not provide an API key I think
- 4:16:03that's because we haven't reloaded our
- 4:16:04application since we added our key
- 4:16:06because if you look at it here we indeed
- 4:16:08are passing our publishable key we might
- 4:16:11also need to fix our scheme scha so
- 4:16:14let's make a change to that in our book
- 4:16:16ride for the merchant identifier we can
- 4:16:19do something like let's maybe do
- 4:16:23merchant. uber.com doesn't really matter
- 4:16:27and then the URL schema has to be the
- 4:16:29same as you have in your app. Json I
- 4:16:32think by default it is set to my app as
- 4:16:35you can see right here so let's leave it
- 4:16:38like that and let's reload our
- 4:16:40application by stopping it from running
- 4:16:43and then rerunning MPX Expo start with-
- 4:16:46C to clear the
- 4:16:47cache and press R to reload the
- 4:16:50application I'll speed up the process of
- 4:16:53going through all these screens and
- 4:16:55would you look at that right here we
- 4:16:57have a beautiful little strip payment
- 4:16:59sheet where you can enter your credit
- 4:17:01card information the fake one of course
- 4:17:04you can even scan your card it is so
- 4:17:06seamless and you can click pay or we
- 4:17:09cannot right now that's because that's
- 4:17:10our next step if we go here the next
- 4:17:13step is to work on this confirm Handler
- 4:17:15so we can actually initiate and process
- 4:17:17a payment so now we have created this
- 4:17:20sheet and we have to next figure out
- 4:17:22what happens after we click the pay
- 4:17:24button next let's copy this confirm
- 4:17:27Handler
- 4:17:29functionality and let's paste it right
- 4:17:31here on top of initialized payment sheet
- 4:17:35this confirm Handler will be used as a
- 4:17:37method on this init payment sheet so
- 4:17:41right after the mode we have the confirm
- 4:17:43Handler which is equal to confirm
- 4:17:46Handler which is this function we just
- 4:17:48created here we had it below so we can
- 4:17:50delete this empty part and now we have
- 4:17:52the real confirm Handler right here the
- 4:17:54next step for all of this to work is to
- 4:17:57create a payment intent so I can
- 4:18:00collapse this one where we collect the
- 4:18:02payment details and finally we are ready
- 4:18:04to create a payment intent meaning
- 4:18:06create the possibility for the user to
- 4:18:09pay and that has to happen on the server
- 4:18:11side so now they created an app. poost
- 4:18:15route in our case we'll be using expose
- 4:18:18API routes so let's go ahead and copy
- 4:18:20this and create this route that will
- 4:18:23create a payment intent that'll be under
- 4:18:26app API and we can create a new folder
- 4:18:31called in parentheses stripe within it
- 4:18:35we can create a new file called create
- 4:18:38plus API dots and within here we can
- 4:18:43paste what we just copied of course
- 4:18:45we'll have to make little tweaks to make
- 4:18:47it fit our Expo API route setup so we
- 4:18:51won't be requiring anything we will
- 4:18:54simply be
- 4:18:55importing stripe capital letter from
- 4:19:01stripe and then we can initialize a new
- 4:19:04instance of stripe by saying con stripe
- 4:19:07is equal to new stripe to which we
- 4:19:10provide our secret key so that's going
- 4:19:12to be be process.
- 4:19:14env.
- 4:19:16stripe
- 4:19:18secretor key and you can add an
- 4:19:20exclamation mark at the end because we
- 4:19:22know it'll be there now we can remove
- 4:19:24this stripe instance and the Imports for
- 4:19:27Express and the setup for creating API
- 4:19:29routes in Expo is just a bit different
- 4:19:31so we're not immediately saying app.
- 4:19:34post rather we're saying export async
- 4:19:39function
- 4:19:41post where we get get access to a
- 4:19:43request of a type
- 4:19:46request and we can extract the body by
- 4:19:49saying const body is equal to await
- 4:19:52request. Json and from here we extract
- 4:19:55everything else we can extract things
- 4:19:58like the name the email and the amount
- 4:20:01from that body after we extract them
- 4:20:03we'll have to check if a name doesn't
- 4:20:05exist or if an email doesn't exist or if
- 4:20:08the amount doesn't exist then we can
- 4:20:11return a new re
- 4:20:13response of
- 4:20:15json.stringify where we can add an error
- 4:20:20that's going to
- 4:20:21say please enter a valid email address
- 4:20:26and we can also pass a
- 4:20:29status of 400 that has to go inside of
- 4:20:33this block right here let's make sure we
- 4:20:36are properly opening and closing
- 4:20:39everything I don't think I properly
- 4:20:41closed this function block right here
- 4:20:42here if we fix that we should be
- 4:20:46good there we go now this is immediately
- 4:20:49structured in a better way by prier and
- 4:20:51the isent and if we have all of this
- 4:20:54information about a user we can start
- 4:20:57creating our customer by saying let
- 4:20:59customer and then we can have a check
- 4:21:02whether the customer exists so we can
- 4:21:04say const does customer
- 4:21:08exist which is equal to a weight stripe
- 4:21:12do customers. list and we're going to
- 4:21:15search for a user with that specific
- 4:21:18email next if a customer does exist in
- 4:21:22that case we can say customer is equal
- 4:21:24to does customer exist. data zero if a
- 4:21:28customer exists we're going to get the
- 4:21:30actual existing customer so we can say
- 4:21:33existing customer from it we can extract
- 4:21:36the data and then that length is greater
- 4:21:38than one that's how we can check whether
- 4:21:40the customer exists
- 4:21:43else if a customer does not exist we
- 4:21:45need to create a new stripe customer by
- 4:21:47saying con new customer is equal to
- 4:21:51await stripe. customers. create and we
- 4:21:55pass a name and an email right within
- 4:21:58the else if we have a new customer we
- 4:22:01want to set the customer to be equal to
- 4:22:03that new customer now how did I know to
- 4:22:06do all of this stuff and not just create
- 4:22:09the payment intent like the doc said
- 4:22:11well even even though this General
- 4:22:14collect payment before creating a
- 4:22:16payment intent page was great it allows
- 4:22:18us to do some basic stuff there is a
- 4:22:21second documentation page this one right
- 4:22:23here that talks specifically about
- 4:22:26accepting payments in react native and
- 4:22:29if you scroll down I think we have
- 4:22:31implemented the couple of these first
- 4:22:33points but one of these is that post
- 4:22:37request about accepting a payment and
- 4:22:40here they talk about creating custom
- 4:22:42customers and then they also talk about
- 4:22:44creating a payment intent for now we
- 4:22:46have dealt with this part about creating
- 4:22:48a customer and now we can copy the rest
- 4:22:50of the stuff the link will also be down
- 4:22:53in the description where we can create a
- 4:22:55key for each customer and then create an
- 4:22:57entire payment intent and return it to
- 4:23:00the front end so let's copy this part
- 4:23:02from line eight and let's paste it right
- 4:23:05below our if for the
- 4:23:07customer you'll notice that here we
- 4:23:09create a key that we attach to a
- 4:23:12specific customer and then we create a
- 4:23:14payment intent using stripe. payment
- 4:23:17intent. create and here we need to
- 4:23:19specify the amount we're trying to
- 4:23:21charge the user in this case notice that
- 4:23:24I'm passing the amount as part of the
- 4:23:25body so what we can do is instead of
- 4:23:28using this default $10.99 price we can
- 4:23:33instead run the parse
- 4:23:36int of the amount and then multiply that
- 4:23:40by 100 because all the the payments in
- 4:23:43here are in cents so to get to the real
- 4:23:46amount we have to multiply it by 100 we
- 4:23:48can change the currency to USD for
- 4:23:51American dollars we have a customer ID
- 4:23:54and then they also enable something of
- 4:23:57automatic payment methods which is very
- 4:23:59cool and we can set that to true but in
- 4:24:02this case just to make it work we'll
- 4:24:04have to allow redirects and set to never
- 4:24:06this is something that I found works
- 4:24:08best with react native applications and
- 4:24:11finally we have to return not res. Json
- 4:24:15but rather a new response that looks
- 4:24:18like this and then we have to first
- 4:24:21stringify it so json. stringify and then
- 4:24:25we have this entire object so let's fix
- 4:24:28that there we go we're passing the
- 4:24:30payment intent in this case we can send
- 4:24:33out the entire payment intent and the
- 4:24:36entire key so I will just leave it like
- 4:24:38this payment intent the key and then the
- 4:24:41customer ID
- 4:24:43and I don't believe we have to send the
- 4:24:45publishable key back because we already
- 4:24:47have it on the front and side so I will
- 4:24:49remove this part from here and this is
- 4:24:52it this is our backend function to
- 4:24:55create a payment intent it is lengthy
- 4:24:59but it is mostly boilerplate code coming
- 4:25:01from stripe that now allows us to come
- 4:25:04back to the payment and implement it
- 4:25:07specifically it'll happen in the confirm
- 4:25:09Handler we're getting three things as
- 4:25:11the param here the payment method the
- 4:25:14should say payment method which we will
- 4:25:16not need to use so I can just rename it
- 4:25:18to an underscore that's kind of a good
- 4:25:20practice if you're not using some of the
- 4:25:22parameters and then we have to make a
- 4:25:24request to our own server and stripe was
- 4:25:27kind enough to already give us an
- 4:25:29example of how we can do that in our
- 4:25:32case we'll do it like this I'll say
- 4:25:36const I'll destructure the payment
- 4:25:39intent and the customer remember this is
- 4:25:41just what we're sending from the back
- 4:25:43end or you can call it Expo API route
- 4:25:46and say await fetch API and we're going
- 4:25:50to go to SL API in parentheses slst
- 4:25:54stripe in parentheses SLC create the
- 4:25:58route that we just created we can pass
- 4:26:00additional options to it such as a
- 4:26:03method of post headers equal to an
- 4:26:07object where the content type is set to
- 4:26:10application Json and most importantly we
- 4:26:13need to pass over the body by running
- 4:26:16json. stringify and passing in a name of
- 4:26:19the person who is buying that's going to
- 4:26:22be equal to a full name in this case
- 4:26:25which we can get from the props into the
- 4:26:28payment function so before we add this
- 4:26:31part right here let's pass some props
- 4:26:34into the payment function from the book
- 4:26:36ride first things first right at the top
- 4:26:39of the book ride we'll need to get some
- 4:26:41information about the user and we can do
- 4:26:43that easily with clerk by saying const D
- 4:26:46structure the user is equal to use user
- 4:26:51how
- 4:26:53convenient now if we go down we can pass
- 4:26:56all of the user related information to
- 4:26:58the payment so we know who is making the
- 4:27:00actual payment we can pass things like
- 4:27:04full name is equal to user question
- 4:27:07mark. full name and we can end each one
- 4:27:10of these in exclamation mark because
- 4:27:12clerk is not sure they're going to be
- 4:27:14there depending on different use cases
- 4:27:16but we know that it will indeed be there
- 4:27:18so we can tell typescript that we can do
- 4:27:21the same thing for the email by saying
- 4:27:23user question mark. email addresses
- 4:27:27z. email address exclamation mark and
- 4:27:31then we need to pass the amount of the
- 4:27:33drive so that's going to be driver
- 4:27:36details question mark. price next we
- 4:27:40need the driver ID as as well which is
- 4:27:42going to be driver details question
- 4:27:44mark. ID and finally ride time which is
- 4:27:48going to be equal to driver details
- 4:27:50question mark.
- 4:27:53time and now we can go into the payment
- 4:27:56and we can accept all of these
- 4:27:58props let's do it right away by getting
- 4:28:02the full name the email the amount the
- 4:28:07driver ID and the ride time and all of
- 4:28:11these will will be of a type payment
- 4:28:14props coming from types now that we have
- 4:28:17these we can send more information to
- 4:28:19the server by saying that the name will
- 4:28:22be equal to either the full name or
- 4:28:27email.it and we can split it by the
- 4:28:29email sign and take the first part we
- 4:28:31can then pass over the email which will
- 4:28:33be equal to email the amount which will
- 4:28:36be equal to amount and the payment
- 4:28:40method
- 4:28:42ID which is going to be equal to payment
- 4:28:45method.
- 4:28:47ID again webstorm nicely found that I
- 4:28:50have a typo it was supposed to be
- 4:28:53payment now that we have this we
- 4:28:55basically have everything we need to get
- 4:28:58a payment intent or rather to create a
- 4:29:00payment intent on the back end and pass
- 4:29:03it over back to us on the front end so
- 4:29:06right here below we can make a check and
- 4:29:09see if payment intent
- 4:29:12centore secret so are we getting any
- 4:29:15secret from here if we are then we can
- 4:29:18actually make a payment based on the
- 4:29:20payment intent that we
- 4:29:22created and to make that happen we'll
- 4:29:25have to create a second API route for
- 4:29:28payments so let's create a new file
- 4:29:31within the stripe folder and let's call
- 4:29:33it Pay Plus api. Ts and it'll start
- 4:29:39similar to create we can copy the import
- 4:29:42of stripe we can copy the part where we
- 4:29:44initialize stripe where we export an
- 4:29:46async function and where we extract some
- 4:29:49data from the body heck this part as
- 4:29:51well will be the same where we check
- 4:29:52whether we have all the necessary info
- 4:29:54so let's copy these initial lines and
- 4:29:57paste them into the payment API and make
- 4:30:00sure to properly close everything of
- 4:30:03course we'll have to make some changes
- 4:30:05instead of getting the name email and
- 4:30:07amount in this case we're getting some
- 4:30:09more payment related stuff such as theay
- 4:30:12payment uncore method _ ID the payment _
- 4:30:17intentor ID and the customer ID and now
- 4:30:21we can make a check whether all of these
- 4:30:23indeed exist and if they don't exist we
- 4:30:26can say something like missing required
- 4:30:29payment information great but if we have
- 4:30:33all of that payment information below
- 4:30:35this if we can finally create a new
- 4:30:38payment method by saying con payment
- 4:30:40method is equal to wait stripe. payment
- 4:30:45methods do attach so which payment
- 4:30:48method we want to attach well the one
- 4:30:50that we have the ID for so payment
- 4:30:53method ID and which customer is paying
- 4:30:56for that well we can provide that in the
- 4:30:58second parameter customer is equal to
- 4:31:01customer uncore ID that's going to look
- 4:31:04something like this and below it we can
- 4:31:07get the result of the payment by saying
- 4:31:09const result is equal to await stripe.
- 4:31:14payment intents do confirm to which we
- 4:31:17can pass the payment intent id and we
- 4:31:20can pass the payment method as the
- 4:31:22second option inside of curly braces
- 4:31:25where we can say payment method is of a
- 4:31:28type payment method. ID finally once we
- 4:31:31have the result we can send it over to
- 4:31:33the front end by returning a new
- 4:31:36response within which we have a Json
- 4:31:39stringify with a success that says true
- 4:31:43a message that says something like
- 4:31:45payment confirmed successfully and a
- 4:31:49result of that payment equal to result
- 4:31:52of course if something goes wrong then
- 4:31:54we have to have a catch so I'll copy
- 4:31:57this entire block of code and put it
- 4:32:00within a try and catch block so this
- 4:32:02part goes into try and in the catch
- 4:32:05where we get the
- 4:32:07error we can consal log the error and we
- 4:32:12can also return a new response that has
- 4:32:16a Json stringify within it that has the
- 4:32:19property of error equal to error and a
- 4:32:23status equal to 500 pointing to a server
- 4:32:27error so now with these two API routes
- 4:32:31first of all we have created a payment
- 4:32:33intent allowing our user to get the
- 4:32:36possibility to pay and then with the
- 4:32:39second API route we are actually
- 4:32:41allowing allwing the user to pay based
- 4:32:43on the provided payment intent so going
- 4:32:46back to the payment we can now receive
- 4:32:48that response on the front ins Side by
- 4:32:50saying const destructure the result and
- 4:32:54say is equal to await fetch API in
- 4:32:59parentheses
- 4:33:00API slash in parentheses stripe SL pay
- 4:33:06it'll have similar properties as before
- 4:33:09such as a method of post headers equal
- 4:33:13to content type of application Json and
- 4:33:17a body which will be a json. stringify
- 4:33:20to which we need to pass all of this
- 4:33:22important information from the payment
- 4:33:24intent such as the payment uncore method
- 4:33:27uncore ID equal to payment method. ID a
- 4:33:32payment uncore intentor ID equal to
- 4:33:36payment intent. ID and what else do we
- 4:33:39need I think it was is going to be let's
- 4:33:43see customer ID so we can also pass the
- 4:33:48customer ID is equal to customer because
- 4:33:52that is actually the ID and now that
- 4:33:55that is successful we can do the last
- 4:33:57thing necessary which is to create a new
- 4:34:00ride that means hooking up our driver to
- 4:34:03our Rider and making sure that the rider
- 4:34:05has actually paid and then we can create
- 4:34:08a new ongoing ride we're not going to
- 4:34:10test the payments yet yet before we can
- 4:34:13create a new ride in the database so
- 4:34:16let's do that next by checking
- 4:34:19if result. centore
- 4:34:23secret if it exists that means that
- 4:34:25everything is ready to create a ride and
- 4:34:28we have to be one scope above right here
- 4:34:30to have access to this result here we
- 4:34:33want to make a call to a new API route
- 4:34:36of ride SLC create so let me close these
- 4:34:41existing routes and let's create one
- 4:34:44route but this time that will not be
- 4:34:46just for stripe it'll be for creating
- 4:34:49our own rides we can do that by creating
- 4:34:52a new folder within our API folder
- 4:34:56that's going to be called ride within
- 4:34:58the ride we can create a new file called
- 4:35:01create plus api. DS and within here we
- 4:35:06have to connect to the neon database and
- 4:35:09create a new record in the database most
- 4:35:11this file will be just a single SQL
- 4:35:13mutation so under Snippets in the GitHub
- 4:35:16read me you can find the API ride create
- 4:35:19plus API and you can copy it from here
- 4:35:22and paste it right there you'll notice
- 4:35:25that this is just a single try and catch
- 4:35:28Block in the catch we're handling the
- 4:35:30error and in the try we are getting all
- 4:35:33the information from the body we are
- 4:35:35destructuring it we're checking if it
- 4:35:38all exists and then if it does we're
- 4:35:40simply create creating a new SQL query
- 4:35:43where we Define the fields and we Define
- 4:35:46the values that we're passing into that
- 4:35:49and finally returning this newly created
- 4:35:51ride back to us again there is about 70
- 4:35:53lines of code just because we had to
- 4:35:55write pure SQL syntax nowadays there's
- 4:35:58also tools like drizzle or Prisma so if
- 4:36:01you'd like me to see use that more often
- 4:36:03just let me know but sometimes it's good
- 4:36:05to understand how Native SQL works
- 4:36:08because these orm tools all use SQL
- 4:36:11behind the scenes
- 4:36:12and as I promised if you want to learn
- 4:36:13more about SQL and also orms like Prisma
- 4:36:17I would highly recommend checking out
- 4:36:19this course that we created which is for
- 4:36:21now completely free for you so here you
- 4:36:23can learn a bit more about different SQL
- 4:36:26mutations such as inserting data which
- 4:36:28is exactly what we're doing in this one
- 4:36:31it teaches you how you can insert
- 4:36:32different properties take a look at this
- 4:36:34it is exactly what we're doing insert
- 4:36:37into users table name and email and then
- 4:36:40you provide the values for that name and
- 4:36:42email check this out insert into rides
- 4:36:47origin address and then you provide the
- 4:36:49value for the origin address pretty
- 4:36:50straightforward but it is a bit lengthy
- 4:36:53so I decided to provide it here for you
- 4:36:55there's also going to be just one more
- 4:36:57similar file to this one one more API
- 4:36:59route where instead of creating
- 4:37:02something we'll be fetching all of these
- 4:37:04things from the rides so that's also
- 4:37:06going to be lengthy so let's just
- 4:37:08quickly create it it's going to be under
- 4:37:10ride create create a new file it'll be a
- 4:37:13dynamic route based on the ID so it's
- 4:37:15going to be square brackets ID plus API
- 4:37:19dots and you can find this file in the
- 4:37:22GitHub readme down below so you can
- 4:37:24paste it as well as you can see instead
- 4:37:26of inserting in this case we're simply
- 4:37:28selecting all of the properties that we
- 4:37:30want to get from this request that we're
- 4:37:33making great now we can go back to
- 4:37:36payment and we can call this API request
- 4:37:39that creates a new ride but before that
- 4:37:42we'll have to get away from our mock
- 4:37:44drivers and we'll have to create real
- 4:37:46drivers in the database remember right
- 4:37:49now I think in the map right we have
- 4:37:52some fake drivers right here now what we
- 4:37:54could do is manually create all of these
- 4:37:57driver accounts but we can also go to
- 4:37:59the SQL editor and we can run an SQL
- 4:38:03mutation to create all of these drivers
- 4:38:06so in this GitHub Snippets read me you
- 4:38:08can see the create driver stable SQL
- 4:38:11which you can copy and then paste right
- 4:38:14here to create a table it says connected
- 4:38:17there we go it's exceeded and then the
- 4:38:19second thing we can do is seed the
- 4:38:21database with the drivers seed is a word
- 4:38:24that is used when you want to quickly
- 4:38:26populate the database with some data so
- 4:38:29we can copy this command and paste it
- 4:38:32right here where we're going to insert
- 4:38:34some drivers right here we can click run
- 4:38:38and it has been successful we can verify
- 4:38:41if we go into tables you should be able
- 4:38:43to see a driver's table with four
- 4:38:45different drivers great so now we can
- 4:38:48remove these fake drivers and we can
- 4:38:51actually fetch real drivers from the
- 4:38:53database let's do just that we're using
- 4:38:56those drivers right here in the use
- 4:38:58effect and even I added a note right
- 4:39:01here that we need to remove that rather
- 4:39:04we have to fetch them for real and we
- 4:39:06can do that by first creating an API
- 4:39:08route that will give us back all of
- 4:39:10those drivers so let's do it by creating
- 4:39:13a new API route in the API folder called
- 4:39:18driver Plus
- 4:39:20api.
- 4:39:21Ts and this one we can write ourselves
- 4:39:24just so we can see how it is to write
- 4:39:26some simple SQL queries we can say
- 4:39:30export async function get where we can
- 4:39:35open up a try and catch
- 4:39:37block with the
- 4:39:40error if if something goes wrong we can
- 4:39:42just console. log. error and we can also
- 4:39:47return a response. Json where we send
- 4:39:51over the
- 4:39:54error which is equal to the error
- 4:39:57message in the try we can actually
- 4:39:59access the neon DP database by saying
- 4:40:01const SQL is equal to Neon coming from
- 4:40:05neon database serverless to which we
- 4:40:08need to provide our database URL or our
- 4:40:11our connection string so let's say
- 4:40:13process. env.
- 4:40:16databaseurl it is that simple and now we
- 4:40:20can say const response is equal to await
- 4:40:24SQL we write a template string and we
- 4:40:28select everything from drivers that's it
- 4:40:33give me back all the drivers and with
- 4:40:35that we can return response. Json where
- 4:40:39we pass over the data which is equal to
- 4:40:42response so now back in the map we can
- 4:40:44fetch all of those drivers let's do that
- 4:40:46right away at the top by saying const
- 4:40:49data which we can rename to
- 4:40:52drivers we also get the loading State
- 4:40:54and the error States and that is equal
- 4:40:57to use fetch we can specify the type
- 4:41:01it'll send back an array of drivers like
- 4:41:04this and here we need to specify the URL
- 4:41:08which we're calling that's going to be
- 4:41:10forward slash in parentheses API SL
- 4:41:14driver I'm going to minimize this just a
- 4:41:17bit I hope you can still see it and
- 4:41:20we're basically fetching all the drivers
- 4:41:21here so now we can make use of the
- 4:41:24loading State and the error states by
- 4:41:27adding something above the map so we can
- 4:41:29say if we are loading or if there is no
- 4:41:34user latitude or if there is no user
- 4:41:38longitude in that case we can return a
- 4:41:41view we can zoom it in and within it we
- 4:41:44can return an activity indicator with a
- 4:41:47size of small and a color equal to Hash
- 4:41:510000
- 4:41:530 it looks like that broke my screen
- 4:41:56share right here no worries we'll fix it
- 4:41:58soon we have to import The View right at
- 4:42:01the top and Below we can check if
- 4:42:03there's an error but let's make sure to
- 4:42:05properly close this I noticed that I'm
- 4:42:07missing the curly braces here if there
- 4:42:10is an error we can basically have a very
- 4:42:12similar view to this one I forgot to add
- 4:42:15the class names so let's give it a class
- 4:42:17names equal to flex justify Dash between
- 4:42:22items - Center and w- full this will
- 4:42:25basically make it appear in the middle
- 4:42:28we can duplicate this entire view if
- 4:42:30there's an error of course let's copy
- 4:42:32the return as well and only instead of
- 4:42:35the activity indicator we'll show a
- 4:42:38text that'll say error and then we can
- 4:42:41render the actual error
- 4:42:43message and we have to import text from
- 4:42:47react
- 4:42:48native great so now we have the error
- 4:42:50handling the loading handlers and we are
- 4:42:54fetching the drivers so let's put those
- 4:42:57drivers to use scrolling down we won't
- 4:43:00be setting the drivers right here we'll
- 4:43:02be setting them somewhere else in that
- 4:43:04second place will be a new use effect
- 4:43:07right below this one because now that we
- 4:43:09have the real drivers we can also create
- 4:43:12a path between the writer and the driver
- 4:43:15so we can show it on the screen you know
- 4:43:17that route the blue line from you and
- 4:43:20the other person that's exactly what
- 4:43:22we'll create basically navigation so
- 4:43:25let's create a new use effect and we can
- 4:43:28have an if statement here if markers do
- 4:43:31length is greater than zero and if
- 4:43:34destination latitude is not equal to
- 4:43:37undefined so we cannot calculate
- 4:43:39something if we don't have a destination
- 4:43:41latitude and if destination longitude as
- 4:43:45well is not equal to
- 4:43:47undefined or we can just say if it
- 4:43:49exists right so if markers that length
- 4:43:53and if destination latitude and
- 4:43:55destination longitude in that case we
- 4:43:58can call a special utility function
- 4:44:00called calculate driver times that's
- 4:44:04going to look a bit like this and to it
- 4:44:06we have to pass a couple of prompts we
- 4:44:09need to pass all of the markers which
- 4:44:11want to show on the screen which are
- 4:44:12basically the cars the user's current
- 4:44:15longitude the user's current latitude
- 4:44:19and the destination latitude as well as
- 4:44:21a destination
- 4:44:24longitude that function is an Asing
- 4:44:27function so we can call a that then on
- 4:44:29it which will give us access to all of
- 4:44:31the drivers and now once we get that we
- 4:44:34can set
- 4:44:36drivers to be drivers as marker data
- 4:44:41array so this is to make sure that the
- 4:44:42map understands that the drivers are
- 4:44:44indeed appearing on the
- 4:44:46screen and we can recall this function
- 4:44:49whenever the markers change when the
- 4:44:51destination latitude changes or when the
- 4:44:54destination logitude changes as well so
- 4:44:57now let's give it a shot I will close
- 4:44:59this sheet and I'll say that I want to
- 4:45:02go let's say somewhere near in San
- 4:45:05Francisco and first of all don't forget
- 4:45:07when you make a lot of changes reload
- 4:45:09the entire application
- 4:45:11so I'll stop it from running and I'll
- 4:45:14rerun it one more time with the Das C
- 4:45:16Tab and then press R to reload the
- 4:45:19entire
- 4:45:21application there we go oh this clerk
- 4:45:24warning just reminded me that we need to
- 4:45:25implement the O still so that's
- 4:45:27something that we'll do very soon but
- 4:45:29now you can see different drivers on the
- 4:45:31screen as you were able to see before
- 4:45:33but now if we go let's say we are in the
- 4:45:36lower Pacific Heights right now if we
- 4:45:38want to go to this nice park we can go
- 4:45:41to Scott Street so let's do
- 4:45:44Scott Street and that's in San
- 4:45:48Francisco you can see that we have San
- 4:45:51Francisco and then Scott Street and we
- 4:45:53can click find now and this will open up
- 4:45:56the different drivers we can select one
- 4:45:58of those drivers and these now are real
- 4:46:01drivers you can see that they changed
- 4:46:03since the last time that we had the
- 4:46:04drivers now they're coming from the
- 4:46:06database we might need to do some work
- 4:46:08to properly show the actual distance in
- 4:46:11minutes so let me do that I think this
- 4:46:14is in the driver card where we have the
- 4:46:17minutes right here let's see if I can
- 4:46:19find it this is the
- 4:46:22price and right next to the price we
- 4:46:25have the time we can use the parse
- 4:46:27integer I believe to make this work and
- 4:46:30now we can see four minutes 3 minutes
- 4:46:32and more that's good and it looks like
- 4:46:35the time needs to be a string so I can
- 4:46:37easily convert this into a string by
- 4:46:40maing it into a template string like
- 4:46:44this great and it still works so now we
- 4:46:48can choose a different driver and you
- 4:46:50can see that on the screen the driver
- 4:46:52that you choose becomes green so you can
- 4:46:54see how they're changing colors right
- 4:46:56here so now if I choose let's go with
- 4:47:00David he seems to be one of the cheapest
- 4:47:02ones and the closest to us oh no no way
- 4:47:05looks like Michael drives a nice yellow
- 4:47:07car $2 and 2 minutes away let's go with
- 4:47:10that one and I'll click select now we
- 4:47:14can see all the information about
- 4:47:15Michael looks like we need to do the
- 4:47:17same thing for the time so let me copy
- 4:47:21this entire thing go to the right
- 4:47:23information so that is I believe under
- 4:47:26pickup
- 4:47:27time in the book ride yes and we just
- 4:47:30need to wrap this properly so it's
- 4:47:32driver details. time let's add it
- 4:47:35here driver
- 4:47:39details. time
- 4:47:42and we can remove this mock
- 4:47:44number let's make sure to close it
- 4:47:47properly and save it and now it says 4
- 4:47:49minutes nice but if I Collapse it I'm
- 4:47:52still not seeing the path from my
- 4:47:54location to where I want to go so let's
- 4:47:58head over to the map and let's look into
- 4:48:00the function that has something to do
- 4:48:02with the drivers this one is setting the
- 4:48:05driver's car locations and I believe we
- 4:48:09have to add some more dependencies to it
- 4:48:11you can see even our webstorm is
- 4:48:12complaining that it needs further
- 4:48:15dependencies those are going to be the
- 4:48:17user
- 4:48:18latitude and the user longitude so
- 4:48:21whenever those change we can also recall
- 4:48:24this use effect but that's not the
- 4:48:26problem the real solution lies right
- 4:48:29here in the map jsx currently we have
- 4:48:32just the map view and we have the
- 4:48:34markers but we have to make a connection
- 4:48:37from our current initial user location
- 4:48:41to the destination location so right
- 4:48:44within the map below these three
- 4:48:47parentheses we can check whether we have
- 4:48:50access to the destination latitude and
- 4:48:52destination
- 4:48:54longitude and if we have then we can
- 4:48:57return a react fragment or should I say
- 4:49:00react native fragment that'll show
- 4:49:03another marker which is going to be the
- 4:49:05marker for the destination let's give it
- 4:49:08a key so we can differentiate it from
- 4:49:10the others
- 4:49:11such as destination let's give it some
- 4:49:13coordinates to show it on the map we
- 4:49:16need to pass it the latitude which is
- 4:49:19going to be equal to you can guess it
- 4:49:21destination
- 4:49:22latitude and the longitude which is
- 4:49:25going to be equal to guess it
- 4:49:28destination longitude we can also pass
- 4:49:31it a title which is going to be equal to
- 4:49:34destination so let's do just that
- 4:49:38destination and we can give it an image
- 4:49:41which is going to be a typical
- 4:49:43icons.
- 4:49:45pin and now check this out I can
- 4:49:48actually see that I wanted to go to
- 4:49:50Scott Street and would you look at that
- 4:49:53there's some trees there that seems like
- 4:49:54a nice place to take a walk around and
- 4:49:57we can see the pin on there on your
- 4:49:59screen you should also be able to see a
- 4:50:01pin near your exact location so you can
- 4:50:04see pin from and to but now let's create
- 4:50:07directions from you to the PIN we can do
- 4:50:11that by installing a new package so
- 4:50:13let's open up a new terminal and say mpm
- 4:50:17install
- 4:50:19react-native-maps D directions and
- 4:50:22that's going to allow us to below the
- 4:50:24marker put this new map view directions
- 4:50:29we of course need to import it at the
- 4:50:31top by saying
- 4:50:34import map view
- 4:50:36directions from react native Maps there
- 4:50:40directions that is great and now we need
- 4:50:43to give it additional information so it
- 4:50:45knows what to show we of course have to
- 4:50:48give it An Origin which is going to be
- 4:50:50our user's latitude that's going to be
- 4:50:53user
- 4:50:54latitude and we have to give it
- 4:50:56longitude which is going to be our
- 4:50:57current user's
- 4:51:00longitude next we have to give it the
- 4:51:02destination which is going to be similar
- 4:51:05to what we have here we can copy the
- 4:51:07coordinates of the pin where we want to
- 4:51:09go latitude is destination latitude and
- 4:51:12the longitude is the destination
- 4:51:14longitude to it we need to provide the
- 4:51:16API key and that key is coming from envs
- 4:51:19so we can say process. EnV Dot and let's
- 4:51:23check the exact name in our
- 4:51:25envs it's going to be Expo public Google
- 4:51:29API key so we can copy it paste it here
- 4:51:33let's make sure to properly close this
- 4:51:35destination and finally below the API
- 4:51:38key we can also choose our stroke color
- 4:51:42so the color of the path that can be a
- 4:51:45bluish color of something like hash 028
- 4:51:496
- 4:51:50FF and a stroke width of about two if we
- 4:51:55save this we have to make sure that
- 4:51:57we're properly enclosing it I think we
- 4:51:59have two extra ending braces and we're
- 4:52:02missing an equal sign right here and
- 4:52:04would you look at that we now have a
- 4:52:07complete path through the streets from
- 4:52:10our current location on the map to the
- 4:52:14destination location how cool is that if
- 4:52:18you want to you can change the color and
- 4:52:20you can make it a bit wider that's
- 4:52:22totally okay too there we go this is
- 4:52:24perfect and now we can even see maybe we
- 4:52:27can go for this driver right here for
- 4:52:28David instead of Michael so let's go
- 4:52:30back let's choose David there we go that
- 4:52:34Rider is now green and we can select the
- 4:52:37ride and see where we want to go from
- 4:52:40our our location to the destination
- 4:52:42location great now where were we I think
- 4:52:46we were on the payments where we want to
- 4:52:48confirm the ride and just before we
- 4:52:50actually pay it we wanted to create a
- 4:52:53ride which we now actually can do
- 4:52:55because we have real drivers in the
- 4:52:57database we have created a real writer
- 4:53:00when we created our account so the only
- 4:53:02thing we have to do is to create a
- 4:53:04server action that will connect it to
- 4:53:07and book us a ride so let's head over to
- 4:53:10to our API calls and check out our ride
- 4:53:14create this is the one where we're
- 4:53:16simply getting all the fields we
- 4:53:18collected so far and then inserting it
- 4:53:20into the database we can call it from
- 4:53:22the front end now or should I say from
- 4:53:24our device screen we can do that by
- 4:53:27saying await fetch
- 4:53:29API to which we can pass the URL of
- 4:53:33Slash in parentheses
- 4:53:36API SL rde SLC create
- 4:53:41as additional options we can pass a
- 4:53:44method equal to
- 4:53:47post we can pass
- 4:53:49headers equal to content type
- 4:53:52application Json and we can pass the
- 4:53:55body now keep in mind you know that in
- 4:53:58the actual API request we are getting a
- 4:54:00lot of things through the body so we
- 4:54:02have to do the same thing here json.
- 4:54:07stringify within an object and now we
- 4:54:09have to pass all of the info we have
- 4:54:12collected so far the user info the
- 4:54:14destination info everything so let's say
- 4:54:18origin address meaning where we're going
- 4:54:21from is going to be equal to user
- 4:54:24address and this user address we can get
- 4:54:26from the location store so right at the
- 4:54:29top we can get all of this great
- 4:54:31information from the location store by
- 4:54:33saying const something is equal to use
- 4:54:37location
- 4:54:38store and right here we we can get the
- 4:54:41user address we can get the user
- 4:54:44longitude user
- 4:54:47latitude distination latitude
- 4:54:50destination address and destination
- 4:54:53longitude now in an Ideal World we
- 4:54:56wouldn't need to destructure all of
- 4:54:57these properties and then now again form
- 4:54:59them properly ideally we would be using
- 4:55:02the same exact names on both the front
- 4:55:05end and the back end but sometimes it's
- 4:55:07not like that sometimes stripe uses
- 4:55:10underscores or Kebab case and you're
- 4:55:12using camel case so it's always better
- 4:55:14to destructure them and make sure that
- 4:55:16you're passing the exact right names of
- 4:55:19the variables on the back end right here
- 4:55:21if we go to create ride or create ride
- 4:55:24API this one right here you can notice
- 4:55:27that we are inserting origin unor
- 4:55:29address and not origin address with a
- 4:55:32capital A right here so for that reason
- 4:55:35we have to properly spell it here as
- 4:55:36well origin address is equal to user
- 4:55:40address address let's continue with
- 4:55:41passing other properties as well such as
- 4:55:44the destination address but make sure to
- 4:55:47use the snake case right here is equal
- 4:55:50to destination address in camel case we
- 4:55:53can get the origin
- 4:55:55latitude equal to user latitude and
- 4:55:59origin longitude equal to user longitude
- 4:56:03we can get the destination latitude
- 4:56:05equal to destination
- 4:56:08latitude make sure to put that in snake
- 4:56:12case as well snake case is the
- 4:56:14recommended case for postgress databases
- 4:56:17that's why we're doing this and we can
- 4:56:19do destination longitude equal to
- 4:56:21destination longitude we can get the
- 4:56:23rore time which is equal to right time.
- 4:56:28to fixed Z we can do faircore
- 4:56:33price to be equal to parse int we take
- 4:56:36the amount and we multiply it by 100 to
- 4:56:40get into sense as that's how strip
- 4:56:42processes payments we can set the
- 4:56:44payment status to be equal to paid
- 4:56:47because this is after we actually
- 4:56:49confirm that the payment went through by
- 4:56:51stripe we need to know which driver
- 4:56:53processed the payment and we need to
- 4:56:55know the user ID that accepted that ride
- 4:56:59and this user ID is coming from use o by
- 4:57:02clerk so we can get it right here at the
- 4:57:04top by destructuring the user ID coming
- 4:57:08from use o from clerk great so now we
- 4:57:13have everything we need that we're
- 4:57:14passing to create a ride and finally we
- 4:57:17can call the call back of the successful
- 4:57:20intent creation so that's intent
- 4:57:22creation call back to which we need to
- 4:57:24pass our client secret which is equal to
- 4:57:27result. client secret you can see that
- 4:57:31stripe uses this snake case as well
- 4:57:34finally this entire time we have been
- 4:57:36within the confirm Handler which is only
- 4:57:39one small part of the intent
- 4:57:43configuration right here as you can see
- 4:57:45now right below the intent configuration
- 4:57:48we can enter the return URL which is
- 4:57:52going to be my app
- 4:57:55Colin book- rde so this is where we want
- 4:57:59to go back to after we complete the
- 4:58:01payment and if there's an error we can
- 4:58:03just
- 4:58:05console.log the error now let's see if
- 4:58:07we have some warnings or errors
- 4:58:09remaining we have one right here with
- 4:58:11the client secret I think this is
- 4:58:13something that we copied way back from
- 4:58:15stripe but we don't need anymore as we
- 4:58:18have implemented it right here above
- 4:58:20where we're basically passing the client
- 4:58:22secret into the intent creation callback
- 4:58:25so we can remove this part right here do
- 4:58:27we have any other warnings or errors we
- 4:58:30can see that the confirm Handler is
- 4:58:32complaining a bit about the types that
- 4:58:34we're passing into it it's saying that
- 4:58:37the payment method shouldn't have a type
- 4:58:39any it seems that we don't have any
- 4:58:42types for the payment method intent
- 4:58:44creation call back and that's why it's
- 4:58:45complaining right here those can be
- 4:58:48easily fixed if you collapse the
- 4:58:50function copy the entire function block
- 4:58:53and paste it right here where it's being
- 4:58:56used like
- 4:58:58this and then you can remove this
- 4:59:01original function because now we're just
- 4:59:03using it automatically within stripe and
- 4:59:06a pretty cool thing is now that it is
- 4:59:08within the intent payment sheet it
- 4:59:10actually knows everything about the
- 4:59:12payment method intent creation call back
- 4:59:15as it infers it from the types above
- 4:59:18that's cool so with that in mind our
- 4:59:20initialized payment sheet is finally
- 4:59:23done with the confirm Handler the return
- 4:59:25URL everything the whole deal and it
- 4:59:29took a bit more time and that's because
- 4:59:31at the same time we were setting up our
- 4:59:33own code functionality such as getting
- 4:59:35the Riders the drivers the ride creation
- 4:59:38and so much more
- 4:59:40but now all of that should be done and
- 4:59:43before we go ahead and test it out just
- 4:59:45bear with me there is one more thing we
- 4:59:47have to do and that is create a success
- 4:59:50model okay remember we just have this
- 4:59:54one unused variable just a single one I
- 4:59:57can delete these ones just so we don't
- 4:59:59have warnings but there's just a single
- 5:00:01unused variable called success we
- 5:00:04wouldn't want to leave that success to
- 5:00:06hang there on its own right so we can
- 5:00:08use it within the mold mod if we're
- 5:00:11successful let's reward our great
- 5:00:14work by creating a react native
- 5:00:18modal and say is visible only if success
- 5:00:24how
- 5:00:25convenient on backdrop press so once we
- 5:00:29exit out of it on backdrop press so once
- 5:00:33we click outside of it we simply want to
- 5:00:36set the success to false so set success
- 5:00:41to false which will hide the model and
- 5:00:44then we can go on with our day and book
- 5:00:46some additional rides or track our
- 5:00:48existing ride so what are we going to
- 5:00:50show within this react native model it
- 5:00:53can be a
- 5:00:54view with a class name equal to flex
- 5:01:00flex-all items Das Center justify Dash
- 5:01:04center background of white padding of
- 5:01:07seven and rounded Das to to excel within
- 5:01:11it we can render a check image so let's
- 5:01:13get the image from react
- 5:01:16native with a source equal to
- 5:01:20images.
- 5:01:22check and a class name of w of
- 5:01:2728 h of 28 and a margin top of five now
- 5:01:31how can we show this success model right
- 5:01:34here well we can show it by turning the
- 5:01:37success to True by default
- 5:01:40just for the time being and closing this
- 5:01:43payment sheet model and going all the
- 5:01:45way back to somewhere
- 5:01:48else so let's do just that and I think
- 5:01:51this is our model but something seems to
- 5:01:53be breaking at the moment oh maybe
- 5:01:56because we forgot to import the view
- 5:01:57from react native once we bring it back
- 5:02:00we'll have to one more time test it out
- 5:02:03oh there we go you can see this even on
- 5:02:05the home screen we can see the last path
- 5:02:07that we drawn out this would be a huge
- 5:02:10path from California all the way to
- 5:02:13Tennessee I recently saw a YouTube video
- 5:02:16where a guy ordered the longest possible
- 5:02:19Uber ride it was panning across multiple
- 5:02:22European countries I think pretty cool
- 5:02:25so let's go over and select a new
- 5:02:28location maybe we want to go to New
- 5:02:32York and I'll select a driver and a ride
- 5:02:37and there we go now we can see this
- 5:02:39small success ESS thing below the image
- 5:02:42let's render a piece of text and make
- 5:02:44sure to import it from react native it
- 5:02:47can say something like booking placed
- 5:02:50successfully or maybe something simpler
- 5:02:52like ride booked we can give it a class
- 5:02:55name of text- 2XL text- Center font D
- 5:03:02Jakarta bold with a margin top of five
- 5:03:05to divide it a bit from the Icon below
- 5:03:07it we can render another piece of text
- 5:03:11that will have a class
- 5:03:13name equal to text-
- 5:03:16MD text- General
- 5:03:19D200 font Das Jakarta medium text-
- 5:03:25Center and margin top of three and it
- 5:03:28can say something like thank you for
- 5:03:31your booking your reservation has been
- 5:03:35placed please proceed with your trip
- 5:03:40there we go that's looking nice and
- 5:03:43below it we can render a custom button
- 5:03:46this button will have a title of back
- 5:03:49home and on press want to have a call
- 5:03:52back
- 5:03:53function that sets the success to false
- 5:03:57once
- 5:03:58again as well as uses the router. push
- 5:04:02okay so I'm going to put this in
- 5:04:04multiple lines so that after we set the
- 5:04:06success we can also use the router
- 5:04:10from Expo router. push and push to slash
- 5:04:14root SL tabs
- 5:04:18slome we haven't been there in quite
- 5:04:21some time there we go and we want to
- 5:04:23style it a bit by giving it a class name
- 5:04:26equal to margin top of
- 5:04:28five
- 5:04:30beautiful what do you say that we
- 5:04:32manually turn the success back over to
- 5:04:35false and try to book an actual ride for
- 5:04:38the first time in this entire
- 5:04:42course let's do it I'll click confirm
- 5:04:45ride from San Francisco to New York for
- 5:04:49$11,200 and 42 hours in pickup time and
- 5:04:54I'll click confirm ride there's one
- 5:04:56mistake that I can notice here and that
- 5:04:58is that the stripe button still says 10
- 5:05:01bucks you definitely wouldn't want to
- 5:05:02make this mistake in your relab because
- 5:05:05people would soon enough make use of it
- 5:05:08so we have to figure out where we're
- 5:05:10passing the amount to stripe and it is
- 5:05:13right here in the intent configuration
- 5:05:15so that is the last part that is
- 5:05:17remaining for us to do we can change the
- 5:05:20merchant display name to something like
- 5:05:24ride
- 5:05:26Incorporated the amount will be set to
- 5:05:29parse
- 5:05:30int amount times 100 to get to cents and
- 5:05:35the currency will be USD if I save this
- 5:05:39and click close the sheet and reopen
- 5:05:41it you can see that now the price is
- 5:05:44correct so you can enter your card
- 5:05:47number for stripe test mode it is
- 5:05:51424242 and you can keep typing that
- 5:05:53until the end you can do the same thing
- 5:05:56for the months and
- 5:05:58years and the CVC but make sure that
- 5:06:01they're valid months and years and you
- 5:06:04can now click pay don't worry no money
- 5:06:06will be taken from your accounts you
- 5:06:08haven't connected your own details with
- 5:06:10this this is just test info so I'll
- 5:06:13click
- 5:06:14pay it says
- 5:06:17processing and it seems to have went
- 5:06:19through ride booked back
- 5:06:22home this is amazing we can track her
- 5:06:25location and even though these recent
- 5:06:28rides are fake now our next step will be
- 5:06:30to add a real recent ride right here so
- 5:06:33we can check it out and see how that is
- 5:06:35going great this means that the main
- 5:06:38primary flow of our Uber application has
- 5:06:42been completed a user can create their
- 5:06:44account search for a location where they
- 5:06:46want to go choose their driver book a
- 5:06:49ride and make a payment beautiful work
- 5:06:54and if you came to this part of the
- 5:06:55video leave a comment down below and
- 5:06:58tell me I'm here I completed the main
- 5:07:01flow not many will get there so great
- 5:07:04job now that we have that out of the way
- 5:07:06as I said we can focus on replacing the
- 5:07:09mock recent rides with the real ones by
- 5:07:11fetching them from the database and then
- 5:07:13after that we'll quickly fix the Google
- 5:07:15o off and then we can focus on the rest
- 5:07:18of these Pages once again great work I'm
- 5:07:21super proud of you to remove our mock
- 5:07:24rides and instead of them use the real
- 5:07:26ones we can head over to our homepage we
- 5:07:29can scroll a bit up and right here you
- 5:07:32can see that we have fake recent rides
- 5:07:35instead of those what do you say that we
- 5:07:36fetch the real ones but to make that
- 5:07:39happen we have to tap into this ride ID
- 5:07:42functionality which is going to fetch
- 5:07:44the specific rides for our own user
- 5:07:47account and bring us back all the
- 5:07:50details so let's go to the home and
- 5:07:53let's say const data which we can rename
- 5:07:56to recent rides we can also get the
- 5:07:59loading from there and that's going to
- 5:08:01be equal to use fetch to the URL SL API
- 5:08:06inside of parenthesis forward SL rde
- 5:08:09forward slash and then we have to do a
- 5:08:11dynamic template string of user question
- 5:08:15mark. ID first let's turn this string
- 5:08:18into a template string there we go and
- 5:08:20now let's actually get the user from the
- 5:08:22use user and we can remove this fake
- 5:08:24loading at the top now it says no recent
- 5:08:28rides as you can see right here and I
- 5:08:30think I know why we created the tables
- 5:08:32for drivers and users but before
- 5:08:34creating a ride we didn't create a table
- 5:08:37for the rides so right here under
- 5:08:39Snippets you have the create rides table
- 5:08:42SQL query which we can execute in our
- 5:08:45SQL editor and
- 5:08:48run there we go it successfully created
- 5:08:51the table and since the table wasn't
- 5:08:53created before right now it doesn't
- 5:08:55exist so let's go through the entire
- 5:08:57application flow one more time and see
- 5:08:59if the ride will get created okay I came
- 5:09:02to the end screen in the flow I can
- 5:09:04enter my credit card details and click
- 5:09:07pay it's processing
- 5:09:10it's successful and if I go back home we
- 5:09:13can now see one recent rides from San
- 5:09:15Francisco to Scranton and it even gives
- 5:09:18us a little screenshot of the location
- 5:09:20where we're going to great so now we can
- 5:09:23remove this recent rise from here as
- 5:09:25we're no longer using them and now all
- 5:09:28of the data in our application is real
- 5:09:31what we can do next is press the log out
- 5:09:33button at the top right we haven't seen
- 5:09:34our onboarding screens in quite some
- 5:09:36time and I'm pressing it but it doesn't
- 5:09:39seem to be working let's see what's up
- 5:09:41with that button that is in a place
- 5:09:44where it says welcome and then we have
- 5:09:47the name so that's going to be right
- 5:09:49here in a stack screen under home and
- 5:09:52here we're handling the sign out
- 5:09:54functionality where you can see that
- 5:09:57it's completely empty so we have to
- 5:09:59implement it the only thing that it'll
- 5:10:01do is it'll call the sign out function
- 5:10:05which is going to come from use o from
- 5:10:07clerk so we can say const sign out is
- 5:10:11equal to use o coming from Clerk and
- 5:10:15then we can call it and we can use the
- 5:10:18router. replace to go to for slash off
- 5:10:22in parentheses slash sign in now let's
- 5:10:26try to click the button one more time
- 5:10:29and this time we are redirected to the
- 5:10:31sign-in page now if I click login with
- 5:10:34Google nothing will happen same thing if
- 5:10:36we go to sign up it's not doing anything
- 5:10:39that's because we have implemented only
- 5:10:41the email authentication and now we have
- 5:10:43to do oath clerk makes that super simple
- 5:10:47with their documentation page on
- 5:10:48building a custom flow for
- 5:10:50authenticating with o o connections so
- 5:10:53you can just search the docs for this
- 5:10:55page it's under custom flows allo
- 5:10:57connections and then you need to switch
- 5:10:59it from nextjs to Expo we can skip this
- 5:11:03Expo linking part skip the browser part
- 5:11:05as well and the only thing we need is
- 5:11:08this start oath flow with the O strategy
- 5:11:12and then the onpress functionality this
- 5:11:14part right here so let's copy that go
- 5:11:17back to the code to our o component
- 5:11:21where we have our custom button and we
- 5:11:23can paste what we just copied I'll paste
- 5:11:25it over this
- 5:11:27function I'll rename the onpress to
- 5:11:30handle
- 5:11:32Google sign
- 5:11:34in and I will override our on press on
- 5:11:37the button click to handle Google Google
- 5:11:39sign in and we can just slightly modify
- 5:11:41this first of all let's import use oo
- 5:11:45from clerk clerk Expo with a strategy of
- 5:11:48Google
- 5:11:49oo next import use call back from react
- 5:11:54after that we can start this o flow and
- 5:11:57we can slightly modify this part right
- 5:11:59here so I'll close it just so we have a
- 5:12:01clean slate and I'll say con result is
- 5:12:05equal to a weight so we have to make
- 5:12:08this function a sync
- 5:12:10and Google oo like this to which we then
- 5:12:15pass the start oo flow function but the
- 5:12:19question is where is this Google ooth
- 5:12:21coming from this Google ooth will be a
- 5:12:24utility function which we can create
- 5:12:26it'll be under lib o and then here we
- 5:12:30have the token cache but now we'll
- 5:12:32create an additional function export
- 5:12:35const Google o o which is going to be an
- 5:12:40async function that accepts the start oo
- 5:12:44flow of a type any for now and we can
- 5:12:48open up a new try and catch Block in the
- 5:12:51catch we of course have the error and in
- 5:12:53the try we'll copy this part about
- 5:12:56linking so here we want to extract this
- 5:12:58linking part and this if and else that
- 5:13:00we removed previously and we can paste
- 5:13:02it right here that's going to check
- 5:13:04whether we have a created session ID and
- 5:13:07whether we can sign up up and we can
- 5:13:10also make a user
- 5:13:12active for that we do need the linking
- 5:13:15so remember what they say right here we
- 5:13:17need to install Expo linking this will
- 5:13:19allow us to link our application to the
- 5:13:22Google signin model that pops up and
- 5:13:24then it allows users to go back to your
- 5:13:25own application so let's run mpm install
- 5:13:29Expo linking and let's make sure to
- 5:13:31import it at the top by saying import
- 5:13:33everything as linking from Expo linking
- 5:13:38and then we're creating creting a new
- 5:13:39URL which we want to redirect to it is
- 5:13:43SL root in
- 5:13:45parentheses SL tabs slome next we're
- 5:13:50checking if it's a signup or a sign in
- 5:13:54rather has the user created an account
- 5:13:56before if they have created an account
- 5:13:59then we're doing sign in else we're
- 5:14:01doing sign up so everything within this
- 5:14:04if will be called both on the sign in
- 5:14:07and the sign up so let me show you what
- 5:14:10we can do we can say if set active
- 5:14:13exists then we can await set active and
- 5:14:17this is basically adding the user
- 5:14:19session but now only if it's sign up so
- 5:14:23if sign up. created user ID then we want
- 5:14:29to also create a database user so we can
- 5:14:31say await fetch
- 5:14:34API with a URL of forward slash in
- 5:14:38parentheses API SL
- 5:14:41user the method will be set to post and
- 5:14:45the body will be json. stringify where
- 5:14:48we can pass a name which is a template
- 5:14:50string of sign up. first name as well as
- 5:14:56sign up. last name let's fix this typo
- 5:15:00we can also pass the email equal to sign
- 5:15:02up. email and we can pass the clerk ID
- 5:15:05equal to signup do created user us ID
- 5:15:10and this creates a user in the database
- 5:15:12we want to go below this two sets of
- 5:15:15double parentheses and Below one more to
- 5:15:18return an object that's going to say
- 5:15:20success is true we can also pass a code
- 5:15:24of
- 5:15:25success and pass a message of you have
- 5:15:29successfully
- 5:15:31authenticated outside of all of these
- 5:15:34braces we can return success to false
- 5:15:38because if we reach this point something
- 5:15:40is not good would a message equal to an
- 5:15:44error occurred finally in the catch
- 5:15:47consol log the error and return success
- 5:15:51false and a message that an error has
- 5:15:54occurred so I can paste this and maybe
- 5:15:57this time we can just do
- 5:16:00error question mark. errors zero
- 5:16:04question mark. long
- 5:16:06message this will give us the full error
- 5:16:09information and let's make the error of
- 5:16:12a type any right
- 5:16:14here great so now we are authenticating
- 5:16:16users using Google oo and we're creating
- 5:16:19an account when they sign up so let's
- 5:16:21import this Google oo from lib o and
- 5:16:24we're getting the result if the result.
- 5:16:27code is triple equal to session unor
- 5:16:30exists then we can alert coming from
- 5:16:34react native. alert success but add a
- 5:16:39message of session exists
- 5:16:43redirecting to homepage and of course
- 5:16:46we'll have to do a router. push slash in
- 5:16:50parentheses root slash in parentheses
- 5:16:53tabs slome outside of that if we can
- 5:16:57check if result. success if that is the
- 5:17:01case we can say success else we can say
- 5:17:04error and that can be within the alert
- 5:17:06so we don't actually need an if so
- 5:17:08alert. alert and then we just show that
- 5:17:11title and as the second parameter we
- 5:17:13render the result. message if we catch
- 5:17:18something then we can just do a console.
- 5:17:20error
- 5:17:22great I think this is it we already have
- 5:17:25the UI now we implemented the logic and
- 5:17:27we can give it a shot let's go through
- 5:17:29the
- 5:17:30onboarding and let's click login with
- 5:17:33Google I noticed a typo there that was
- 5:17:36supposed to be with right here
- 5:17:39there we
- 5:17:40go and let me click the
- 5:17:44button Expo wants to use google.com to
- 5:17:46sign in yes let's allow it I chose my
- 5:17:51account and I'll click continue and it
- 5:17:54didn't redirect I think I know why I
- 5:17:57misspelled exists right here so session
- 5:18:00exists okay I can fix this typon success
- 5:18:04as well and if we go back to off in the
- 5:18:08return right here so this is at the
- 5:18:10bottom of our Google all OD function we
- 5:18:13also need to pass the code and the code
- 5:18:16will be success if you're successful or
- 5:18:19here at the bottom in the catch the code
- 5:18:21will be equal to error. code now this
- 5:18:26code will sometimes correspond to
- 5:18:30session uncore exists even though it's
- 5:18:32not really an error I mean technically
- 5:18:34it is because we're trying to sign up to
- 5:18:37an account that exists but still in that
- 5:18:39case we're going to say success
- 5:18:41redirecting to homepage and one more
- 5:18:44thing I noticed here in oth instead of
- 5:18:46saying email address I just used email
- 5:18:49right here which is wrong so this also
- 5:18:51could have broken the application so if
- 5:18:53we fix that we can give it one more shot
- 5:18:56I'll click login with Google continue
- 5:18:58next I'll say continue one more
- 5:19:02time and we still didn't get redirected
- 5:19:05but if I open up the terminal I can see
- 5:19:07a conso log that I added before and if I
- 5:19:10press R for reload you can see that we
- 5:19:12are within our application and now it
- 5:19:14says welcome Adrien which means that
- 5:19:16we're successfully logged in with our
- 5:19:18real account and we have one recent ride
- 5:19:21beautiful I'm still not sure why this oo
- 5:19:24is not redirecting this is definitely
- 5:19:26something we need to come back to later
- 5:19:28on but for now let's quickly implement
- 5:19:30the all rides screen as it's going to be
- 5:19:33super simple it's just going to be a
- 5:19:35collection of recent rides and we're
- 5:19:38showing that already on the home so it's
- 5:19:40going to be super simple to show it here
- 5:19:41as well we can head over to our rides
- 5:19:44page which is right here Under tabs and
- 5:19:47within it we can render a flat list
- 5:19:51similar to the one that we have in the
- 5:19:52home so let's quickly go to the home
- 5:19:55let's find our flat list and let's copy
- 5:19:59the entire thing just until the end of
- 5:20:01the flat list and we can put it right
- 5:20:04here within the safe area view make sure
- 5:20:06to import flat list right here from from
- 5:20:08react native and save it of course
- 5:20:11there's going to be some fixes that we
- 5:20:12have to do to make it work for example
- 5:20:14we have to also fetch the recent rides
- 5:20:17same as we're doing in the home so right
- 5:20:19here at the top here we're fetching the
- 5:20:21recent rides and here we're fetching the
- 5:20:23user so we can copy those two things and
- 5:20:26add them to the rides use user is coming
- 5:20:29from clerk Expo and this is pretty cool
- 5:20:32when I copy things from the other file
- 5:20:34webstorm actually copies the Imports for
- 5:20:36me which is amazing right now if we go
- 5:20:39to all rides it kind of breaks and
- 5:20:41that's because we don't need all this
- 5:20:43data here so let's clean it up instead
- 5:20:46of slicing the recent rides we can show
- 5:20:48all the recent rides next under list
- 5:20:51empty component we can more or less
- 5:20:53leave it the same and under the header
- 5:20:55it's going to be much simpler than what
- 5:20:57we have here we don't have to have the
- 5:20:58sign out button nor the Google text
- 5:21:01input so we can basically remove
- 5:21:03everything from here and just keep one
- 5:21:06single piece of text that's going to say
- 5:21:09all rides and we can give it a class
- 5:21:11name equal to text- 2XL font D jaarda
- 5:21:16bold and we can save it and right here
- 5:21:19before the use fetch what we're
- 5:21:20expecting to get back is an array of
- 5:21:23rides which are coming from types so we
- 5:21:26can Define the ride right here that way
- 5:21:28flatlist knows what it is accepting and
- 5:21:31believe it or not since we're reusing a
- 5:21:33lot of the components we don't need
- 5:21:35these Imports too and it was super simp
- 5:21:38simple to just recreate this all rides
- 5:21:41list right now it is just one but once
- 5:21:44we book some more they'll all be shown
- 5:21:46here we can also add a margin y of five
- 5:21:50right here to divide it a bit from top
- 5:21:52and bottom beautiful and I couldn't
- 5:21:54proceed further without fixing this
- 5:21:56redirect on the Google button so while I
- 5:21:59took a bit of a break from recording I
- 5:22:01went ahead and tested it out a bit
- 5:22:03further and I think I've came to a
- 5:22:06conclusion first of all we can go to the
- 5:22:08Google text input and for some reason
- 5:22:12Android devices have a problem when a
- 5:22:14font weight is typed in as a number so I
- 5:22:18went ahead and just wrapped it in a
- 5:22:20string not a big deal but just something
- 5:22:22that needed to be done for the Android
- 5:22:24devices this won't fix the redirect on
- 5:22:27its own but now we can head over to o o
- 5:22:31right here and so far we've been only
- 5:22:34redirecting if a session already exists
- 5:22:37but here I can add an or and say if
- 5:22:40result. code is triple equal to success
- 5:22:44in that case we also want to redirect we
- 5:22:48don't need to show the success message
- 5:22:51and we can also remove this bottom alert
- 5:22:53right here I thought we didn't need this
- 5:22:55because Google in the O should do the
- 5:22:58actual redirection here to the home but
- 5:23:01for some reason it wasn't doing it so
- 5:23:03maybe we need to do it manually like
- 5:23:05this which is okay also don't forget
- 5:23:08that in the O this right here has to be
- 5:23:10email address not just email and while I
- 5:23:14was further testing it I experienced
- 5:23:16some additional issues such as this
- 5:23:18error saying too many files open and
- 5:23:21then my Expo server would crash
- 5:23:24basically there is a solution and it is
- 5:23:27to run Brew install Watchman on Mac OS
- 5:23:31at least it fixes it for Mac very weird
- 5:23:34issue but it worked for me another even
- 5:23:36weirder issue is is that I got another
- 5:23:39error saying use process and then work
- 5:23:42with asnc plugins for some reason and a
- 5:23:45solution to that is to downgrade
- 5:23:48Tailwind to
- 5:23:513.3.2 instead of carrot
- 5:23:553.3.2 so if you're having some issues
- 5:23:57you can go to package.json
- 5:23:59and you can find tailin CSS remove this
- 5:24:03carrot from here then you'll have to
- 5:24:08clear the Expo folder clear the node
- 5:24:11modules and delete it and also delete
- 5:24:14the package lock Json rerun mpmi and
- 5:24:18then start the Expo server again that
- 5:24:20should fix it there's many of these very
- 5:24:22small but weird issues but thankfully
- 5:24:25I've managed to find solutions to them
- 5:24:26what you can do next just to make sure
- 5:24:28we're in the same page is delete all
- 5:24:30clerk
- 5:24:33users and you can delete all neon users
- 5:24:36as well
- 5:24:39if you have any rides delete those two
- 5:24:41just so we have a clean slate once you
- 5:24:43do that start the application again and
- 5:24:46while we're here we can try to find a
- 5:24:47way to suppress this clerk warning at
- 5:24:50the bottom since we know that everything
- 5:24:52works I can quickly go into the main
- 5:24:54layout that's the app layout right here
- 5:24:57and right at the top we can write
- 5:24:59something like this import logbox from
- 5:25:03react native and then we can say logbox
- 5:25:07do ignore log logs patterns warning and
- 5:25:10then that cleans it up so now we have a
- 5:25:14nice clean onboarding and we can get
- 5:25:16started I'll log in with Google I'll
- 5:25:19click continue and we got redirected
- 5:25:22that is great I know we changed a lot of
- 5:25:25things so if this didn't work for you
- 5:25:27don't worry it it happens it is possible
- 5:25:30feel free to reach out on Discord or
- 5:25:33check out the description where we can
- 5:25:35mention some of the most common issues
- 5:25:37that people have experienced
- 5:25:38and solutions to them if you cannot find
- 5:25:41a frequently Asked question then
- 5:25:42definitely feel free to ask on Discord
- 5:25:45the link is down in the description what
- 5:25:46I would highly recommend is also
- 5:25:48comparing your files to the final files
- 5:25:51in the GitHub repository it's possible
- 5:25:53that you have a typo here or there or
- 5:25:55that the route is misspelled or
- 5:25:57something even though we have linters
- 5:25:59and typescript and all the other great
- 5:26:02things mistakes happen which is okay but
- 5:26:04for me it works right now so let's give
- 5:26:07it another shot by going over the entire
- 5:26:09applications
- 5:26:11process we can select a ride let's give
- 5:26:14James an opportunity now there we go
- 5:26:16this looks good we can confirm the ride
- 5:26:20and I can make a payment I'll enter my
- 5:26:23test
- 5:26:25details and click
- 5:26:28pay it's
- 5:26:32processing we got a success and we can
- 5:26:35go back home where we can see our recent
- 5:26:38ride right this is working beautifully
- 5:26:41for me if I reload I can still see the
- 5:26:43clerk warning here so I think we can
- 5:26:45quickly go back to layout and change
- 5:26:48this from warning to clerk this way
- 5:26:50Clerk's warnings will be suppressed and
- 5:26:53make sure to remove the three dots as
- 5:26:54well so now if we
- 5:26:59reload you can see it is gone and we can
- 5:27:01continue exploring our application by
- 5:27:03going to the ride screen and we can see
- 5:27:06our recent ride there's only one right
- 5:27:07here which is amazing so we have the
- 5:27:10home and we have tested the entire
- 5:27:13procedure of the flow of creating the
- 5:27:15rides and now we can also super simply
- 5:27:19just log in press
- 5:27:21continue and we are in now as an
- 5:27:25exercise I have left two different
- 5:27:27screens for you one is the profile it
- 5:27:30looks something like this you have a
- 5:27:32profile photo your name email maybe even
- 5:27:35an email status but it is not necessary
- 5:27:38and then maybe even a phone number it is
- 5:27:40optional you should be able to reuse the
- 5:27:42input that we have created so far to
- 5:27:44quickly spin up this screen and these
- 5:27:46fields don't have to be editable so they
- 5:27:49can be read only if you want to
- 5:27:51implement it on your own feel free to
- 5:27:53pause this video and give it a shot the
- 5:27:55code for that will go inside of the
- 5:27:57profile page and you can use the input
- 5:27:59field component we have created so far
- 5:28:02so pause this video if you want to
- 5:28:03implement it on your own or if not if
- 5:28:06you really want to be done with this
- 5:28:07great applic
- 5:28:08since the primary flow is now done I'll
- 5:28:10provide you with a code it's going to be
- 5:28:12in the GitHub read me where all of the
- 5:28:14other code pieces have been and you can
- 5:28:16simply paste it right here it'll look
- 5:28:18something like this you get your very
- 5:28:20simple image which we can pull from
- 5:28:23clerk especially if you logged in using
- 5:28:25Google we get your first name and last
- 5:28:27name which we show in uneditable input
- 5:28:30fields and then we can show the email
- 5:28:33and the phone this is it very simple now
- 5:28:37when it comes to messaging this is
- 5:28:39something that I left completely
- 5:28:41open-ended in this video I'll just
- 5:28:43provide you with this illustration which
- 5:28:45is just going to say no messages yet so
- 5:28:47this project will not include messaging
- 5:28:50but if you really want to bring this
- 5:28:52project to another level you can go
- 5:28:54ahead and Implement an entire messaging
- 5:28:56system use some kind of a package or a
- 5:28:59library or a service that will allow you
- 5:29:01to do that in a simpler way if you do
- 5:29:03decide to implement it well we are on
- 5:29:06Instagram so you can simply tag us and
- 5:29:09I'll gladly reshare your work you can
- 5:29:11also tag me on Twitter where we're
- 5:29:13sharing a lot of the great work that you
- 5:29:15guys do for example I shared one 14
- 5:29:18hours ago by mahad and we are on
- 5:29:20LinkedIn too so if you create something
- 5:29:22cool I'll gladly share your work if not
- 5:29:25no worries I'll still provide you with a
- 5:29:27way to finish this great project off so
- 5:29:29you can share it with your friends and
- 5:29:31potential employers you can do that by
- 5:29:33going to the chat component and then
- 5:29:35copy and paste the chat component from
- 5:29:38the GitHub read me and paste it here as
- 5:29:40you can notice it is a very simple safe
- 5:29:43area view where we have an image and
- 5:29:45some text so if we head over to that
- 5:29:47screen this is how it looks like with
- 5:29:50that in mind even though it seems like
- 5:29:52we only have a couple of screens
- 5:29:54actually there's so many more don't
- 5:29:56forget about our great on boarding that
- 5:29:58we saw at the start and that you can get
- 5:30:00to if you reload your application this
- 5:30:03looks great next we have a beautiful
- 5:30:07Authentication login and sign up forms
- 5:30:10where we can easily log into our account
- 5:30:12we have a super responsive map where we
- 5:30:15can see everything on the screen as well
- 5:30:17as the recent rides and what do you say
- 5:30:19that we give it one more shot let's go
- 5:30:22to Pao Alto visit Steve Jobs we can
- 5:30:27choose our writer there we
- 5:30:29go this is looking great we can verify
- 5:30:32our ride and click confirm and for one
- 5:30:36last time we can pay just make sure that
- 5:30:38our entire app is working seamlessly and
- 5:30:42it's successful we can go back home to
- 5:30:44see it in real time or go to all rides
- 5:30:47where we can also see this new ride it
- 5:30:49is a very comprehensive app with a lot
- 5:30:51of moving pieces so I'm amazed that you
- 5:30:54came to the end of this video if you're
- 5:30:56still here definitely leave a comment
- 5:30:58down below and tell me hey I finished it
- 5:31:02I could have turned this into a paid
- 5:31:03course but I decided to release it for
- 5:31:06free here on YouTube Just so you can
- 5:31:08learn about webstorm which is the new
- 5:31:10IDE I'll be using in future videos too
- 5:31:13clerk so you can Implement
- 5:31:14authentication very easily and neon
- 5:31:17which is my database of choice for all
- 5:31:19future applications and now you know how
- 5:31:21to use all of these great Dev tools to
- 5:31:24implement apps such as the mighty Uber
- 5:31:26clone and if you haven't already
- 5:31:29definitely download the ultimate react
- 5:31:31native guide just so you have a written
- 5:31:33guide by your side when you continue
- 5:31:36your react native Journey p P this video
- 5:31:38and here on the first page I tell you a
- 5:31:41bit more about something great that's
- 5:31:43coming I have started to develop the
- 5:31:45ultimate react native course if you
- 5:31:47liked what we have done in this video
- 5:31:49and you obviously have since you're at
- 5:31:51the end of this video then you're going
- 5:31:53to love what's coming in this Pro course
- 5:31:55if you download the guide I'll keep you
- 5:31:57updated with that in mind thank you so
- 5:31:59much for watching and coming to the end
- 5:32:01of this video great job on building the
- 5:32:03Uber clone and I'll see you in the next
- 5:32:06one have a wonderful day
About this transcript
This page contains the full transcript of Build a Full Stack React Native App with Payments | PostgreSQL, TypeScript, Stripe, Tailwind by JavaScript Mastery, generated from the public captions YouTube serves with the video. The transcript has 52,551 words across 7,258 segments, with the original timestamps preserved so you can click any line to jump to that moment in the embedded player.
What you can do with it
Use the transcript to take notes, quote the speaker, build a study guide, generate a summary with ChatGPT or Claude via the YouTube Summary tool, or export it as a timed subtitle file with YouTube to SRT. You can also re-open it in the transcriber to translate the transcript into 100+ languages.
Free YouTube transcript tool
YouTube2Text is a free YouTube transcript generator — no signup, no daily limit. Paste any YouTube link and get the full transcript instantly, with timestamps, click-to-jump, translation to 100+ languages, AI prompts for ChatGPT, Claude, and Gemini, and exports to TXT, SRT, VTT, or Markdown.