Welcome to this comprehensive full stack React Native tutorial. In this course, you will learn how to build a complete cross-platform grocery list application from scratch using Expo and React Native. Throughout the lessons, we will integrate modern technologies like Clerk for secure authentication, Neon Postgress with Drizzle OM for the database, and Native Wind for styling. By the end, you will have the practical skills needed to confidently develop and deploy your own full stack mobile applications for both iOS and Android. Barack from Code Consistency developed this course. This is the mobile application that we're going to build in this tutorial using React Native and Expo. I will assume that you don't have any mobile development experience at all. So, it is completely fine to follow along as a complete beginner. We are going to build it in a way that it'll work both on Android and iOS smoothly without any issues. Before we jump into coding, I'd like to give you a quick demo of the end result so that you know what we are building in this course. So this is a full stack application where we can list our groceries. You can think of it like a to-do app but it is built for grocery list. You can use it with your partner or with family members. And in total it has four different screens which are authentication list planner and insights. To be able to use this app first you have to authenticate. And for this we have three different options which are Google, Apple and GitHub. If you want to add more of these oath providers like Facebook, Twitch, Slack, so on and so forth. I'll show you how to do it a bit later in the video. Now once you log in you will be redirected to the list screen where you will see the list of items that you need to buy. Now here you can check the items update the quantity and delete them. And under the planner tab you can add items to the list by filling in this form. And finally under the insights you can see the profile information with a log out button, a quick analytics section and a button to clear all completed items from your application. On top of all these, you will also learn how to add a feedback button so that your users can give you some suggestions about what feature to include or what is buggy so that you can jump into your codebase and fix those problems. Now, notice how we have the liquid glass effect on the tabs, which is one of the latest features on iOS, and you're going to learn how to build it in this course from absolute scratch. To build this application, we are going to use the latest and greatest technologies. So for the database we are going to be using Postgress and integrate it with an OM called Drizzle and we are going to deploy this database on the cloud using neon. For authentication we will integrate clerk which is completely secure and easy to set up. When it comes to styling we will use native wind which is tailwind but for react native we are going to handle global state management with zastand which is also pretty easy to get started with. So that's the tech stack and overall once you complete this project you should be able to build your own mobile applications because this guide will give you everything you need to get started with mobile development with React Native and Expo. All the tools we use in this course are completely free. So you don't need a credit card to be able to follow along. As usual, the source code of this project will also be free. You can find the link in the description. So if you're ready, let's get started. In this project, we are going to be using Sentry to implement the feedback button and I will leave a special link in the description which is going to provide you with $80 free credits. Go ahead and sign up and get those free credits. Now, one thing I want to mention before you get started, this course will teach you the fundamentals of mobile development by building a full stack app from absolute scratch. But if your goal is to build a real app that people actually use and pay for, that's a completely different game. Things like app store deployment, pay walls and subscriptions, user onboarding, real-time databases, authentication, privacy policy, terms of service, contact and support pages, app marketing, getting your first users, monetization, and so on. These are the things that turn a coding project into an actual business. And that's exactly what we are doing inside my school community right now. We are currently building a fitness app using AI. And this app is designed to help skinny people gain muscle and transform their physique by tracking their calories daily. This is a 100 day app building challenge where I'm documenting the entire process in real time. Now, as of today, we are on day 10, but you can jump in at any point and catch up on all previous lessons because everything is recorded. Inside this community, you will see exactly how I turn an idea into a real product. Use AI to create designs and UI UX. Build the app step by step. Test and improve the user experience. Publish the app to the app store. Add monetization systems. Do the marketing with the AI influencers. Generate the revenue from the finished product. Now, here nothing is hidden. I'm sharing the wins, mistakes, decisions, and strategies as we go. So, if you ever wanted to see what it actually looks like to go from idea to customers, this is probably the most valuable thing that I can show you. Lifetime access is currently just $25. Now, this isn't just a course. It's a community where we stay in touch, keep each other accountable, and help each other make progress. As of recording this video, we have 25 members from all around the world, and everyone is building their own app idea while following along with the challenge. and I am adding new content every single day. So, the price will increase as the community and content library grow. You can join now and log in lifetime access for the lowest price possible. Thanks for watching and I'll see you inside. All right, so to get started with I have an empty folder which is opened up in VS Code. This is the name that I came up with. It is called Crosify, but you can call it anything that you wish. Just go ahead and open this up in VS Code or any ID that you wish. Now before we start writing any code, I'd like to show you some diagrams that I have prepared so that we can understand React Native and Expo before we start writing any code. Okay, so let's start with the question, what is React Native in the first place? So it is a framework that allows you to build mobile applications using React, specifically JavaScript or TypeScript. In this video, we're going to be using TypeScript, which is I think a lot better than JavaScript because you get the type safety, but if you wanted to, you can still use JavaScript to build it. Okay, so once again, it is a framework that allows you to build mobile applications using React. Now, there is something called crossplatform development, and this basically means that you write code once, and that can run on multiple platforms. And this is exactly what React Native allows you to have. It is a cross-platform framework because you can write one codebase in JavaScript and you can deploy it to both iOS and Android. This could be also TypeScript. So you get the point. It is crossplatform. Basically you write one codebase in one language which is JavaScript. Then you can deploy it to multiple platforms. Okay. Now, this wasn't really the case back in the old days. So, for iOS, you need to learn Swift or I think Objective C and for Android, you need to learn Java or Cotlin, which is not really convenient, right? But now, you can just basically learn JavaScript and be able to both like be able to build both web applications with React and mobile applications with React Native. Now, let's just scroll to the bottom. Now, React Native itself by itself it is not enough. And this is a screenshot coming from the React Native documentation. They say we believe that the best way to experience React Native is through a framework and specifically they recommend us to use Expo. Let's just double check from React Native. This is the documentation they have reactive. Just say get started. And here you'll see that's exact same screenshot that I took. Now expo like what is expo right it is you can think of it like basically a platform that is built on top of react native. It gives you everything that react native provides but on top of it it has extra features. So you will get more components that is optimized you know you can you can use this even to deploy your app to app store. Now we will get into the details for now. Just know that this is something that you can use to get started with and this is actually what React Native official documentation recommends. Okay, let's just scroll to the bottom. Our goto framework for React Native is going to be Expo which is completely production ready. So you can build apps and deploy it to App Store. Now again uh they are not the same thing. React Native is different than Expo because like some people think they are the same thing. Well, not really. React Native is the core framework. Expo is built on top of it. Okay, so when you're writing when you're using Expo, at the end of the day, you are still writing React Native code, but on top of it, you have some extra features like let's say API routes, which is something that we'll get into the details. So you have more performance optimizations. Let's put this in that way. So if you ever used React and Nex.js, it is the similar concept. When you're using Nex.js, at the end of the day, you are still using React, right? But you have some additional features like the image component which is optimized. You have font optimizations. I don't know like you have server actions, server components, things like that. So it is the similar concept and here are some applications that are built with expo that is very popular like the Coinbase, the Phantom crypto wallet app, the blue sky social. Um like this is just an example to let you know that Expo is completely production ready and these are one of the top startups that are using Expo. All right. So now that we understand React Native and Expo, just before we jump into coding, I'd like to show you some differences between React and React Native and some similarities. So let's started with the component structure. Okay, so on web we would have things like a div, H1, P, so on and so forth, right? And we would write JSX. So here it is almost the exact same thing in React Native but basically instead of using a div which is kind of like a box you would use a view element which is imported from React Native and then you can get text for any kind of text that could be H1 H2 P tag span it doesn't really matter anytime you have a text you're going to use the text element so here if you write view this is going to fail it'll say if you are going to have text it should be within the text element okay and we will see this in detail just you know like just see the differences you don't need to memorize at all and then when it comes to styling in web you would have a class name then within a CSS file you would create that class name add your styles here in React Native it's a little bit different you would create a stylesheet so you would import this then create an object then here you would give the class name, then the styles would be under an object. And then if you wanted to use this class, you would say styles.cart. It'll get you all these styles and apply it to right here. Then you can say styles.profile image, so on and so forth. And now this is the old way of doing it. I wouldn't say old, but you know, it's the default way. On top of this, we're going to be using tailwind. So we can just add our classes just like that within the view. itself instead of creating a JavaScript object. So this is something that we'll get into a bit later in the video. Oops, what have I done? Then we have event handling. Now on web you would have things like on click, on mouse over, things like that. But on React Native, we don't have a mouse, right? So we use things like on press, on double press, on long press, so on and so forth. And instead of using a button element, we would use something like touchable opacity. And I think this is kind of like an old way of doing it. The better way is now to use a pressable component. And we will get into uh we will get into the details as well. Okay. So very last two examples. When it comes to the lists in React web, you would use items.m map and then you would map through it, right? For every single item, you would display something. You can do the exact same thing on React Native. But there is a better and more performant way which is called flat list. And we will get into the details later in the video. Just know that instead of using items.m map or you know array.m map there is an alternative called flat list which is more performant. You can keep it in your notes if you really wanted to. You can also get these diagrams. The link will be in the description for completely free. Okay. Finally, we have forms. In React web, you would have a form onsubmit, input, onchange, value, so on and so forth. It is very similar to React Native, but we don't have a form element. Instead, you would add the submit on the button with on press and instead of using input, you would use a text input element just like this one. The rest is mostly the same. You can give the style, value, on change, placeholder, so on and so forth. So as you can tell React and React Native is very very similar. If you have the fundamentals of React, you should be good to go. Um I'll try to explain most of the things that you need to basically follow along with this course. Okay. So let's jump into VS Code. We will open up our terminal and we're going to be using Expo to initialize a template application. Okay. So, we're going to say MPX create expo app. We will say latest and let's say I'll just kill the left hand side. Let me zoom in. We're going to say dash template default. We're going to be using the default template. And here I'll put add next at the end. Now, depending on when you are watching this video, you don't need to add the next. I'm going to put it in the description of this video. But at the time that I'm recording, I need to add the next so that we can use the latest version. Okay. So before you run this command, just take a look at the description of this video. I'll tell I'll tell you like if you should include this or not. Okay. So I'll say add next. And I'm going to put dot at the end which means create it under the current folder. So I'm going to run this. This will get some files and folders. Then it'll install the dependencies. Then we can run our application. Now, while this is installing, you're going to find two different links in the description where we can set up our database and authentication. So, go ahead and click to those links, then sign up to both clerk and neon, which is completely free to get started with. You don't need to pay anything. And if you go with the link, they would know that you are coming from this video and I would appreciate that. Now, clerk is the platform where we will have the authentication. So, we're going to store the users here. Everything will be safe. Then we can get the social authentication service like Google, GitHub, LinkedIn, Facebook, so on and so forth. And I'll like I'll show you how to implement that. Then we will have Neon which is going to provide us a Postgress database on the cloud. So they're going to deploy it. They're going to handle it so that we don't really need to think about setting up our own database. Okay. Now let's go and sign up to clerk and then once you sign up you will be under the dashboard. So here we can create an application. Let's give it a name. I'll just say grossify but once again you can call it anything that you wish. Then you can toggle any of these providers. So I'm going to keep the email. I'll have the Google, let's say GitHub as well as Apple. Okay. So I'll say create application. And if you want to add more, you would just toggle them. Now in free plan, you can add only three options. But if you're in the paid plan, you can add more. I think you don't need to pay anything to get started with at the moment. And it is very very generous. So I'll say create the application and then we can get the expo SDK. So they have bunch of different SDKs but we are interested in this one. Now here we will follow along the steps but first let's go ahead and get the neon as well. I will try to log to my account and then we will create a project. So once you're authenticated you will be in the console where you can create a project. Now here I have bunch of different projects but we will start from scratch. You can just ignore them completely. We'll say create a new project. Let's give it a name. So here I already have corrosify test. This is something that I have created last week to test things out. But we will start from scratch. So here I'll say grossify and I'll leave everything as it is. Then I'll say create the project. Then we will be using the connection string like this one so that we can connect to our database. Actually I'll just copy it right now. Let's go into our you know VS code here. This is done. I'll get into the details first. Let's create thev file right here. and I will paste this in. And we can do a similar thing for the clerk. Just scroll to the bottom. You're going to see the expo public clerk publishable key which should be under the env file. So again, go ahead, copy that and paste that in. Okay. So these are the environment variables that we are going to be using a little bit later in the video. All right. So that was the setup for clerk and neon. Now I'd like to walk you through the codebase what we have at the moment because it it might look a little bit confusing as a beginner but don't worry it is not really that confusing and we will actually delete most of the things and we will start from scratch. Now first off we have the source folder as you can tell. So this is where we have the application code. Things like our custom hooks, you know, components, screens, app logic, anything would go under the source. So I'll get into the details in a second. Other than this, we have some scripts. This is going to reset the project. You will see what that means. We have node modules, assets where we have images, icons, so on and so forth. And I have a VS code folder. This is just for configuration. You can ignore this completely. Then we have some more configuration files like app.json. This gives the you know information about our app. You can add more plugins which is something that we'll do later in the video. So just know that DS is for configurations right? Then we have package.json with some scripts and all the dependencies. Now once you use expo which is what we have done as you can tell you get a giant list of dependencies which is very cool. So that means almost all these um like all these packages are installed for us. So we can use expo image expo linking expo router so on and so forth. Okay. So these are the default packages that are installed when you use expo. Okay. So other than this let's take a look at this source folder. You have some components. It's not really important. You can delete this completely. You can delete the constants. I mean, if you're interested, you can take a look at the details, but that would be pretty confusing. So, we'll just basically delete everything and start from scratch. You can delete them manually, but you can also run this script. So, you can open up your terminal. Let's clear this up. I'll say mpm run reset project. So by doing this you are basically calling this script called reset project and it's going to run this file. Let's just run that. I'll press no. So it'll basically delete everything. Okay. So all the default templates that we had. So all the default files and folders we had are now gone. And here I said no so that it doesn't store it right here. If you say yes, it would take everything and put it under an example folder. Okay. Now, anyways, everything has been cleared out. How do we run this application? Now, there is two different ways. Let me uh let me first show the first one. So, I am on Mac. I'll be running the simulator. If you're on Mac, you can do the same thing. But if you're on Windows, you can run a simulator with Android Studio. Okay. Now, let's just try to run it with iOS. And if you don't have a simulator, I'll show you how to run it in your actual device. Okay. Now, you would basically say MPX expo and I will put them side by side. Looks like I have another application running. Let me just kill this in my second screen. I'm going to kill that application and I'll just run this once again. MPX Expo. Okay. Now you can press I to load the iOS simulator. You can press A to run it on the Android. So I'll press I. So here it says we should install this version. Like I'll say yes. It's going to basically get the Expo application with the latest version. And you can install this app in your physical device as well. I'll show you that in a second. And actually while this is installing, let me walk you through it. Now there are two different ways to follow along this course. So first you can install the Xoggo application in your actual device. So either from oops let's go back either from app store or play store you would go ahead and install it. Then when you say MPX expo you would get this QR code. Then you can scan this in your actual device. Then it is going to run this app in your phone. Okay. So that's the most convenient way. The other way is what I'm doing right here. You would install a simulator and you would run it. If you're on Windows, you would run it in Android Studio. If you're in Mac OS, you would run it with Xcode. Okay, so this is a bit a slower installation process, but in the long term, I think this is better because you don't really need to always use your phone, right? you can just get the simulator, put them side by side. Okay, in this course I'll be using the simulator since you need to see it. But if you wanted to, you can use the, you know, the first option where you can use your actual device. So with that being said, let's take a look at the app that we have at the moment. So what you see here is the content we have under the index.tsx file. And you can, you know, change it and save it. It's going to update in real time. Okay. So, there is like a hot reload going on. And you can add more styles. Let's say something like the background color is going to be something like red. It should work out. Right now, we will get into the details. But first, let's take a look at the source folder where we have the app folder. Now, this is a special folder called app. And anything that you put here would become a screen. So this has what we call filebased routing. Let me just delete the background color first. Let's try to create another route. So before we do so, let's take a look at the root layout as well. This is a file where we have the stack component. We will get into the details for now. Just please don't get confused. I'll just try to go very slowly until we understand everything. And once you understand most of the things then we can speed up the process. So we will get into this file. Just know that this is a special file. You have to call it in this way underscore layout. The extension could be tsx or jsx depending on if you want to use typescript or javascript but basically the name should be underscore layout. And you can have multiple versions of this file. Now let's go under the app. We are going to create a let's say an about screen. Within this you can have underscore layout.tsx as well. Then you can have index.tsx file. I'll just say rnf. And I'll get this boilerplate code. If you would like to get the same thing, you can install this extension called react and react native snippets. Go ahead and install this. Then you should be able to say something like R NF which means React Native functional component and I'm going to call this as the screen. Now let's go here under the home screen. We can add a link. This is just an example by the way. You don't need to follow along. So this will be a link element. We'll say href take us to about screen. Here you can tell it is type safe and I'll just say about screen link. So we just got the link. I can click it and it'll take us to the about screen. Now we have a layout file right here. But we are not using it. So we can use this. I'll just say rnf. We are going to return a stack component coming from expo router. And now if you let me just go here once again. If you want to get rid of this kind of like the title, you can say screen options, you can add the header shown to be equal to false. Notice how the header is gone. Right? So this is one of the ways to use layout component. You can add different configurations. So you can add logic for redirection etc. And we're going to see it later in the video. So once again, please don't get confused if some of these things looks a little bit weird. That's completely normal, but we will get into the details later in the video in more detail. Now here, let's just try to kind of like repeat what we have done. What we have we have a root layout where we are using the stack component. And by using the stack, you can also get rid of the header. Again, you would say screen options header shown is going to be equal to false. And now it's gone as you can tell. So, there are a ton of other options that you can use to customize it, but for now, we'll just keep it simple. And then we have the home screen, right? We are using a view element with some styles. We have a text element, which is this one. And then we have a link element coming from Expo router. And when you clicked it, it takes us to it takes us to about screen. Now here you can tell the content is overflowing with the status bar. This is a very popular bug, but we are going to fix it. I'll show you how to fix this behavior a little bit later in the video. Then here we have the about screen. If you want to have a new screen, you can create folders like this one about or let's say you want to have a contact screen, then you would create a folder and then put a file into it. Or if you wanted to, I believe you can just call it as a file as well, like contact.tsx. Let's test this out. It's been a while since I haven't tried it, but I'll just say contact screen. And I'm going to duplicate this link. Let's say can we go to contact? Yes, we can do so. So, I'll just say contact screen. Let's go back. If I clicked it, notice how we are in the contact screen. But the problem with this is that you can't really add a layout file for contact. Right here, you can add a layout file and customize some stuff if you're interested, but here you cannot really do it. So I would recommend that whenever you want to create a new route just create a folder and within that create the index file as well as the layout. Okay. So these were just examples. Now we can delete the above screen. We don't really need it. We can delete these link elements. And I think we can also delete the styles for now. I'll just leave it. And let me show you some more components before we end the section. So you can get the image component both from React Native and Expo image. But this is more performant. This is optimized. So I would almost always use the Expo image. And here you would put some props like the source. If you wanted to import a local image like from the assets, let's try to get I don't know the icon.png, then you need to require it. So here you'll say require go one up and then another up. So basically you would add the relative path to you know to the icon that you would like to have. So here we go under the assets under the images and then we get expo.png. I think we don't really have it. So maybe we can use icon.png. Now when you save you are not going to see anything because you need to add the width and height. So we'll say style width and height. Now it is right here visible. We can add anything that you want like border radius. Let's just say something like 20. It should work out. So you get the point. You would import the component. Then if you want to import a local image like from your codebase, then you would add the relative path. But if you want to get an image, let's say from Unsplash, then you would just paste the URL, right? and then you would see the actual icon. So this is something that we'll see later in the video. But just know that you also need to add the style where you have a width and height. Now there are more components that we can take a look at like we have a text input. We have I believe things like pressable, right? Which is a button. We have touchable opacity. So on and so forth. But instead of using all of them, I'll leave this section right here and we are going to learn these components as we need them. Okay, so I hope that makes sense. Now let's just quickly do a recap of this section and then we are going to end it. So we initialized an Expo React Native application using the Expo CLI which was this one at the very top. I think I cannot see it but it was okay I cannot see it but it was MPX create expo app at the latest then we set template default at next. So you got the point. So we get the application then we run the script to reset our project then we have a root layout as well as the index file. So this is our home screen that we can see at the moment where we can have some styles, components, so on and so forth and under the root layout we have the stack element. Now we will get into the details what this means but for now just know that the underscore layout is a special file and here you can add like customizations. You can add some providers which is something that we'll do later in the video. And finally we have the app folder which is a special folder. Anything that you put here becomes a screen. Right? Finally we got um some environment variables. And that's it. So with this let's try to end the section. I don't really want to make it any more confusing or complicated. Just try to follow along with the diagrams. Maybe pause the video read it just to get the hang of it and then we will move forward with the next section. So I'll see you there. And just before I end this section, let's try to commit our changes. I'll go under the get ignore and I'll just add the env file so that this is ignored. Right? We don't really want to push this to GitHub. Once we have done this, we can go right here. Let me just shrink this. I'll say stage everything. So press this button. Then we can create a you know a commit message with AI. So it says refactor, clean up project structure and remove unused components. That's correct. Let's say commit. And I think that should be fine. Later in the video, we can create a git um GitHub repo and push it. And actually, let's do it right now. I'll visit my GitHub account. And then I'll say create a new repository. Let me zoom in. I'll say crossify expo. And then for now I'm going to make it private but at the time that you are watching this video it's going to be public. Okay. So for now I'll leave it private. If you wanted to you can make yours public you know if you really wanted to. Here I'll say create the repository. We're going to go here copy this which says if you have an existing repository you can basically copy and paste this. It'll take this code and push it to GitHub. So let me paste this in after like maybe five on or 10 seconds it should be right here. Let's refresh. Okay. So our code is now on GitHub and at the end of every single section we are going to add a new command. Okay. So with this hopefully I'll see you in the next section. All right. So in this section we are going to set up native event which is Tailwind CSS but for React Native. Head over to nativeevent.dev dev and say get started. We are using the version 4 at the moment which is completely fine. It is the latest version. Now there is version five but it is not really stable. So I want you to use the version 4. Okay let's follow these steps. We already have an application. We are going to skip this one. Here it says install the native event. I'm going to copy this. Go into my codebase. I'll kill my terminal. Let's clear this up and I will paste this in. While this is installing, let's try to copy this file name called tailwind config.js. We will create it under the root. Okay, not under the source, not under the app, but here under the root and I'll copy this file and then we'll just paste this in as the content. Now, we'll update this in a second. For now, let's go and get the next step, which is global.css file. And again, it's going to be under the root. Let's copy the content. Paste this in. Now, I'm not going to lie, these steps are kind of annoying because it's like seven different steps, but it's just something that you don't need to completely understand. Just copy and paste. It's going to work. Let's get the babelconic.js. All in all, it is just setting up Tailwind for React Native, right? So, create this file, get the content, and paste this in. Then, we're going to get the Metroconfig.js file as well. Let's grab the content. And I believe our packages have been installed. And then we can get the global.css basically imported under the root layout. So here I will paste this in. Let's see if this path is correct. I think it's not. We need to go one up because at the moment we are under the app, right? We will go one up under the source. And then from here we will go one up so that we are under the root. Then we can get the global.t CSS file. As you can tell now VS code can see it. Now there is one thing that we need to fix and then it's going to work which is under the tailwind config.js file. Now here it says implement tailwind CSS to all the files that are under the components and also the app.tsx file but we don't really have app.tsx file right this is just the template. So instead of doing it in this way, I'm going to delete this part actually this part completely and I'll say anything under the source like this and then it should work. Basically it says anything under the source folder under the components has any of these extensions JavaScript, JSX, TS, TSX it should implement the you know tailwind successfully. Now by doing this it only includes the components folder but if we delete this part it should include anything under the source. So both the app folder you know let's say later you would have the components you would have I don't know like the um let's just say hooks anything it's going to implement the tailwind nicely in these folders right even though in hooks we don't really need tailwind but that was just an example let's see the next step I think we can skip this because it is already done we will get this part which is optional but this is To make TypeScript happy, I'll say native event. Let me just get this file under the root. So native event env.ts, which is for type declarations. Copy this and paste it. And once again, just don't get confused. These are some steps that you need to follow along. Even if you don't understand completely, just know what we are doing right here. Okay. So we put the correct path so that Tailwind is working under the source folder. Now with this let's try to run our application. I'll say MPX expo and then I'll press I which is going to start our application and you can press R to reload it. Okay. Now we can go under the app and try to add a class name to test out the tailwind. Now I'll say text red of 500. And as soon as I save here, you can tell it is working. So we can add things like text forex large. It's going to get bigger. We can add maybe like background of say purple. So you get the point. Tailwind is working. Now if you're not able to get these highlights or suggestions, that means you don't have this extension called Tailwind IntelliSense. just go ahead and install it. Then you should be able to see the exact same thing what I see right here. Okay. So that was the native event setup. Once again we haven't done anything special other than following along the documentation. So we installed the packages set up some files and for some reason it is working magically. So with this now you know how to implement native wind in your next react native projects. So this is the exact same setup you will be following if you're building a new project in the future. That's the exact same setup. Okay. So for now let's keep this section as it is. Let's put it simple. I'll try to stage everything. I think it is stage. Let's create a commit message. And then we're going to end the section. So here, as you can tell, I'll be using AI and I'll say commit, then sync this up, which will take everything that we have right here and push it to our GitHub account. Let me open up the repo. Where the hell is that? We'll say GitHub and the repo name was Grossify Expo. Now we can tell we can see the latest commit. Okay, so that's it for this section. Hopefully I'll see you in the next one. So this is where we left. Now in this section, I would like to implement authentication. Let's first take a look at the documentation of clerk because we are going to follow these steps. So head over to dashboard, select your project and press the expo SDK. Now here the first step is to create an expo application. We already have it so we're going to skip that. The second step is to clear the template files. And since we have already deleted them, we can skip this as well. Then we will start with the third step. So we need to install the packages. I'm going to copy this, open up my terminal, and I will run, you know, we will install the cleric expo and expo secure store. So these are the packages that we need to implement the authentication. Then we already like we already got the environment variable, right? It is right here. And then we are going to wrap our entire application with the clerk provider component. So let me just copy this part. Go under the root layout as you can tell which is under the app and I will paste this in. We're just getting the environment variable. If it is not defined, we are throwing an error. And then we're going to import the clerk provider as well as the token cache. I'll import it at the very top. And then we are going to wrap the stack element. Let's just say return. Wait, let me clear this up. So here we will paste the stack as it was before and we will wrap it with the clerk provider component and we're going to pass the publishable key also the token cache as well. But I think I need to copy it and paste it at the top. For some reason it has been deleted. So let's say token cache and paste it you know pass it as it is which is this one and it should be cleric provider. Okay. So once again we got the if check if it is not defined we will throw an error but else we are going to wrap our application with the cleric provider. Now I'm using stack here in the documentation that they use slot which is not very different. Um basically what we have here is also going to work and I'll explain what the stack component is. Let me just add a to-do for myself. I'll say explain stack a bit later in the video. Okay. So now the next step is to create the authentication screen. So we're going to create a folder called oath under the app and we're going to wrap it with the brackets just like that. And we will also create another folder for the home screen. Now make sure to add the brackets. This makes it a route group so that you can add you know related files to authentication. You can group them under a specific folder. And under this we're going to create a biod file. Just follow along with me for now. I promise everything will say everything will make sense in a couple of minutes. We will have signin.tsx file and then we will have sign up.tsx file. Okay. Now let's first get the layout file for the authentication screen. I'm going to copy this paste this in. Let me walk you through it. So we are getting the use oath hook from clerk. We're just going to check if user is signed in or not. It'll also check if clerk is loaded or not. Right? So we will say if clerk is not loaded, don't return anything. Just wait until clerk is loaded. And then we will say if user is signed in, take them to the home screen. Right? Because if they are signed in, they should not be able to visit the authentication screen. We're going to take them to the home screen. But if they are not authenticated, then we can show them the stack component. So this basically says show the you know authentication screen and let's scroll to the bottom. I will copy the signup screen. Paste this in. Now here you can tell we have a ton of different styles. You can ignore this. This is just CSS. This has nothing to do with React Native. And let's just go to the top. I will explain the logic for now. Let's ignore everything. Just paste this as it is. We have a warning. I think this would be fixed. Let's go under the sign in and copy this content as well and paste that in right here. Again, it is mostly styles and some logic that we are going to see in a couple of minutes. Now, let's go under the home layout. Copy this as well. Again, this is for redirection. It basically says if user is not signed in take them to the sign-in page because if they're not signed in they cannot visit the home screen right so we will go under the home create a layout file paste this in then we will create I believe index.tsx KSX file and just copy the content. Paste that in. Now, this will make sense, I promise. For now, just save everything and run our application with MPX Expo. And then we're going to press I as well as reloading the application. Now, once you start the app, you're going to see all the errors are gone. And let's see what we have now. I think we need to delete this index.tsx that is right here. So under the app we have index.tsx which was the test file. So we can delete that. And then we can see the sign in screen right and you can say sign up. You'll be right here. And then let's try to sign up with you know one of the accounts that I have just to test this out. I'll uh press command shift K to get the keyboard to get the add symbol. Then you can say gmail.com and let me add a password like test 1 2 3. We have a button. I don't know if it is visible but here it says sign up. It is white. It is not really visible. Okay. It says password must be eight characters. So let me just say 456 sign in once again. So since the password is super simple like test 1 2 3 4 5 it says you need to change it right. So that's the beauty of clerk it thinks about every kind of edge case. So here let me just put an actual password maybe I'll say sign up. Now we got a verification code. I'll go ahead and grab it from my inbox. So as you can tell we got this zero minutes ago. I'm going to copy it and then I'll paste it right here and I'll say verify. So there is a button again. I think it is not visible from the video but I can see it. I'll say verify. As you can tell we are redirected to the home screen which is this one here. It says you know hello the username or the email right and then it says sign out. If you clicked it it's going to call the sign out method coming from clerk. And we can get the user with this hook. Okay. So once again we have use user to get the user information. We have sign out method coming from use clerk. When you click to it it's going to sign you out. But here notice how we have a different component called show. Right? So you can say show this content when user is signed out and show this content when user is signed in. At the moment we are signed in. So we can see this part. So this component is coming from clerk as well. Now there is another component that we can use. Let me just save this. We will say sign out. This is working. Now before we use that component, let me pretty quickly explain the sign up and sign in screens how they work. Let's start with sign up. So first off, let's scroll to the top. We are getting this hook where we can get the status errors and the sign up method. Then we have this check if user is signed in or not. We have the router so that we can navigate the user. Then we have let's see you know we have the email state. We have the password and then the verification code. Now when you submit this what happens is that you send the email address as well as the password to this method and if there is an error it's going to fail. But else we are going to call the verification step. So it's going to send an email to your inbox. Once you put the verification code and submit that we are going to call this method by passing the code and it'll say if it is done successfully just navigate the user to the home screen. So that's the logic. You can take a look at it in detail if you're interested. But that's the general gist of it. And here we have an if check which is going to display the verification UI right. So like once you put your information you would get the verification UI which is thanks to this if statement. And finally you have the form which is what you see here. So please feel free to pause the video take a look at it. Basically we have some components like view text input. We have things like placeholder, placeholder text color, keyboard type, so on and so forth. These are the things that you can understand by yourself just by pausing the video. Yeah, like that's it. Now what we would like to do maybe just go and close these files. Also the same thing for sign in. It is very very simple like very similar. You can pause the video and try to read it. So, it's not really that complicated to be honest. So, I'm going to close these files. And now, let's say you don't really want to build your own UI, right? Let's say you would like to use a custom UI coming from Clerk. Is something like this existed, right? Is it possible? Yes, it is. And I'll show you how to set that up. So, first off, we need to visit the clerk documentation. Just type Expo Clerk quick start and then scroll to the very bottom. They just released a new feature where they have some pre-built native components. So it is under the beta but it is working. So there are a couple of different requirements. SDK 53 or later. So we are using 55 which is completely fine. And then they say you need to use a development build because like I'll explain what that is but basically at the moment we are running our application under the Xpogo application right once again our mobile app is running under the Xpogo. Now this is fine but this is mostly for very basic applications. Whenever you want to build something serious, you need to get a development build. And it is basically your own custom app as if it is installed on your device like one of these examples that I have in the past. And here is how you can do it. Just kill your terminal. Clear this up and say mpx run, sorry, MPX expo run iOS. And if you're on Windows or if you want to do it for Android, just say Android here. Since I'm using iOS, I'll say iOS. And for the first time, this will take a couple of minutes, like maybe one or 2 minutes. As you can tell, we got the iOS folder. It'll basically build our app, and then it's going to get the development build, install it right here. Then we can run our application. So it is going to work in the exact same way but you know on top of it we can have some native modules. Okay. So if it sounds confusing overall just understand that expo go application is for simple apps. Okay. So it is for learning purposes for students but whenever you want to have some serious features like this one that we will have at the moment you need to get a development build. So go ahead and run this and then wait for it to be completed. And actually while this is installing we can take a look at the other requirement. It says you need to visit app.json and get this under the plugins. So copy this string. Okay. So under the expo under the plugins let's find the app.json file under the plugins maybe just right above the expo router. paste this in which is clerk expo and then add a comma. So we're going to save that. Now we can scroll to the bottom. They have three different components. So we can just use the oath view component under the sign-in screen. So I'm going to copy everything we have right here. Then I will go into the signin screen which is this one. So remember what we had. That's the current signin UI we have right it is like 200 lines of code even 250 but instead of having all this we can just have 15 lines of code where we have the oath view element which is going to allow the users to sign in or sign up. This is coming from clerk. Notice how they have three different modes. Sign in, sign up or both of them. Okay. So, we're going to save that and let's wait for this to be completed. Then we can see the end result. Hopefully, it should be working out nicely. If not, we're going to fix the errors. So, as you can tell, it is done. It is trying to install it. Then, it says, let's open this application, right? So, I'll just say open. It's going to bundle it. And hopefully, we should see that it is working. Looks like we got an error. Let's see what's the problem. O view is this option true? Yes, it's correct. Let's just see what is going on. View config not found for component. I think this is like it should be working out. I'm going to reload this. Press I once again. Okay. So, for some reason it is failing. Let's see what's the problem. So, I found the solution. Basically, I just paused the video, deleted the iOS folder, and then I run this command once again, which is called MPX export run iOS. Let me try to display it if I can find it. So, I cannot find it. But basically, I deleted the iOS folder and then I run this once again. Okay. So, once you have done this, hopefully it should be working out. As you can tell, this is the 03 UI that you get from clerk out of the box. So these are the providers that we included when we set up this application. We also set up the email authentication, right? So here you can both sign in and sign up. Now I'll just try to select my Google account and I'll try to sign in with it. And once we are authenticated, we are in the home screen. So everything is working as expected. Now we can go under the home screen and use a different component. So within the show when user is signed in I think it is called user button like this one. I'm going to copy this and paste it. Let's see what we're going to get. Right after the pressible, I will get the user button from clerk expo native and then I'll save. So we have the user button. If you clicked it here, you can see we can update the profile. You know, we can select a different image from the photo library. Let's go with the default one. You can update the first name, last name, you can save it, and you can also cancel it. We have the security tab. We can sign out. So that's the beauty of clerk. You just get this component without writing any code. And other than the user button, there is one more component called user profile view. I'm going to copy it. Let's see where that is. Wait, this is for web. We would like to have it for, you know, for React Native. So we have O user button where is user profile. So let me go find it under the overview. Okay. So I'm going to copy this part. Let's just paste it and see what we will get right after this view. Import the user profile. It is basically what you have right here. But it is built in to the UI, right? It doesn't open like within a model. It is just right here. you know, if you're interested, you can use it in that way. And we can also sign out from here if we really wanted to. Okay, so that's the default component. And let's just try to get rid of the header under the oath. So here you can say screen options header shown to be equal to false. So that's the default UI. If you wanted to, you can keep this. But in this application, I will actually customize it completely. So, we're going to have this UI, right? I think this looks a lot more cleaner. We have our own branding. We have an like a hero image. And we also have three different sign-in options. In this project, I will like I'm not going to be using the email option, but if you wanted to, you can include it somewhere in this UI. Okay. So, this is what we'll have. For that reason, I'm going to get rid of this one for now. Let's leave this section right here. And in the next section, we're going to make the authentication UI look like this. And we will make every single one of these button actually work. And by the way, this is working out of the box. Like if you click to Apple sign in, it should work out as well. Here it took us to the settings to give the you know access and sign into our Apple account. But if you were in your physical device and if you were signed in, it would just work out of the box. Right? Then we have the GitHub login. Let's see. You can put your information and it's going to log in and create the account. You can also check out the dashboard like right here under the users here. I can tell we have this user who just signed up and the profile image also has been updated. So if you're just getting started with Expo, the clerk authentication I think is the best option. This is what I would use as a complete beginner. And honestly, as a professional React Native developer, I'm still using it. It's very generous. Pro plan is also not that expensive, like $20 a month. And in the free plan, you have up until 50,000 monthly active users. That's crazy. Like until you hit this amount of users, it's completely free. And like hitting this amount of users is very, very hard. Trust me. So in free plan you can basically build a complete app with 50,000 users while paying nothing. So yeah that was the first setup for the authentication. Now we can delete the signup screen because we don't really need it since we can both sign in and sign up from this component. Right? We can go right here. Basically we can you know delete this entire part. We don't really need these links. Okay. For now, we can leave everything as it is. And in the next section, we are going to, you know, as I said, we're going to build this custom UI. And we will create a custom hook as well right here. But for now, let's close everything and commit our changes. Once again, let me try to give a quick recap like 1 minute under the root layout. What we have done is wrapping our entire application with the cleric provider. We got the publishable key from the MV file. pass it right here as well as the token cache and I will explain this as well. For now, just ignore that. So that was the root layout setup. Then we created two different folders for the authentication screen and for the home screen. Under the layout file, we check if clerk is loaded. We handle the navigation, right? And under the sign-in screen, we have this component which is the default template you get from clerk. And then under the home screen again we have the I mean under the layout we have the navigation and under the index.tsx we have the home content which is very simple but it allows you to sign out by using this method. Okay. Now let's finally try to explain the uh stack component and then we're going to end the section. Now let me try to give you an example here. Here I'll visit Safari and let's say I will open up a new tab. Let's visit somewhere like Instagram if I can type it. Instagram.com and after this one I'll visit somewhere like google.com and finally I'll say facebook.com. Okay. So notice how if I want to go back the previous screen comes from the left, right? It is like at the bottom and the next screen is coming from the right. So it is like a stack of plates, right? Like it is literally in this way you have a plate and on top of it you have another plate top of it. On top of it you have another plate, right? So just notice how this one is above the previous one, right? like this is literally above the previous one. So this is the stack navigator behavior. Basically the new screens comes from the right and previous screens comes from the left. Now this behavior is within the browser at the moment, right? But we would like to implement it in our actual application which is this one. So to be able to implement this, we use the stack element. I hope that makes sense. And you can take a look at it in more detail. just say stack expo and take a look at the documentation. You can read it but it's basically what I have explained. It says a stack navigator is the foundational way of navigating between routes in an application. On Android, a stacked route animates on top of the current screen. On iOS, a stacked route animates from the right. Just like what I what I have explained, it comes from the right hand side on iOS. But in Android apparently it comes from the top of the current screen. Okay. And you can see like in more details you're using the stack component. You can add more options. So on and so forth. Okay. So please feel free to take a look at it in more detail. Since I have explained it, I can delete this. And let's try to stage all of our changes. I'm going to say stage everything. Generate a commit message. Let's commit sync this up and then hopefully I'll see you in the next section. All right, so this is where we left. Now in this section, as I said, we would like to build our own custom UI for the authentication screen and you can find the screenshots in the diagram. So basically, I put the dark mode for the iOS and Android. Then same thing for light mode. Okay, so this is how that would look like in light mode in iOS and in light mode in Android. Now, this is what we would like to build for the UI. And as you can tell, we have a custom green color, right? And to make everything simpler, we will set this up in in the Tailwind config file. So before we get into UI, let's go ahead and set that up. And notice how we have dark mode and light mode. Now, this is going to work out of the box. Whenever we go and say something like let me go under the settings. So just scroll to the bottom we have developer tools. So here we can toggle the state. So notice how in in this simulator itself dark mode works out of the box. Now how do we make that work in our application as well? So we'll go ahead and set that up right here. Now first off I'll visit Tailwind config.js file. I want you to visit the source code. Okay. So find this file under the source code. You will find the colors object. So go ahead, copy that and paste that in. So basically we have couple of different variables. So this is how we use tailwind. If you don't know already, let's say you would like to use the background color. You would just go into a component. Let's say can go maybe right here under the class name. You would just say background. And let's say you would like to use the background color, right? You would say background. Or let's say you would like to update the text color. You would say text. And then let's say you would like to get I don't know like muted foreground, right? So you would say muted foreground. So you got the point. This is the basics of Tailwind. Now we have all these CSS variables or let's say the Tailwind colors and as you can tell they are using some CSS variables, right? like background, foreground, card foreground, so on and so forth. And we would like to set this up under the global.css file. I want you to visit the source code, find this file, and here are the variables. Now, notice how we have the same values twice because this is for the light mode. Okay? So, these are the colors that we're going to be using in the light mode. Notice how the green is a little bit different than this one, right? because we update it in the dark mode. So these are the colors for the dark mode. Okay. And these are the colors for the light mode. So go ahead and save this file. One more thing that we will do under the Tailwind config here just above the theme. I'll say dark mode. Now this has three different values. We are going to be using the media in this case. And I'll just leave a comment right here. Let me grab it from my from my notes. Like what this does this basically tells to native event that it should follow the device color scheme. So if device is using light theme, our application should be using the light colors, right? And if you are in the dark theme, it should use the dark colors. Okay, I hope that makes sense. Now we'll go finally under the root layout. I'll just set up one more thing and then we should be good to go with the light mode and dark mode. Okay, so we have the stack element, right? This is the let's say our application. Now we would like to wrap this with the theme provider component coming from react navigation/native. And here we are going to pass a value. So this will be let's just get the color scheme and we need to get it from a custom hook. So we'll import use color scheme coming from React Native and we'll say if this value is equal to dark and it has like three different values. We'll get the dark. If we are in the dark mode, we would like to use the dark theme. Else we would like to use the default theme. Okay. So just go ahead type this out and we should be good to go. Now let's try to see if it is already working. But we don't really have any content, right? Let's just go under the like our application. I'll just try to run this. Let's reload it. Now we are in the dark mode. Let's try to use the light mode. As you can tell, it's already been updated. Now maybe even if we didn't set this up, this component would work because it is coming from clerk. But in the incoming sections, you're going to see that our colors will also work. Okay. So, we are in the authentication screen. Now, we would like to change this as I said. So, under the sign-in screen, we don't really want to have this component. Instead, we'll we will build our own UI. First off, let's delete the use effect. We don't really need it because we already handle the redirection under the layout file. So, I'm going to delete this part for now. Basically, we are going to create a custom hook something like use social oath. Okay, so this is a hook that we will create and this will get us two different values. The first one is a method like handle social oath let's say and we're going to call this method by passing like um a value that is either Apple, GitHub or Google. And then we're going to have a loading state. Let's say loading strategy. So I just paste this in called loading strategy. You're going to see why. Basically, we're going to call every single one of these options as a strategy. Okay. Now, let's try to build the component. I promise it's going to make sense. First, let's build the custom hook under the hooks. So, I'll say TS file and then we can jump into it and build the logic. So, first off, I'll import couple of different things. So from clerk expo we're going to get use SSO which is single sign on. Then we have use state as well as the alert from react native. So we're going to create the use social oath method. Now here we will have a uh state for the loading strategy. Okay. Initially that's going to be equal to null but it can get a string value as well. So if you click to this button the value of it will be Google. If you click to this one it'll be GitHub and this one it'll be Apple. So that we know like if you click to this one this will have a loading spinner. Right? If you click to this button this will have the loading spinner. So we would like to know which button is clicked so that we can show a loading spinner until the authentication popup displayed. Right? Then from the use single sign on hook we are going to get start SSO flow. This is a method. This is coming from clerk documentation. You don't need to memorize it. Just try to understand what we are doing here. Okay. So we're going to create this method called handle social oath which will be an async method and this will get an argument which will be called as strategy. Now let's make the typescript happy. Let's say this can get only three different values. So we'll say oath Google and it has to be typed in this way then like we'll say or it can be oath github or it could be oath apple. Okay. So these are the options that strategy can take and then we'll say set loading strategy to be equal to whatever they pass and then we'll have a try and catch block. Now within the try I'll say const and we're going to get two different values by calling this method. So I will say await start single sign on flow pass the strategy which is one of these. Okay. And then this is going to give us two different values. So first off, I'll just add an if check. I'll say if we don't have the created session ID or if we don't have the set active method, that means something failed, right? So we can just return out of this method and just before we return, we can display an alert. And this is how we can use it. You would say alert. Then first you would pass the title and then the message, right? You can type anything but here I'll say sign in incomplete. Sign in did not complete. Please try again. And you will see how that would look like in a second. But if this is not the case that means everything is done successfully. So we can just call the set active method by passing the session which is created session ID. Okay. So believe it or not that's the entire thing. Let's handle the catch. We're going to get the error. I'll just put a console log for debugging purposes. And then I'll show another alert. That's the title and that's the message. Now finally, either we succeed or we fail. Eventually, I'd like to run this block so that I can say the loading state will be equal to null. And at the end we'll just say return handle social oath as well as the loading strategy because these are the values that we are destructuring right let's try to import this hook I think we need to say export default use social oath not this one let me do Ctrl C okay if you save now this should be visible we can import And here I'll just add one more thing. This is an optimization. We will say if we are already in the loading state, we don't want to do anything, right? We'll just say if return because just imagine if user let me go back. So let's say you click to this one. While this is loading, if you click this one, what's going to happen? This will also get the loading state, right? But we don't really want this to happen. We'll say if we are already in the loading state just don't do anything right don't call this method once again. So we'll just say return this return out of it immediately and it'll just say quart against concurrent flows. Okay. So that's the entire hook. Now once we use it I think it'll be even more clearer. Right? For now just save and let's go into the sign on screen and get started with it. Now I will provide this image. You can find it from the source code. I'll actually go ahead copy it and paste it. So you can find it under the assets under the images. There will be a file called oath.png. So find it from the source code and paste this in and we'll be using it now. Now first things first, we'd like to get rid of the o view element because we're going to build our own custom UI, right? So first off, I'll just have a view element which is coming from React Native. And within this, let's just have a text maybe I'll say first, let's try to import it from React Native. And here I'll say something like hey everyone. And for the view class I'm going to say flex of one. So it is taking the entire space and we'll say justify centered as well as item centered so that the content is in the middle of the screen. Now in the past we had this problem where the text was in the status bar right it was right here if you remember it was not really visible to be able to fix that issue like at the moment we cannot see it but let's just try to delete this part like as you can tell it is right here right how do you fix it it's very simple there is a couple of different ways one of the ways is to use this element called save area view so go ahead import it and Notice how it's immediately fixed. The content is within the safe area, right? It is not really overlapping with the status bar. So that's the first thing. Now I will say use the background primary for some reason like did it work? Background primary maybe let's just say EG red of 500. Okay, so this is working but for some reason primary did not work. Maybe we need to rebuild our application. So I'm going to open up my terminal. I'm going to kill this. And here I'd like to install a package because every single time we have to run MPX expo run iOS to start our application which is not very convenient. So there is a package that we can install. Just say MPX expo install expo dev client. So by doing this, you only need to rebuild your application whenever you install some native packages, native modules. Now, we just installed this one. I'm going to say clear. I will delete the iOS folder and I'm just going to rebuild my application. So I'll say mpx expo run iOS. And once this is done, hopefully the colors should be working out. I'm going to kill the application. Let's wait for this to be completed. And I'll just be right back. Okay. So, as you can tell, it has just done. It's completed. Now, it's going to rerun our application. And here we go. The background primary is working now. Let's just check if we are in the light mode or in the dark mode. I'm going to go into the dark mode. Notice how it's going to update like it's a bit more light. And if you wanted to, you can say in the dark mode, don't use primary, but use the secondary color. Now, with this, once you save, you're going to see that background would update. Let's say in your case, it doesn't. Maybe, you know, you might get a bug where it looks like black. You can just go ahead delete the text. So, it would be probably because you don't have a content. So, just have a view. Give the class name. Let's import this by the way. So, we'll say class name. Just give the flex of one. Then you should be able to see this background. Okay. Once again, by default, we are going to be using the background primary here. But let's say in the dark mode, this is too light. And this is what I think. In the dark mode, this is like a bit too light. So I'll say in the dark mode, go ahead and use the secondary color. Okay. Now, let's build the rest of the UI. As you can tell, we have two different kind of like circles. And we are going to position them absolutely to the top left and kind of like top right. So this has nothing to do with React Native. It is just some decorative elements with CSS. I'll add a comment. I'll say decorative elements. And I'm going to copy it, paste it from source code. It is literally two lines of code. Notice how we are using the position absolute. We position that give width and height. Make it circle. update the background color and in the dark mode you know we use a different color and that's it. So I'm going to put them side by side. Once you save you're going to see these circles. So right after this we're going to have a wheel element and this will get the class name. Let's say petting x of six and petting top of four. Within this I'm going to have a text that will say corrosify which is our let's say the brand name. Let's import the text from React Native. Here we go. That's what we have at the moment. Right below it, I'm going to have another text. This will be plan smarter shop like shop happier, but the color should be white for some reason. Here we have black. Let's see what we are missing. So, we're going to update the color for now. Let's keep going. Right after this text, but still within this view, we're going to have another view. So this is going to hold the image but we're going to add this kind of like background that you can see here the rectangular. So this is that view. We'll just say class name should be equal to margin top of six. We'll say rounded and you can give custom colors like 30 pixels by doing this. Then you can say we'll add a border. Border color will be white but we're going to update the opacity. We'll say 20%. Then we'll say background should be white and again 10% this time we'll say petting x of three or actually petting from all directions will be equal to three. Then we're going to import the image component if I can type it correctly from expo image. Then we're going to add the source where we need to get the o.png. So I'm going to pass the relative path. We're going to give the width and height. I'll go with 100% to 300 pixels. Then content fit will be equal to contain. Once you save, you're going to see that image is right here. If you wanted to, you can update the values. So we'll go below to both of these views. Just above the save area view, we'll have another one. I'll say class name margin top of eight. Let's say flex of one. So it is taking the entire remaining space. Then I'll add the rounded top of 30 um 36 pixels. Now as you can tell only the top corner is rounded right not the bottom. So that's what we are saying basically. Then we'll just say background color should be the card padding x of six y of eight. Sorry, maybe like bottom of eight and padding top of six. And within this, we will have a view as well as a text element. As you can tell, it says welcome back. Like, we just built this part. And like I literally don't know why here it's black, but in the demo it is white. Because this is the same code that I have in my notes. It's working in the white color. Probably we are missing something. Um, we're going to fix that for now. Let's just ignore the colors. But notice how we have the text. Then right below to this view, I'll have another text. I'm going to copy and paste to right here. Okay. Then what else? So it was this text. Now we're going to add our buttons one by one. Right. So the first one is the continue with Google. Below to this text have a view element. We're going to say class name margin top of six and within this we'll have a pressable element. Now this will get some class classes as you can imagine. First off I will create a variable actually a couple of variables. So I'll say if the loading strategy is equal to oath Google that means the Google button is just clicked right we'll say is Google clicked if this is the case that means Google button clicked then we will have the same thing for apple clicked I'm going to duplicate it finally we will have it for GitHub And we need to update this part. Let's say that's going to be both Apple and GitHub. Now if any of them is equal to true, let's say const is loading. We'll say if Google is clicked, you know, or Apple basically we're going to put all of them side by side. If any of these equal to true, that means we are in the loading state. So we'll go right here within the pressable because the class name is going to be like dynamic. I'm going to say class name curly braces back text and actually I'd like to copy and paste rather than typing this out. Okay. So I'll just paste this in and walk you through it. So these are the classes that we will implement for every single button. But we will say if it is in the loading state add the opacity of 70%. But if it is not in the loading state just don't do anything right. And here we will say this pressible should be disabled if we are in the loading state. And finally we'll say on press since this is the Google button right on press we are going to call the handle social oath by passing the Google as the strategy right and for the text we can say actually we'll have some content like the icon right and the text and then another icon. So for the Google image I think I'm going to provide it to you. You can find it under the source code. Just go under the assets images you will find google.png and just copy it then paste it right here. And within the pressible we are going to be using it now. So again this is just CSS. So for that reason I'd like to copy and paste. So we just have a view with the white background. Then we have the image. We are just importing it, giving width and height and that's it. Now right below to this view we're going to have a text element. Let me put this in. Now here by default it says continue with Google but if we are in the loading state let's just say true. It's going to say connecting Google and three dots. Right? So you got the point. And finally, we're going to have an icon on the right hand side. I'd like to copy it and paste it right here. So, we're going to use font awesome. This is how we can use icons from expo. Let's try to import it. So, I'm going to go right here. We'll say import something from at Expo. I think it should be expo/ vector icons. Now we can get bunch of different font families or the icon families like we have ion icons, font awesome and actually in this page we're going to be using font awesome and font awesome version 6. Go ahead and import them. Then here you need to pass the name. So let's delete this part. If you press control space, you're going to see they have millions of different icons. And this is what we would like to use. Size and color. put it. It should be visible right here. So that's the very first pressable. The rest will be almost the same. We will just update this part right. We will update the icon, the text and that's it. So I'm going to copy the next pressable just put it right below to this and I will walk you through it. So here it says is GitHub clicked mismatch. Let me just update this part. It should be is GitHub I'll just uppercase DH. Okay, so this is what I just copied and pasted. Let me walk you through it. We have the same classes. If it is in the loading state, let me just make it true. So you can see it pass the updates elbow. Then when you press to this button, what happens is that we are calling this method by passing the GitHub as the option. Instead of using an image, we use the icon coming from font awesome. Then we have the text. You know, it's the same thing. And we'll just do it one more time for the apple. If you wanted to, you can pause the video and just do do it by yourself. But in this case, I'm going to copy and paste. Okay. So, as you can tell, it is right here. Finally, we're going to put a text at the very end. So, above, sorry, below to this pressable and view. Paste this text. It is like it is this what we see here. So here I just pause the video and try to fix the colors make it accessible. Notice how everything is white already. And the solution for this is that here I am missing one zero under the primary foreground under the dark theme. So if you copy and paste it from the source code probably you already have the correct colors. But in my case I just had to fix this part. Now with this everything is working fine. But why does this part is not matching with this background? Right? So that's because of the safe area view element. Now safe area view is not only this part, right? It's also the bottom. But we can just eliminate this part by saying this edges should only apply to the top, right? Only this part should be within the safe area view, not this part. And now that fix it. And we can see the exact same output just like in the demo application. Now let's try to give it a go. I'll press this one. Okay, looks like it failed. Why this is the case? Let's take a look at the terminal. So looks like we need to install this package expo o session right and actually it says install them by pasting this. I'm going to copy it. Kill this terminal. I'm going to clear this in and paste this in and let's try to rerun our application. I'll say mpx expo. Since we are using the expo dev client, it is already using the development build. I'm going to say rerun this. As you can tell, as soon as you click, it says connecting. But looks like we're missing another module called Expo Crypto. Let me double check. Yeah. So, I'm just going to install that one as well. I'll say MPX expo install. Is it like expo- crypto? Okay, so it's been installed. I'm going to rerun my application. So this is real world development. Like you would get some unexpected errors and you just need to read it and then fix it. Like I'm not going to cut this part from the video so that you can see how we fix these issues. I'm going to rerun the app by pressing I. Let's just say okay. Press this one. Hopefully, it should work. Fingers crossed. But what the hell? It says cannot find. Maybe we need to rebuild our application, right? I'm going to stop my terminal. Now, why do I think in this way? Because I can see it says there is no native module. That means probably it is something related to the development build. And to double check, I'm going to delete the iOS folder and then I'll say mpx expo run iOS. So this is what I would do whenever I get some native module issues. I would probably delete the iOS folder and then run this script or the command so I can rerun my application or rebuild it. Once this is done, we'll test out if everything is working successfully or not. All right. So, here we go. It's done successfully. I'll just say let's try to continue with Google. So, I'm going to say continue. Okay. So, as you can tell, it is working. Now, if I wanted to, I can cancel it. Then, we see this alert. Now, notice how this is the exact same thing how we set this up, right? So, we say the title will be equal to sign in incomplete and that's the message. So this is how you build an alert. Now just say actually try to log in with this account. Hopefully it should take us to the home screen once we are authenticated. And here we go. We are in the home screen. We cannot see the text because colors are not really accessible. We're going to fix it. But overall everything is working. Now we'll go under the home screen. As you can tell we have the sign up button. If I press I should be redirected to the authentication page. Okay. So with that we can leave this section right here. Let's try to quickly reiterate like what we have done. So we built a custom hook right and here we have basically one call where we pass a strategy which is either Google, GitHub or Apple and clerk wants you to pass it in this way like ooth Google. Same for GitHub and Apple, right? If everything is done successfully, we're going to call the set active to pass our session ID. That means user is authenticated. And from this hook, we are getting two different values, right? And we grab it under the sign-in screen just like that. Then we have the loading state depends on these variables. We have our UI like this is mostly CSS I would say. Don't worry about this too much. Just try to understand the logic. You can always try to you know build a beautiful UI by taking some time or even build it with AI. Now at the moment just try to understand the logic. Anyways, we have three of these buttons. When you click you pass the specified like strategy either Google, Apple or GitHub and then everything works successfully. Okay. So that's it. One last thing that I'd like to mention, we added these variables, these CSS variables so that everything is working successfully like in the light mode and dark mode, right? Let's try to actually switch and see the light mode. As you can tell, that's the exact same UI we have in our screenshots. Right. Okay. So, it's almost identical. Now I'll just go into the dark mode and then we're going to commit our changes. So I'll close everything stage it all get a commit message with AI and then we're going to sync this up. Okay. So with that hopefully I'll see you in the next section. In this section let's try to get into our database. At the moment, all we have is a database URL where we can connect to our database, which is this one. But it doesn't have any tables, any data, nothing. Right? So, let's try to set this up where we can create a table for the items. Right? So, every single item will have a name, category, quantity, so on and so forth. So, let's see how we can set this up. Now, we are going to be using an ORM called Drizzle. And you can think of an RM like let me try to visualize it. So we have our codebase and we have a database right. So here we would like to write some code so that we can communicate to our database. So we will basically get an ORM like drizzle and we can just still write a JavaScript code but it is going to take that JavaScript code and convert it to SQL because we have a Postgress database right. So you will be able to have some abstractions. You will still write JavaScript at the end of the day but it'll be converted converted to SQL. So it is more than this but basically if you're interested you can check what is an RM right and then specifically you can take a look at the result. I'll try to walk you through it as much as possible but that's the general gist of it. Okay so we are going to be writing JavaScript at the end of the day it'll be converted to SQL or you know yeah I think SQL in this case. So I'll just try to clear this up. Let's jump into VS Code. We're going to install a couple of different packages. First, I'll clear this up. Let's say mpm install. We're going to have drizzle-rm. And then we're going to get one more package for neon database. So, it'll be at neon database/serverless. Go ahead and run this. It's going to install these packages and we're going to get one more package, but that's going to be for the development. Okay, so this is done successfully. I'll clear this up. So, why is it so slow? Let's say mpm install. This time we're going to say trizle dashkit and we'll say d-savedev. So, this will be installed. Let's go under the source. We will create a folder called lib and within the lib I will create a server folder and within this we can have one more folder called database or db within the db we're going to have some files like client.ts and we're going to have schema.ts Yes. So schema file as the name suggests this is where we can define our schema like which tables we are going to have which fields so on and so forth and within the client file we can generate an object so that we can interact with our database. So I'm going to get a couple of different imports. I'll get neon from this package that we just installed. We're going to get the result and we're going to get schema from the schema file in a second. For now, let's just say const schema. This is just for testing purposes. For now, leave it as an empty object. Then we can get the database URL from the process. Okay. So, we have the database URL. I'll just add a check if this is undefined. I'm going to throw an error. I'll say this is this is required. Then we can create a SQL object by calling the neon method passing our environment variable. Right? And at the very end we'll just say export const DB. This will be the object that we will be using to be able to interact with our database. So I'm going to say call and we're going to pass an object. So, we're going to pass the client, which is this SQL variable or the object, and we're going to pass our schema. Since they are the same thing, we can shorten it. And this is not going to be an empty object. This is just for testing purposes for now. Let's actually create it. Okay. So, I think I just made a mistake. This should not be under the schema file. Sorry, my bad. This should be under the client. I thought we were in the client file. Um I'll just paste it here. Now we're going to get the get into the schema file and build our schema. Now from the drizzle rm from the posgress core we are going to import couple of different values and we'll be using them right now. So we're going to say export con items. Let me type this out correctly. items and we're going to say postgrass table. We can give the name of the table. We can put anything. The name that I'll be going with will be grocery. Wait, what the hell? Why can I I cannot type. So this should be grocery items. And we're going to pass every single column. So every single item will have an ID and it's going to be type of text. We'll say this is primary key. Then every single item will have a name. So we're going to be using text and we will say this cannot be null. Then we will have the category. So I'm just going to copy and paste because it is super simple. Just understand what we are doing. You don't need to memorize the syntax. This is coming from the drizzle documentation. You can always double check. So we're going to be using quantity which is integer not null and by default it's going to be one. Then we'll have the purchased field which will be boolean either true or false. And this is needed because depending on that we can toggle the state right if you press it's going to go like at the very bottom of the screen it'll say like this is purchased okay this is what we are doing and finally we'll have the priority so as you can tell we have high low and I think we also have medium in this screenshot you cannot see it but by default it'll be medium and finally we will have the updated that field and we are going to be using this value so that we can sort it. Right? So you will see the latest one at the very top or the latest updated one. Right? So super simple, nothing complicated. Just go ahead type this out or get it from the source code. Here we have some extra details. Not really that important like it has nothing to do with React Native. So I'm just going to skip that. These are all the columns that we're going to have in the um like in our database right in the table. So now we will go here instead of having this hard-coded schema, we will actually import our own schema that we just created. So I'm going to say import everything as schema from the schema file. Right? So if this is confusing, let me explain because I remember when I was a beginner, I was like, what the hell does this mean? Right? Just imagine here you have multiple different tables like you have users. Let me just say users, you have maybe like products, books, posts, so on and so forth. You basically import everything as schema. Then you can just come here. We can say schema users schema grocery items. Right? So this is what that means. And we just get the schema as an entire object and pass it right here. So I hope that makes sense. So that's it for the client setup as well as the schema setup. Let's try to create a file because at the moment we don't have any data, right? I would like to add some test data under the tables and we don't even have our table. Let's just try to first push this schema to our database. For this we can create a script. So here I'll add a comma. I'll say database push and then we can use drizzle kit push. So that's it. But we need to create the drizzle config file. I almost forgot, but this is a file that you definitely need. Under the root, just say drizzle.config.ts file. Yeah, it should be TypeScript and copy it. Then paste it from the source code. It is like 10 lines of code. From the result kit, we get define config. Call this method and pass some objects. So, we say here is our schema file. It is under the source lib server db and here is the file. Then the out directory will be drizzle dialect. We are using posgress and our database credentials is right here. So that's it. That's the config file. Now with this we can save everything and go into our terminal. We will just run this script. So I'm going to clear this out. I'll say mpm run db push. So this is going to do some magic. Basically it'll take the schema and push it to our database. Let's go here refresh this file or this page. As you can tell we got our table called grocery items because this is how we called it. If you put hello that would be hello as well. So we got all the columns like the ID, name, category, quantity, so on and so forth. Now let's create some test data. I will go under the should we go under the source maybe like outside um like where should we put it? Yeah, I think I'll just put it under the root. I'll just say scripts and then we can add a seed file. I'll explain what that means. We'll say seed dash grocery.js or I'll just say commonjs. This is what I have in my notes. So I'll just stick to it. Now seeding is a concept where you would like to have some initial test data and I have prepared this file for you actually with AI. Basically we have couple of different items. I think total like in total it has 10 different items. We have some bananas. Here's the category, quantity, priority, and if it is purchased or not. Okay, so overall you can read it. This will basically create the table. If not exists, then it's going to push this data to our database. So save this file. We're going to create a script. I'm going to say db seed and we would like to basically run this file right and actually instead of calling this database I'll just say seed and let's say grocery this is just naming preference like I'll go with this one then we would like to run this file with node so I'll say go under the scripts find this file and run it so just make sure you put cjs right Okay, now we'll open up our terminal. We'll say mpm run seed grocery. Okay, looks like it failed. Why this is the case? So I think it cannot find the database URL. So instead of having it as an environment variable, let me copy this value just for like 10 seconds. I'll put it right here. And then I'm going to rerun this file. Hopefully it should work. Okay, as you can tell, it's completed. It inserted 10 different items. I'll bring this back because I don't want to push my credentials to GitHub. Okay, let's double check. We didn't had any data. Let's refresh. Now, we should have 10 different items. Now, we are going to be using them a bit later in the video. For now let's create our actions and then we are going to end this section. So under the lib I think should we go under the DB maybe like under the server I'll say like database actions dot ts file and here we will have some queries and mutations. A query is basically when you want to fetch some data and mutation is when you want to create something delete or update. So once again a query allows you to fetch data and mutation allows you to insert update or delete data. Now here we'll go ahead and import two different things from drizzle OM which says you know in the descending order and equal we'll be using them. Then from the client we're going to get the DB object which is this one. And finally we're going to get the grocery items from the schema. Right? So we're going to get this object. Now let's go ahead and create our very first query. I'll say const list grocery items. So this will basically get every single item in our database and we can say con rows. We can call await database dot select. So call this. Okay. Then we'll say from the name of the table which is grocery items and then we'll say order by in the descending order and the field that we will be descending or the like order by is going to be grocery items do updated at field. So believe it or not that's the entire thing. We'll just say return the rows which is like the documents. Okay. So, super simple. You don't need to memorize this. Like this is coming from the Rizzle documentation. And as you use this more and more, it'll just stick to your mind. Now, in the similar concept, we would like to create a mutation. So, I'll say create grocery item. And this is not only going to take name. So, I'm going to delete this part. We'll say let me just kill the AI. It is kind of annoying. Okay. And by the way, I just press commandshiftp or control shiftp to open this up. And then you can say toggle status bar, right? So just keep that in mind. Okay. So we're going to have the input coming from user. And this can be let's say it's going to have a name which is type of string. Then it's going to have the category again it'll be type of string. quantity as well as priority. Now we don't have to type this out but since we are using TypeScript if you don't add it this will get mad and it is a best practice to always add the type. Okay. So within this method we are going to say await database doinsert into the grocery items table and we're going to say here are the values that we would like to have. So for the ID we can use crypto.random random UYU ID. So it is just going to generate a random ID. Okay. Then for the name, we're going to say input.name, right? Okay. Same for the category. Let me just get the rest of it and I will walk you through it. So we have the quantity. It can be like minimum of one. We are using max because just imagine if this is equal to minus 5 it's going to get the maximum value which is one. But if it was + 5 it would get the five. Right? This basically says get the maximum value but at minimum it could be one. I hope that makes sense. Then the purchased by default it's equal to false pass the priority and updated that is date. Now, now at the very end, we'll just say dot returning. So, it'll basically say return all these fields back. So, we can say const rows and we'll just say return like this is an array. Okay, we would like to get the first option which is an object. So, that's the mutation. Now, in the same way, I'll just grab this and paste it from the source code and I will walk you through it. Let's import the equal from drizzle rm. Okay. So this is the method that we are going to call whenever you press one of these items. So when you press this would be marked as purchased. Right? So here set grocery item purchased. We're going to pass the ID of the item and the purchased field either true or false. And we say database.update update under this table and set this field called purchased whatever user is passing and update the updated at time and we'll say where it's equal to this ID so if you press this one it should update this one right if you press that one it should update that one so that's how we can filter it with the wear clause and we say if there is not a value return null but if there is just return that value. Now we'll do similar thing when you want to update the quantity, right? So if you press this one, it'll be decremented and here it'll be incremented. So it is very similar. I'd like to copy and paste instead of typing this out. So just pause the video and try to read it. I promise you will understand it. Again, we say update something in this database. Here is our wear clause. Here is the fields that we would like to update which is updated at and the quantity once again it could be at minimum of one here if you pass minus 5 right this could be one because quantity cannot be less than one and then we finally return the value and now we are going to have another mutation when you press this button it's going to delete that item right so it's going to be just one single line we say delete something from this table where it is matching with this ID right and very last mutation so I think under the profile screen or under the insights if you press this button it's going to clear everything from the database but it's going to clear the completed items okay so I'm just going to copy and paste it it's very very simple and similar to this one here we say If purchase field is equal to true, just go ahead and delete it. So these are all the actions that we are going to be using later in the video. For now, we can leave this section right here. Just before we do so, I'd like to give you a quick recap of what we have done. So we created a drizzle config.ts file to tell to drizzle like here is our schema. This would be our out directory. This is dialect that we're using because you can also pass something like my SQL single store SQL light so on and so forth but we are using Postgress SQL and here is our database URL and then under the source folder we created a DB folder right so we have the client where we pass our schema as well as our SQL object. So by using this DB we can have our actions right notice how we are always using the DB object to update something delete something create so on and so forth then we have our schema where we say that's our table these are the fields and finally we have our DB actions now we didn't have any data right we didn't had like anything so we created a seed file and to be able to run this we created a script script. So once you run that, it's going to create some test data. And to be able to like to be able to create this table or this schema, we run database push, right? It's going to take the schema and push it to Postgress or in the Neon dashboard. Okay. So I hope that makes sense. Now we can close everything. We'll go and commit our changes. So I'm going to stage everything, generate a message, and then commit that. Finally, let's sync this up. And once it is done, hopefully we can end this section right here. I'll see you in the next one. In this section, we are going to learn how to build a tab navigator. Now, what does that mean? Basically a tab navigator is this kind of a component that you would have and depending on the current tab UI would update. So like this is the list tab. This that's the planner and that's the insights. This is a very common navigation pattern that we have in React Native. Now just before we jump into coding let's take a look at the documentation. So you can just search for expo tab navigation and you're going to see that they say tabs are a common way to navigate between different sections of an application and expo router provides a couple of different ways of implementing that. So we have JavaScript tabs, native tabs and custom tabs. Now if you would like to get the native feeling, what does that mean? Let's say you open up a native application like fitness app that iOS has. You're going to see that they have this liquid glass effect which is the latest version of the tabs that is built into Apple, right? How do you get this? Do you build it from scratch or do you use like a component? Well, you definitely don't need to build it from scratch because export router gives you native tabs and this is the one that we will be using. You can take a look at the other ones as well. Let's say you are building a very complex UI where everything is custom. Then in this case, you can use the custom tabs. Okay, but in our case, we're going to be using the native tabs which is very very cool and I'll try to explain as much as possible. Okay. So just know that this is working I think from SDK 54 and above. But we are in SDK 55. So it is completely fine to work with this. Now first off we're going to jump into VS Code and we're going to create a folder. So under the source under the app actually instead of calling this home I'll just call it as tabs and we're going to put all of our tabs into it. So the index is going to be the very first tab that we have which is a list. Then I'm going to have planner and then insights. So for every single tab you would create a file. So I'm going to say planner.tsx and then I'm going to create insights.tsx. Let's try to generate a test content for now like rnf. I'll say insights screen and let's say planner screen. Okay, I'll try to authenticate first. Now just by adding these files is not going to work. You need to set this up under the layout file. So I'll try to login. And here instead of calling this only layout, you can change the name. It's not really needed but let's just say this is going to be called as a tabs layout and instead of only returning stack here we are going to return the native tab element. So just like in the documentation we're going to import the native tabs. This is the parent element. So we'll say native tabs and within this for every single tab we're going to have the trigger. So I'm going to copy this one. actually both of them. So just follow along. In two minutes it should make sense. Okay. So the very first tab we have is for the index screen, right? And then the other one is for the settings, but we don't have the settings screen. We would like to have it for let's say planner, right? So I'm going to say planner. And then for the trigger icon I can use maybe not settings but I'll just try to update it. So here under the SF I'll say maybe like plus circle and MD here I'll say add. Now MD is used in Android and SF used in iOS. Okay. So in Apple you're going to get this icon and the like on Android you would get MD. Okay. Same thing right here. For now, let's just use house. That's fine. And here for the text, I'm going to say planner. Let's save what we're going to get. Maybe we should rerun our application. So, I'll say MPX expo. And I'm going to reload my app. Okay. So, as you can tell, we already got our tabs, right? Let's take a look at it how that work. So first off you have the parent element called native tabs. And then for every single tab you add a trigger. You give the name of the file. So we have the home which is this one. Right? We can update it. Like for the label you have native tabs.trigger.label. Instead of saying home I'll say list. And we're going to update the icon as well. So for the icon as I said you would be using this. For iOS, you would update SF. Let's say I think I'm going to use a list bullet circle or I think clipboard. Do we have it like list dot bullet clipboard? Okay, so that's what we have as well just like in the demo application. Now here the color is green, right? By default we have blue. We are going to fix it. But for now, just understand the concept. Let's do the same thing for the very last tab which is called as insights. You need to put the file name. And then you can put the label, anything you want. I'll say insights as well. Let's update the icons. That's going to be chat bar like this. Okay. Looks like it failed. not chat, it should be chart. My bad. Then for the MD, it's going to be um sorry, it should be analytics. And I think this should be list. Okay. So, as you can tell in the planner screen, we have this text. Let's just make the class name text of white. It should be visible. It is right here. You can make this a safe area view. So, you get the point. Whenever you click to one of the tabs, you see that specific screen. Now, this is the simplest way of using it. You can of course customize it. Like let's say if this is active, we can update the icon. So, under the SF, I'm going to delete this. This should be an object, we're going to say in the default case, use this icon, which is what we just cut, right? But we'll say if this is selected then you can use this icon list bullet clipboard but it should be filled in. Notice how if it is not selected it uses the default one but if it is selected it is filled in. So we're going to do the same thing for the other icons as well. I'm going to delete this part. If it is selected it should be filled. Um, wait. I think I just made a mistake. It should be under the icon. Okay. Now, if it is selected, notice how it is filled. If you wanted to, you can change the icon completely. Like, do we have home? Let's just say HomeKit. If it is selected, icon is changing. But this is what we will be using. Let's do the same thing for this one. I'm going to delete the SF. Okay. Now, how do we update the color? So, you can go under the native tabs and you can say tint color and then I think you can add a color. So, here for now, I'll just add a string like red. As you can tell, it's been updated. But, of course, we don't really want to use red. We're going to be using a custom value depending on the theme. So I'm going to get the color scheme first. So I'm going to import this from React Native. Then we will check if we are in the dark mode or not. If that's equal to dark, that means we are in the dark mode. And depending on the dark mode, we are going to get this tint color. So either it's this value or that one. And I'll just pass this in. I'll say tab tint color. So as you can tell it is working. Let's try to make this in the light mode. Okay. So it is still working. And if you wanted to, you can customize it. You know, if you didn't like the colors. Wait, why this is complaining? Color scheme. Um, I think this should be coming from not React Native, but it should be native wind. My bad. We need to maybe rerun this. Okay, now it's fixed and we don't really have any warnings. Now, if you wanted to, you can add some badges as well. Let's say you have some notifications. You would say triggerbatch and at like 9 plus. And this is coming from the documentation. Just feel free to pause the video and take a look at the other feature features of your if you are interested. Okay? Like if you leave it empty, it would look like you have a notification but it doesn't show you any numbers. Okay? So with this I'll just leave this layout as it is and maybe we can end this section right here. We just learned about the native tabs. I don't really want to make this any more complicated. So once again we have the native tabs as the parent element. Then for every single one of these tabs you would create a trigger pass the file name that you would like to see as the content. Then give it a label as well as an icon. And if you wanted to you can update the default state as well as the selected state. To be able to update the colors we update the tint color and just pass our object or the string value. Sorry, not object but just a string value which is a color. Okay, so these are all the things that we have done in this section. I'm just going to close everything and let's try to stage our changes and then we're just going to commit that sync this up and hopefully I'll see you in the next section. All right, so this is where we left in the previous section. And we have built these native tabs. And in this section, we are going to learn something called API routes. This is coming from Expo. This is a feature that they have and it's really cool. So we're going to learn it. Just type Expo API routes. Then go into the documentation. Okay. So this is basically a concept or yeah, I think we can just call it as a concept. So you don't really need to build a separate back end to be able to run the code on the server side. So if you have ever used Nex.js, it is the similar concept. Under the app folder, you would create an API folder and then you would put your backend code. If you have never used Nex.js, that's completely fine. I'll try to explain from scratch. But if you used it, just know that it is the similar concept. So if you want to create an API route, you just need to add this plus API at the end of the file. So here, let's go ahead and actually test this out under the app. You can put it right here like under the root. But my convention like not only mine, but I would say every developer that knows how to use this correctly would create an API folder. like this is a convention that we would do and within this you would create the file. So this makes your codebase organized. You just know all your API routes are under here, right? It's not it's not like randomly under the app folder, right? Okay. So just make sure to create this folder for the best practices. Now we can create hello.ts file but remember to put plus API just before the dot. Okay. So here you would create methods and it could be called as get, delete, I think, put, patch, so on and so forth. So let's just get the get request. I'm going to copy this and just paste this in. So we have the function called get. This is a get request. The first object is request that you can get. This is something that Expo provides you out of the box. And here we just like return a simple response. Just make sure to run your application. And one more thing, if you want to use this, you need to visit app.json just like what they say here. And under the web, all code should be equal to server. Okay, by default it is static. Just make sure to replace it as server. And this is what they say in the documentation as well. So that's the first step. And then we can call this endpoint. Now, make sure that you're running your application and I can open up a new terminal. We will just send a get request like we're going to call this basically. And I think they have the example. So, I'm going to copy this. So, this is using the curl. If you don't know what that is, basically this allows you to send Oops. Let's go here. This allows you to send a get request to this endpoint. Now, this is what you would run normally, but since we put it under the API folder, we should add API right here. So, I'm going to call this. Notice how we got the hello world. If you don't add the API, let me just paste that in. Like, it's going to say this route did not found or I think we don't really get any response at all. Okay, I think we got it's like 404, right? Like we just got some errors. Let's clear this up once again. Since we have the API folder, you would add it into the URL. Okay, so we got the response that means it is working correctly. I'll just give you another example. Let's say under the API, let's just say we have something like I don't know payments. You would like to send a request to API payments, right? And in this case, you would create a file and I'm going to call it as index plus api. Yes. Now when you call it index, that means you don't really need to add anything else to here. So you don't need to say index. Okay? When you just call it in this way, it's going to find the index file. And again, I'll just copy this. Let's say this will be a get request. Let's say I don't know like success of true. Now I'll send the request. As you can tell it is working. So I hope this gives you an idea how that work. We are going to be building couple of different API routes so that we can call our actions. So here we have like this is what we built a delete request right another one for the delete. Then we have like update. For this we can use patch or put. Then for insert we can use post request. Right? Then here we have get request where we fetch some data. Okay. So I'm going to go ahead and delete the payments because we don't really need it. That was for testing purposes. I'm going to delete the hello API route as well. But here instead we are going to create a folder called items. And within this first off, I'll create the index plus sorry index plus api.ts file. So this is going to be the endpoint. Let me just type this out like into the terminal. That's going to be / ai slash items. Okay, since we call it as index, you don't really need to put anything else. Then here we will have a get request. So I'm going to say export async function. Let me zoom in. Okay, for the name since it's a get request, make sure it is all uppercased and call it as get. Here you can get the request just like a second ago. But here I think we don't really need it. Uh I'm going to skip that. Then we'll have the try and catch block. Now under the try, we will basically say call our query called list grocery items. So this is going to do like that's going to make the database call, right? Then I'm going to say const. We're going to get some items. And we can just return this back to the client. So I'll say return response.json. And let's pass the items. So that's the key. That's the value which is this one. Since they are the same, I'm going to delete this part. And under the catch, first off, I'll just get the error. And I'm going to, you know, like kind of like add a check. I don't know how to call it. Uh basically we have a turnary operator. We say if this is the instance of error get the message else we're going to add a generic error message and then we're going to send this back to the client response.json here is the error and status is 500. Let's actually test this out. Now in our database we have 10 different items right? So this should give us 10 different items. So I'm going to go here. We are calling API items. Let's run this. Hopefully, we should get 10 different items. As you can tell, like we have the items as the key and then the value is an array of objects where we have like eggs, banana, so on and so forth. So, this is working. That's the get request. We are going to be calling it from the client. So, for now, let's just build the API routes. Now, in the similar way, we're going to have a post request within this file. So I'm going to say export let me actually copy this part instead of get that's going to be post and we will get the request let's say type is request and within this we will say try and catch log now instead of typing out I'll just copy and paste and walk you through it because I'm such a slow typer so instead of typing it I'm just going to explain. So we're going to get the request and we're going to call the JSON function. Then we're going to await it which will give us the data that user passed and user is going to pass things like name, category, quantity and priority. Now if any of these are equal to undefined we can throw an error. So I'll say if any of these three values undefined we'll say please provide all required fields. quantity is not like um how do we call it? It's not required because within the method when we call our mutation we pass one out of the box right just in case if this is not provided let's say this is equal to zero or undefined you know we are going to just get the one okay so if this is the case we are going to return 400 as the error status code right and then we can call our mutation if this is not the case. So I'm going to say await create grocery item call this method. Then we're going to pass the name. We're going to pass the category, quantity and priority. Then this will give us the created item and we can just return this back to client. So status code will be 201 which means something is created successfully. And we'll do the similar thing for the catch block just like what we have done above. This time it'll say fail to create the item. So that's it for this entire file. We have two different endpoints or API routes which is a get request and a post request. We are going to be calling them a little bit later in the video. Now let's try to create another file. This is going to be for let's say clear clear dash purchased. Am I typing correctly? Like purchased plus API.ts. So this is going to be a post request. And let's see when you press this button under the inside screen, it's going to clear all the completed items, right? And we already have the action. Let's say clear purchased items. We'll just import it. Then let's say export async function. That's going to be a post request. We don't really need any arguments here. I'll have the try and catch block. Under the try, I'll say call the clear purchased items. Once this is done, we can say return a, you know, response.json. Maybe something like okay of true or success of true. Depends on what you would like to send. In my notes, I have okay. Okay. So, I'm just going to send it in this way. Then let's handle the catch. It's going to be pretty classic. Okay. Just like that. This is going to call the method where we can delete all the completed items. Now, a very last file that we will create. And here we will learn something new. Basically, this will be a dynamic dynamic route. And for this, you would create a file and wrap it with the brackets. So we're going to say ID. You can put anything really but basically we're going to get an ID in the URL. So just call it as ID. Then again same convention plus API.ts. And before we build it, let me explain how we're going to be calling it. So from the client, we will say something like fetch. So / API/ items and then you would pass the ID of the item. Let's say its ID is like 35, right? So that means this value could be dynamic. It could be anything. It could be 1 1,000. So you got the point. It's like passing it in this way. Okay. Now let's try to create this file. This will get I think two different methods. Let me first give you the delete one. Okay. So that's going to be a delete method where we get the request. Now here we pass as like I'll explain. Okay, just forget that we got two different arguments and we're going to call this method called delete grocery item. How do we get the ID? It's basically the second um it's the second argument. So let me just delete this and let's type this out. As usual, you would get the request, right? And then you would get an object here. we will get it as ID because that's how we call our file name. If it was hello then this would be hello as well. Let's make it type safe. We're going to say we're getting an ID which is type of string and let's say this is going to be type of request. Now since we are not using this variable a convention is to put underscore so that you know okay we import this but we are not using it. So that's the reason once you delete it you send okay of true and if we have any errors we're going to be you know sending this as the message. So in the similar way we're going to be having a patch request. I'll just paste this in. If you wanted to you can type this out or just get it from the source code. Let me just import everything and I will walk you through it. Okay. So, first off, we got we got the body from the client, right? From the request. Now, this is going to do one of these things. It's going to either update the quantity or it's going to set it as purchased. And this is going to be depending on if user passes a quantity or not. Okay. So, if user pass a quantity by calling this endpoint, we are going to call this method. But else we are going to call this method. Okay. And let's say if this is not provided, we'll just say call it as true. And then we'll say if there is no item in the database, right? In this case, we're going to say 404 item not found. But else we are going to return the item. And as usual, we're going to handle the catch. So that's it for all of our API routes. I hope that wasn't really confusing. Once again, the convention is to basically add this suffix at the end called plus API, right? File name could be anything, but just make sure to put the suffix right at the end. And the best practice is to put them under the API folder so that you know like just imagine here you have 10 different folders. If you wanted to find your API routes, you would just take a look at the API folder and then you could see everything. All right. So, let's leave this section right here. I'd like to keep it simple. Now, I know that we haven't like we didn't build UI so far, but that's fine. We're just trying to understand bunch of different concepts like native tabs, API routes, so on and so forth. Once you understand everything, then it'll be very easy to build the UI because if you think about it, this is just some CSS. It has nothing to do with React Native, right? At the moment, we are building the backend logic. so that later in the video it could be very easy to implement all these UI elements. Okay. So with this I'll go right here. I'm going to stage everything create a commit message. Once it's ready we're going to commit it and sync this up. And with this hopefully I'm going to see you in the next section. All right. So in the previous section we have built our API routes. Right now it's time to call them from our client code. Now we are not going to be doing it randomly because we would like to keep our codebase clean and for this I will create a store. Now if you don't know the concept you will understand it. For now let's create a folder called store and this will basically have a file called let's say grocery dash store.ts file. So we're going to have couple of different methods and states and this will be global. That means we can use it in any of these components like any of these files. Um, for this we'll be using a package. Let me just go here and search for the stand. You can take a look at the details from their documentation. But I'll just try to explain as simply like as simple as possible and it's like very very popular as you can tell. 22 million or 21 million weekly downloads. That's crazy. And I'll just try to explain. First off, let's try to import that. I'm going to kill this terminal. Kill my app. Let's say clear mpm install. Did I just say let's install this terminal? It should be let's install this package. I'll say mpm install zand. Okay. So, it's been installed. Now, let's try to run our app. I'll say mpx expo. It's going to run it in the background. Now, for now, let's just build a very, very simple store. I just want you to understand the concept. So, first off, you would import the create method from the stand package. And then you would create a store. Let's just say export con something like use grocery store. And this would be calling the create method. And within this we're going to get a callback method. And instead of having a function, we will wrap it with the brackets. That means return an object. So what we return here is a global object. This is our global state. And we can get two different arguments. The setter method and then the getter method. We will be using them for now. Let's say we're going to have the I don't know like I I want to keep it simple. Let's say we're going to have a state called posts. And here we can have first post. Let's say second post. And then you can have I don't know like anything. Let's just say is loading. Let's just say true. Now you can save this file and you can literally get these states in any component just by calling this hook. Let's go under the app, maybe under the home screen. So I'm just going to call use grocery store and you can get these values now. So you can get the is loading state and you can get the posts, right? Let's try to console log it. I'm going to say posts. Let's save and take a look at it. I'll just reload my app. Notice how we got the posts. So that's how easy it is to get this state, right? You just call this method. Now you can do the same thing in any of these components. So that's the beauty of using zestand. So you get the global state without doing too much work. You would just copy and paste and get any of these values. Okay. Now, of course, we are not going to keep it this simple, right? I'm going to delete these. But we will have our API calls like some methods so that we can call these routes that we created in the previous section. Okay, I hope that makes sense. And notice how this is not type safe. We would like to make it type safe. So I'm going to delete this part. And here this is how we would make it type safe by passing a generic. So I'm going to say grocery store. And we will create this as a type. So here I'll just provide you a bunch of different types. You can grab it from the source code if you don't want to type this out. First off, for the grocery category, we'll have five different categories. Okay, this is how you would type it. This is TypeScript. This has nothing to do with React Native. So I'd like to show you pretty quickly when you create an item. As you can tell, we have five different types. So this is what we just built. And then for the priority we have three different types. It could be low, medium or high. And then I'll get another type for the grocery item. So basically that's the type for a grocery item. Every single item will have an ID which is type of string. We have name, category and you can read the rest. Then we will get another type for create item input. So if you want to create an item, you need to pass these types, okay? Like fields and their types, then we're going to get the items response as well as the item response. So this is basically an array of grocery items. And this is just one item. So we're going to be using these types. I hope you don't mind it that we just copy and paste, but basically this has no logic other than some types. We'll say very last type which is called grocery store. And then within this we're going to say this store will have some items which is type of grocery item like I'll just copy and paste. We're going to say it's going to be an array of grocery items. Then we'll say it's going to have a loading state. This is when we fetch the data. It's going to be either true or false. say boolean. Then we're going to have the error state. This could be either a string or it could be a null value. Then we're going to have the load items method. I'd like to just copy and paste. Let's say this will be returning a promise of void. Then we're going to have the add item. Again, this will be a method where we get the input. Here is the type. And this is what like this is the return type. Let's add I think three more methods. Update quantity. You can just read it. This is some type declarations. Toggle purchased, remove item and finally clear purchased. Now within this state, we are going to create all these files. Since we pass this as a generic, if you press control space, notice how we get all these fields. It is type safe. So first off I'll say items by default will be an empty array and once we fetch them we are going to update this state. Then we'll say is loading initially it could be I think false and error could be equal to null. Then we're going to create our methods. So for now I'll say load items. Let's say this will be an async method. For now I'll just leave it empty. And let's build the rest so that we don't get the errors or warnings. Let's actually build this one. Just forget about the this like red lines. Typescript says you need to add all these methods into right here. And here I will actually add it so that we can get rid of these warnings. So I'm just going to let AI to complete it. Okay. So we add all these methods and TypeScript is not complaining. And let's get started with the load items method. Here we would like to update the loading state. Let me kill AI so it is not really confusing. So we'll have a try and catch block. But before we do anything else, we would like to update the loading state. And this is how we can do it. You're going to call the set method. And the states that you would like to update, you would just pass them. So I would like to make the loading state to be equal to true. And I'll say error should be equal to null because we are just trying to fetch something. And then we can say just call the API items endpoint with the fetch method and we're going to get a response back. And then we can say const something like payload or data. Let's just say res.json. Now type is equal to any as you can tell. So for that reason I'm going to wrap this with the brackets and I'll say as items response. Now if you hover over it this is type safe right? It knows the type. Then we'll say if you know response is not okay. Then we can throw I'll just copy and paste never mind. So throw new error request failed and just put the status. And in the else case, if we don't have any errors, we are going to update the items array. We'll say payload dot items. Okay, so that's how easy it is to create a method. And under the catch, we can just add a console log for debugging purposes. And for the error state, we're going to say something went wrong. And finally, as you can imagine, we're going to say the loading state should be equal to false. either we succeed or we fail. Eventually is loading state will be equal to false. Now if you wanted to call this method, you already know it like how to do it. You would go into a file in this case under the root layout and you would just import this hook. Let's say use grocery store. And let's say here you would like to get the load items, right? And you can call it under a use effect. So, I'm just going to go here maybe right after the tint color. I'm going to say use effect, initialize it. We only want to run this once, right? So, I'm going to say call the load items and that should be it. I will save this and let's get the items as well. And I'm going to console log the items. So, let's say items. Let's just add an emoji to make it obvious. Okay. So, as you can tell, we have the items. It's fetched and we can see it under the terminal. And this is actually what we're going to have right here. Let's go under the grocery store and build the rest of the methods so that we can use them easily later in the video. So here I'll get into the add item method. So we're going to say first off set the error state to be equal to null and then I'll say try and catch block. Under the try we're going to call let me just say con res. We're going to call the fetch method by passing our endpoint which is API slash items and if you remember we had a post request right so right here we have a post method and we need to pass it as an object so we'll say method it'll be equal to post then we can say headers will be application JSON and then we'll say body we'll say JSON stringify we're going to pass an object and like once again I'd like to display we're going to pass all these fields right I'd like to copy and paste so we're going to pass the name category a quantity as well as the priority okay so we're going to get a response back just like above we're going to get the payload type castes and we'll say if response is not okay handle it like throw an error but else we would like to update our state. So I'm going to say call the set method. Now notice how this is the add item method. I'd like to show you something. Let's say you add an item. Once you submit that form, it should be at the very top, right? Like this is going to go down and it'll be right here. So that means we're going to keep all the items but on top of it we're going to add the new one. So how do we make that work? We're going to call this and we can get the previous state. So I'm just going to say give us the state and then we're going to return this object. So we'll say items. It's going to be equal to all the previous items. You can just say state dot items and spread this like this. Okay. So that's going to get all the previous items but at the very top we'll say payload dot item which is the newly added one. I hope that makes sense. Now we can just say return like payload dot item. Okay. Under the catch, we will add a console log and we will update the error state. So that's it for this method as well. Once again, we update the error to be null because we are just getting started. Under the catch, we update the error. That means something went wrong. But under the try, we call our endpoint. The method was posted. We add the headers body and you know eventually we update our state. we keep all the previous items but at the very top we added the latest created one. Okay. So with this now we can go into the next method which is called update quantity. So user is going to pass the ID and quantity from the client and then we can get like a variable. I'm going to call next quantity. And let me explain what this will be. Let's say we have like 12 different like 12 eggs, right? If user press this one, the next quantity will be 13, right? So that's what we call the next quantity. It's going to be equal to math dot maximum either one or the quantity. And you already know why we add this one because if this is like - 10 or minus one, we don't really want to get this. it's going to get the one. Okay, so that's the next quantity. Once again, we'll say set error to be equal to null. And I'm just going to copy and paste the rest of it because it's very very similar. The only difference here is that the endpoint. Okay, so we pass the ID so that we know which item that we are updating. Then the method headers pass this as the argument or the body right handle the errors but else update the state. So this has nothing to do with React Native. This is basic JavaScript and I hope you you guys already know this. Okay. So for that reason I'm not going to explain super like in super detail. I'll just go into this method. And once again I'd like to copy and paste. This is just JavaScript. Let me copy and paste and then we'll go through it. Okay. So, we will find the current item. This is how we can get that. We're going to call the get method and we're going to get the items. So, that's our state and we're going to find the item that we just pass as the ID. So, let's say you would like to update this one, right? You press this button. You're going to send the ID of this item to this method. You're going to find the current item. Then we have some validation checks. If there is no item, we'll just return. We are not going to do anything. And then we're going to find the next state. If it is equal to true or not, we're going to negate it. Then we're going to call our endpoint once again by passing this field. Handle the errors and update the state immediately. Now, this is not updating the database, right? This is updating the UI immediately. Okay. Um then finally we have the catch block where we handle the errors. So we will do the similar thing for the remove item. If you don't want to type this out just grab it from the source code. This is our endpoint method is equal to delete and we just filter this item. You know we just filter this out from the UI. And then finally the clear purchased method. Again, we're going to call our endpoint pass the method and that's it. So, I can already feel like there will be some comments saying, "Hey man, you didn't really explain this. You just copy and paste it. You are not really a good teacher." So on and so forth. But this has nothing to do about being a teacher. Like this is just basic JavaScript code, right? And we have done much more complicated stuff than this. I have explained the very first two methods so that you understand the flow like the type casting calling the fetch method handling the errors updating the state so on and so forth. Um this is basically like literally the same thing nothing complicated. So I hope you guys don't mind it that we copy and paste it. Um with this I think we are completely done with this file. The only thing we left is to calling these methods. So we are going to go let's say under the insights screen like right here when we press this button we are going to call this method right called clear purchased or if we are under the planner screen when we say create an item we will call this method called add item. So that's the only thing we left. We'll just build some UI elements, write some CSS code, and call these methods. So for that reason, I'd like to leave the section right here just to keep it simple and not complicated. I'll try to maybe like stage everything, create a commit message, commit that, and sync this up. And hopefully in the next section we're going to get started with the home screen where we can fetch the items, display them, and then we're going to build the planner screen. Finally, the insights. So with this, I'll see you in the next section. Now, it is time to build the list tab UI. It'll be easier than what you think because all we have to do is fetching the data and calling our methods whenever we press one of these buttons. So we'll just go into VS Code and under the tabs. We're going to find the index.tsx which is our list screen. So I'll just change the name to be equal to list screen. That's not really important but you know I'll just follow the conventions. I'm going to delete everything that we have in this component. Actually delete the styles and let's put them side by side. And for now, let's even delete the style because we don't have these styles. And actually, instead of having having a view, I will have a scroll view element. Let's import it from React Native. Now, as the name suggests, this is going to allow you to have a view which is scrollable. At the moment, that was not really scrollable, right? But here, since we're going to have bunch of different items, you'll be able to scroll through this screen. So we're going to say scroll view. Let's say class name of flex one. So it is taking the entire space. We'll say bg of background. And I will say petting y of four. And I think that should be it. Now within this we can add for now maybe like a text. I'll say hey. Once you save as you can tell we got this text. Now I think we cannot scroll it because we don't have enough content. We will see it a little bit later in the video. Now here you can add more props like you can say shows vertical scroll indicator. By default this is equal to true but you can make it as false. So whenever you scroll you are not going to see an indicator right here. By default it would be visible. I'll just hide it. So I'll say false. Then you can add something like content container style. And here you can pass fields like petting like all kinds of CSS fields. I'll say petting of 20 from all directions. I'll say gap of 14. And let's just first get started with a component called tab screen background. Now this will be a self-closed component. And let me show you which one that is. As you can tell, we have some circles, right? And this is something that we will repeat in three of these tabs under the list, planner, and inside like they will all have the same background. So instead of typing this out every single time, I'll just create this component. I'm going to copy the name. Let's go under the components where that is. Okay, it's right here. So I'm just going to create this file and I'll say tsx. Now, this has nothing to do with React Native other than some CSS files or CSS classes, I would say. So, I'm just going to copy and paste from the source code and let me walk you through it. So, since we have two different children, we wrap it with a fragment. Then, we add some classes into this view, which will be on, you know, like this position, left top, it is this one. Then we have the one on the right and we say pointer events of none. So user cannot really select it. So that's it. Just CSS, no logic at all. I'm going to save this. Let's try to import it. As we can tell, we have this one. But where the hell is the other one? Let's go into dark mode. Is it even visible in the dark mode? Yeah, we cannot even see it on the dark mode. Why this is the case? Left top. Um, maybe I'll just reload my app. Let's see if this is the case. Yeah. Okay. So, once you reload, it's right here. Maybe that was a stupid bug. Now, other than this component, we are going to build a list hero card, which is this one. So, let's try to create that one. We are going to call it right here list hero card. We will create it under the components. Now instead of putting it randomly, I'm going to create a folder called list. So we're going to put all components that is belong to this tab under this folder. So I'll say tsx. Let's say we're going to call RNFE and give a bit space. I will call my store get the items because we're going to use some values. Now I will say items do filter. We're going to find every single item and we'll say if item is equal to purchased just get the length of it. Okay. So this is going to give us the amount of completed items. So I'll say completed count. Then we'll say the pending count and we can calculate it just by saying the entire items length minus completed count. Right? And finally we are going to calculate this rate so that we can put this progress bar. If it is done completely this would be 100%. If it is zero, it would be right here. 50% so on and so forth. And this has some basic math calculation. I'll just provide it to you. This is how we can calculate it. I'm not going to go into the details. You can just take a look at it. All right. Here we will return a view. Let's say class name rounded of 3x large. Then I'll say background of primary padding of five from all directions. And then we'll have a text which will say today. Okay. So this is what we're building. I'm going to copy and paste just like this text small font semi bold uppercase it. Add some tracking. And you might be asking what is tracking? It's basically letter spacing. And here we are using one pixel. Then text primary foreground that's the color and we will add some opacity. So that's it for the text and right below that we will have your grocery board which is this text. So I don't want to waste any time by typing this out like it's very stupid to type this out. I hope you don't mind it. Then right below it we're going to put the pending count count as well as the completed. So, I'm going to paste this in. And finally, we're going to have that progress bar. Now, you might be asking, how do we calculate the width? Well, basically, we'll say width, which is equal to this value, and then the percent sign. So, this is just CSS. Let's go here, import it, and take a look at the end result. Okay. So, looks like I don't know if you can see it from the video, but we have eight pending and two completed. And like that's the code. That's the UI. Just imagine if that was equal to 100, it would be filled, right? If it was zero, it would not be filled. So, we got the point. Let's just say 50. Okay, I'll just bring this back. And that's it for this component. Right below it, what are we going to have? I think we can add this text. So instead of having this as a component, I'll just put it right here, right after the list hero card, import the view as well as the text from React Native. And here we say pending items.length. So, we can get this from our custom hook. And I think we don't really need this. So, I'm going to delete them. Say const items. Grab it from use grocery store. And we can get the pending items. Let's say items. Where the item is not purchased. So this is going to give us the amount of pending items just reload. As you can tell we have eight active which means that we need to complete that. Now right after this view we are going to get every single item and for each we are going to you know return a card and we are going to create this as a component. First, I'd like to say pending items do map for every single item. We're going to call this component. Let's say pending item card. And here we can pass the key. So, I'm going to say item do ID and we can send the item as well. So, once I save, it's going to format it. And I think we have an error. Let's try to fix that. So basically it says you don't have this component. So we will create it under the components under the list. Let's say tsx rnf. And wait, we'll just try to import that. Okay. So as you can tell for every single pending item, we have this pending card component. Now let's go ahead and make this type save. First we'll say we're going to get an item. And here let's say item what is the type of it? I think we already have the type. So we will just say something like this was called grocery item. Okay. Now here we will call our store. We will get the let me just import that. Okay. I'll zoom out so you can see it clearly. We're going to get the remove item method update quantity as well as the toggle purchased. Now I will give you two different objects. The first one is priority pill background. So notice how depending on the priority the background color updates right. So if it is high it's in this red color so on and so forth. And this is how we can map that. We will be using it. And then same for the text. And let me zoom in. So these are the class names that we're going to be using in a second. Here for the view, I'll say class name rounded of 3x large. And let me actually get the classes. 3x large. Give it a border. This means like one pixel. Background of card. Padding of four from all directions. I'll save. And within this we'll have another view. This will get some classes as well like we'll say flex of row item start and gap of three. So basically we are building this entire thing. We say flex of row so that everything is side by side. That's the first item that's the second one and that's the third one. And we just give it a gap. So it's the gap this one and that one. Right? And we say items of start. So this is not like in the middle but it is at the top right just like this one. So that's pretty basic CSS but still I wanted to mention and as soon as you save you're going to see something. Now within this view we are going to have a pressable and this is going to be the first button which is this one where we can toggle the state. So I will go right here. I will get the pressable element imported from React Native and we're going to give some classes. So I will say class name paste this in where we have margin top of one. We give width and height of six and in tailwind you can shorten this just by saying size of six. If they're the same thing you can just say size and whatever the value is. Then we center like center with items justify make it a circle and give the border of two. Then we can also update the background color or maybe the border color. So I'll say border of border which means like one pixel and we'll say background of card. Okay. So I think this is yeah that's the border color not border one pixel. Now within this pressible whenever we press this we'll say on press and we're going to call the toggle method. So we will say call the toggle purchased and pass the item do ID and as for the content we can put an icon getting from font awesome. Let's import this from expo icons. Okay. Now we can save. Um like we already have the check marks but we don't really want to see the check mark because um yeah I think we don't really want to see it because it's not done. That's the pending items. So for the content you can leave it empty. Now if you click to one of them it would be purchased. Like I'm going to click this one. As you can tell UI updates let's press this one. It is just gone. Right. Now for the content, let's try to put something right after the pressible. We'll have another view and we'll get the class name flex one. So it is taking the entire remaining place. Then we'll have a view with some text. So I'm going to copy and paste. Let me get the text element from React Native. I'll maximize the screen. Zoom out. So this is what I just copied and pasted. We have a view with the text. It shows the item name. Then we have another view that shows the priority. Okay. So it's like pretty simple. We get the item priority. Use this object to get the class name. And that's the end result. Okay. So for some reason classes are not working. Let's just reload the app. Is it going to fix it? Yeah, as you can tell now, it's been fixed. Now, right after this view, so after the flex one, shrink this one. Go below it and paste this part, which will display the item category. As you can tell, it is right here. We can see it if it is snacks, pantry, bakery, so on and so forth. And then right below to this view, we'll have another view. Let's say class name margin top of three flex of row. So they are side by side item centered gap of two. And as for the content we're going to have a pressable which is going to update the quantity and this will get the minus icon. Let me import the font awesome. Okay. So, as you can tell, we got the minus. If you press that, what'll happen? It's going to call the update quantity method by passing the item ID as well as the quantity minus one. Now, if we take a look at the end result, you're going to see that we will have the actual quantity and then the plus sign. Let's try to build it. Right after this pressable, we will have the item quantity as the text and then finally another pressable which is going to be plus icon. And if you press it's going to increment by one. Now for some reason border color is like black. Maybe this should be border. Yeah, I think I'll go with the border instead of input. Okay. So let's try to press this plus icon. Is it going to work? Yes. After like 1 second, it's been updated. Let's press again. It updates the database as well. You can press minus again again. And now if you press once again, it's not going to be zero because at minimum we get one, right? If this is equal to like minus sorry 1 minus one which means zero. It's going to get the maximum value which is one. Okay. Same for this one. But this is just plus so it can go until infinity. Okay. What else do we miss? I think that's the delete button. Let's put it right here. So I think after this view we will go ahead and even after this view so just click above these two views we're going to have one pressable which will get the trash icon and if you press that we are going to call the remove item by passing the ID. Let me just say reload this app so that the background is working. We got the background destructive. Let's try to delete one of them. And just before we delete, I'll go into my database. So, I'd like to show you that it is actually updating the database as well. Okay. So, I think I just made a mistake. Let's say we would like to delete the dark chocolate, right? At the moment, quantity is one. Before I delete, I'm going to increment this. It's been two. Let's refresh. Dark chocolate is now two. That means plus is working. Let's say minus. It should be go back to one. It's two. Let's refresh. It's one. Now let's try to delete. So UI has been updated as you can tell. Now it should be gone as well. So everything is working as expected. Now I know that we copied and pasted some stuff which was just styling and not really any logic. Okay, I hope you don't really mind it. We just like we are trying to understand how everything works rather than typing everything like step by step doing item centered justify centered so on and so forth. We don't really want to waste too much time. Let's double check this in the light theme as well if the colors are correct. Okay, so I think that looks pretty cool. Now I said we are using scroll view element and like I just wanted to show you this. Let's say true. If that's equal to true, notice how we have the scroll indicator, right? Okay. And we have gap of 14. Let's just say zero. What happens? like every item is just squished, right? We would like to give some gap. You can make it excessive, but doesn't make any sense. So, we'll just say 14. You can add the padding. Let's just delete it just to see what that does. Basically, from all directions, we give the padding. Right. And I'd like to make this to be false. If you wanted to, you can keep it as true. Now in this screen, the very last thing that we would like to have is going to be the completed items because at the moment we can only see the active items. So I'll I'll just create a component called completed items. Call this and let's try to create it under the list. Sorry, under the components under the list, let's say.tsx RNF. Save it. Let's try to import that. Okay, now this will be easier than what you think. Basically, it'll have almost no logic at all, but just some UI elements. We're going to call our hook or the store, whatever you would like to call it. We're going to get both of these methods and we're going to get the items so that we can check the completed items. So, we're going to filter this out. we will only get the purchased items and we can say if there is nothing right if the length is equal to zero we'll just return nothing but else we can return this view let me give you the classes and then for the text we're going to say completed which is this part now we will display every single item so I'm going to say completed items do map for every single item. We can return this element. I'm going to say return a view. Let's give it a key which will be item do ID and then class name. I'm too lazy to type this out. Let me provide this to you. Okay. So, as you can tell, we got the completed items, but it doesn't have any content. So, let's try to build it. We'll have view class name flex of row item center it gap of two within this we're going to have a pressable and like let's just copy and paste once we see the end result I'll explain let's get the font awesome let's save okay so why it's not visible let me maybe just say background red of 500 it. Okay. So, here we can tell that's the check icon. When we press this, it's going to call the toggle purchased method by passing the ID, right? ID of the item. And I don't know why BGS success did not work. Maybe we don't have that class. So, we have but for now they say primary. Okay. I think that looks cleaner. Let's see if it is working in the dark mode as well. Okay. So, I'm going to leave it as background primary. And here, let's just try to press one of them. It should update the UI. Okay. After like once it updates the database, it'll also update the UI. Okay. Let's put the rest of the content. So, right after the pressible, we'll have the text where we can display the item name. Just like this. It says tomato sauce. I'm going to click to it. Once it is unchecked, we can see it. It's right here. I'll press it again. Now it is right here. Bananas, it's right here. Pasta, pasta, however you call it. It's right here. Okay. So, what else we are missing? Maybe one more pressible where we can put this into trash, which is right here. So, I'll press this one. Tomato sauce should be deleted from the database. Now since we are not doing anything after the await, we can basically delete it. Delete the async as well. Delete the curly braces. Just make it a single line. Okay, I'll do the same thing right here. It should be like this. Can delete async and it should be working out as well. So I'll press pasta, bananas, and Greek yogurt. Now, as you can tell, progress is equal to zero. Let's try to add all of them. Like it just updates, and we can delete any of them as we wish. Now, with this, we are actually pretty much done with the entire list screen. But there is one thing that I'd like to talk about. So in the past when we did the comparisons I said that instead of using items.m mapap in react native we use a component called flat list. Now of course you can still use items.m map which is fine if you have a small list but here in this example just imagine that you're going to have 100 different items. You don't really want to use items map. Instead flat list would be a lot more performant. And let me explain why. I'll just go into the diagrams. Let's find the screen. Okay. So here when you do items.m map just imagine you have 100 items. Okay. It's going to render all of them even though you can only see five items, right? So the rest will be still rendered like 100 items. Just imagine even though you cannot see it, it is rendered. But if you use flat list, it's going to only render the five of them, right? And as you scroll to the bottom, it's going to render more and more, which makes it a lot more performant, so it doesn't use extra memory. Okay, now let's see how we can make this exact same thing by using flat list. I'm going to copy this and paste it as a comment below. So I'm going to say first version with items do map so that you can have it in the source code. Okay. So I will paste this as a comment. And now we'll be building this with flat list. So here basically I'm going to delete the map and instead we will use the flat list item. Let's get it from React Native. And yeah, I think right here I'm going to say class name of maybe like flex of one or do we really need it? Like for now I'm going to delete the class name. First off, we'll just say data. The data that we would like to map through which are the pending items, right? So we'll say pending items. For every single item, we can just add the key extractor. This is just like adding the key in React. Let me display pretty quickly. So when you say key item do ID it's the similar thing or the same thing you would just say get every single item and pass a unique thing like ID and then for every single item we're going to call render item method here. This will be an arrow function let's say and you can grab the item. There is also two different fields like the index as well as these separators. So here we will get every single item and for each we will return the pending like this component pending item cart and we're going to pass the item. Okay. So let's try to save and see the output. Looks like it is working but the gap is not there right. So we can add the gap just like here. I'm going to copy it. Paste it right here. So, we got the padding as well as the gap. Now, notice how this has extra padding because we have it right here as well. I'm going to delete that. Now, this part is not working. So, instead of having all these items, we will actually delete everything and put it under the flat list. So, it's going to make sense. I promise. Let's delete everything and have only flat list item because flat list is much more complex. only then these props you can add the header component footer component and empty state so on and so forth so I'm going to save this for now that's what we got but how do we add this header component so you can literally just say list header component and you can do the same thing for the footer so you can say list footer component and for the footer we had completed items section. Okay. So, looks like we cannot import it. I don't know why. I'll get it manually. Okay. Like this is kind of buggy right now. I'm going to say reload window. Sometimes VS Code just gets really stupid. Okay. for the list header like so annoying. Why can't you see this? We have completed items, not the section. My bad. Okay, we got the completed items. Let's add the header now. So for the header, I'm going to return a view element. And this will get the style. Let's just say gap of 14. And then we can add all these components that we just had like the tab screen background. We're going to get the list hero card. AI is kind of annoying. Let me kill that. Okay, so we're going to get the list hero card element. Then we can get that text we just had. And that should be it. Let's get the text element. Now once I save everything will make sense. So that's almost the exact same UI that we had couple of seconds ago. Right now one thing that we are missing is the class name. So we can just say class name flex of one. So it is taking the entire space and then we can update the background color. Now that's been fixed. And the other thing that we are missing is that this element is sticky to the status bar. Right? So to fix this, we can add this option called content insert adjustment behavior. And I'll just say automatic. Now, as you can tell, I'll reload it as well. By default it is not like it's not overlapping with this element. So it is like working nicely. It is kind of like safe area view. So with this we have the exact same output just like the first version. So instead of using a scroll view and putting everything from like top to bottom what we have done is putting a flat list instead of using map then we have the footer element which is completed items. So after this list we have our footer element and above this list we have the header element which is this part. So I hope you're able to see this like we have the header component which is the background which is also the list hero card the text then we have our flat list which is our list of items. Then we have the footer component. Now we can add more things like what happens if this is an empty array, right? Like you don't see anything for the list. So you can just say list empty component. You can return maybe like a text. Let's just say like no items in database. That's what you would see right here. And of course you could make this a lot more complicated like a very nice not found UI. But you got the point. I'm going to delete this part and let's just say get the pending items. Okay. So overall with this flat list element now our application is a lot more performant than using it in this way with items.m map. Okay. So I hope that makes sense. That's how we use the flat list element. You can double check this from the React Native documentation if you're interested. It's a flat list React Native. And I think they built even a better version of it. Like on top of flat list, you have legend list. I'm not going to get into the details, but you can take a look at it as well. Just know that something like this existed. And there's also, I believe, flash list. Yeah, if you're interested, just take a look at all of these options. So, with this, I will go ahead and stage all of our changes. In this section, we completed the list tab. In the next one, we're going to build the planner. And then finally, we're going to build the inside screen. Okay. So, I'll just stage everything, get a commit message. Oops. And then we're going to commit this. Finally, we will sync this up. Okay. So, with this, hopefully I'll see you in the next section. So, this is where we left. In this section, we would like to build the planner screen, which is going to look like this. So, we're going to have a card. We're going to display some stats. Then, we'll have an hero image and then a form where we can create an item. So, let's try to build it from top to the bottom. For this, we will visit the planner file which is under the tabs. Before we build the UI element, let's try to get our store because we will be using the items. So let's give a bit spacing. We are going to import this. And from the items array, we are going to calculate three different values. So the the count of pending items, the high priorities as well as the total units. Like here we have 12 + 2 + 1. In total, that's going to be the total units. Okay. So, from the items, I'll just say, go ahead and filter the items that are not purchased and just give us the length. Okay. Super basic JavaScript. No need to type. Just copy and paste and explain. Okay. Same thing right here. We're going to get the high priority count. We'll say find every single item which is not purchased and priority is equal to high and just get the length. Finally, we're going to get all the items, you know, for the total quantity. So, we're going to get every single item that are not purchased. Then, we can use the reduce method on top of it. Starting from zero is going to calculate how many total like how many items we have in total. Okay, so that's it for the variables. Now let's get into the return statement. Instead of just having a view, this should be a scroll view element so that we can scroll through this element or this page. So I'm going to add some classes like I'll give flex of one. It is taking the entire space. We're going to say bg should be background and maybe petting y of four. Now let's try to save what we're going to get. Okay, so this is working. But now we have this problem where the content is overlapping with the status bar. We can fix this. One of the previous solutions that we have seen was save area view. But now we are going to be using a different solution with the scroll view element. So you can say content adjustment behavior and you can set it to be automatic. Once you save, notice how it's fixed. So just keep this in mind. Maybe you can take it as a note so that you don't forget that. Then we can say shows vertical scroll indicator. If you wanted to, you can leave it as true, but I'm going to leave it as false. And finally, I'm going to leave some paddings and gaps by using content container style. Notice how we got the padding from all directions. Instead of having a text, I'm going to get the tab screen background. So this is something that we built in the past where we will get these decorative elements. Now I'm going to have a view. This will be our card. As you can tell, we have a card, right? So I will go ahead import the view from React Native. And I'll just give some class names like gap of four, rounded 3x large, border, border color, the background color, and padding from all directions. Now it doesn't have any content. So let's have another view within this. Let me format it. So this will get a class name. Let's say flex- row items start. And then I'll say justify between. Now here we will have like maybe two different items. Something on the left and something on the right. Within this, I'll just get the left hand side first. Let me paste this in. And we're going to get the text element from React Native. So, as you can tell, this is what we have. But now, right next to it, we need to put the icon as well. For this, I'll be using Font Awesome. Let me import it from Expo Vector icons. Once you save, that's the output. Now, this doesn't have any logic. Please feel free to pause the video and read it. We just have some CSS classes and magically it works, right? It's not really magic, but just some CSS classes. Okay, so what else are we going to do? Right after this font awesome and after these two views, just go here still within this one, we're going to have another view element. So this will be the second part where we have our stats. This is going to get the class name. Let's say flag dash row gap of two. And then this will have one more view. I'll give you the classes. So this will get things like flex of one, rounded to 2x large, border, background color, and padding from all directions. First off, we're going to have the pending text just like that. But now we need to put the actual stats, right? which is something that we calculated right here. So, we'll get the pending count and put it right here. Now, this is only one of the cards, right? We would like to duplicate it. Is it this one? Yeah, I think it should be this one. I'm going to paste it once again. That's what we got. Let's paste this once again. And then we'll just update the values. So, here we'll say high priority. Then we can use that variable. Here we will use I think the units. How did we call it? Total quantity. Okay. So these are the stats that we have in this screen. Let's try to go right below to this text and after these two views and I think even after this one. So just above the scroll view, we're going to have an element called planner hero image and I will create this under the components. Now just like what we have done under the list screen, I will create a folder for the planner just to make my codebase a little bit more organized. And within this I will create this file and I'm going to say rnf. Now, here we will be using an image. You can grab this from the source code. Just head over to the assets. Under the images, you're going to see an image called I think hero.png. So, I'm going to install it and paste it right here. Now, within this component, we would like to use that image. First, I'll get some imports like we are going to get linear gradient from expo. And let's try to first install it. So you can search for expo linear gradient and from here you can copy the command and paste it into your terminal. So I'm going to kill this, clear it and paste this in. So it's been installed and let me explain why are we using this component in the first place. So if you just add the image by itself, it works nice but it is too bright. I don't know if it is visible from this screenshot, but there is a linear gradient like kind of like a black fade in from the top and from the bottom. And this is what we'd like to implement. You can take a look at the documentation in detail how they use it, but I'll try to explain as quickly as possible right here. So, first off, I want you to visit the source code, find this file, and grab the content. It's nothing complicated. We just have one image. And let's try to import this. By the way, we need to run our application. Let's run this. And then I'll explain what we just done. Okay. So, I think we got some warnings that we're going to fix like why this did not did not work. Let me kill the terminal. I'm going to say clear this up. Okay. So, I'll just say clear and maybe I'll say mpx explore run iOS. Maybe we need to rebuild our application. Did we had a warning? Yeah, I think we need to like rebuild it. Let's wait for this to be completed. And while this is building, I can explain what we have just done. So, first off, we created created this parent div which is this one. So we give some classes to get rid of the overflow, make it rounded, so on and so forth. And then we have our image where we get it from the images folder. But that's the important part. So we give gradient from the top and then from the bottom. So we can add things like the colors. In this case, we have a black color that is fade out and we go to transparent. So from black to transparent. And then you can add the start position, the end position, and then the style. And by the way, the build is done. As you can tell, now it is working correctly. So I'll try to delete both of these gradients. Notice how it immediately updates and like UI difference is visible. Image is too bright in this case. So we add the linear gradient. Now this is kind of like fade out and it's looking a lot more cleaner. Now just to show you how this work, let's say the first color will be red, the other one will be blue. So notice how it starts from red and it goes up until like the blue color. But when you use black and transparent from here, it goes like from black to transparent. Okay, so it's pretty clear. Let's just make this to be maybe 0.9. So it is more visible as you can tell. Like let's just delete the alpha value. It's completely black and it goes until like the transparent. So, I hope you got the point. You can add more props, but I'm just going to leave it as it is. The focus of this tutorial is not this component. But just know that something like this existed and you can be very creative and build beautiful components by adding gradients. For the entire reference, just take a look at the expo documentation. Okay, so that's it for this component. Now we will have one more text which is going to be this part. So let's go here right after the image. I will provide this to you. It will be five lines of code. We have one text kind of like a title and then a description. Now right below to it we will have very last component called planner form card. So we are going to create this under the components under the planner. Let's say RNF generate the content and import it right here. So this is going to include the actual logic where we have some inputs, we have categories and then we can select a priority. At the very end there will be a button where we can press that is going to create this data in the database. Okay. So let's try to go step by step. First off, we're going to visit the planner form card component. And here we need to get some states, right? Because we are going to store all these values like the item name, the quantity, category, priority, so on and so forth. So let's go ahead and import use state and create all of them one by one. The initial value is going to be an empty string. Then we'll get the quantity. It's going to be one. Now I would like to create some types. Let's go here. You know, just to make TypeScript happy. First off, I'm going to say actually this will be an array, not a type. Let's say categories. And this will be equal to an array. It could be one of these values. So it could be produce. It could be diary. Let me provide this to you. So we have five different categories, right? Which are one of these or all of them. So that's the array. Now let's try to make this type safe. I'm going to say this should be the type that we already created which is called grocery category. And this is going to be an array, right? That's the type that we created in the past. So that's our categories array. Then we will have the priorities. Same thing. Let's try to get the type. So it could be one of these values and we're going to be using them, I promise. And then we're going to have the icons map. So for produce, this will be the icon. For diary, this will be the icon. So on and so forth. I'd like to create this as an object where the key is the category and value is the name of the icon. Okay. So these are the things. Now let's go here. We will create the category. This will be a state by default it'll be produce and we will add the type. So here if you try to make it something like hello it's going to fail. It says it can be only one of these values. So that's why we are creating the types in the first place. Then we'll say priority by default is going to be medium. Then we can use our store to get this method where we can add an item and check if there are any errors or not. Now I will create a val um a value boolean. So I'll say can create if user type something in only then they can create it otherwise the button will be disabled. So I'm going to say name.trim and we'll say length if this is greater than zero that means user can create this item. And then I will have a method. Let's say con handle quantity change. This will get a value. Let's say it'll be type of string. And then here basically we're going to say set quantity. And we'll say value. We don't just paste this as it is. Okay. Very annoying. Let me type this out correctly. Now the problem with this is that what happens if user wants to say you know something like hello right we should only allow them to type digits. So it could be 1 2 1,000 but not any text. So we can use a let's say regular expression. We will basically take every single value that is not digit and we're going to replace it. Okay. So I'll leave a comment. This is a regular expression. If you're not familiar with it, it'll basically, you know, it'll just delete all non-numeric values. That's the method that we'll use a little bit later in the video. Now, we will just have one more method and then we'll get into the return statement. So, this is what we call the create item. So, that's the async function where we call the add item. So, this is our method that we're getting from the store. We're going to pass the name, category, priority, and quantity. And we just convert it to be a number before we send it. And then we are going to reset our form. So everything will be in the initial state. Okay. So I hope that makes sense. Now let's get started with the UI itself and we'll just make everything work step by step. So this parent view is going to get a class name. We will give rounded of 3x large border border color background as well as the padding. So that's the end result. Let's delete this text. Instead, we're going to say item name. So it is this part that we just built. And right below that, we're going to have an icon and an input, a text input. So I'm going to wrap them with a view element. I'll give some classes. Let me provide this to you. That's what we have. Within this, I will have the font awesome. And for the icon, I'll be using bag shopping. Okay, let's import the font awesome. And right below to the icon, we can have the text input. So, this is a component. Let me first save. This is a component that we will import from React Native. Now this will get a couple of different props. We're going to pass the value which is our state called name and we can add the on change text. We're going to pass our setter method which is set name and then we can add a placeholder. And here I'll just say example blueberries. That's what we have. Then right after the placeholder I'm going to add the class name. Let me say margin left of three, flex of one, text base and text foreground. Now we can add I think let me just go right here. So right after the class name I'm going to add the placeholder text color. Notice how it's been fixed. And for the border color I'll be using border dashboard. Now let's try to test this out if state updates is working or not. I'm going to say console.log log maybe like the name itself and as soon as you type like initially it does undefined when you type notice how it updates immediately. So that means this handler is actually working. Okay, so that's the very first input. Now we will have almost the exact same thing but this time for quantity. Okay, so I'll just leave a comment. I'm going to say that's the item name. Then we'll have the quantity. It's almost the same thing. Let me provide this to you. Okay. So, we have the text that says quantity, which is this one. And right below it, we have another input. I'm going to make this to be border dash border as well. We have a different font or icon, I should say. Then we have the text input. We pass the value as quantity on change which is this method. Now notice how I cannot type something like ABC right as soon as I type it just replace it. But I can type any numbers and the keyboard type is equal to number pad and the rest is just some classes and we also have a placeholder of one. Now we can save this and I think I'm going to put this comment right above the text. Okay, now we're going to have our categories. And notice how if a category is selected, its background and text color is different. Also, the icon color, right? So, we're going to map through every single category. And we're going to check if it is active. We will update the background color, text color, as well as the icon color. So, let's go here. After the quantity I'm going to say categories and I will get my text which says category and then we are going to map through the categories itself. So let me maximize the screen so you can see it clearly. If you don't want to type this out you can get it from the source code. Just import a principle and I will walk you through it. So we have this parent view with these classes. As you can tell, we are using flex row so that they are side by side and we use flex wrap so they wrap to the second line if there is not enough space and then we give the gap of two. Okay, so notice how we get every single option and we check if it is active. If it is active, we update the background color, we update the font color or the icon color I should say and also the text color. And if you press it's going to call this method by passing that option. So the rest is some CSS styling. And let's test this out. So we got all of our categories. You can press and it's going to update the category. Now we will do the exact same thing for the priority. I'm going to shrink this. Let's say priority. And again you can grab it from the source code. It's the exact same thing. We map through every single option. Check if it is active. Then we can get the icon as well. And once you press, we update the state. And depending on the active state, we update some styling mostly the colors. Now let's try to put them side by side. As you can tell, we got the low, medium, high, and it is working as you press. Now at the very end finally we are going to have a pressible where we can call the method that is called create item. So right after the priority I'm going to paste this in which is a pressible it is taking the entire width. So we say if user can create background should be primary. Now notice how as soon as I delete if I don't have any content we are using background muted for the button because this is equal to false as soon as I type in it updates. Okay. And we say this would be disabled if user cannot create on press call this method and the rest is an icon as well as a text. Okay. Now let's try to actually test this out. I'm going to say oops not here. Let me bring this back. I'm going to say test item. For quantity, I'll say something like five. And I'll leave everything as default. Let's add it. Okay, looks like it's been created, right? Because form has been reseted. Let's go here. Take a look at the database. We should have the test item. So, it is working as expected. Now, if we have any errors, we can display a text. So I'm going to go here and I'll say if there is an error for now let's make it true and I'm going to say just error. So this is what you would see. Let's make the text maybe update the text color to be something like white. Okay. And let's bring this back. You know, this is a very simple error placeholder, but if you wanted to, you can make it even better. You can customize it. I'm just going to leave it just to have some placeholder. And here we say if there is not an error, display nothing. At the moment, there is no errors. So, we don't see anything. Now, one optimization or I would say an optional feature. You could say show an alert if it is created successfully. So, you would say alert. Add a title like success and you can say item created successfully or anything. Let's try to test this out. I'm going to put a te you know test value random low snacks created. You can add a loading spinner as well but I'm just going to keep it simple. And as you can tell once it's been created it says success. And we can say okay. Okay. So that's it. I'm going to delete this. Maybe just leave it as a comment and I'll say optional. Now I would say we are completely done with this section. But there is a problem. I don't know if you have realized. So if you press one of these inputs and if you open up the keyboard with command shift K that's how we can toggle it. Notice how it's going to overlap with the text input. So you need to manually scroll and then type this in. Right? And just imagine if there was not enough space, it would stay like this and you couldn't scroll. And to be able to fix this, we are going to install a package called React Native keyboard controller. So you can find this from the Expo documentation. Just copy this script or the command. Open up your terminal. Kill this. Let's stop it. And I'm going to run this. And since we added a new module, we need to rerun our application. So I'll say mpx explore runos. We need to rebuild our app. And let's wait for this to be completed. Okay. So once it is done successfully, head over to root layout file and import this keyboard provider. Then wrap your entire application with this element. So that's the first step. Then you're going to visit the planner.tsx. So in the past we just had scroll view element, right? But replace it with keyboard aware aware scroll view. Then you know have the everything as same previously but on top of it at the bottom offset which is 80 in this case. And then keyboard should persist tabs should be equal to handled. Okay. So once again wrap your application with this element. Then go under the planner wrap it with keyboard aware scroll view. Then add these two extra fields. So with this now if you try to press notice how it automatically scrolls and that's the solution. So with this I think we are completely done with the planner screen. So we can commit our changes and finally in the next section we are going to build the inside screen. So I'll go here stage everything and notice how this looks like as if we have an error but not really. This is just some stupid bug in VS Code. If you press command shiftp, reload the window, it should be gone. As you can tell, now we don't really get that error warning. But anyways, we stage everything. Now we're going to say get a commit message and then we're going to sync this up. Okay, so with this hopefully I'll see you in the next section. All right, so this is where we left in this section. and we would like to build the inside screen which is going to look like this. So here is the end result. We're going to have couple of different components like the user profile, some stats, maybe like categories, so on and so forth. So let's get started with the insights file. I'll go under the tabs. That's what we have at the moment. I'm going to give all the spacing and then I'll make this to be a scroll view element. Let's import it from React Native and turn this off. Delete the text. Let's give some classes. I'm going to say flex of one bg background. And then I'll get the petting y4. So that's going to be for all the classes. Now I'd like to get rid of the vertical scroll indicator as usual. So I'm just going to say false. Then I'll give some styling on the container style like the padding and gap. This is something that we do. So this is pretty usual. And finally, we are going to say content insert adjustment behavior is going to be automatic. This is something that we have explained in the past. Now let's go ahead and get the tabs screen background component. I'm going to save and like it's working out of the box. Now right after this element, we're going to build the user profile component. Let's copy the name. We'll go under the components. I will create a folder called insights. And within this, we're going to create this file. Let's shrink it. I'll say RNFE and import it. Now, we can get started with this component. It's going to be pretty simple to get started with. So, first off, let's get our imports. As you can tell, we are getting some stuff from Clerk Expo, Expo image, and React Native. Now we're going to get the sign out method as well as the user object from clerk. Then we can get the email address because we are going to be displaying it and this is how we can get that. And we would like to get the display name of the user. So first off we'll say if user has a full name uh just get that value. But in case this is equal to undefined we're going to get the email. Let's say if it looks like something like this like gmail.com we will split it by at and we're going to get the first part. So that would be the display name. This is what we are doing. And then we can get into the return statement. So I'm going to delete the text. We're going to have view with some classes. Let's save. Maybe if I save I'll lose all these imports. So I'm not going to save. Let me get another view. And within this we're going to have the actual content. So I'm going to paste this in and walk you through it. So we have the image element. As you can tell, we are passing the user image URL. We give the width and height. We're just taking the entire space of the parent element. Then we say this user is signed in as. Then we display the display name, email, and then we have the sign out method. So once you press it's going to sign you out. And for the content, we have this icon. So pretty easy to understand guys. I don't want to spend like 10 minutes typing this out. So I just copied and pasted. Please feel free to pause the video and take a look at the source code. Okay. So once again we are getting some hooks um getting the data out of the user and then making the UI work. Let's try to test out if not is going to work or not. Like we already know that's going to work but you know let's just prove that. Okay. Now try to login once again. Then we will go ahead and build the second component. So we would like to import it first under the insights.tsx. I'll just say this should be the insights stat section. So I'm going to copy this name and create this. And then I will go ahead and import that. Now we will have couple of different components as well like the category section. Let's copy the name. Create this file as well. And we're going to be building them one by one. So I'm going to import all of them. Then we'll have the priority section. And finally the clear completed button. I'll say RNF. Let's try to import that one as well. And by the way, if you want to close a file with a shortcut, you would you would press control W or command W, right? Okay, let's import this one as well. And let's get started with this component which is called the stats. Now this is super simple. It is very similar what we have done in this screen. We basically get some values out of the items. So what I'll be doing, I'll just delete this entire thing. Grab it from the source code. It is 60 lines of code and I will walk you through it step by step. So we have some imports. Then we are getting the items so that we can calculate the total amount of items, right? So we're going to get the total amount completed and pending, right? Sorry, like total, completed, and pending. And then we're going to basically create these cards and put the data in it. Like nothing complicated at all. So we got the total items, completed items, and pending items. We also have a completion rate so that we can display this progress bar. Okay. So we can take a look at the code. Let me save and see the end result first. Now, even though it says 33%, this looks like zero. I'd like to reload this. I hope it should be fixed. Okay, now with this it is working. So once again, we got like three different views. That's the first one, right? That's the second card and then that's the third one. And at the very end, we have the completion rate. Basically, depending on this math, we add the value and we add the percent. so that it gets that width, right? Let's make it something like 100%. As you can tell, it would be filled. I'll just bring this back. Okay, so that's it for this entire component. I hope you don't mind it, but we are at the very end of this course. I think it's been around 4 hours, so we can just speed up the process a little bit. And here we will go under the category section, which is going to be this part. And once again, we will have a similar logic, right? We will have like different colors. We will have different labels, but the general idea is the same. Now, let's jump into VS Code and get started with it. Again, I'm going to delete everything and just grab it from the source code. Then I will walk you through it step by step. First, let's save and see the end result. Then I'll try to walk you through it. Okay. So, that's the element that we just built. So we have the category colors which is an object. This is just TypeScript types. You don't have to add it. But if you don't add that, TypeScript will not be happy with you. So we say this is going to be a record which is basically an object where the key is a string value and the value is also a string type. Right? So for the produce we have this color for snacks. This one so on and so forth. Then we got the items get the total amount. Then we get the categories. And again we have the types. You don't have to add this part but if you don't add it again TypeScript will not be happy with you. And then we have the category entries. Now this is just some math we are using so that we can calculate everything. You don't have to understand this completely. But if you're interested just pause the video and take a look at the code and you can ask AI to explain this in detail like how everything works in detail. And then the rest is the UI. So we have items by category text. Then we have the length of the category entries. Like in this case we have five categories. Then what else? We are mapping through every single category and we just built the UI like nothing complicated. We already have the data right here, right? And we are just um like we're just putting it into the UI. So I'm not going to get into the details. Let me maximize the screen. if you're interested in. And at the very end, we just have one check just in case if there are no entries, we will say add items to reveal your category mix or your stats. Okay, so that's it for this component as well. Now, we're going to add the priority section. So, this will say how many of them you have. In this case, I think it is three of high priority. Okay? And if you don't have anything, it'll just say you don't have any. you don't have any high priority items. So something like that. Let's try to get into this component as well. I'm just going to grab the code from the source code. It is 30 lines of code. Let's save. See the end result and I will walk you through it. Okay. So in our case, we have one high priority. And if you don't have any like let's say if that's equal to zero, it'll say everything critical is covered. But else you would see this text which is right here. Okay. So very very simple nothing complicated. We get the items count the amount of high priority items and then just put some UI so that we can have this end result. Okay. So I'm going to save. Let's finally go into clear completed button component which is going to be a simple button. And once you clicked it it's going to call a method that we created in the past. So this will be like 10 lines of code. I'm going to grab it from the source code. We are getting our store so that we can get this method. And once you press it's going to delete all the cleared elements. Like in our case, we have three. I'm going to say clear everything. Once it is done, they should be gone, right? And if you take a look at the database, they should also be deleted. As you can tell, three of them has just gone. So with this we are completely done with this project but I just want to test this out on Android as well just to make sure everything is working successfully. So I will open up the Android Studio and I'll say more actions and maybe I'll say virtual device manager so that I can run this u simulator. So this is something that I have already installed in my machine and from the terminal now we were pressing I to run it on iOS right but now we can press A to run it on Android as well. I'll just give couple of seconds for this to be installed or start. Okay, now I'll press A. I think we need to build it for Android as well. So I'm going to say mpx expo run Android. So this is going to create the Android folder as you can tell. And I'll just wait for this to be completed. Once this is done, we are going to get the development build and we should be able to run the application successfully. All right. So it's done successfully. As you can tell, we are running this application in Android. Now we can try to login as well. Now in the past when I was trying to build it with Android, it was always failing and the reason was I was using the latest version of Java, I downgraded to 17 and then it started working. If in your case it fails, just keep that in mind. Maybe you should downgrade your Java version to 17. Okay? Or ask AI. I don't know what kind of issues you will get because if I don't see the error, I cannot really provide a solution. If you get any kind of error in terminal, just copy it and paste it to AI and say, "Hey, I was trying to build my app with Expo. That's what happened. Help me out." So, that's what I've done in the past and it just fixed that. Now, I'm going to try to continue with this account. Unmatched route. Like, what do you mean? Let's try to say go back and reload. Okay, it is working now, but for some reason it didn't work initially. Um, we can double check and try to fix that. Let's just see other things like our tabs are working, right? We have the insights. We can clear everything. Let's actually test this out. Let's go here. Like I'm going to make this to be completed and I'll say clear the completed ones. That's gone. We can uh increment the quantity. We can decrement it. We can mark it as completed. We can also toggle the state. Right? I'm going to press this once again. We can delete them. We can create items. So here I'll just say test. So it's been added. Let's go here. Test is right here. And we can try to log out as well. So this is something that you get from expo like a dev tool. If you wanted to, you can toggle this. And now it is not visible. I'll press log out. Here we go. We are logged out. Now I'm going to reload my app. And once you press R, notice how it reloads in both of the simulators. Now once again, I'll try to login with Google. I'll just see if we are going to get that error where it takes us to not found route. If that's the case, we can fix it. Okay, so for some reason it takes us to SSO call back. So I just paused the video and try to find a solution. Now it's actually pretty easy and simple to fix this. As you can tell, it navigated us to SSO- callback page, but we don't really have it. So Expo says there is an unmatched route. So we will go ahead and create this under the app. I will just say SSO- callback.tsx. Now remember at the beginning of this course I said whatever you put under the app is going to be a screen, right? So this is our callback screen. And here we will have no logic other than redirection. So I'd like to grab this just like under the oath layout. So I think I'll just grab this entire thing and let me get r I can zoom in. I'll say SSO call back screen. This is not going to return any UI elements. Let's get the use o hook. We will get the redirect from export router. And at the very end here we can say you know if user is not signed in we can take the user and redirect them to sign in screen. I'll just say slash it was under the oath and we had the sign in screen. Okay so super simple nothing complicated we are getting these values. We check if clerk is loaded or not. If it is not loaded we don't return anything. Then we uh check if user is signed in. We take them to the home screen. If not, we take them to the sign-in screen. Now with this, I'm going to rerun my application and we'll just test out one last time. So I'll try to log out. Now if we log in, it shouldn't throw that error, right? because it's going to take us to SSO call back screen and the navigation should happen. Now we didn't got the error and after like one or two seconds we are redirected to the home screen because we are assigned it. Okay. So that means everything is working correctly and as expected. Now notice how here this is almost um how do we call it? It is like sticky to the status bar on Android not on iOS. So for this we can go under the tabs find here and maybe you can just say like margin top of 10. Would this work? I don't think so. We need to find the header. Let's just say I don't know like petting top maybe or margin top. Let's just say 20. It did not work. Let me reload. Okay. So as you can tell we have some spacing. So that means this is how we can fix that. Adding some paddings from the top. If you're not really happy with the other screens, you can also add this kind of a fix. But at this point, I'm happy. So I'm going to leave it as it is. All right. So with all that being said, I think we are completely done with this project. We started from an empty folder, but now we have an application that works on both Android and iOS. We have authentication. We have database connection and that database is hosted on the cloud using neon which provides us a Postgress database and we have light mode and dark mode support. I think I didn't show you on Android but let's go ahead test this out. I think we should visit the settings and then I'm going to toggle the theme. Let's see where that is. Maybe under the display a dark theme. Let's make it to be light. And this should be accessible as soon as you switch. As you can tell, colors are working nicely. Let's try to log out. And authentication screen is also looking pretty clean. So yeah, overall I hope you enjoyed it. Congratulations to be able to follow along up until now. It was more than 4 hours, but following along take around 10 hours or maybe a couple of days. Okay, so hopefully I'll see you in the next project. All right. So, even though we are completely done with this project, I'd like to implement one extra feature, which is something that I've explained at the beginning of this course. So, it's going to be this feedback button where users can press this button and fill in their information and then they can explain what's the bug they encountered, right? What did they expect or what are the features they would like to have in the future, right? And once they submit this, we're going to get this request so that we can jump into our codebase and fix those issues. So it's really important to grab feedback from your users and we will see how to do it in this section. Now for this we're going to be using Sentry which is completely free to get started with and on top of it I have included a link which will give you $80 free credits. So go ahead and sign up. I already have an account under centry.io. Here I'll just say sign in. Now this is much more than a feedback button platform, right? This is just their one of their tiny features. This is the actual platform where you would handle the errors, you know, error monitoring, logging. They now have AI code reviews and much more. But since this is a beginnerfriendly course, we'll just implement the feedback button. So I will go ahead and log in. Then we will create a new application. So as you can tell I already have grossify test. But now I'll go here create a new project with React Native. Let's give the project slug as grossify. You can call it anything. I will leave everything as it is. And then I'll create the project. They're going to provide us a script or a command that we can just copy and paste it into our terminal. So, I'm going to kill this. I will just paste this in and I think it's going to ask couple of different questions. So, it's going to install Sentry React Native. All right. So, it just installed this package and then automatically it took me to browser where I can authenticate and then now we are back into VS Code. Here it's going to ask couple of different questions. where do we want to implement session replay? Now, normally I would include this, but in this project, we don't really need it. We only need that feedback button. So, I'm going to say no. I don't want to. Well, actually, I would like to get the feedback widget. So, I'm going to say yes so that we can collect feedback from our users. I will say yes. Uh for logs, we don't really need it. But if you say yes, I'll just show you what'll happen. Now it basically says grab this and put it into your root layout. So I'm going to go ahead open up the root layout and we will paste it just above the root layout. We need to import sentry. I think we already got it. I'm just put it like I'll put it at the very top. Okay. So this is the string we are using so that we can connect to our centry project. And then it says enable logs. Since I said yes, it's equal to true, right? If you wanted to, you can delete this since we don't really need it. And like some more options for now, we can delete them. And then for the integrations, we will only leave the feedback integration. So I'm going to save this and let's take a look at the terminal. Yes, we apply this. I'll just say yes, continue. Um, no for MCP. We don't really need it. And I'll just say yes, everything is done successfully. Let's run our application. Maybe we need to rebuild it. I'll say mpx explore run iOS. If you're on Android, do it for Android. And while this is building it, we can go ahead kill the application and implement it under the inside screen. So here, let me show you the end result. Under the inside screen we have a button which is floating right. So we will put this by using position absolute. So I will go under the insides.tsx file and I will wrap this with fragment because we're going to have two different children. That's the scroll view. Right below to it, I'm going to call the sentry feedback button. And we are going to create this component. I think we can put it under the insights like components insights. Put this in and say.tsx R NF. And then let's try to import it right here. Now here I'd like to import sentry as well. I'm going to copy this. Paste this right here. I will get font awesome. And then here I will also import the pressible component. Now for this view I'll say class name. I think we're going to be using style and you will see why. So I'll just say style and let's put an object and I'll just grab the values. So I'm going to get position of absolute right of 16 and we'll say zindex of 50. Then we would like to also put the bottom position right now if you say bottom of zero probably it would be right here. But instead we are going to be using a safe hook. So I'm going to say for the bottom instead of just saying something like 80 like 80 pixels we're going to say on top of it add the insets bottom and we're going to get this inserts by calling a hook. I'm going to say use save area inserts and you will see what this does in a second. here. Instead of having a text, we're going to have a pressable. And once you press that, like let me import the pressable. Okay. So once you press this, we're going to call this method from sentry which which says show feedback widget. We have some classes, an icon, and then a text that says feedback. Okay, super simple, nothing complicated. just a button that calls this method. Now, let's wait for this to be started. And here we go. We have the button. If you click, looks like something failed. We can fix that. Let me just say dismiss and reload this app. Okay, it fails. I think we are missing something. Okay, so to fix this, we are just missing something where we will take this entire function and we're going to wrap it with sentry. So this is one of these steps that I forgot. We'll just say sentry. Wrap call this and wrap everything with it. Now with this it should be working out. If you press here we go we got this model where we can uh you know dismiss that or we can submit the information. Now here I'd like to show you the insets bottom. If you delete this part where you say 80 pixels, it'll take from bottom 80, right? But this value will be different on every single device. Let's say on iPhone 16, you need to maybe have it like 90 pixels. On Pro Max, it's 80 pixels. Let's say iPhone, you know, 7 or 6S, I don't know, maybe you need to use like 100 pixels, right? So you can't really calculate it. um dynamically. To be able to fix this, you're going to say inserts bottom. It'll always make sure that it is not overlapping with the safe area view from the bottom. You can also use like top, left, right, like all these variables are available. In this case, we're going to be going with bottom. Let's say just delete the 80. What'll happen? It is right here. But on top of it, we can add some values like 20 would be fine. I think I'll go with 80. But if you wanted to feel free to update this value, maybe like 70. Yeah, I think 80 should be fine. Um, even like 90 so that it doesn't really overlap with this button. Okay. So, let's try to save and maybe just add a feedback. I'm going to put my name. Let's put the email. And for the description, I'll say something like, "Please fix the logo feature. It does not work." Okay. So, I'm going to say sent this bug report. Thank you for your report. That means it's done successfully. Now, we can go into our Sentry dashboard and try to find that um you know, find the reports. So, head over to issue section. You're going to see the user feedback. And from here, select your application, right? In this case, that's what I have. And just a minute ago, we got this feedback from this user. And you can see more details by clicking to it. Things like the device, you know, the environment, which is iOS. So that you would know that they have this error for only iOS, right? Um, so yeah, that's how you would use it. You can assign this to one of your teammates so that they can fix it. You can mark this as spam, mark unread, delete, so on and so forth. Feel free to, you know, explore this from the dashboard. But this is how we are going to leave it at this point. So once again, super simple. We just have one DSN, right? This is our string where we can connect to our project. Our integration is only feedback. If you wanted to add more integrations, you would just add it right here, but we're going to leave it as it is. Then we wrapped our entire application with this method. I don't know why this failed. Let's rerun this. Okay, so we wrapped our entire application with sentry. And then here we have a method where we call whenever we press that button. And by the way, it was failing because I accidentally deleted this part. Now let's save. And now we can rerun this. It should be working out. Okay, so that was the entire project. I hope you enjoyed it. And just before we end it, you might realize that Sentry has created.local file. Now, this is kind of confusing. You might be like you might be asking why do we have both of them? Well, you can take this content, cut it, and put it right here. Then you can delete this file. So, env.local, we don't really need it because we already had thev file. And the other thing that I'd like to do, instead of having this as a hard-coded value, I'm going to cut this from here. And I'm going to get this from process. Menv. So, I'm going to say not oath token, but let me get the env file. And I will say expo public sentry DSN. and then just paste this value. Okay, so with this hopefully it should be working out as well. I'm going to reload my app. So as you can tell it is working without any issues. Okay. So, with this hopefully I'll see you in the next
Generated algorithmically for Search Engine
Indexing.